diff --git a/src/realm/exec/CMakeLists.txt b/src/realm/exec/CMakeLists.txt index 53b4407fc9f..9f1ed148081 100644 --- a/src/realm/exec/CMakeLists.txt +++ b/src/realm/exec/CMakeLists.txt @@ -24,14 +24,14 @@ target_link_libraries(RealmTrawler Storage) add_executable(RealmBrowser EXCLUDE_FROM_ALL realm_browser.cpp ) set_target_properties(RealmBrowser PROPERTIES - OUTPUT_NAME "realm-browser-6" + OUTPUT_NAME "realm-browser-10" DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) target_link_libraries(RealmBrowser Storage) add_executable(Realm2JSON realm2json.cpp ) set_target_properties(Realm2JSON PROPERTIES - OUTPUT_NAME "realm2json-6" + OUTPUT_NAME "realm2json-10" DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) target_link_libraries(Realm2JSON Storage) diff --git a/src/realm/sync/noinst/client_history_impl.cpp b/src/realm/sync/noinst/client_history_impl.cpp index 88f0c71a05a..af9ddb73022 100644 --- a/src/realm/sync/noinst/client_history_impl.cpp +++ b/src/realm/sync/noinst/client_history_impl.cpp @@ -811,8 +811,10 @@ void ClientHistoryImpl::update_sync_progress(const SyncProgress& progress, version_type(root.get_as_ref_or_tagged(s_progress_download_client_version_iip).get_as_int())); REALM_ASSERT(progress.upload.client_version >= version_type(root.get_as_ref_or_tagged(s_progress_upload_client_version_iip).get_as_int())); - REALM_ASSERT(progress.upload.last_integrated_server_version >= - version_type(root.get_as_ref_or_tagged(s_progress_upload_server_version_iip).get_as_int())); + if (progress.upload.last_integrated_server_version > 0) { + REALM_ASSERT(progress.upload.last_integrated_server_version >= + version_type(root.get_as_ref_or_tagged(s_progress_upload_server_version_iip).get_as_int())); + } auto uploaded_bytes = std::uint_fast64_t(root.get_as_ref_or_tagged(s_progress_uploaded_bytes_iip).get_as_int()); auto previous_upload_client_version = @@ -829,8 +831,10 @@ void ClientHistoryImpl::update_sync_progress(const SyncProgress& progress, RefOrTagged::make_tagged(progress.latest_server_version.salt)); // Throws root.set(s_progress_upload_client_version_iip, RefOrTagged::make_tagged(progress.upload.client_version)); // Throws - root.set(s_progress_upload_server_version_iip, - RefOrTagged::make_tagged(progress.upload.last_integrated_server_version)); // Throws + if (progress.upload.last_integrated_server_version > 0) { + root.set(s_progress_upload_server_version_iip, + RefOrTagged::make_tagged(progress.upload.last_integrated_server_version)); // Throws + } if (downloadable_bytes) { root.set(s_progress_downloadable_bytes_iip, RefOrTagged::make_tagged(*downloadable_bytes)); // Throws diff --git a/src/realm/sync/noinst/server_history.cpp b/src/realm/sync/noinst/server_history.cpp index 65b5e738ab1..fec558bf8fa 100644 --- a/src/realm/sync/noinst/server_history.cpp +++ b/src/realm/sync/noinst/server_history.cpp @@ -850,8 +850,16 @@ auto ServerHistory::do_bootstrap_client_session(SaltedFileIdent client_file_iden if (download_progress.server_version > current_server_version) return BootstrapError::bad_download_server_version; auto last_integrated_client_version = version_type(m_acc->cf_client_versions.get(client_file_index)); - if (download_progress.last_integrated_client_version > last_integrated_client_version) - return BootstrapError::bad_download_client_version; + if (download_progress.last_integrated_client_version > last_integrated_client_version) { + if (last_integrated_client_version == 0) { + // We assume we are booting on a pre-downloaded client file + last_integrated_client_version = download_progress.last_integrated_client_version; + recip_hist_base_version = download_progress.server_version; + } + else { + return BootstrapError::bad_download_client_version; + } + } // Validate `server_version` { @@ -1014,7 +1022,9 @@ bool ServerHistory::fetch_download_info(file_ident_type client_file_ident, Downl download_progress = download_progress_2; cumulative_byte_size_current = std::uint_fast64_t(cumulative_byte_size_current_2); cumulative_byte_size_total = std::uint_fast64_t(cumulative_byte_size_total_2); - upload_progress = UploadCursor{upload_client_version, upload_server_version}; + if (upload_client_version > upload_progress.client_version) { + upload_progress = UploadCursor{upload_client_version, upload_server_version}; + } return true; } diff --git a/src/realm/sync/server.cpp b/src/realm/sync/server.cpp index f9527b0df52..2abf248cba5 100644 --- a/src/realm/sync/server.cpp +++ b/src/realm/sync/server.cpp @@ -3637,7 +3637,7 @@ class Session final : private FileIdentReceiver { bool body_is_compressed = false; version_type end_version = last_server_version.version; DownloadCursor download_progress; - UploadCursor upload_progress = {0, 0}; + UploadCursor upload_progress = m_upload_threshold; std::uint_fast64_t downloadable_bytes = 0; std::size_t num_changesets; std::size_t accum_original_size; diff --git a/test/object-store/realm.cpp b/test/object-store/realm.cpp index 6d63ce45a8d..26421037e2a 100644 --- a/test/object-store/realm.cpp +++ b/test/object-store/realm.cpp @@ -566,7 +566,13 @@ TEST_CASE("Get Realm using Async Open", "[asyncOpen]") { std::lock_guard lock(mutex); return bool(realm_ref); }); + // Write some data SharedRealm realm = Realm::get_shared_realm(std::move(realm_ref)); + realm->begin_transaction(); + realm->read_group().get_table("class_object")->create_object_with_primary_key(2); + realm->commit_transaction(); + wait_for_upload(*realm); + wait_for_download(*realm); client_file_id = realm->read_group().get_sync_file_id(); realm->write_copy(config3.path, BinaryData()); } @@ -582,7 +588,7 @@ TEST_CASE("Get Realm using Async Open", "[asyncOpen]") { wait_for_download(*realm); // Make sure we have got a new client file id REQUIRE(realm->read_group().get_sync_file_id() != client_file_id); - REQUIRE(realm->read_group().get_table("class_object")->size() == 2); + REQUIRE(realm->read_group().get_table("class_object")->size() == 3); // Check that we can continue committing to this realm realm->begin_transaction(); @@ -593,7 +599,7 @@ TEST_CASE("Get Realm using Async Open", "[asyncOpen]") { // Check that this change is now in the original realm wait_for_download(*origin); origin->refresh(); - REQUIRE(origin->read_group().get_table("class_object")->size() == 3); + REQUIRE(origin->read_group().get_table("class_object")->size() == 4); } SECTION("downloads Realms which exist on the server") { diff --git a/test/object-store/sync/app.cpp b/test/object-store/sync/app.cpp index 704c19f4d92..66d6a6d2f62 100644 --- a/test/object-store/sync/app.cpp +++ b/test/object-store/sync/app.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "collection_fixtures.hpp" #include "util/baas_admin_api.hpp" @@ -1777,6 +1778,101 @@ TEST_CASE("app: set new embedded object", "[sync][app]") { } } +TEST_CASE("app: make distributable client file", "[sync][app]") { + auto config = get_integration_config(); + auto base_path = util::make_temp_dir(); + util::try_remove_dir_recursive(base_path); + util::try_make_dir(base_path); + util::try_make_dir(base_path + "/orig"); + util::try_make_dir(base_path + "/copy"); + + // Create realm file without client file id + { + TestSyncManager sync_manager(TestSyncManager::Config(config), {}); + auto app = sync_manager.app(); + app->log_in_with_credentials(AppCredentials::anonymous(), + [&](std::shared_ptr user, Optional error) { + REQUIRE(!error); + REQUIRE(user); + }); + + ThreadSafeReference realm_ref; + + realm::Realm::Config realm_config; + realm_config.sync_config = std::make_shared(app->current_user(), bson::Bson("foo")); + realm_config.schema_version = 1; + realm_config.path = base_path + "/orig/default.realm"; + + std::mutex mutex; + auto task = realm::Realm::get_synchronized_realm(realm_config); + task->start([&](ThreadSafeReference ref, std::exception_ptr error) { + std::lock_guard lock(mutex); + REQUIRE(!error); + realm_ref = std::move(ref); + }); + util::EventLoop::main().run_until([&] { + std::lock_guard lock(mutex); + return bool(realm_ref); + }); + SharedRealm realm = Realm::get_shared_realm(std::move(realm_ref)); + + // Write some data + realm->begin_transaction(); + CppContext c; + Object::create(c, realm, "Person", + util::Any(realm::AnyDict{{"_id", util::Any(ObjectId::gen())}, + {"age", INT64_C(64)}, + {"firstName", std::string("Paul")}, + {"lastName", std::string("McCartney")}})); + realm->commit_transaction(); + wait_for_upload(*realm); + wait_for_download(*realm); + + realm->write_copy(base_path + "/copy/default.realm", BinaryData()); + + // Write some additional data + realm->begin_transaction(); + Object::create(c, realm, "Dog", + util::Any(realm::AnyDict{{"_id", util::Any(ObjectId::gen())}, + {"breed", std::string("stabyhoun")}, + {"name", std::string("albert")}, + {"realm_id", std::string("foo")}})); + realm->commit_transaction(); + wait_for_upload(*realm); + } + // Starting a new session based on the copy + { + TestSyncManager sync_manager(TestSyncManager::Config(config), {}); + auto app = sync_manager.app(); + app->log_in_with_credentials(AppCredentials::anonymous(), + [&](std::shared_ptr user, Optional error) { + REQUIRE(!error); + REQUIRE(user); + }); + + ThreadSafeReference realm_ref; + + realm::Realm::Config realm_config; + realm_config.sync_config = std::make_shared(app->current_user(), bson::Bson("foo")); + realm_config.schema_version = 1; + realm_config.path = base_path + "/copy/default.realm"; + + SharedRealm realm = realm::Realm::get_shared_realm(realm_config); + wait_for_download(*realm); + + // Check that we can continue committing to this realm + realm->begin_transaction(); + CppContext c; + Object::create(c, realm, "Dog", + util::Any(realm::AnyDict{{"_id", util::Any(ObjectId::gen())}, + {"breed", std::string("bulldog")}, + {"name", std::string("fido")}, + {"realm_id", std::string("foo")}})); + realm->commit_transaction(); + wait_for_upload(*realm); + } +} + TEST_CASE("app: sync integration", "[sync][app]") { const auto schema = Schema{{"Dog", {{"_id", PropertyType::ObjectId | PropertyType::Nullable, true}, diff --git a/tools/run_baas_docker_image.sh b/tools/run_baas_docker_image.sh new file mode 100755 index 00000000000..3290e9d04b8 --- /dev/null +++ b/tools/run_baas_docker_image.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +PROJECT_DIR=$(git rev-parse --show-toplevel) +MDBREALM_TEST_SERVER_TAG=$(grep MDBREALM_TEST_SERVER_TAG ${PROJECT_DIR}/dependencies.list |cut -f 2 -d=) +docker run --rm -p 9090:9090 -v ~/.aws/credentials:/root/.aws/credentials -it docker.pkg.github.com/realm/ci/mongodb-realm-test-server:${MDBREALM_TEST_SERVER_TAG}