From 2e0b69e2fc7d9b72c66e63b479052211a8cb45c9 Mon Sep 17 00:00:00 2001 From: Anindya Chatterjee <696662+anidotnet@users.noreply.github.com> Date: Sun, 30 Jun 2024 14:14:46 +0530 Subject: [PATCH] Fix for #990 (#991) * #990 is fixed * test case updated * remove migration test for in-memory mvstore adapter * test cases fixed --- .gitignore | 1 + .../dizitart/no2/mvstore/MVStoreUtils.java | 45 ++++++++++-------- .../no2/mvstore/compat/v1/UpgradeUtil.java | 7 ++- .../java/org/dizitart/no2/NitriteTest.java | 44 ++++++++++++++++- .../collection/BaseCollectionTest.java | 2 +- .../CollectionCompoundIndexNegativeTest.java | 2 +- .../no2/mvstore/MVStoreUtilsTest.java | 8 ++-- .../no2/mvstore/NitriteMVStoreTest.java | 2 +- .../src/test/resources/no2-v3.db | Bin 0 -> 16384 bytes 9 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 nitrite-mvstore-adapter/src/test/resources/no2-v3.db diff --git a/.gitignore b/.gitignore index 6c74eda30..0eb467263 100644 --- a/.gitignore +++ b/.gitignore @@ -451,6 +451,7 @@ captures/ test.log /build !no2-old.db +!no2-v3.db .diffblue infer-out secring.gpg \ No newline at end of file diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreUtils.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreUtils.java index 93cd5f56a..2bd30c13e 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreUtils.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreUtils.java @@ -17,18 +17,15 @@ package org.dizitart.no2.mvstore; import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.meta.Attributes; import org.dizitart.no2.exceptions.InvalidOperationException; import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.mvstore.compat.v1.UpgradeUtil; -import org.h2.mvstore.MVMap; import org.h2.mvstore.MVStore; import org.h2.mvstore.MVStoreException; import java.io.File; +import java.util.Map; -import static org.dizitart.no2.common.Constants.META_MAP_NAME; -import static org.dizitart.no2.common.Constants.STORE_INFO; import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; /** @@ -38,6 +35,10 @@ @Slf4j(topic = "nitrite-mvstore") @SuppressWarnings("ALL") class MVStoreUtils { + private static final String OLD_DATABASE_FORMAT = "Old database format detected."; + private static final String OLD_STORE_FORMAT = "The write format 1 is smaller than the supported format"; + private static final Integer OLD_DATABASE_FORMAT_VERSION = 29062024; + private MVStoreUtils() { } @@ -48,7 +49,10 @@ static MVStore openOrCreate(MVStoreConfig storeConfig) { File dbFile = !isNullOrEmpty(storeConfig.filePath()) ? new File(storeConfig.filePath()) : null; try { store = builder.open(); - testForMigration(store); + if (dbFile != null) { + // if the store is file based, test for migration + testForMigration(store); + } } catch (MVStoreException me) { if (me.getMessage().contains("file is locked")) { throw new NitriteIOException("Database is already opened in other process"); @@ -105,7 +109,7 @@ static MVStore openOrCreate(MVStoreConfig storeConfig) { } private static boolean isCompatibilityError(Exception e) { - return e.getMessage().contains("The write format 1 is smaller than the supported format"); + return e.getMessage().contains(OLD_DATABASE_FORMAT) || e.getMessage().contains(OLD_STORE_FORMAT); } private static MVStore.Builder createBuilder(MVStoreConfig mvStoreConfig) { @@ -210,22 +214,23 @@ private static void switchFiles(File newFile, File orgFile) { private static void testForMigration(MVStore store) { if (store != null) { - if (store.hasMap(STORE_INFO)) { - return; + Map storeHeader = store.getStoreHeader(); + if (storeHeader == null || storeHeader.isEmpty()) { + throw new MVStoreException(OLD_DATABASE_FORMAT_VERSION, OLD_DATABASE_FORMAT); } - MVStore.TxCounter txCounter = store.registerVersionUsage(); - MVMap metaMap = store.openMap(META_MAP_NAME); - try { - // fire one operation to trigger compatibility issue - // if no exception thrown, then the database is compatible - metaMap.remove("MigrationTest"); - } catch (IllegalStateException e) { - store.close(); - throw e; - } finally { - if (!store.isClosed()) { - store.deregisterVersionUsage(txCounter); + if (storeHeader.containsKey("format")) { + Object rawFormatValue = storeHeader.get("format"); + if (rawFormatValue instanceof Integer) { + int format = (int) rawFormatValue; + if (format < 3) { + throw new MVStoreException(OLD_DATABASE_FORMAT_VERSION, OLD_DATABASE_FORMAT); + } + } else { + int format = Integer.parseInt((String) storeHeader.get("format")); + if (format < 3) { + throw new MVStoreException(OLD_DATABASE_FORMAT_VERSION, OLD_DATABASE_FORMAT); + } } } } diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v1/UpgradeUtil.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v1/UpgradeUtil.java index 5099915a2..827ba3766 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v1/UpgradeUtil.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v1/UpgradeUtil.java @@ -190,7 +190,12 @@ private static Document document(Compat.Document value) { Document document = Document.createDocument(); for (Map.Entry entry : value.entrySet()) { Object val = entry.getValue(); - Object migratedVal = migrateValue(val); + Object migratedVal; + if (DOC_ID.equals(entry.getKey())) { + migratedVal = String.valueOf(val); + } else { + migratedVal = migrateValue(val); + } document.put(entry.getKey(), migratedVal); } return document; diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java index a4a07c3bc..1a3d26524 100644 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java @@ -436,6 +436,44 @@ public void testIssue193() throws InterruptedException { pool.shutdown(); } + @Test + public void testUpdateDocumentsFromVersion3() throws IOException { + if (Files.exists(Paths.get(System.getProperty("java.io.tmpdir") + File.separator + "no2-v3.db"))) { + Files.delete(Paths.get(System.getProperty("java.io.tmpdir") + File.separator + "no2-v3.db")); + } + + InputStream stream = ClassLoader.getSystemResourceAsStream("no2-v3.db"); + if (stream == null) { + stream = ClassLoader.getSystemClassLoader().getResourceAsStream("no2-v3.db"); + } + assert stream != null; + + Files.copy(stream, Paths.get(System.getProperty("java.io.tmpdir") + File.separator + "no2-v3.db")); + + String oldDbFile = System.getProperty("java.io.tmpdir") + File.separator + "no2-v3.db"; + Nitrite db = TestUtil.createDb(oldDbFile); + NitriteCollection testCollection = db.getCollection("test"); + Document document = testCollection.find().firstOrNull(); + document.put("name", "new-name"); + + boolean exception = false; + try { + testCollection.update(document); + } catch (Exception e) { + exception = true; + log.error("Error while updating document", e); + } + assertFalse(exception); + + db.close(); + + try { + Files.deleteIfExists(Paths.get(oldDbFile)); + } catch (IOException e) { + log.error("Error while deleting db", e); + } + } + @Test public void testReadCompatibility() throws IOException { // ******* Old DB Creation Code Start ********* @@ -531,7 +569,11 @@ public void testReadCompatibility() throws IOException { db.close(); - //TODO: CHeck reopen with repo. That should also fails too. + try { + Files.deleteIfExists(Paths.get(oldDbFile)); + } catch (IOException e) { + log.error("Error while deleting db", e); + } } @Test diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java index 200d7c873..033a279ed 100644 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java @@ -64,7 +64,7 @@ public abstract class BaseCollectionTest { public Retry retry = new Retry(3); @Parameterized.Parameters(name = "InMemory = {0}, Secured = {1}, " + - "Compressed = {2}, AutoCommit = {3}, AutoCompact = {4}") + "Compressed = {2}, AutoCommit = {3}") public static Collection data() { return Arrays.asList(new Object[][]{ {false, false, false, false}, diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java index 746fe397b..b9e627250 100644 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java @@ -57,7 +57,7 @@ public void testCreateUniqueMultiKeyIndexOnArray() { public void testCreateOnInvalidField() { insert(); // multiple null value will be created - collection.createIndex( "my-value", "lastName"); + collection.createIndex("my-value", "lastName"); } @Test(expected = IndexingException.class) diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java index 78f61ef9b..0873e21a7 100644 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java @@ -33,9 +33,9 @@ public void testOpenOrCreate() { assertEquals(0, actualOpenOrCreateResult.getUnsavedMemory()); assertEquals(0, actualOpenOrCreateResult.getStoreVersion()); assertEquals(0, actualOpenOrCreateResult.getRetentionTime()); - assertEquals(2, actualOpenOrCreateResult.getMetaMap().size()); + assertEquals(0, actualOpenOrCreateResult.getMetaMap().size()); assertEquals(Long.MAX_VALUE, actualOpenOrCreateResult.getMaxPageSize()); - assertEquals(1, actualOpenOrCreateResult.getMapNames().size()); + assertEquals(0, actualOpenOrCreateResult.getMapNames().size()); assertEquals(48, actualOpenOrCreateResult.getKeysPerPage()); assertEquals(0, actualOpenOrCreateResult.getAutoCommitMemory()); } @@ -50,9 +50,9 @@ public void testOpenOrCreate2() { assertEquals(0, actualOpenOrCreateResult.getUnsavedMemory()); assertEquals(0, actualOpenOrCreateResult.getStoreVersion()); assertEquals(0, actualOpenOrCreateResult.getRetentionTime()); - assertEquals(2, actualOpenOrCreateResult.getMetaMap().size()); + assertEquals(0, actualOpenOrCreateResult.getMetaMap().size()); assertEquals(Long.MAX_VALUE, actualOpenOrCreateResult.getMaxPageSize()); - assertEquals(1, actualOpenOrCreateResult.getMapNames().size()); + assertEquals(0, actualOpenOrCreateResult.getMapNames().size()); assertEquals(48, actualOpenOrCreateResult.getKeysPerPage()); assertEquals(0, actualOpenOrCreateResult.getAutoCommitMemory()); } diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java index 99968fe49..955748e22 100644 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java @@ -38,7 +38,7 @@ public void testOpenOrCreate() { nitriteMVStore.openOrCreate(); assertFalse(nitriteMVStore.isReadOnly()); assertFalse(nitriteMVStore.isClosed()); - assertTrue(nitriteMVStore.hasUnsavedChanges()); + assertFalse(nitriteMVStore.hasUnsavedChanges()); } @Test diff --git a/nitrite-mvstore-adapter/src/test/resources/no2-v3.db b/nitrite-mvstore-adapter/src/test/resources/no2-v3.db new file mode 100644 index 0000000000000000000000000000000000000000..c9ace3b5daf359adf68444dbca7b09944fbcabc4 GIT binary patch literal 16384 zcmeI3Piz!b9LIk%+u47GS}3%FmVH$c4{n#)KW%pxjZ;8uH%m1_Kn$__cIIt6Fgvr( zzAXz;LsdXR3>@@=HLk>qO1NP{j7bp>9z4jwix;=*&3MyDq7mPlZdSxNyETl5QiWj2nYg#fFK|U2m*qD zARq_`0)l`bAPC%70wW^--&g*kb3s555CjAPK|l}?1Ox#=KoAfF1OY+dUJ#i7kw4z5 z0Z2qG!hh;7;|i+>DC2rIsjE?&)G7P3f+t9oon6PF*%Ye~P*o$P<0v)DtYVnd8R^`wpj2I0@3<2&!#r$K?9!O+Bw}MGbrqA6 zQ3DV}Ug#X1kU`2rz%+Jat41hv=J(?%yvf4$#HPIB*b|%U74!^rXlo$GAB8pklRuyS z=G3DtCfqyJ$CNh-u8EzCuM+o1t4n+|@reKKf(&cpCi;qnF-ndl_DXFuDkm_GGZ^7-q>NMpau2A+*MS znn3@BI$ybe$)CuQyf(6rk}B=GwlGU*`7Eu7l?lbMVM<-ISVND4H&?m$x5yC4L3^v} zWEWdxIS7+_#dHtt!5t>eL8pbQbcgp3G$Ep`4(&W->%_=Gu!@3_JS%F+Ls)k#i|CY% ziNfmZrh6x%53>2rLtCw88hl6+pFqhQ06N})!UOPGV?`4{rqG7YM<|7jr9@^R9#_-- zgN9z}Pi0EDzgS8b{VFLH14D@ceW<9W+1TIkU4fuH>{r-Eip3R8fkZ)xBztXKCb5k+ zTb689j+?eY>f?O$uW&})O{G`sfpPQ%gbLjn^85Kti^Y%l+0{Le)p`nP$Tng3Y`Rcx zO5II=IVdHigcJ{_R1JIyV?b?$eVGAWr+A$8>~)vDS$B(<@{P=|Wv%doU(e@H9D;x# zAP5Kof`A|(2nYg#fFN+E2`taw3w8AIr8@d_%217g(%@Z*(hEiY3-R#T*v|C2)o&MZ2B#Jz9;UrSX=zLJrhJf?K44vEp#%CJxkEZ&1=j)4iIxe0&u=aSzFIB>iW_bu1itKR z34sf@5(0BG)8NO`!$;@#Prv^0@YcDJ>9(#(XHTzf@Pvu2qRKOm};Cy=X7NR1-p>CGAx>%i{Xk!et)U=VmV#u6l9( zYM_<5)7qW(mXbPG0=FID=Xavl+ERdD(nm~Jt>Tg^<|(I^Z2CWw zv>=kaZ#yQE*qJ}BS4qsCah1fZ3R6j*Tw<>j8v&;S4c literal 0 HcmV?d00001