From 0542b500c30d175c9e80441f1ea6b36b294ace32 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Thu, 13 Jul 2023 20:51:44 -0700 Subject: [PATCH] fix some tests Signed-off-by: garyschulte --- .../controller/BesuControllerBuilder.java | 5 +- .../controller/BesuControllerBuilderTest.java | 1 - .../worldstate/PrunerIntegrationTest.java | 1 + .../ethereum/storage/StorageProvider.java | 2 - .../keyvalue/KeyValueStorageProvider.java | 8 ---- .../KeyValueStorageProviderBuilder.java | 7 --- .../core/InMemoryKeyValueStorageProvider.java | 1 - .../besu/ethereum/bonsai/RollingImport.java | 48 +++++++++---------- .../RocksDBKeyValuePrivacyStorageFactory.java | 2 +- .../RocksDBKeyValueStorageFactory.java | 2 +- .../storage/rocksdb/RocksDBTransaction.java | 1 + .../RocksDBColumnarKeyValueStorage.java | 14 ++++-- .../segmented/RocksDBSnapshotTransaction.java | 3 ++ .../kvstore/InMemoryKeyValueStorage.java | 13 ++++- .../kvstore/InMemoryStoragePlugin.java | 15 ++++-- .../SegmentedInMemoryKeyValueStorage.java | 35 ++++++++++++++ 16 files changed, 98 insertions(+), 60 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index aed7e9cb8bb..c5b9e8e8ebc 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -621,10 +621,7 @@ public BesuController build() { Optional maybePruner = Optional.empty(); if (isPruningEnabled) { - if (!storageProvider.isWorldStateIterable()) { - LOG.warn( - "Cannot enable pruning with current database version. Disabling. Resync to get the latest database version or disable pruning explicitly on the command line to remove this warning."); - } else if (dataStorageConfiguration.getDataStorageFormat().equals(DataStorageFormat.BONSAI)) { + if (dataStorageConfiguration.getDataStorageFormat().equals(DataStorageFormat.BONSAI)) { LOG.warn( "Cannot enable pruning with Bonsai data storage format. Disabling. Change the data storage format or disable pruning explicitly on the command line to remove this warning."); } else { diff --git a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java index bd8d06d2a5e..fd35430e273 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java @@ -134,7 +134,6 @@ public void setup() { when(storageProvider.createWorldStateStorage(DataStorageFormat.FOREST)) .thenReturn(worldStateStorage); when(storageProvider.createWorldStatePreimageStorage()).thenReturn(worldStatePreimageStorage); - when(storageProvider.isWorldStateIterable()).thenReturn(true); when(worldStateStorage.isWorldStateAvailable(any(), any())).thenReturn(true); when(worldStatePreimageStorage.updater()) diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/worldstate/PrunerIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/worldstate/PrunerIntegrationTest.java index 6ae0e3a4de8..86f2694c3c0 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/worldstate/PrunerIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/worldstate/PrunerIntegrationTest.java @@ -33,6 +33,7 @@ import org.hyperledger.besu.ethereum.worldstate.Pruner.PruningPhase; import org.hyperledger.besu.evm.worldstate.WorldState; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; import org.hyperledger.besu.testutil.MockExecutorService; import java.util.ArrayList; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java index 3cbf8e45b4f..6cc9741cb22 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java @@ -41,6 +41,4 @@ BlockchainStorage createBlockchainStorage( KeyValueStorage getStorageBySegmentIdentifier(SegmentIdentifier segment); SegmentedKeyValueStorage getStorageBySegmentIdentifiers(List segment); - - boolean isWorldStateIterable(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java index afd39db1c25..d4ce90dc235 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java @@ -48,7 +48,6 @@ public class KeyValueStorageProvider implements StorageProvider { protected final Function, SegmentedKeyValueStorage> segmentedStorageCreator; private final KeyValueStorage worldStatePreimageStorage; - private final boolean isWorldStateIterable; protected final Map, SegmentedKeyValueStorage> storageInstances = new HashMap<>(); private final ObservableMetricsSystem metricsSystem; @@ -56,11 +55,9 @@ public class KeyValueStorageProvider implements StorageProvider { public KeyValueStorageProvider( final Function, SegmentedKeyValueStorage> segmentedStorageCreator, final KeyValueStorage worldStatePreimageStorage, - final boolean segmentIsolationSupported, final ObservableMetricsSystem metricsSystem) { this.segmentedStorageCreator = segmentedStorageCreator; this.worldStatePreimageStorage = worldStatePreimageStorage; - this.isWorldStateIterable = segmentIsolationSupported; this.metricsSystem = metricsSystem; } @@ -106,11 +103,6 @@ public SegmentedKeyValueStorage getStorageBySegmentIdentifiers( return segmentedStorageCreator.apply(segments); } - @Override - public boolean isWorldStateIterable() { - return isWorldStateIterable; - } - @Override public void close() throws IOException { storageInstances.entrySet().stream() diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProviderBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProviderBuilder.java index 6137e61a695..47635c9d27a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProviderBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProviderBuilder.java @@ -23,8 +23,6 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory; import org.hyperledger.besu.services.kvstore.LimitedInMemoryKeyValueStorage; -import java.util.List; - public class KeyValueStorageProviderBuilder { private static final long DEFAULT_WORLD_STATE_PRE_IMAGE_CACHE_SIZE = 5_000L; @@ -60,14 +58,9 @@ public KeyValueStorageProvider build() { final KeyValueStorage worldStatePreImageStorage = new LimitedInMemoryKeyValueStorage(DEFAULT_WORLD_STATE_PRE_IMAGE_CACHE_SIZE); - // this tickles init needed for isSegmentIsolationSupported - storageFactory.create( - List.of(KeyValueSegmentIdentifier.BLOCKCHAIN), commonConfiguration, metricsSystem); - return new KeyValueStorageProvider( segments -> storageFactory.create(segments, commonConfiguration, metricsSystem), worldStatePreImageStorage, - storageFactory.isSegmentIsolationSupported(), (ObservableMetricsSystem) metricsSystem); } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java index de488846d6f..3687643c6d9 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java @@ -41,7 +41,6 @@ public InMemoryKeyValueStorageProvider() { super( segmentIdentifiers -> new SegmentedInMemoryKeyValueStorage(), new InMemoryKeyValueStorage(), - SEGMENT_ISOLATION_SUPPORTED, new NoOpMetricsSystem()); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/RollingImport.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/RollingImport.java index 3f454fd5b8c..46e5b6af9f8 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/RollingImport.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/RollingImport.java @@ -17,6 +17,10 @@ package org.hyperledger.besu.ethereum.bonsai; import static com.google.common.base.Preconditions.checkArgument; +import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE; +import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE; +import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE; +import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE; import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage; @@ -26,11 +30,15 @@ import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; +import org.hyperledger.besu.services.kvstore.SegmentedInMemoryKeyValueStorage; import org.hyperledger.besu.util.io.RollingFileReader; import java.io.IOException; import java.nio.file.Path; +import java.util.List; import org.apache.tuweni.bytes.Bytes; @@ -51,26 +59,18 @@ public static void main(final String[] arg) throws IOException { final BonsaiWorldState bonsaiState = new BonsaiWorldState( archive, new BonsaiWorldStateKeyValueStorage(provider, new NoOpMetricsSystem())); - // TODO: fixme and use segmented/composed - // final InMemoryKeyValueStorage accountStorage = - // (InMemoryKeyValueStorage) - // - // provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE); - // final InMemoryKeyValueStorage codeStorage = - // (InMemoryKeyValueStorage) - // provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.CODE_STORAGE); - // final InMemoryKeyValueStorage storageStorage = - // (InMemoryKeyValueStorage) - // provider.getStorageBySegmentIdentifier( - // KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE); - // final InMemoryKeyValueStorage trieBranchStorage = - // (InMemoryKeyValueStorage) - // - // provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE); - // final InMemoryKeyValueStorage trieLogStorage = - // (InMemoryKeyValueStorage) - // - // provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE); + final SegmentedInMemoryKeyValueStorage worldStateStorage = + (SegmentedInMemoryKeyValueStorage) + provider.getStorageBySegmentIdentifiers( + List.of( + ACCOUNT_INFO_STATE, + CODE_STORAGE, + ACCOUNT_STORAGE_STORAGE, + TRIE_BRANCH_STORAGE)); + + final InMemoryKeyValueStorage trieLogStorage = + (InMemoryKeyValueStorage) + provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE); int count = 0; while (!reader.isDone()) { @@ -127,11 +127,7 @@ public static void main(final String[] arg) throws IOException { } } System.out.printf("Back to zero!%n"); - // TODO: fixme, this is why we held onto allocated in-memory storage in the in mem factory - // accountStorage.dump(System.out); - // codeStorage.dump(System.out); - // storageStorage.dump(System.out); - // trieBranchStorage.dump(System.out); - // trieLogStorage.dump(System.out); + worldStateStorage.dump(System.out); + trieLogStorage.dump(System.out); } } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactory.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactory.java index 34fe0e1ab1e..355cc056924 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactory.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactory.java @@ -101,7 +101,7 @@ public boolean isSegmentIsolationSupported() { @Override public boolean isSnapshotIsolationSupported() { - return publicFactory.isSegmentIsolationSupported(); + return publicFactory.isSnapshotIsolationSupported(); } @Override diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java index 7a755eac66d..0f08e3c0f9b 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java @@ -189,7 +189,7 @@ public SegmentedKeyValueStorage create( case 1, 2 -> { if (segmentedStorage == null) { final List segmentsForVersion = - segments.stream() + configuredSegments.stream() .filter(segmentId -> segmentId.includeInDatabaseVersion(databaseVersion)) .collect(Collectors.toList()); if (isForestStorageFormat) { diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBTransaction.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBTransaction.java index 6ac295f2318..a448e40aaab 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBTransaction.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBTransaction.java @@ -41,6 +41,7 @@ public class RocksDBTransaction implements SegmentedKeyValueStorageTransaction { /** * Instantiates a new RocksDb transaction. * + * @param columnFamilyMapper mapper from segment identifier to column family handle * @param innerTx the inner tx * @param options the options * @param metrics the metrics diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java index f85688bf596..567b3f623b9 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java @@ -116,7 +116,7 @@ public abstract class RocksDBColumnarKeyValueStorage implements SegmentedKeyValu * Instantiates a new Rocks db columnar key value storage. * * @param configuration the configuration - * @param segments the segments + * @param defaultSegments the segments * @param ignorableSegments the ignorable segments * @param metricsSystem the metrics system * @param rocksDBMetricsFactory the rocks db metrics factory @@ -124,7 +124,7 @@ public abstract class RocksDBColumnarKeyValueStorage implements SegmentedKeyValu */ public RocksDBColumnarKeyValueStorage( final RocksDBConfiguration configuration, - final List segments, + final List defaultSegments, final List ignorableSegments, final MetricsSystem metricsSystem, final RocksDBMetricsFactory rocksDBMetricsFactory) @@ -136,7 +136,7 @@ public RocksDBColumnarKeyValueStorage( try { final ColumnFamilyOptions columnFamilyOptions = new ColumnFamilyOptions(); - trimmedSegments = new ArrayList<>(segments); + trimmedSegments = new ArrayList<>(defaultSegments); final List existingColumnFamilies = RocksDB.listColumnFamilies(new Options(), configuration.getDatabaseDir().toString()); // Only ignore if not existed currently @@ -216,7 +216,7 @@ void initColumnHandles() throws RocksDBException { .filter( ch -> { try { - return ch.getName() == segment.getId(); + return Arrays.equals(ch.getName(), segment.getId()); } catch (RocksDBException e) { throw new RuntimeException(e); } @@ -244,6 +244,12 @@ BlockBasedTableConfig createBlockBasedTableConfig(final RocksDBConfiguration con .setBlockSize(ROCKSDB_BLOCK_SIZE); } + /** + * Safe method to map segment identifier to column handle. + * + * @param segment segment identifier + * @return column handle + */ protected ColumnFamilyHandle safeColumnHandle(final SegmentIdentifier segment) { RocksDbSegmentIdentifier safeRef = columnHandlesBySegmentIdentifier.get(segment); if (safeRef == null) { diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java index a01e6ab1b8e..c1c404628d9 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java @@ -92,6 +92,7 @@ private RocksDBSnapshotTransaction( /** * Get data against given key. * + * @param segmentId the segment id * @param key the key * @return the optional data */ @@ -138,6 +139,7 @@ public void remove(final SegmentIdentifier segmentId, final byte[] key) { /** * Stream. * + * @param segmentId the segment id * @return the stream */ public Stream> stream(final SegmentIdentifier segmentId) { @@ -152,6 +154,7 @@ public Stream> stream(final SegmentIdentifier segmentId) { /** * Stream keys. * + * @param segmentId the segment id * @return the stream */ public Stream streamKeys(final SegmentIdentifier segmentId) { diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java index 6b51eab91a7..233bc45545e 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; +import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -61,12 +62,20 @@ private static Map>> asSegmentMap protected final ReadWriteLock rwLock; public InMemoryKeyValueStorage() { - super(SEGMENT_IDENTIFIER, new SegmentedInMemoryKeyValueStorage()); - rwLock = ((SegmentedInMemoryKeyValueStorage) storage).rwLock; + this(SEGMENT_IDENTIFIER); } public InMemoryKeyValueStorage(final Map> initialMap) { super(SEGMENT_IDENTIFIER, new SegmentedInMemoryKeyValueStorage(asSegmentMap(initialMap))); rwLock = ((SegmentedInMemoryKeyValueStorage) storage).rwLock; } + + public InMemoryKeyValueStorage(final SegmentIdentifier segmentIdentifier) { + super(segmentIdentifier, new SegmentedInMemoryKeyValueStorage()); + rwLock = ((SegmentedInMemoryKeyValueStorage) storage).rwLock; + } + + public void dump(final PrintStream ps) { + ((SegmentedInMemoryKeyValueStorage) storage).dump(ps); + } } diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryStoragePlugin.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryStoragePlugin.java index f0480b70fc6..648de893ff4 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryStoragePlugin.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryStoragePlugin.java @@ -25,7 +25,9 @@ import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,6 +94,8 @@ private void createFactoriesAndRegisterWithStorageService() { public static class InMemoryKeyValueStorageFactory implements KeyValueStorageFactory { private final String name; + private final Map, SegmentedInMemoryKeyValueStorage> storageMap = + new HashMap<>(); /** * Instantiates a new Memory key value storage factory. @@ -113,7 +117,10 @@ public KeyValueStorage create( final BesuConfiguration configuration, final MetricsSystem metricsSystem) throws StorageException { - return new InMemoryKeyValueStorage(); + var kvStorage = + storageMap.computeIfAbsent( + List.of(segment), seg -> new SegmentedInMemoryKeyValueStorage(seg)); + return new SegmentedKeyValueStorageAdapter(segment, kvStorage); } @Override @@ -122,7 +129,9 @@ public SegmentedKeyValueStorage create( final BesuConfiguration configuration, final MetricsSystem metricsSystem) throws StorageException { - return new SegmentedInMemoryKeyValueStorage(); + var kvStorage = + storageMap.computeIfAbsent(segments, __ -> new SegmentedInMemoryKeyValueStorage()); + return kvStorage; } @Override @@ -137,7 +146,7 @@ public boolean isSnapshotIsolationSupported() { @Override public void close() { - // Nothing to do + storageMap.clear(); } } } diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java index 65f570a61a4..72bb55ac8ce 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java @@ -23,8 +23,10 @@ import org.hyperledger.besu.plugin.services.storage.SnappableKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.SnappedKeyValueStorage; +import java.io.PrintStream; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -32,6 +34,7 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.common.collect.ImmutableMap; @@ -62,6 +65,16 @@ public SegmentedInMemoryKeyValueStorage() { this.hashValueStore = hashValueStore; } + /** Instantiates a new In memory key value storage with specific set of segments. */ + public SegmentedInMemoryKeyValueStorage(final List segments) { + this( + segments.stream() + .collect( + Collectors + .>>toMap( + s -> s, s -> new HashMap<>()))); + } + @Override public void clear(final SegmentIdentifier segmentIdentifier) { final Lock lock = rwLock.writeLock(); @@ -247,4 +260,26 @@ public void rollback() { removedKeys.clear(); } } + + public void dump(final PrintStream ps) { + final Lock lock = rwLock.readLock(); + lock.lock(); + try { + ImmutableSet.copyOf(hashValueStore.entrySet()).stream() + .forEach( + map -> { + ps.println("Segment: " + map.getKey().getName()); + map.getValue().entrySet().stream() + .filter(bytesEntry -> bytesEntry.getValue().isPresent()) + .forEach( + entry -> + ps.printf( + " %s : %s%n", + entry.getKey().toHexString(), + Bytes.wrap(entry.getValue().get()).toHexString())); + }); + } finally { + lock.unlock(); + } + } }