diff --git a/block-storage/src/main/java/org/lucares/pdb/map/PersistentMap.java b/block-storage/src/main/java/org/lucares/pdb/map/PersistentMap.java index 927700f..66c3254 100644 --- a/block-storage/src/main/java/org/lucares/pdb/map/PersistentMap.java +++ b/block-storage/src/main/java/org/lucares/pdb/map/PersistentMap.java @@ -188,6 +188,13 @@ public class PersistentMap implements AutoCloseable { private long version; + /** + * + * @param path file relative to {@code storageBasePath} + * @param storageBasePath base path + * @param keyEncoder encoder for keys + * @param valueEncoder encoder for values + */ public PersistentMap(final Path path, final Path storageBasePath, final EncoderDecoder keyEncoder, final EncoderDecoder valueEncoder) { this.path = path; @@ -633,6 +640,14 @@ public class PersistentMap implements AutoCloseable { return stats; } + public synchronized boolean isEmpty() { + final long rootNodeOffset = readNodeOffsetOfRootNode(); + final PersistentMapDiskNode node = getNode(rootNodeOffset); + + final List entries = node.getEntries(); + return entries.size() == 1; // the empty map has a single NodeEntry for the PersistentMapDiskNode.MAX_KEY + } + private void swapFiles(final Path newFile) throws IOException { final Path backupFile = path.getParent().resolve(path.getFileName() + "." + DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss").format(OffsetDateTime.now()) + ".backup"); diff --git a/block-storage/src/test/java/org/lucares/pdb/map/PersistentMapTest.java b/block-storage/src/test/java/org/lucares/pdb/map/PersistentMapTest.java index b1a1a55..0e761a9 100644 --- a/block-storage/src/test/java/org/lucares/pdb/map/PersistentMapTest.java +++ b/block-storage/src/test/java/org/lucares/pdb/map/PersistentMapTest.java @@ -375,6 +375,29 @@ public class PersistentMapTest { } } + @Test + public void testIsEmpty() throws IOException { + final Path file = dataDirectory.resolve("map.db"); + try (final PersistentMap map = new PersistentMap<>(file, dataDirectory, PersistentMap.LONG_CODER, + PersistentMap.LONG_CODER)) { + Assertions.assertTrue(map.isEmpty(), "new created map is empty"); + } + + try (final PersistentMap map = new PersistentMap<>(file, dataDirectory, PersistentMap.LONG_CODER, + PersistentMap.LONG_CODER)) { + Assertions.assertTrue(map.isEmpty(), "map is empty after reading an empty map from disk"); + + map.putValue(1L, 2L); + + Assertions.assertFalse(map.isEmpty(), "map is empty after putting a value"); + } + + try (final PersistentMap map = new PersistentMap<>(file, dataDirectory, PersistentMap.LONG_CODER, + PersistentMap.LONG_CODER)) { + Assertions.assertFalse(map.isEmpty(), "map is empty when reading a non empty map from disk"); + } + } + private void assertValuesInMap(final Map insertedValues, final PersistentMap map) { final AtomicInteger counter = new AtomicInteger(); final AtomicInteger maxDepth = new AtomicInteger();