• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / github_pull_request_312964

19 Feb 2025 07:31PM UTC coverage: 90.814% (-0.3%) from 91.119%
github_pull_request_312964

Pull #8071

Evergreen

web-flow
Bump serialize-javascript and mocha

Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) to 6.0.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `serialize-javascript` from 6.0.0 to 6.0.2
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](https://github.com/yahoo/serialize-javascript/compare/v6.0.0...v6.0.2)

Updates `mocha` from 10.2.0 to 10.8.2
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v10.2.0...v10.8.2)

---
updated-dependencies:
- dependency-name: serialize-javascript
  dependency-type: indirect
- dependency-name: mocha
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #8071: Bump serialize-javascript and mocha

96552 of 179126 branches covered (53.9%)

212672 of 234185 relevant lines covered (90.81%)

3115802.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.68
/src/realm/backup_restore.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include <realm/backup_restore.hpp>
20
#include <realm/util/file.hpp>
21
#include <realm/util/time.hpp>
22

23
#include <vector>
24
#include <chrono>
25

26
namespace realm {
27

28
/*
29
 * IMPORTANT: The following two arrays must be kept updated
30
 * as new versions are released or if rollback is ever done.
31
 */
32

33
using VersionList = BackupHandler::VersionList;
34
using VersionTimeList = BackupHandler::VersionTimeList;
35

36
// Note: accepted versions should have new versions added at front
37
const VersionList BackupHandler::accepted_versions_ = {24, 23, 22, 21, 20, 11, 10};
38

39
// the pair is <version, age-in-seconds>
40
// we keep backup files in 3 months.
41
static constexpr int three_months = 3 * 31 * 24 * 60 * 60;
42
const VersionTimeList BackupHandler::delete_versions_{{23, three_months}, {22, three_months}, {21, three_months},
43
                                                      {20, three_months}, {11, three_months}, {10, three_months}};
44

45

46
// helper functions
47
static std::string backup_name(const std::string& prefix, int version)
48
{
218,139✔
49
    return util::format("%1v%2.backup.realm", prefix, version);
218,139✔
50
}
218,139✔
51

52
static bool backup_exists(const std::string& prefix, int version)
53
{
217,635✔
54
    std::string fname = backup_name(prefix, version);
217,635✔
55
    return util::File::exists(fname);
217,635✔
56
}
217,635✔
57

58
std::string BackupHandler::get_prefix_from_path(const std::string& path)
59
{
36,300✔
60
    auto size = path.size();
36,300✔
61

62
    // remove a suffix ".realm" but add back the "."
63
    if (size > 6 && path.substr(size - 6, 6) == ".realm") {
36,300✔
64
        return path.substr(0, size - 5); // include '.'
20,313✔
65
    }
20,313✔
66

67
    // if no ".realm" suffix, at least ensure a terminating "."
68
    if (path[size - 1] == '.') {
15,987✔
69
        return path;
×
70
    }
×
71
    return path + ".";
15,987✔
72
}
15,987✔
73

74
BackupHandler::BackupHandler(const std::string& path, const VersionList& accepted,
75
                             const VersionTimeList& to_be_deleted)
76
{
36,294✔
77
    m_path = path;
36,294✔
78
    m_prefix = get_prefix_from_path(path);
36,294✔
79
    m_accepted_versions = accepted;
36,294✔
80
    m_delete_versions = to_be_deleted;
36,294✔
81
}
36,294✔
82

83
std::string BackupHandler::get_prefix() const
84
{
×
85
    return m_prefix;
×
86
}
×
87

88
bool BackupHandler::must_restore_from_backup(int current_file_format_version) const
89
{
36,294✔
90
    if (current_file_format_version == 0)
36,294✔
91
        return false;
21,657✔
92
    if (is_accepted_file_format(current_file_format_version))
14,637✔
93
        return false;
14,625✔
94
    for (auto v : m_accepted_versions) {
51✔
95
        if (backup_exists(m_prefix, v))
51✔
96
            return true;
6✔
97
    }
51✔
98
    return false;
6✔
99
}
12✔
100

101
bool BackupHandler::is_accepted_file_format(int version) const noexcept
102
{
29,268✔
103
    for (auto v : m_accepted_versions) {
29,949✔
104
        if (v == version)
29,949✔
105
            return true;
29,250✔
106
    }
29,949✔
107
    return false;
18✔
108
}
29,268✔
109

110
void BackupHandler::restore_from_backup()
111
{
6✔
112
    for (auto v : m_accepted_versions) {
9✔
113
        if (backup_exists(m_prefix, v)) {
9✔
114
            prep_logging();
6✔
115
            auto backup_nm = backup_name(m_prefix, v);
6✔
116
            m_logger->info(util::LogCategory::storage, "%1 : Restoring from backup: %2", m_time_buf, backup_nm);
6✔
117
            util::File::move(backup_nm, m_path);
6✔
118
            return;
6✔
119
        }
6✔
120
    }
9✔
121
}
6✔
122

123
void BackupHandler::cleanup_backups()
124
{
36,288✔
125
    auto now = time(nullptr);
36,288✔
126
    for (auto v : m_delete_versions) {
217,575✔
127
        try {
217,575✔
128
            if (backup_exists(m_prefix, v.first)) {
217,575✔
129
                std::string fn = backup_name(m_prefix, v.first);
384✔
130
                // Assuming time_t is in seconds (should be on posix, but...)
131
                auto last_modified = util::File::last_write_time(fn);
384✔
132
                double diff = difftime(now, last_modified);
384✔
133
                if (diff > v.second) {
384✔
134
                    prep_logging();
3✔
135
                    m_logger->info(util::LogCategory::storage, "%1 : Removing old backup: %2   (age %3)", m_time_buf,
3✔
136
                                   fn, diff);
3✔
137
                    util::File::remove(fn);
3✔
138
                }
3✔
139
            }
384✔
140
        }
217,575✔
141
        catch (...) // ignore any problems, just leave the files
217,575✔
142
        {
217,575✔
143
        }
×
144
    }
217,575✔
145
}
36,288✔
146

147
void BackupHandler::ensure_logger()
148
{
153✔
149
    m_logger = std::make_unique<util::AppendToFileLogger>(m_path + ".backup-log");
153✔
150
}
153✔
151

152
void BackupHandler::prep_logging()
153
{
153✔
154
    ensure_logger();
153✔
155
    // preformat time string for later logging
156
    std::time_t t = std::time(nullptr);
153✔
157
    auto tm = util::gmtime(t);
153✔
158
    std::strftime(m_time_buf, sizeof(m_time_buf), "%c", &tm);
153✔
159
}
153✔
160

161

162
void BackupHandler::backup_realm_if_needed(int current_file_format_version, int target_file_format_version)
163
{
36,285✔
164
    if (current_file_format_version == 0)
36,285✔
165
        return;
21,657✔
166
    if (current_file_format_version >= target_file_format_version)
14,628✔
167
        return;
14,514✔
168
    std::string backup_nm = backup_name(m_prefix, current_file_format_version);
114✔
169
    if (util::File::exists(backup_nm)) {
114✔
170
        return;
42✔
171
    }
42✔
172
    try {
72✔
173
        // ignore it, if attempt to get free space fails for any reason
174
        if (util::File::get_free_space(m_path) < util::File::get_size_static(m_path) * 2) {
72✔
175
            prep_logging();
×
176
            m_logger->error(util::LogCategory::storage, "%1 : Insufficient free space for backup: %2", m_time_buf,
×
177
                            backup_nm);
×
178
            return;
×
179
        }
×
180
    }
72✔
181
    catch (...) {
72✔
182
        // ignore error
183
    }
×
184
    {
72✔
185
        prep_logging();
72✔
186
        m_logger->info(util::LogCategory::storage, "%1 : Creating backup: %2", m_time_buf, backup_nm);
72✔
187
    }
72✔
188
    std::string part_name = backup_nm + ".part";
72✔
189
    // The backup file should be a 1-1 copy, so that we can get the original
190
    // contents including unchanged layout of data, freelists, etc
191
    // In doing so we forego the option of compacting the backup.
192
    // Silence any errors during the backup process, but should one occur
193
    // remove any backup files, since they cannot be trusted.
194
    try {
72✔
195
        util::File::copy(m_path, part_name);
72✔
196
        util::File::move(part_name, backup_nm);
72✔
197
        prep_logging();
72✔
198
        m_logger->info(util::LogCategory::storage, "%1 : Completed backup: %2", m_time_buf, backup_nm);
72✔
199
    }
72✔
200
    catch (...) {
72✔
201
        try {
×
202
            util::File::try_remove(part_name);
×
203
            util::File::try_remove(backup_nm);
×
204
        }
×
205
        catch (...) {
×
206
        }
×
207
    }
×
208
}
72✔
209

210
} // namespace realm
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc