From efc0f7ccbae672daf224c8c2d4e5f61404074f36 Mon Sep 17 00:00:00 2001 From: Anindya Chatterjee Date: Wed, 29 May 2024 09:30:12 +0530 Subject: [PATCH 1/3] safe openMVMap introduced --- .../dizitart/no2/mvstore/NitriteMVStore.java | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java index 8834cc838..1d299e9d3 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java @@ -17,7 +17,9 @@ package org.dizitart.no2.mvstore; +import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.common.util.StringUtils; +import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.index.BoundingBox; import org.dizitart.no2.store.AbstractNitriteStore; import org.dizitart.no2.store.NitriteMap; @@ -26,6 +28,7 @@ import org.dizitart.no2.store.events.StoreEvents; import org.h2.mvstore.MVMap; import org.h2.mvstore.MVStore; +import org.h2.mvstore.MVStoreException; import org.h2.mvstore.rtree.MVRTreeMap; import java.util.Map; @@ -35,6 +38,7 @@ * @since 1.0 * @author Anindya Chatterjee */ +@Slf4j public class NitriteMVStore extends AbstractNitriteStore { private MVStore mvStore; private final Map> nitriteMapRegistry; @@ -109,7 +113,7 @@ public NitriteMap openMap(String mapName, Class keyT return (NitriteMVMap) nitriteMapRegistry.get(mapName); } - MVMap mvMap = mvStore.openMap(mapName); + MVMap mvMap = openMVMap(mapName, null); NitriteMVMap nitriteMVMap = new NitriteMVMap<>(mvMap, this); nitriteMapRegistry.put(mapName, nitriteMVMap); return nitriteMVMap; @@ -131,7 +135,7 @@ public void closeRTree(String rTreeName) { @Override public void removeMap(String name) { - MVMap mvMap = mvStore.openMap(name); + MVMap mvMap = openMVMap(name, null); mvStore.removeMap(mvMap); getCatalog().remove(name); nitriteMapRegistry.remove(name); @@ -140,7 +144,7 @@ public void removeMap(String name) { @Override @SuppressWarnings({"rawtypes"}) public void removeRTree(String rTreeName) { - MVMap mvMap = mvStore.openMap(rTreeName, new MVRTreeMap.Builder<>()); + MVMap mvMap = openMVMap(rTreeName, new MVRTreeMap.Builder<>()); mvStore.removeMap(mvMap); getCatalog().remove(rTreeName); nitriteRTreeMapRegistry.remove(rTreeName); @@ -153,7 +157,7 @@ public NitriteRTree openRTree(Strin return (NitriteMVRTreeMap) nitriteRTreeMapRegistry.get(mapName); } - MVRTreeMap map = mvStore.openMap(mapName, new MVRTreeMap.Builder<>()); + MVRTreeMap map = (MVRTreeMap) openMVMap(mapName, new MVRTreeMap.Builder<>()); NitriteMVRTreeMap nitriteMVRTreeMap = new NitriteMVRTreeMap(map, this); nitriteRTreeMapRegistry.put(mapName, nitriteMVRTreeMap); return nitriteMVRTreeMap; @@ -171,4 +175,33 @@ private void initEventBus() { } } } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private MVMap openMVMap(String mapName, MVMap.MapBuilder builder) { + Exception exception = null; + try { + MVMap.MapBuilder mapBuilder = builder == null ? new MVMap.Builder<>() : builder; + long version = mvStore.getCurrentVersion(); + + while (version >= 0) { + try { + return mvStore.openMap(mapName, mapBuilder); + } catch (MVStoreException me) { + if (version == 0) { + throw me; + } + + log.warn("Error opening map {} with version {}, retrying with previous version", mapName, version, me); + // open map with earlier version + mvStore.rollbackTo(version - 1); + version = mvStore.getCurrentVersion(); + exception = me; + } + } + } catch (Exception e) { + exception = e; + } + + throw new NitriteIOException("Unable to open map " + mapName, exception); + } } From 0c20818f52a669fbec0334c6a963c537b8636ae8 Mon Sep 17 00:00:00 2001 From: Anindya Chatterjee Date: Thu, 30 May 2024 22:24:18 +0530 Subject: [PATCH 2/3] handling mvstore file corruption gracefully --- .../org/dizitart/no2/mvstore/NitriteMVStore.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java index 1d299e9d3..e4b80e627 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java @@ -34,6 +34,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.h2.mvstore.DataUtils.*; + /** * @since 1.0 * @author Anindya Chatterjee @@ -192,9 +194,15 @@ private MVMap openMVMap(String mapName, MVMap.MapBuilder builder) { } log.warn("Error opening map {} with version {}, retrying with previous version", mapName, version, me); - // open map with earlier version - mvStore.rollbackTo(version - 1); - version = mvStore.getCurrentVersion(); + if (me.getErrorCode() == ERROR_READING_FAILED || me.getErrorCode() == ERROR_WRITING_FAILED + || me.getErrorCode() == ERROR_FILE_CORRUPT || me.getErrorCode() == ERROR_SERIALIZATION + || me.getErrorCode() == ERROR_CHUNK_NOT_FOUND || me.getErrorCode() == ERROR_BLOCK_NOT_FOUND) { + // open map with earlier version + mvStore.rollbackTo(version - 1); + version = mvStore.getCurrentVersion(); + } else { + throw me; + } exception = me; } } From 43628e8ef7a8ce68f8be369b6fa5c3cd8c18aed6 Mon Sep 17 00:00:00 2001 From: Anindya Chatterjee Date: Thu, 30 May 2024 22:26:20 +0530 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76adcc951..25c11267d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Fix for #948 - Fix for #961 - Fix for #966 +- Fix for #977 ## Release 4.2.2 - Mar 5, 2024