Skip to content

Commit

Permalink
Add RealmConfig::needs_file_format_upgrade (#7336)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedelbo authored Feb 13, 2024
1 parent 628de5f commit 7df0def
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Updated bundled OpenSSL version to 3.2.0 (PR [#7303](https://github.com/realm/realm-core/pull/7303))
* Added `SyncSession::get_file_ident()` so you can trigger a client reset via the BAAS admin API ([PR #7203](https://github.com/realm/realm-core/pull/7203)).
* Audit event scopes containing zero events to save no longer open the audit realm unneccesarily ([PR #7332](https://github.com/realm/realm-core/pull/7332)).
* Added a method to check if a file needs upgrade. ([#7140](https://github.com/realm/realm-core/issues/7140))

### Fixed
* Uploading the changesets recovered during an automatic client reset recovery may lead to 'Bad server version' errors and a new client reset. ([#7279](https://github.com/realm/realm-core/issues/7279), since v13.24.1)
Expand Down
1 change: 1 addition & 0 deletions bindgen/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ classes:
# Converts char* and length to a combined string_view argument to callback.
# TODO: Consider making preverify_ok a bool.
make_ssl_verify_callback: '(callback: (server_address: const std::string&, server_port: int, pem_data: std::string_view, preverify_ok: int, depth: int) off_thread -> bool) -> SSLVerifyCallback'
needs_file_format_upgrade: '(config: const RealmConfig&) -> bool'

Logger:
cppName: util::Logger
Expand Down
5 changes: 5 additions & 0 deletions bindgen/src/realm_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ struct Helpers {
return callback(server_address, server_port, std::string_view(pem_data, pem_size), preverify_ok, depth);
};
}

static bool needs_file_format_upgrade(const RealmConfig& config)
{
return config.needs_file_format_upgrade();
}
};

struct ObjectChangeSet {
Expand Down
5 changes: 5 additions & 0 deletions src/realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,11 @@ RLM_API void realm_config_set_should_compact_on_launch_function(realm_config_t*,
*/
RLM_API bool realm_config_get_disable_format_upgrade(const realm_config_t*);

/**
* True if you can open the file without a file_format_upgrade
*/
RLM_API bool realm_config_needs_file_format_upgrade(const realm_config_t*);

/**
* Disable file format upgrade on open (default: false).
*
Expand Down
25 changes: 25 additions & 0 deletions src/realm/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2146,6 +2146,31 @@ void DB::enable_wait_for_change()
m_wait_for_change_enabled = true;
}

bool DB::needs_file_format_upgrade(const std::string& file, const std::vector<char>& encryption_key)
{
SlabAlloc alloc;
SlabAlloc::Config cfg;
cfg.session_initiator = false;
cfg.read_only = true;
cfg.no_create = true;
if (!encryption_key.empty()) {
cfg.encryption_key = encryption_key.data();
}
try {
alloc.attach_file(file, cfg);
if (auto current_file_format_version = alloc.get_committed_file_format_version()) {
auto target_file_format_version = Group::g_current_file_format_version;
return current_file_format_version < target_file_format_version;
}
}
catch (const FileAccessError& err) {
if (err.code() != ErrorCodes::FileNotFound) {
throw;
}
}
return false;
}

void DB::upgrade_file_format(bool allow_file_format_upgrade, int target_file_format_version,
int current_hist_schema_version, int target_hist_schema_version)
{
Expand Down
2 changes: 2 additions & 0 deletions src/realm/db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ class DB : public std::enable_shared_from_this<DB> {

bool is_attached() const noexcept;

static bool needs_file_format_upgrade(const std::string& file, const std::vector<char>& encryption_key);

Allocator& get_alloc()
{
return m_alloc;
Expand Down
5 changes: 5 additions & 0 deletions src/realm/object-store/c_api/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ RLM_API bool realm_config_get_disable_format_upgrade(const realm_config_t* confi
return config->disable_format_upgrade;
}

RLM_API bool realm_config_needs_file_format_upgrade(const realm_config_t* config)
{
return config->needs_file_format_upgrade();
}

RLM_API void realm_config_set_disable_format_upgrade(realm_config_t* config, bool b)
{
config->disable_format_upgrade = b;
Expand Down
5 changes: 5 additions & 0 deletions src/realm/object-store/shared_realm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ class CountGuard {
};
} // namespace

bool RealmConfig::needs_file_format_upgrade() const
{
return DB::needs_file_format_upgrade(path, encryption_key);
}

Realm::Realm(Config config, util::Optional<VersionID> version, std::shared_ptr<_impl::RealmCoordinator> coordinator,
Private)
: m_config(std::move(config))
Expand Down
2 changes: 2 additions & 0 deletions src/realm/object-store/shared_realm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ struct RealmConfig {
return schema_mode == SchemaMode::ReadOnly;
}

bool needs_file_format_upgrade() const;

// If false, always return a new Realm instance, and don't return
// that Realm instance for other requests for a cached Realm. Useful
// for dynamic Realms and for tests that need multiple instances on
Expand Down
6 changes: 5 additions & 1 deletion test/object-store/migrations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2052,7 +2052,11 @@ TEST_CASE("migration: SoftResetFile", "[migration]") {
ObjectStore::table_for_object_type(realm->read_group(), "object")->create_object();
realm->commit_transaction();
}
auto realm = Realm::get_shared_realm(config);
SharedRealm realm;
if (!config.needs_file_format_upgrade()) {
realm = Realm::get_shared_realm(config);
}
REQUIRE(realm);
auto ino = get_fileid();

SECTION("file is reset when schema version increases") {
Expand Down
11 changes: 10 additions & 1 deletion test/test_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,16 +634,25 @@ TEST(Shared_EncryptedRemap)
TEST(Shared_Initial)
{
SHARED_GROUP_TEST_PATH(path);
std::vector<char> key;

CHECK_NOT(DB::needs_file_format_upgrade(path, key)); // File not created yet

auto key_str = crypt_key();
{
// Create a new shared db
DBRef sg = DB::create(path, false, DBOptions(crypt_key()));
DBRef sg = DB::create(path, false, DBOptions(key_str));

// Verify that new group is empty
{
ReadTransaction rt(sg);
CHECK(rt.get_group().is_empty());
}
}
if (key_str) {
key.insert(key.end(), key_str, key_str + strlen(key_str));
}
CHECK_NOT(DB::needs_file_format_upgrade(path, key));
}


Expand Down
1 change: 1 addition & 0 deletions test/test_upgrade_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,7 @@ TEST_IF(Upgrade_Database_22, REALM_MAX_BPNODE_SIZE == 4 || REALM_MAX_BPNODE_SIZE
// Make a copy of the database so that we keep the original file intact and unmodified
File::copy(path, temp_copy);
auto hist = make_in_realm_history();
CHECK(DB::needs_file_format_upgrade(temp_copy, {}));
auto sg = DB::create(*hist, temp_copy);
auto rt = sg->start_read();

Expand Down

0 comments on commit 7df0def

Please sign in to comment.