From f0b12975e1c7f914d9a6ce34d678ed3b055f5308 Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Fri, 2 Mar 2018 23:03:45 +0000 Subject: [PATCH 1/5] - Calling downloadRemoteChanges when the Realm is opened with full schema (including Permission schema) - Removing old workarounds for PK migrations --- dependencies.list | 2 +- .../assets/080_annotationtypes.realm | Bin 4096 -> 0 bytes .../assets/0841_annotationtypes.realm | Bin 4096 -> 0 bytes .../assets/0841_pk_migration.realm | Bin 8192 -> 0 bytes .../io/realm/internal/PrimaryKeyTests.java | 94 --------------- .../src/main/cpp/io_realm_internal_Table.cpp | 114 ------------------ realm/realm-library/src/main/cpp/object-store | 2 +- .../src/main/java/io/realm/RealmCache.java | 55 +++------ .../main/java/io/realm/internal/Table.java | 18 --- 9 files changed, 18 insertions(+), 267 deletions(-) delete mode 100644 realm/realm-library/src/androidTest/assets/080_annotationtypes.realm delete mode 100644 realm/realm-library/src/androidTest/assets/0841_annotationtypes.realm delete mode 100644 realm/realm-library/src/androidTest/assets/0841_pk_migration.realm diff --git a/dependencies.list b/dependencies.list index 993ad77a5c..2bdcd670f1 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,7 +1,7 @@ # Realm Sync Core release used by Realm Java # https://github.com/realm/realm-sync/releases REALM_SYNC_VERSION=3.0.0-beta.10 -REALM_SYNC_SHA256=7c36a38c0e5c0a46b22d5eee2b494bd9cc0219a526087a040ada86332f13401d +REALM_SYNC_SHA256=d5f2b1639efb5d64369d628c38e6d0698a1fbe6c2112b0f3321a85e170d6824e c # Object Server Release used by Integration tests. Installed using NPM. # Use `npm view realm-object-server versions` to get a list of available versions. diff --git a/realm/realm-library/src/androidTest/assets/080_annotationtypes.realm b/realm/realm-library/src/androidTest/assets/080_annotationtypes.realm deleted file mode 100644 index 1252c79172b4a9cab10260bea71ccbf1ba331d96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmeHGJxtqB5Wc$?2&w>ug=VSBm<5TEu^^DlQXw@%HtN<-#DY3jVjBDbSD;uC-q4Mi@qJhQ_Qhq0-)@ADiEu3#*Y|J(8J zoSoxn0=F6^aSWq`;`3Hm&rgnu_}8iRK~2{4;UKre;zCRfU!PMQNZ&`8LW`#pot?NY zS3M5a0M_5fr}@;uZO!&|6{pPE!#-AZMQ>w1i{s{|Q?=o~Jhw@cnL#cqX_naYAH^`u zjzw=UzXx+B?ZYpltCR??BY3WHf{)tCsa5PtdULSorDdE;RL@=cIlu9OKrPy+_@OCw ze2cRFJviK^lo#k=f$NNC1C)B-cYVc2vkej9VvqWCPMpUll8*u}zg7v6@PG=^CKYn7 z9?9Hjlk7kqsmt@z9VtjoF89W}@<;c!_TBSUm#Y1Ylb+~#9#>;bH}pU){#(kuPI069 zbCg%Xy=4UVq2Q($9D9GMPoVGXMfzQOCpYa$KI8vpaQV>uG`VS3qXZck2n+-U0t118 Sz(8OiFc26B3v-@0 diff --git a/realm/realm-library/src/androidTest/assets/0841_annotationtypes.realm b/realm/realm-library/src/androidTest/assets/0841_annotationtypes.realm deleted file mode 100644 index c605500aab3df986097bcd2fcbefee8ee5f7407e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmeHFJx>Bb5S^JrAu0wMq%onSF|o8nqlwm1*x@M`y@1E%ZeyU^lG2irl9JNW(w|^y zY3WaJW^aLmXyOmpX=dlmo3D2VklBnf-#$7&^E^NR4f_DzQ=t5=uY60}bO&*76IzQ8 z@B4n5c21*cpnMe$qV^~b(iLS#=CGN0d+eWsBxM>yEBu1@&@hIHFxPRM=WyoH6kZKW zczhD^fMs0fIPP_nf7cHzSmZcP262$6kw698pG!5!+zktz*G`-N2nCHwX;1qBQI0c*nP64NY QQ@|6p`SOj9(rV5+KNL@0a zjEosGX3WUQ$jF$Hk*&S+osDfmK#@9Bx*IsZfA9YDfB()R0BlrDHt&7h{9Gu21PZ__ z0Q1BStOF~sI4wWDbC2_(41WK!WBGn_&pPrm@ff^i>zkf+7|dh5Ve7k|bL5=Hn^H4h z-?2~jZ7&s%ANl(CZr~g)$iLV2Z0leS;Wg8*d)-5)W7oTW5NBrdE4KcnZ3Wv-evwet z*?OdZzU`dm-CE=MyY5-X@}A7UWBa~!WM{Q0;_vsvpIbcu_xEvPo{F#UoOJ@nC0)uB zR{%mvmFP@>^vm{qr%PM$5dR8LD9aVODi`u`sh)}xo?Md~GW;PlvR@|HppVfAVU=L_ zxEWacow!s?uzs*F^xuB9!0*e1aP6LJK^?`VAL!C#hf^ z;DY%bok#Y_j~)a395KKT4d1~}2t!G~Q%u%g7O1EC$s%zF8H)N9Q~9xp>XEPH8L5rE zFY%-397HJov-+=b5Y_oDR>fyo!Idn8NAJV?BKHf!LfjYH_laCr;=Z%$LMW21kbI;w zbcFOl;vmAbzpm0#`bu)HqPR-wgl`l6SmAyVOm#-eB;iv$RIZlNohf$;pr>^!D63mW z8z|;eT@%&NbM=xUNV)7Bw@@4Pa(X0>G)Tp1-VhC+%{$M>37VqoT>i9=_qlrR5U4Sq z>fRz#eXgE)x*KX$-BO?S(N(iPw$)z3r@9Tbzm)Ds9jns?y0e__t$LU6sqVE3IA1Th zk5c}A(Eg?SSjH7x!`XUCKBWPa7=IpXBt%+BD%){Y&lokv{eN;rkZO z{r=o(_nM|ZUH68bt-GRE^_Wj}OZt|culpr^ZtJcdF3=t2bT9RB!l$|eeY%wHtv=K5 z7wDFaY`rC;V#Iu^s~J_}xq8$0rD3!T*U0)y@<{zuoaXHrgCsA(W?OD4H%c9iP+1+S zCU)@*x3pWWp1Hu8}fN(%KARG`52nU1%!U5rca6mZlA2{$A!YzQ$ diff --git a/realm/realm-library/src/androidTest/java/io/realm/internal/PrimaryKeyTests.java b/realm/realm-library/src/androidTest/java/io/realm/internal/PrimaryKeyTests.java index 04c431318f..75ca14bbb0 100644 --- a/realm/realm-library/src/androidTest/java/io/realm/internal/PrimaryKeyTests.java +++ b/realm/realm-library/src/androidTest/java/io/realm/internal/PrimaryKeyTests.java @@ -25,10 +25,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - import io.realm.DynamicRealm; import io.realm.DynamicRealmObject; import io.realm.FieldAttribute; @@ -38,9 +34,7 @@ import io.realm.RealmSchema; import io.realm.rule.TestRealmConfigurationFactory; -import static junit.framework.Assert.assertFalse; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @RunWith(AndroidJUnit4.class) @@ -170,92 +164,4 @@ public void addEmptyRowWithPrimaryKeyLong() { assertEquals(42L, row.getLong(0)); sharedRealm.cancelTransaction(); } - - @Test - public void migratePrimaryKeyTableIfNeeded_first() throws IOException { - configFactory.copyRealmFromAssets(context, "080_annotationtypes.realm", "default.realm"); - sharedRealm = OsSharedRealm.getInstance(config); - Table.migratePrimaryKeyTableIfNeeded(sharedRealm); - Table t = sharedRealm.getTable("class_AnnotationTypes"); - assertEquals("id", OsObjectStore.getPrimaryKeyForObject(sharedRealm, "AnnotationTypes")); - assertEquals(RealmFieldType.STRING, sharedRealm.getTable("pk").getColumnType(0)); - } - - @Test - public void migratePrimaryKeyTableIfNeeded_second() throws IOException { - configFactory.copyRealmFromAssets(context, "0841_annotationtypes.realm", "default.realm"); - sharedRealm = OsSharedRealm.getInstance(config); - Table.migratePrimaryKeyTableIfNeeded(sharedRealm); - Table t = sharedRealm.getTable("class_AnnotationTypes"); - assertEquals("id", OsObjectStore.getPrimaryKeyForObject(sharedRealm, "AnnotationTypes")); - assertEquals("AnnotationTypes", sharedRealm.getTable("pk").getString(0, 0)); - } - - // See https://github.com/realm/realm-java/issues/1775 - // Before 0.84.2, pk table added prefix "class_" to every class's name. - // After 0.84.2, the pk table should be migrated automatically to remove the "class_". - // In 0.84.2, the class names in pk table has been renamed to some incorrect names like "Thclass", "Mclass", - // "NClass", "Meclass" and etc.. - // The 0841_pk_migration.realm is made to produce the issue. - @Test - public void migratePrimaryKeyTableIfNeeded_primaryKeyTableMigratedWithRightName() throws IOException { - List tableNames = Arrays.asList( - "ChatList", "Drafts", "Member", "Message", "Notifs", "NotifyLink", "PopularPost", - "Post", "Tags", "Threads", "User"); - - configFactory.copyRealmFromAssets(context, "0841_pk_migration.realm", "default.realm"); - sharedRealm = OsSharedRealm.getInstance(config); - Table.migratePrimaryKeyTableIfNeeded(sharedRealm); - - Table table = sharedRealm.getTable("pk"); - for (int i = 0; i < table.size(); i++) { - UncheckedRow row = table.getUncheckedRow(i); - // io_realm_internal_Table_PRIMARY_KEY_CLASS_COLUMN_INDEX 0LL - assertTrue(tableNames.contains(row.getString(0))); - } - } - - // PK table's column 'pk_table' needs search index in order to use set_string_unique. - // See https://github.com/realm/realm-java/pull/3488 - @Test - public void migratePrimaryKeyTableIfNeeded_primaryKeyTableNeedSearchIndex() { - sharedRealm = OsSharedRealm.getInstance(config); - sharedRealm.beginTransaction(); - OsObjectStore.setSchemaVersion(sharedRealm,0); // Create meta table - Table table = sharedRealm.createTable(Table.getTableNameForClass("TestTable")); - long column = table.addColumn(RealmFieldType.INTEGER, "PKColumn"); - table.addSearchIndex(column); - OsObjectStore.setPrimaryKeyForObject(sharedRealm, "TestTable", "PKColumn"); - sharedRealm.commitTransaction(); - - assertEquals("PKColumn", OsObjectStore.getPrimaryKeyForObject(sharedRealm, "TestTable")); - // Now we have a pk table with search index. - - sharedRealm.beginTransaction(); - Table pkTable = sharedRealm.getTable("pk"); - long classColumn = pkTable.getColumnIndex("pk_table"); - pkTable.removeSearchIndex(classColumn); - - // Tries to add a pk for another table. - Table table2 = sharedRealm.createTable(Table.getTableNameForClass("TestTable2")); - long column2 = table2.addColumn(RealmFieldType.INTEGER, "PKColumn"); - table2.addSearchIndex(column2); - try { - OsObjectStore.setPrimaryKeyForObject(sharedRealm, "TestTable2", "PKColumn"); - } catch (IllegalStateException ignored) { - // Column has no search index. - } - sharedRealm.commitTransaction(); - - assertFalse(pkTable.hasSearchIndex(classColumn)); - - Table.migratePrimaryKeyTableIfNeeded(sharedRealm); - assertTrue(pkTable.hasSearchIndex(classColumn)); - - sharedRealm.beginTransaction(); - // Now it works. - table2.addSearchIndex(column2); - OsObjectStore.setPrimaryKeyForObject(sharedRealm, "TestTable2", "PKColumn"); - sharedRealm.commitTransaction(); - } } diff --git a/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp b/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp index d85ad5e1d9..bde5d75f13 100644 --- a/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp +++ b/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp @@ -1197,120 +1197,6 @@ JNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsValid(JNIEnv*, j return to_jbool(TBL(nativeTablePtr)->is_attached()); // noexcept } -static bool pk_table_needs_migration(ConstTableRef pk_table) -{ - // Fix wrong types (string, int) -> (string, string) - if (pk_table->get_column_type(FIELD_COLUMN_INDEX) == type_Int) { - return true; - } - - // If needed remove "class_" prefix from class names - size_t number_of_rows = pk_table->size(); - for (size_t row_ndx = 0; row_ndx < number_of_rows; row_ndx++) { - StringData table_name = pk_table->get_string(CLASS_COLUMN_INDEX, row_ndx); - if (table_name.begins_with(TABLE_PREFIX)) { - return true; - } - } - // From realm-java 2.0.0, pk table's class column requires a search index. - if (!pk_table->has_search_index(CLASS_COLUMN_INDEX)) { - return true; - } - return false; -} - -// 1) Fixes interop issue with Cocoa Realm where the Primary Key table had different types. -// This affects: -// - All Realms created by Cocoa and used by Realm-android up to 0.80.1 -// - All Realms created by Realm-Android 0.80.1 and below -// See https://github.com/realm/realm-java/issues/1059 -// -// 2) Fix interop issue with Cocoa Realm where primary key tables on Cocoa doesn't have the "class_" prefix. -// This affects: -// - All Realms created by Cocoa and used by Realm-android up to 0.84.1 -// - All Realms created by Realm-Android 0.84.1 and below -// See https://github.com/realm/realm-java/issues/1703 -// -// 3> PK table's column 'pk_table' needs search index in order to use set_string_unique. -// This affects: -// - All Realms created by Cocoa and used by Realm-java before 2.0.0 -// See https://github.com/realm/realm-java/pull/3488 - -// This methods converts the old (wrong) table format (string, integer) to the right (string,string) format and strips -// any class names in the col[0] of their "class_" prefix -static bool migrate_pk_table(const Group& group, TableRef pk_table) -{ - bool changed = false; - - // Fix wrong types (string, int) -> (string, string) - if (pk_table->get_column_type(FIELD_COLUMN_INDEX) == type_Int) { - StringData tmp_col_name = StringData("tmp_field_name"); - size_t tmp_col_ndx = pk_table->add_column(DataType(type_String), tmp_col_name); - - // Create tmp string column with field name instead of column index - size_t number_of_rows = pk_table->size(); - for (size_t row_ndx = 0; row_ndx < number_of_rows; row_ndx++) { - StringData table_name = pk_table->get_string(CLASS_COLUMN_INDEX, row_ndx); - size_t col_ndx = static_cast(pk_table->get_int(FIELD_COLUMN_INDEX, row_ndx)); - StringData col_name = group.get_table(table_name)->get_column_name(col_ndx); - // Make a copy of the string - pk_table->set_string(tmp_col_ndx, row_ndx, col_name); - } - - // Delete old int column, and rename tmp column to same name - // The column index for the renamed column will then be the same as the deleted old column - pk_table->remove_column(FIELD_COLUMN_INDEX); - pk_table->rename_column(pk_table->get_column_index(tmp_col_name), StringData("pk_property")); - changed = true; - } - - // If needed remove "class_" prefix from class names - size_t number_of_rows = pk_table->size(); - for (size_t row_ndx = 0; row_ndx < number_of_rows; row_ndx++) { - StringData table_name = pk_table->get_string(CLASS_COLUMN_INDEX, row_ndx); - if (table_name.begins_with(TABLE_PREFIX)) { - // New string copy is needed, since the original memory will be changed. - std::string str(table_name.substr(TABLE_PREFIX.length())); - StringData sd(str); - pk_table->set_string(CLASS_COLUMN_INDEX, row_ndx, sd); - changed = true; - } - } - - // From realm-java 2.0.0, pk table's class column requires a search index. - if (!pk_table->has_search_index(CLASS_COLUMN_INDEX)) { - pk_table->add_search_index(CLASS_COLUMN_INDEX); - changed = true; - } - return changed; -} - -JNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeMigratePrimaryKeyTableIfNeeded(JNIEnv* env, jclass, - jlong shared_realm_ptr) -{ - TR_ENTER_PTR(shared_realm_ptr) - auto& shared_realm = *reinterpret_cast(shared_realm_ptr); - try { - if (!shared_realm->read_group().has_table(PK_TABLE_NAME)) { - return; - } - - auto pk_table = shared_realm->read_group().get_table(PK_TABLE_NAME); - if (!pk_table_needs_migration(pk_table)) { - return; - } - - shared_realm->begin_transaction(); - if (migrate_pk_table(shared_realm->read_group(), pk_table)) { - shared_realm->commit_transaction(); - } - else { - shared_realm->cancel_transaction(); - } - } - CATCH_STD() -} - JNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeHasSameSchema(JNIEnv*, jobject, jlong thisTablePtr, jlong otherTablePtr) { diff --git a/realm/realm-library/src/main/cpp/object-store b/realm/realm-library/src/main/cpp/object-store index bb559df923..b250563ea1 160000 --- a/realm/realm-library/src/main/cpp/object-store +++ b/realm/realm-library/src/main/cpp/object-store @@ -1 +1 @@ -Subproject commit bb559df9237ece49f9c889993f7c1aff619b48f9 +Subproject commit b250563ea1eb9f32ec7dbd76f2c6f8f1a26914cc diff --git a/realm/realm-library/src/main/java/io/realm/RealmCache.java b/realm/realm-library/src/main/java/io/realm/RealmCache.java index 3dac06e938..db46ab40ee 100644 --- a/realm/realm-library/src/main/java/io/realm/RealmCache.java +++ b/realm/realm-library/src/main/java/io/realm/RealmCache.java @@ -36,9 +36,7 @@ import io.realm.internal.Capabilities; import io.realm.internal.ObjectServerFacade; import io.realm.internal.OsObjectStore; -import io.realm.internal.OsSharedRealm; import io.realm.internal.RealmNotifier; -import io.realm.internal.Table; import io.realm.internal.Util; import io.realm.internal.android.AndroidCapabilities; import io.realm.internal.android.AndroidRealmNotifier; @@ -289,43 +287,6 @@ private synchronized E doCreateRealmOrGetFromCache(RealmCo if (getTotalGlobalRefCount() == 0) { copyAssetFileIfNeeded(configuration); - boolean fileExists = configuration.realmExists(); - - OsSharedRealm sharedRealm = null; - try { - if (configuration.isSyncConfiguration()) { - // If waitForInitialRemoteData() was enabled, we need to make sure that all data is downloaded - // before proceeding. We need to open the Realm instance first to start any potential underlying - // SyncSession so this will work. TODO: This needs to be decoupled. - if (!fileExists) { - sharedRealm = OsSharedRealm.getInstance(configuration); - try { - ObjectServerFacade.getSyncFacadeIfPossible().downloadRemoteChanges(configuration); - } catch (Throwable t) { - // If an error happened while downloading initial data, we need to reset the file so we can - // download it again on the next attempt. - sharedRealm.close(); - sharedRealm = null; - // FIXME: We don't have a way to ensure that the Realm instance on client thread has been - // closed for now. - // https://github.com/realm/realm-java/issues/5416 - BaseRealm.deleteRealm(configuration); - throw t; - } - } - } else { - if (fileExists) { - // Primary key problem only exists before we release sync. - sharedRealm = OsSharedRealm.getInstance(configuration); - Table.migratePrimaryKeyTableIfNeeded(sharedRealm); - } - } - } finally { - if (sharedRealm != null) { - sharedRealm.close(); - } - } - // We are holding the lock, and we can set the invalidated configuration since there is no global ref to it. this.configuration = configuration; } else { @@ -336,6 +297,7 @@ private synchronized E doCreateRealmOrGetFromCache(RealmCo if (refAndCount.localRealm.get() == null) { // Creates a new local Realm instance BaseRealm realm; + boolean fileExists = configuration.realmExists(); if (realmClass == Realm.class) { // RealmMigrationNeededException might be thrown here. @@ -346,6 +308,21 @@ private synchronized E doCreateRealmOrGetFromCache(RealmCo throw new IllegalArgumentException(WRONG_REALM_CLASS_MESSAGE); } + if (configuration.isSyncConfiguration() && !fileExists) { + try { + ObjectServerFacade.getSyncFacadeIfPossible().downloadRemoteChanges(configuration); + } catch (Throwable t) { + // If an error happened while downloading initial data, we need to reset the file so we can + // download it again on the next attempt. + realm.close(); + // FIXME: We don't have a way to ensure that the Realm instance on client thread has been + // closed for now. + // https://github.com/realm/realm-java/issues/5416 + BaseRealm.deleteRealm(configuration); + throw t; + } + } + // The Realm instance has been created without exceptions. Cache and reference count can be updated now. refAndCount.localRealm.set(realm); refAndCount.localCount.set(0); diff --git a/realm/realm-library/src/main/java/io/realm/internal/Table.java b/realm/realm-library/src/main/java/io/realm/internal/Table.java index 533603d665..4ebdda2e35 100644 --- a/realm/realm-library/src/main/java/io/realm/internal/Table.java +++ b/realm/realm-library/src/main/java/io/realm/internal/Table.java @@ -513,22 +513,6 @@ public void removeSearchIndex(long columnIndex) { nativeRemoveSearchIndex(nativePtr, columnIndex); } - /* - * 1) Migration required to fix https://github.com/realm/realm-java/issues/1059 - * This will convert INTEGER column to the corresponding STRING column if needed. - * Any database created on Realm-Java 0.80.1 and below will have this error. - * - * 2) Migration required to fix: https://github.com/realm/realm-java/issues/1703 - * This will remove the prefix "class_" from all table names in the pk_column - * Any database created on Realm-Java 0.84.1 and below will have this error. - * - * The native method will begin a transaction and make the migration if needed. - * This function should not be called in a transaction. - */ - public static void migratePrimaryKeyTableIfNeeded(OsSharedRealm sharedRealm) { - nativeMigratePrimaryKeyTableIfNeeded(sharedRealm.getNativePtr()); - } - public boolean hasSearchIndex(long columnIndex) { return nativeHasSearchIndex(nativePtr, columnIndex); } @@ -780,8 +764,6 @@ public static String getTableNameForClass(String name) { public static native void nativeSetLink(long nativeTablePtr, long columnIndex, long rowIndex, long value, boolean isDefault); - private static native void nativeMigratePrimaryKeyTableIfNeeded(long sharedRealmPtr); - private native void nativeAddSearchIndex(long nativePtr, long columnIndex); private native void nativeRemoveSearchIndex(long nativePtr, long columnIndex); From a66daaf17e0e41951a3906f963ff9f98667eb7de Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Fri, 2 Mar 2018 23:09:08 +0000 Subject: [PATCH 2/5] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e78eeebdcf..e032911048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * `realm.subscribeForObjects()` have been removed. Use `RealmQuery.findAllAsync(String subscriptionName)` and `RealmQuery.findAllAsync()` instead. * Removed previously deprecated `RealmQuery.findAllSorted()`, `RealmQuery.findAllSortedAsync()` `RealmQuery.distinct() and `RealmQuery.distinctAsync()`. * Renamed `RealmQuery.distinctValues()` to `RealmQuery.distinct()` +* Removing workarounds for old Realms versions [0.80.1](https://github.com/realm/realm-java/issues/1059), [0.84.1](https://github.com/realm/realm-java/issues/1703) and [2.0.0](https://github.com/realm/realm-java/pull/3488). ### Enhancements From e5170cdcfb73e3b5a18343270e072dad1882dd0e Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Sat, 3 Mar 2018 18:59:57 +0000 Subject: [PATCH 3/5] Fixing some affected tests --- .../src/androidTest/java/io/realm/RealmTests.java | 7 +++---- .../src/main/java/io/realm/RealmCache.java | 1 + .../java/io/realm/SSLConfigurationTests.java | 10 ++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/realm/realm-library/src/androidTest/java/io/realm/RealmTests.java b/realm/realm-library/src/androidTest/java/io/realm/RealmTests.java index 9124ace416..d4577e1d49 100644 --- a/realm/realm-library/src/androidTest/java/io/realm/RealmTests.java +++ b/realm/realm-library/src/androidTest/java/io/realm/RealmTests.java @@ -1144,8 +1144,7 @@ public boolean shouldCompact(long totalBytes, long usedBytes) { assertEquals(1, compactOnLaunchCount.get()); realm = Realm.getInstance(realmConfig); - // Called 2 more times. The PK table migration logic (the old PK bug) needs to open/close the Realm once. - assertEquals(3, compactOnLaunchCount.get()); + assertEquals(2, compactOnLaunchCount.get()); Thread thread = new Thread(new Runnable() { @Override @@ -1153,7 +1152,7 @@ public void run() { Realm bgRealm = Realm.getInstance(realmConfig); bgRealm.close(); // compactOnLaunch should not be called anymore! - assertEquals(3, compactOnLaunchCount.get()); + assertEquals(2, compactOnLaunchCount.get()); } }); thread.start(); @@ -1166,7 +1165,7 @@ public void run() { realm.close(); - assertEquals(3, compactOnLaunchCount.get()); + assertEquals(2, compactOnLaunchCount.get()); } @Test diff --git a/realm/realm-library/src/main/java/io/realm/RealmCache.java b/realm/realm-library/src/main/java/io/realm/RealmCache.java index db46ab40ee..3779db68a2 100644 --- a/realm/realm-library/src/main/java/io/realm/RealmCache.java +++ b/realm/realm-library/src/main/java/io/realm/RealmCache.java @@ -311,6 +311,7 @@ private synchronized E doCreateRealmOrGetFromCache(RealmCo if (configuration.isSyncConfiguration() && !fileExists) { try { ObjectServerFacade.getSyncFacadeIfPossible().downloadRemoteChanges(configuration); + realm.refresh(); } catch (Throwable t) { // If an error happened while downloading initial data, we need to reset the file so we can // download it again on the next attempt. diff --git a/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java b/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java index 7eb39fc43d..327ae01514 100644 --- a/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java +++ b/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java @@ -263,14 +263,12 @@ public void combiningTrustedRootCA_and_disableSSLVerification() throws Interrupt .disableSSLVerification() .build(); realm = Realm.getInstance(syncConfigDisableSSL); + looperThread.closeAfterTest(realm); RealmResults all = realm.where(StringOnly.class).findAll(); - try { - assertEquals(1, all.size()); - assertEquals("Foo", all.get(0).getChars()); - } finally { - realm.close(); - } + assertEquals(1, all.size()); + assertEquals("Foo", all.get(0).getChars()); + looperThread.testComplete(); } From 458c6face9695d31bfee883dec9405a58a8423df Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 21 Mar 2018 16:31:29 +0000 Subject: [PATCH 4/5] - Adding a schema less dynamic Realm constructor used primarily with waitForInitialRemoteData --- .../src/main/java/io/realm/DynamicRealm.java | 15 ++++++++++++++ .../src/main/java/io/realm/RealmCache.java | 20 ++++--------------- .../internal/SyncObjectServerFacade.java | 19 ++++++++++++++++++ .../java/io/realm/SSLConfigurationTests.java | 10 ++++++---- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/realm/realm-library/src/main/java/io/realm/DynamicRealm.java b/realm/realm-library/src/main/java/io/realm/DynamicRealm.java index c8e164bc64..26e14a7599 100644 --- a/realm/realm-library/src/main/java/io/realm/DynamicRealm.java +++ b/realm/realm-library/src/main/java/io/realm/DynamicRealm.java @@ -81,6 +81,11 @@ public void onResult(int count) { this.schema = new MutableRealmSchema(this); } + private DynamicRealm (RealmConfiguration configuration) { + super(configuration, null); + schema = null; + } + private DynamicRealm(OsSharedRealm sharedRealm) { super(sharedRealm); this.schema = new MutableRealmSchema(this); @@ -267,6 +272,16 @@ public void executeTransaction(Transaction transaction) { } } + /** + * Creates a schemaless {@link DynamicRealm} instance. + * + * @param configuration {@link RealmConfiguration} used to open the Realm. + * @return an empty Realm without any schema. + */ + public static DynamicRealm createSchemalessInstance(RealmConfiguration configuration) { + return new DynamicRealm(configuration); + } + /** * Creates a {@link DynamicRealm} instance without checking the existence in the {@link RealmCache}. * diff --git a/realm/realm-library/src/main/java/io/realm/RealmCache.java b/realm/realm-library/src/main/java/io/realm/RealmCache.java index 3779db68a2..8a6ec054cf 100644 --- a/realm/realm-library/src/main/java/io/realm/RealmCache.java +++ b/realm/realm-library/src/main/java/io/realm/RealmCache.java @@ -299,6 +299,10 @@ private synchronized E doCreateRealmOrGetFromCache(RealmCo BaseRealm realm; boolean fileExists = configuration.realmExists(); + if (configuration.isSyncConfiguration() && !fileExists) { + ObjectServerFacade.getSyncFacadeIfPossible().downloadRemoteChanges(configuration); + } + if (realmClass == Realm.class) { // RealmMigrationNeededException might be thrown here. realm = Realm.createInstance(this); @@ -308,22 +312,6 @@ private synchronized E doCreateRealmOrGetFromCache(RealmCo throw new IllegalArgumentException(WRONG_REALM_CLASS_MESSAGE); } - if (configuration.isSyncConfiguration() && !fileExists) { - try { - ObjectServerFacade.getSyncFacadeIfPossible().downloadRemoteChanges(configuration); - realm.refresh(); - } catch (Throwable t) { - // If an error happened while downloading initial data, we need to reset the file so we can - // download it again on the next attempt. - realm.close(); - // FIXME: We don't have a way to ensure that the Realm instance on client thread has been - // closed for now. - // https://github.com/realm/realm-java/issues/5416 - BaseRealm.deleteRealm(configuration); - throw t; - } - } - // The Realm instance has been created without exceptions. Cache and reference count can be updated now. refAndCount.localRealm.set(realm); refAndCount.localCount.set(0); diff --git a/realm/realm-library/src/objectServer/java/io/realm/internal/SyncObjectServerFacade.java b/realm/realm-library/src/objectServer/java/io/realm/internal/SyncObjectServerFacade.java index 58928d0b3d..c8b100172a 100644 --- a/realm/realm-library/src/objectServer/java/io/realm/internal/SyncObjectServerFacade.java +++ b/realm/realm-library/src/objectServer/java/io/realm/internal/SyncObjectServerFacade.java @@ -24,6 +24,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import io.realm.DynamicRealm; +import io.realm.Realm; import io.realm.RealmConfiguration; import io.realm.SyncConfiguration; import io.realm.SyncManager; @@ -33,6 +35,7 @@ import io.realm.exceptions.RealmException; import io.realm.internal.network.NetworkStateReceiver; import io.realm.internal.sync.permissions.ObjectPermissionsModule; +import io.realm.log.RealmLog; @SuppressWarnings({"unused", "WeakerAccess"}) // Used through reflection. See ObjectServerFacade @Keep @@ -162,11 +165,27 @@ public void downloadRemoteChanges(RealmConfiguration config) { if (config instanceof SyncConfiguration) { SyncConfiguration syncConfig = (SyncConfiguration) config; if (syncConfig.shouldWaitForInitialRemoteData()) { + // Create an empty schemaless Realm then wait for ROS to populate it + // with remote schema and potential data. + DynamicRealm emptyRealm = DynamicRealm.createSchemalessInstance(syncConfig); SyncSession session = SyncManager.getSession(syncConfig); try { session.downloadAllServerChanges(); } catch (InterruptedException e) { + // If an error happened while downloading initial data, we need to reset the file so we can + // download it again on the next attempt. + + // FIXME: We don't have a way to ensure that the Realm instance on client thread has been + // closed for now. so delete may throw + // https://github.com/realm/realm-java/issues/5416 + try { + Realm.deleteRealm(config); + } catch (IllegalStateException exception) { + RealmLog.warn(exception); + } throw new DownloadingRealmInterruptedException(syncConfig, e); + } finally { + emptyRealm.close(); } } } diff --git a/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java b/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java index 327ae01514..7eb39fc43d 100644 --- a/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java +++ b/realm/realm-library/src/syncIntegrationTest/java/io/realm/SSLConfigurationTests.java @@ -263,12 +263,14 @@ public void combiningTrustedRootCA_and_disableSSLVerification() throws Interrupt .disableSSLVerification() .build(); realm = Realm.getInstance(syncConfigDisableSSL); - looperThread.closeAfterTest(realm); RealmResults all = realm.where(StringOnly.class).findAll(); - assertEquals(1, all.size()); - assertEquals("Foo", all.get(0).getChars()); - + try { + assertEquals(1, all.size()); + assertEquals("Foo", all.get(0).getChars()); + } finally { + realm.close(); + } looperThread.testComplete(); } From 371b84ffefe606afe5f8520a83cb293b0fb3e35a Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 21 Mar 2018 18:03:01 +0000 Subject: [PATCH 5/5] update ObjectStore --- realm/realm-library/src/main/cpp/object-store | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/realm/realm-library/src/main/cpp/object-store b/realm/realm-library/src/main/cpp/object-store index b250563ea1..f2a536d29d 160000 --- a/realm/realm-library/src/main/cpp/object-store +++ b/realm/realm-library/src/main/cpp/object-store @@ -1 +1 @@ -Subproject commit b250563ea1eb9f32ec7dbd76f2c6f8f1a26914cc +Subproject commit f2a536d29de48e34e60799a5bf3f36e13806387e