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

realm / realm-core / github_pull_request_281750

30 Oct 2023 03:37PM UTC coverage: 90.528% (-1.0%) from 91.571%
github_pull_request_281750

Pull #6073

Evergreen

jedelbo
Log free space and history sizes when opening file
Pull Request #6073: Merge next-major

95488 of 175952 branches covered (0.0%)

8973 of 12277 new or added lines in 149 files covered. (73.09%)

622 existing lines in 51 files now uncovered.

233503 of 257934 relevant lines covered (90.53%)

6533720.56 hits per line

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

85.71
/src/realm/sync/noinst/client_reset_operation.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2021 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/transaction.hpp>
20
#include <realm/sync/history.hpp>
21
#include <realm/sync/noinst/client_history_impl.hpp>
22
#include <realm/sync/noinst/client_reset.hpp>
23
#include <realm/sync/noinst/client_reset_operation.hpp>
24
#include <realm/util/scope_exit.hpp>
25

26
namespace realm::_impl {
27

28
namespace {
29

30
constexpr static std::string_view c_fresh_suffix(".fresh");
31

32
} // namespace
33

34
ClientResetOperation::ClientResetOperation(util::Logger& logger, DBRef db, DBRef db_fresh, ClientResyncMode mode,
35
                                           CallbackBeforeType notify_before, CallbackAfterType notify_after,
36
                                           bool recovery_is_allowed)
37
    : m_logger{logger}
38
    , m_db{db}
39
    , m_db_fresh(std::move(db_fresh))
40
    , m_mode(mode)
41
    , m_notify_before(std::move(notify_before))
42
    , m_notify_after(std::move(notify_after))
43
    , m_recovery_is_allowed(recovery_is_allowed)
44
{
336✔
45
    REALM_ASSERT(m_db);
336✔
46
    REALM_ASSERT_RELEASE(m_mode != ClientResyncMode::Manual);
336✔
47
    m_logger.debug(util::LogCategory::reset,
336✔
48
                   "Create ClientResetOperation, realm_path = %1, mode = %2, recovery_allowed = %3", m_db->get_path(),
336✔
49
                   m_mode, m_recovery_is_allowed);
336✔
50
}
336✔
51

52
std::string ClientResetOperation::get_fresh_path_for(const std::string& path)
53
{
3,464,208✔
54
    const size_t suffix_len = c_fresh_suffix.size();
3,464,208✔
55
    REALM_ASSERT(path.length());
3,464,208✔
56
    REALM_ASSERT_DEBUG_EX(
3,464,208✔
57
        path.size() < suffix_len || path.substr(path.size() - suffix_len, suffix_len) != c_fresh_suffix, path);
3,464,208✔
58
    return path + c_fresh_suffix.data();
3,464,208✔
59
}
3,464,208✔
60

61
bool ClientResetOperation::is_fresh_path(const std::string& path)
62
{
3,332✔
63
    const size_t suffix_len = c_fresh_suffix.size();
3,332✔
64
    REALM_ASSERT(path.length());
3,332✔
65
    if (path.size() < suffix_len) {
3,332✔
66
        return false;
×
67
    }
×
68
    return path.substr(path.size() - suffix_len, suffix_len) == c_fresh_suffix;
3,332✔
69
}
3,332✔
70

71
bool ClientResetOperation::finalize(sync::SaltedFileIdent salted_file_ident, sync::SubscriptionStore* sub_store,
72
                                    util::UniqueFunction<void(int64_t)> on_flx_version_complete)
73
{
336✔
74
    m_salted_file_ident = salted_file_ident;
336✔
75
    // only do the reset if there is data to reset
168✔
76
    // if there is nothing in this Realm, then there is nothing to reset and
168✔
77
    // sync should be able to continue as normal
168✔
78
    auto latest_version = m_db->get_version_id_of_latest_snapshot();
336✔
79

168✔
80
    bool local_realm_exists = latest_version.version != 0;
336✔
81
    m_logger.debug(util::LogCategory::reset,
336✔
82
                   "ClientResetOperation::finalize, realm_path = %1, local_realm_exists = %2, mode = %3",
336✔
83
                   m_db->get_path(), local_realm_exists, m_mode);
336✔
84
    if (!local_realm_exists) {
336✔
85
        return false;
×
86
    }
×
87

168✔
88
    REALM_ASSERT_EX(m_db_fresh, m_db->get_path(), m_mode);
336✔
89

168✔
90
    client_reset::LocalVersionIDs local_version_ids;
336✔
91
    auto always_try_clean_up = util::make_scope_exit([&]() noexcept {
336✔
92
        clean_up_state();
336✔
93
    });
336✔
94

168✔
95
    VersionID frozen_before_state_version = m_notify_before ? m_notify_before() : latest_version;
296✔
96

168✔
97
    // If m_notify_after is set, pin the previous state to keep it around.
168✔
98
    TransactionRef previous_state;
336✔
99
    if (m_notify_after) {
336✔
100
        previous_state = m_db->start_frozen(frozen_before_state_version);
244✔
101
    }
244✔
102
    bool did_recover_out = false;
336✔
103
    local_version_ids = client_reset::perform_client_reset_diff(
336✔
104
        m_db, m_db_fresh, m_salted_file_ident, m_logger, m_mode, m_recovery_is_allowed, &did_recover_out, sub_store,
336✔
105
        std::move(on_flx_version_complete)); // throws
336✔
106

168✔
107
    if (m_notify_after) {
336✔
108
        m_notify_after(previous_state->get_version_of_current_transaction(), did_recover_out);
188✔
109
    }
188✔
110

168✔
111
    m_client_reset_old_version = local_version_ids.old_version;
336✔
112
    m_client_reset_new_version = local_version_ids.new_version;
336✔
113

168✔
114
    return true;
336✔
115
}
336✔
116

117
void ClientResetOperation::clean_up_state() noexcept
118
{
336✔
119
    if (m_db_fresh) {
336✔
120
        std::string path_to_clean = m_db_fresh->get_path();
336✔
121
        try {
336✔
122
            // In order to obtain the lock and delete the realm, we first have to close
168✔
123
            // the Realm. This requires that we are the only remaining ref holder, and
168✔
124
            // this is expected. Releasing the last ref should release the hold on the
168✔
125
            // lock file and allow us to clean up.
168✔
126
            long use_count = m_db_fresh.use_count();
336✔
127
            REALM_ASSERT_DEBUG_EX(use_count == 1, use_count, path_to_clean);
336✔
128
            m_db_fresh.reset();
336✔
129
            // clean up the fresh Realm
168✔
130
            // we don't mind leaving the fresh lock file around because trying to delete it
168✔
131
            // here could cause a race if there are multiple resets ongoing
168✔
132
            bool did_lock = DB::call_with_lock(path_to_clean, [&](const std::string& path) {
336✔
133
                constexpr bool delete_lockfile = false;
336✔
134
                DB::delete_files(path, nullptr, delete_lockfile);
336✔
135
            });
336✔
136
            if (!did_lock) {
336✔
NEW
137
                m_logger.warn(util::LogCategory::reset,
×
NEW
138
                              "In ClientResetOperation::finalize, the fresh copy '%1' could not be cleaned up. "
×
139
                              "There were %2 refs remaining.",
×
140
                              path_to_clean, use_count);
×
141
            }
×
142
        }
336✔
143
        catch (const std::exception& err) {
168✔
NEW
144
            m_logger.warn(util::LogCategory::reset,
×
NEW
145
                          "In ClientResetOperation::finalize, the fresh copy '%1' could not be cleaned up due to "
×
146
                          "an exception: '%2'",
×
147
                          path_to_clean, err.what());
×
148
            // ignored, this is just a best effort
149
        }
×
150
    }
336✔
151
}
336✔
152

153
} // namespace realm::_impl
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

© 2025 Coveralls, Inc