Skip to content

Commit

Permalink
Fix for #990 (#991)
Browse files Browse the repository at this point in the history
* #990 is fixed

* test case updated

* remove migration test for in-memory mvstore adapter

* test cases fixed
  • Loading branch information
anidotnet authored Jun 30, 2024
1 parent c0404b5 commit 2e0b69e
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ captures/
test.log
/build
!no2-old.db
!no2-v3.db
.diffblue
infer-out
secring.gpg
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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() {
}

Expand All @@ -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");
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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<String, Object> storeHeader = store.getStoreHeader();
if (storeHeader == null || storeHeader.isEmpty()) {
throw new MVStoreException(OLD_DATABASE_FORMAT_VERSION, OLD_DATABASE_FORMAT);
}

MVStore.TxCounter txCounter = store.registerVersionUsage();
MVMap<String, Attributes> 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);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ private static Document document(Compat.Document value) {
Document document = Document.createDocument();
for (Map.Entry<String, Object> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 *********
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Object[]> data() {
return Arrays.asList(new Object[][]{
{false, false, false, false},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand All @@ -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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void testOpenOrCreate() {
nitriteMVStore.openOrCreate();
assertFalse(nitriteMVStore.isReadOnly());
assertFalse(nitriteMVStore.isClosed());
assertTrue(nitriteMVStore.hasUnsavedChanges());
assertFalse(nitriteMVStore.hasUnsavedChanges());
}

@Test
Expand Down
Binary file not shown.

0 comments on commit 2e0b69e

Please sign in to comment.