Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for #990 #991

Merged
merged 4 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.