diff --git a/CHANGELOG.md b/CHANGELOG.md index a47fb3cd942..42e42706754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Breaking Changes +- Removed support for version 0 of the database as it is no longer used by any active node. + ### Additions and Improvements - EvmTool now executes the `execution-spec-tests` via the `t8n` and `b11r`. See the [README](ethereum/evmtool/README.md) in EvmTool for more instructions. - Improve lifecycle management of the transaction pool [#5634](https://github.com/hyperledger/besu/pull/5634) diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java index d2afc2e6d39..5136cc64ab3 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java @@ -80,16 +80,6 @@ public BackupRoundTripAcceptanceTest( public static Object[][] getParameters() { return new Object[][] { // First 10 blocks of ropsten - new Object[] { - "Before versioning was enabled", - "version0", - 0xA, - singletonList( - new AccountData( - "0xd1aeb42885a43b72b518182ef893125814811048", - BigInteger.valueOf(0xA), - Wei.fromHexString("0x2B5E3AF16B1880000"))), - }, new Object[] { "After versioning was enabled and using multiple RocksDB columns", "version1", diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java index d116a5cafcf..291506498ba 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java @@ -56,16 +56,6 @@ public DatabaseMigrationAcceptanceTest( public static Object[][] getParameters() { return new Object[][] { // First 10 blocks of ropsten - new Object[] { - "Before versioning was enabled", - "version0", - 0xA, - singletonList( - new AccountData( - "0xd1aeb42885a43b72b518182ef893125814811048", - BigInteger.valueOf(0xA), - Wei.fromHexString("0x2B5E3AF16B1880000"))), - }, new Object[] { "After versioning was enabled and using multiple RocksDB columns", "version1", diff --git a/acceptance-tests/tests/src/test/resources/org/hyperledger/besu/tests/acceptance/database/version0/besu-db-archive.tar.gz b/acceptance-tests/tests/src/test/resources/org/hyperledger/besu/tests/acceptance/database/version0/besu-db-archive.tar.gz deleted file mode 100644 index 894c8e76a69..00000000000 Binary files a/acceptance-tests/tests/src/test/resources/org/hyperledger/besu/tests/acceptance/database/version0/besu-db-archive.tar.gz and /dev/null differ diff --git a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java index 81796f89f29..a55ad27f20a 100644 --- a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java +++ b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java @@ -24,16 +24,19 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.MessageFrameTestFixture; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder; -import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.rocksdb.segmented.OptimisticRocksDBColumnarKeyValueStorage; +import org.hyperledger.besu.services.kvstore.SnappableSegmentedKeyValueStorageAdapter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import com.google.common.io.MoreFiles; import com.google.common.io.RecursiveDeleteOption; @@ -58,12 +61,18 @@ private OperationBenchmarkHelper( public static OperationBenchmarkHelper create() throws IOException { final Path storageDirectory = Files.createTempDirectory("benchmark"); - final KeyValueStorage keyValueStorage = - new RocksDBKeyValueStorage( + final OptimisticRocksDBColumnarKeyValueStorage optimisticRocksDBColumnarKeyValueStorage = + new OptimisticRocksDBColumnarKeyValueStorage( new RocksDBConfigurationBuilder().databaseDir(storageDirectory).build(), + List.of(KeyValueSegmentIdentifier.BLOCKCHAIN), + emptyList(), new NoOpMetricsSystem(), RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); + final KeyValueStorage keyValueStorage = + new SnappableSegmentedKeyValueStorageAdapter<>( + KeyValueSegmentIdentifier.BLOCKCHAIN, optimisticRocksDBColumnarKeyValueStorage); + final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.builder().blockchainKeyValueStorage(keyValueStorage).build(); final MutableBlockchain blockchain = executionContext.getBlockchain(); 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 ee20b85e968..042fdd15d3f 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 @@ -38,7 +38,7 @@ public class RocksDBKeyValuePrivacyStorageFactory implements PrivacyKeyValueStor private static final Logger LOG = LoggerFactory.getLogger(RocksDBKeyValuePrivacyStorageFactory.class); private static final int DEFAULT_VERSION = 1; - private static final Set SUPPORTED_VERSIONS = Set.of(0, 1); + private static final Set SUPPORTED_VERSIONS = Set.of(1); private static final String PRIVATE_DATABASE_PATH = "private"; private final RocksDBKeyValueStorageFactory publicFactory; @@ -96,7 +96,7 @@ private int readDatabaseVersion(final BesuConfiguration commonConfiguration) thr commonConfiguration.getStoragePath().resolve(PRIVATE_DATABASE_PATH).toFile().exists(); final int privacyDatabaseVersion; if (privacyDatabaseExists) { - privacyDatabaseVersion = DatabaseMetadata.lookUpFrom(dataDir).maybePrivacyVersion().orElse(0); + privacyDatabaseVersion = DatabaseMetadata.lookUpFrom(dataDir).maybePrivacyVersion().orElse(1); LOG.info( "Existing private database detected at {}. Version {}", dataDir, privacyDatabaseVersion); } else { 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 81aa1a37087..45eefc67182 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 @@ -30,7 +30,6 @@ import org.hyperledger.besu.plugin.services.storage.rocksdb.segmented.OptimisticRocksDBColumnarKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.rocksdb.segmented.RocksDBColumnarKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.rocksdb.segmented.TransactionDBRocksDBColumnarKeyValueStorage; -import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage; import org.hyperledger.besu.services.kvstore.SegmentedKeyValueStorageAdapter; import org.hyperledger.besu.services.kvstore.SnappableSegmentedKeyValueStorageAdapter; @@ -50,7 +49,7 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory { private static final Logger LOG = LoggerFactory.getLogger(RocksDBKeyValueStorageFactory.class); private static final int DEFAULT_VERSION = 1; - private static final Set SUPPORTED_VERSIONS = Set.of(0, 1, 2); + private static final Set SUPPORTED_VERSIONS = Set.of(1, 2); private static final String NAME = "rocksdb"; private final RocksDBMetricsFactory rocksDBMetricsFactory; @@ -58,7 +57,6 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory { private Integer databaseVersion; private Boolean isSegmentIsolationSupported; private RocksDBColumnarKeyValueStorage segmentedStorage; - private KeyValueStorage unsegmentedStorage; private RocksDBConfiguration rocksDBConfiguration; private final Supplier configuration; @@ -163,17 +161,7 @@ public KeyValueStorage create( // version. Introducing intermediate booleans that represent database properties and dispatching // creation logic based on them is error-prone. switch (databaseVersion) { - case 0 -> { - segmentedStorage = null; - if (unsegmentedStorage == null) { - unsegmentedStorage = - new RocksDBKeyValueStorage( - rocksDBConfiguration, metricsSystem, rocksDBMetricsFactory); - } - return unsegmentedStorage; - } case 1, 2 -> { - unsegmentedStorage = null; if (segmentedStorage == null) { final List segmentsForVersion = segments.stream() @@ -249,7 +237,7 @@ private void init(final BesuConfiguration commonConfiguration) { } private boolean requiresInit() { - return segmentedStorage == null && unsegmentedStorage == null; + return segmentedStorage == null; } private int readDatabaseVersion(final BesuConfiguration commonConfiguration) throws IOException { @@ -283,9 +271,6 @@ private int readDatabaseVersion(final BesuConfiguration commonConfiguration) thr @Override public void close() throws IOException { - if (unsegmentedStorage != null) { - unsegmentedStorage.close(); - } if (segmentedStorage != null) { segmentedStorage.close(); } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/DatabaseMetadata.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/DatabaseMetadata.java index 49b54315b32..1faf610cdc9 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/DatabaseMetadata.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/DatabaseMetadata.java @@ -151,7 +151,7 @@ private static DatabaseMetadata resolveDatabaseMetadata(final File metadataFile) try { databaseMetadata = MAPPER.readValue(metadataFile, DatabaseMetadata.class); } catch (FileNotFoundException fnfe) { - databaseMetadata = new DatabaseMetadata(0, 0); + databaseMetadata = new DatabaseMetadata(1, 1); } catch (JsonProcessingException jpe) { throw new IllegalStateException( String.format("Invalid metadata file %s", metadataFile.getAbsolutePath()), jpe); diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java deleted file mode 100644 index 6f32bd89c19..00000000000 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented; - -import static java.util.stream.Collectors.toUnmodifiableSet; - -import org.hyperledger.besu.plugin.services.MetricsSystem; -import org.hyperledger.besu.plugin.services.exception.StorageException; -import org.hyperledger.besu.plugin.services.metrics.OperationTimer; -import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; -import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetrics; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbIterator; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbUtil; -import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration; -import org.hyperledger.besu.services.kvstore.KeyValueStorageTransactionTransitionValidatorDecorator; - -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import org.apache.commons.lang3.tuple.Pair; -import org.apache.tuweni.bytes.Bytes; -import org.rocksdb.BlockBasedTableConfig; -import org.rocksdb.LRUCache; -import org.rocksdb.OptimisticTransactionDB; -import org.rocksdb.Options; -import org.rocksdb.ReadOptions; -import org.rocksdb.RocksDBException; -import org.rocksdb.RocksIterator; -import org.rocksdb.Statistics; -import org.rocksdb.Status; -import org.rocksdb.WriteOptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** The Rocks db key value storage. */ -public class RocksDBKeyValueStorage implements KeyValueStorage { - - static { - RocksDbUtil.loadNativeLibrary(); - } - - private static final Logger LOG = LoggerFactory.getLogger(RocksDBKeyValueStorage.class); - - private final Options options; - private final OptimisticTransactionDB db; - private final AtomicBoolean closed = new AtomicBoolean(false); - private final RocksDBMetrics rocksDBMetrics; - private final WriteOptions tryDeleteOptions = - new WriteOptions().setNoSlowdown(true).setIgnoreMissingColumnFamilies(true); - private final ReadOptions readOptions = new ReadOptions().setVerifyChecksums(false); - - /** - * Instantiates a new Rocks db key value storage. - * - * @param configuration the configuration - * @param metricsSystem the metrics system - * @param rocksDBMetricsFactory the rocks db metrics factory - */ - public RocksDBKeyValueStorage( - final RocksDBConfiguration configuration, - final MetricsSystem metricsSystem, - final RocksDBMetricsFactory rocksDBMetricsFactory) { - - try { - final Statistics stats = new Statistics(); - options = - new Options() - .setCreateIfMissing(true) - .setMaxOpenFiles(configuration.getMaxOpenFiles()) - .setTableFormatConfig(createBlockBasedTableConfig(configuration)) - .setStatistics(stats); - options.getEnv().setBackgroundThreads(configuration.getBackgroundThreadCount()); - - db = OptimisticTransactionDB.open(options, configuration.getDatabaseDir().toString()); - rocksDBMetrics = rocksDBMetricsFactory.create(metricsSystem, configuration, db, stats); - } catch (final RocksDBException e) { - throw new StorageException(e); - } - } - - @Override - public void clear() throws StorageException { - throwIfClosed(); - - try (final RocksIterator rocksIterator = db.newIterator()) { - rocksIterator.seekToFirst(); - if (rocksIterator.isValid()) { - final byte[] firstKey = rocksIterator.key(); - rocksIterator.seekToLast(); - if (rocksIterator.isValid()) { - final byte[] lastKey = rocksIterator.key(); - db.deleteRange(firstKey, lastKey); - db.delete(lastKey); - } - } - } catch (final RocksDBException e) { - throw new StorageException(e); - } - } - - @Override - public boolean containsKey(final byte[] key) throws StorageException { - return get(key).isPresent(); - } - - @Override - public Optional get(final byte[] key) throws StorageException { - throwIfClosed(); - - try (final OperationTimer.TimingContext ignored = - rocksDBMetrics.getReadLatency().startTimer()) { - return Optional.ofNullable(db.get(readOptions, key)); - } catch (final RocksDBException e) { - throw new StorageException(e); - } - } - - @Override - public Set getAllKeysThat(final Predicate returnCondition) { - return stream() - .filter(pair -> returnCondition.test(pair.getKey())) - .map(Pair::getKey) - .collect(toUnmodifiableSet()); - } - - @Override - public Stream> stream() { - throwIfClosed(); - - final RocksIterator rocksIterator = db.newIterator(); - rocksIterator.seekToFirst(); - return RocksDbIterator.create(rocksIterator).toStream(); - } - - @Override - public Stream> streamFromKey(final byte[] startKey) { - return stream().filter(e -> Bytes.wrap(startKey).compareTo(Bytes.wrap(e.getKey())) <= 0); - } - - @Override - public Stream streamKeys() { - throwIfClosed(); - - final RocksIterator rocksIterator = db.newIterator(); - rocksIterator.seekToFirst(); - return RocksDbIterator.create(rocksIterator).toStreamKeys(); - } - - @Override - public Set getAllValuesFromKeysThat(final Predicate returnCondition) { - return stream() - .filter(pair -> returnCondition.test(pair.getKey())) - .map(Pair::getValue) - .collect(toUnmodifiableSet()); - } - - @Override - public boolean tryDelete(final byte[] key) { - throwIfClosed(); - try { - db.delete(tryDeleteOptions, key); - return true; - } catch (RocksDBException e) { - if (e.getStatus().getCode() == Status.Code.Incomplete) { - return false; - } else { - throw new StorageException(e); - } - } - } - - @Override - public KeyValueStorageTransaction startTransaction() throws StorageException { - throwIfClosed(); - final WriteOptions options = new WriteOptions(); - options.setIgnoreMissingColumnFamilies(true); - return new KeyValueStorageTransactionTransitionValidatorDecorator( - new RocksDBTransaction(db.beginTransaction(options), options, rocksDBMetrics)); - } - - @Override - public boolean isClosed() { - return closed.get(); - } - - @Override - public void close() { - if (closed.compareAndSet(false, true)) { - tryDeleteOptions.close(); - options.close(); - db.close(); - } - } - - private BlockBasedTableConfig createBlockBasedTableConfig(final RocksDBConfiguration config) { - final LRUCache cache = new LRUCache(config.getCacheCapacity()); - return new BlockBasedTableConfig().setBlockCache(cache); - } - - private void throwIfClosed() { - if (closed.get()) { - LOG.error("Attempting to use a closed RocksDBKeyValueStorage"); - throw new IllegalStateException("Storage has been closed"); - } - } -} diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBTransaction.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBTransaction.java deleted file mode 100644 index ffd5a1596f6..00000000000 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBTransaction.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented; - -import org.hyperledger.besu.plugin.services.exception.StorageException; -import org.hyperledger.besu.plugin.services.metrics.OperationTimer; -import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetrics; - -import org.rocksdb.RocksDBException; -import org.rocksdb.Transaction; -import org.rocksdb.WriteOptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** The RocksDb transaction. */ -public class RocksDBTransaction implements KeyValueStorageTransaction { - private static final Logger logger = LoggerFactory.getLogger(RocksDBTransaction.class); - private static final String NO_SPACE_LEFT_ON_DEVICE = "No space left on device"; - - private final RocksDBMetrics metrics; - private final Transaction innerTx; - private final WriteOptions options; - - /** - * Instantiates a new RocksDb transaction. - * - * @param innerTx the inner tx - * @param options the options - * @param metrics the metrics - */ - RocksDBTransaction( - final Transaction innerTx, final WriteOptions options, final RocksDBMetrics metrics) { - this.innerTx = innerTx; - this.options = options; - this.metrics = metrics; - } - - @Override - public void put(final byte[] key, final byte[] value) { - try (final OperationTimer.TimingContext ignored = metrics.getWriteLatency().startTimer()) { - innerTx.put(key, value); - } catch (final RocksDBException e) { - if (e.getMessage().contains(NO_SPACE_LEFT_ON_DEVICE)) { - logger.error(e.getMessage()); - System.exit(0); - } - throw new StorageException(e); - } - } - - @Override - public void remove(final byte[] key) { - try (final OperationTimer.TimingContext ignored = metrics.getRemoveLatency().startTimer()) { - innerTx.delete(key); - } catch (final RocksDBException e) { - if (e.getMessage().contains(NO_SPACE_LEFT_ON_DEVICE)) { - logger.error(e.getMessage()); - System.exit(0); - } - throw new StorageException(e); - } - } - - @Override - public void commit() throws StorageException { - try (final OperationTimer.TimingContext ignored = metrics.getCommitLatency().startTimer()) { - innerTx.commit(); - } catch (final RocksDBException e) { - if (e.getMessage().contains(NO_SPACE_LEFT_ON_DEVICE)) { - logger.error(e.getMessage()); - System.exit(0); - } - throw new StorageException(e); - } finally { - close(); - } - } - - @Override - public void rollback() { - try { - innerTx.rollback(); - metrics.getRollbackCount().inc(); - } catch (final RocksDBException e) { - if (e.getMessage().contains(NO_SPACE_LEFT_ON_DEVICE)) { - logger.error(e.getMessage()); - System.exit(0); - } - throw new StorageException(e); - } finally { - close(); - } - } - - private void close() { - innerTx.close(); - options.close(); - } -} diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactoryTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactoryTest.java index 7106b1ad4f4..19ee5c197ec 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactoryTest.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactoryTest.java @@ -48,7 +48,7 @@ public class RocksDBKeyValuePrivacyStorageFactoryTest { @Mock private SegmentIdentifier segment; @Test - public void shouldDetectVersion0DatabaseIfNoMetadataFileFound() throws Exception { + public void shouldDetectVersion1DatabaseIfNoMetadataFileFound() throws Exception { final Path tempDataDir = temporaryFolder.newFolder().toPath().resolve("data"); final Path tempDatabaseDir = temporaryFolder.newFolder().toPath().resolve("db"); final Path tempPrivateDatabaseDir = tempDatabaseDir.resolve("private"); @@ -69,9 +69,10 @@ public void shouldDetectVersion0DatabaseIfNoMetadataFileFound() throws Exception assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).maybePrivacyVersion()).isNotEmpty(); - assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).getVersion()).isEqualTo(0); + assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).getVersion()).isEqualTo(DEFAULT_VERSION); - assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).maybePrivacyVersion().get()).isEqualTo(0); + assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).maybePrivacyVersion().get()) + .isEqualTo(DEFAULT_VERSION); } @Test diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java index 000b5079c04..9a3fd3ade53 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java @@ -71,7 +71,7 @@ public void shouldCreateCorrectMetadataFileForLatestVersion() throws Exception { } @Test - public void shouldDetectVersion0DatabaseIfNoMetadataFileFound() throws Exception { + public void shouldDetectVersion1DatabaseIfNoMetadataFileFound() throws Exception { final Path tempDataDir = temporaryFolder.newFolder().toPath().resolve("data"); final Path tempDatabaseDir = temporaryFolder.newFolder().toPath().resolve("db"); Files.createDirectories(tempDatabaseDir); @@ -85,7 +85,7 @@ public void shouldDetectVersion0DatabaseIfNoMetadataFileFound() throws Exception storageFactory.create(segment, commonConfiguration, metricsSystem); - assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).getVersion()).isZero(); + assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).getVersion()).isEqualTo(DEFAULT_VERSION); } @Test @@ -118,14 +118,14 @@ public void shouldDetectCorrectVersionInCaseOfRollback() throws Exception { final RocksDBKeyValueStorageFactory storageFactory = new RocksDBKeyValueStorageFactory( - () -> rocksDbConfiguration, segments, 1, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); + () -> rocksDbConfiguration, segments, 2, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); storageFactory.create(segment, commonConfiguration, metricsSystem); storageFactory.close(); final RocksDBKeyValueStorageFactory rolledbackStorageFactory = new RocksDBKeyValueStorageFactory( - () -> rocksDbConfiguration, segments, 0, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); + () -> rocksDbConfiguration, segments, 1, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); rolledbackStorageFactory.create(segment, commonConfiguration, metricsSystem); } diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest.java index 2c9fc86df13..ba65b62ff64 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.plugin.services.storage.rocksdb.segmented; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbSegmentIdentifier; @@ -26,7 +27,10 @@ import java.util.List; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) public class OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest extends RocksDBColumnarKeyValueStorageTest { @@ -55,4 +59,18 @@ protected SegmentedKeyValueStorage createSegmentedStor new NoOpMetricsSystem(), RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); } + + @Override + protected SegmentedKeyValueStorage createSegmentedStore( + final Path path, + final MetricsSystem metricsSystem, + final List segments, + final List ignorableSegments) { + return new OptimisticRocksDBColumnarKeyValueStorage( + new RocksDBConfigurationBuilder().databaseDir(path).build(), + segments, + ignorableSegments, + metricsSystem, + RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); + } } diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java index 98eaf034960..e342d6ddcb1 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java @@ -16,9 +16,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.hyperledger.besu.kvstore.AbstractKeyValueStorageTest; +import org.hyperledger.besu.metrics.BesuMetricCategory; +import org.hyperledger.besu.metrics.ObservableMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.exception.StorageException; +import org.hyperledger.besu.plugin.services.metrics.Counter; +import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; +import org.hyperledger.besu.plugin.services.metrics.OperationTimer; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbSegmentIdentifier; @@ -33,13 +45,21 @@ import java.util.Optional; import java.util.Set; import java.util.function.Consumer; +import java.util.function.LongSupplier; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; public abstract class RocksDBColumnarKeyValueStorageTest extends AbstractKeyValueStorageTest { + @Mock private ObservableMetricsSystem metricsSystemMock; + @Mock private LabelledMetric labelledMetricOperationTimerMock; + @Mock private LabelledMetric labelledMetricCounterMock; + @Mock private OperationTimer operationTimerMock; + @TempDir public Path folder; @Test @@ -257,6 +277,80 @@ public void dbWillBeBackwardIncompatibleAfterExperimentalSegmentsAreAdded( } } + @Test + public void createStoreMustCreateMetrics() throws Exception { + // Prepare mocks + when(labelledMetricOperationTimerMock.labels(any())).thenReturn(operationTimerMock); + when(metricsSystemMock.createLabelledTimer( + eq(BesuMetricCategory.KVSTORE_ROCKSDB), anyString(), anyString(), any())) + .thenReturn(labelledMetricOperationTimerMock); + when(metricsSystemMock.createLabelledCounter( + eq(BesuMetricCategory.KVSTORE_ROCKSDB), anyString(), anyString(), any())) + .thenReturn(labelledMetricCounterMock); + // Prepare argument captors + final ArgumentCaptor labelledTimersMetricsNameArgs = + ArgumentCaptor.forClass(String.class); + final ArgumentCaptor labelledTimersHelpArgs = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor labelledCountersMetricsNameArgs = + ArgumentCaptor.forClass(String.class); + final ArgumentCaptor labelledCountersHelpArgs = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor longGaugesMetricsNameArgs = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor longGaugesHelpArgs = ArgumentCaptor.forClass(String.class); + + // Actual call + + final SegmentedKeyValueStorage store = + createSegmentedStore( + folder, metricsSystemMock, List.of(TestSegment.FOO), List.of(TestSegment.EXPERIMENTAL)); + + KeyValueStorage keyValueStorage = + new SnappableSegmentedKeyValueStorageAdapter<>(TestSegment.FOO, store); + + // Assertions + assertThat(keyValueStorage).isNotNull(); + verify(metricsSystemMock, times(4)) + .createLabelledTimer( + eq(BesuMetricCategory.KVSTORE_ROCKSDB), + labelledTimersMetricsNameArgs.capture(), + labelledTimersHelpArgs.capture(), + any()); + assertThat(labelledTimersMetricsNameArgs.getAllValues()) + .containsExactly( + "read_latency_seconds", + "remove_latency_seconds", + "write_latency_seconds", + "commit_latency_seconds"); + assertThat(labelledTimersHelpArgs.getAllValues()) + .containsExactly( + "Latency for read from RocksDB.", + "Latency of remove requests from RocksDB.", + "Latency for write to RocksDB.", + "Latency for commits to RocksDB."); + + verify(metricsSystemMock, times(2)) + .createLongGauge( + eq(BesuMetricCategory.KVSTORE_ROCKSDB), + longGaugesMetricsNameArgs.capture(), + longGaugesHelpArgs.capture(), + any(LongSupplier.class)); + assertThat(longGaugesMetricsNameArgs.getAllValues()) + .containsExactly("rocks_db_table_readers_memory_bytes", "rocks_db_files_size_bytes"); + assertThat(longGaugesHelpArgs.getAllValues()) + .containsExactly( + "Estimated memory used for RocksDB index and filter blocks in bytes", + "Estimated database size in bytes"); + + verify(metricsSystemMock) + .createLabelledCounter( + eq(BesuMetricCategory.KVSTORE_ROCKSDB), + labelledCountersMetricsNameArgs.capture(), + labelledCountersHelpArgs.capture(), + any()); + assertThat(labelledCountersMetricsNameArgs.getValue()).isEqualTo("rollback_count"); + assertThat(labelledCountersHelpArgs.getValue()) + .isEqualTo("Number of RocksDB transactions rolled back."); + } + public enum TestSegment implements SegmentIdentifier { FOO(new byte[] {1}), BAR(new byte[] {2}), @@ -302,6 +396,12 @@ protected abstract SegmentedKeyValueStorage createSegm final List segments, final List ignorableSegments); + protected abstract SegmentedKeyValueStorage createSegmentedStore( + final Path path, + final MetricsSystem metricsSystem, + final List segments, + final List ignorableSegments); + @Override protected KeyValueStorage createStore() throws Exception { return new SnappableSegmentedKeyValueStorageAdapter<>(TestSegment.FOO, createSegmentedStore()); diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBKeyValueStorageTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBKeyValueStorageTest.java deleted file mode 100644 index 78968873ecf..00000000000 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBKeyValueStorageTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright Hyperledger Besu Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.plugin.services.storage.rocksdb.segmented; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.hyperledger.besu.kvstore.AbstractKeyValueStorageTest; -import org.hyperledger.besu.metrics.BesuMetricCategory; -import org.hyperledger.besu.metrics.ObservableMetricsSystem; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.services.metrics.Counter; -import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; -import org.hyperledger.besu.plugin.services.metrics.OperationTimer; -import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; -import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration; -import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder; -import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage; - -import java.nio.file.Path; -import java.util.function.LongSupplier; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.io.TempDir; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class RocksDBKeyValueStorageTest extends AbstractKeyValueStorageTest { - - @Mock private ObservableMetricsSystem metricsSystemMock; - @Mock private LabelledMetric labelledMetricOperationTimerMock; - @Mock private LabelledMetric labelledMetricCounterMock; - @Mock private OperationTimer operationTimerMock; - @TempDir static Path folder; - - @Override - protected KeyValueStorage createStore() throws Exception { - return new RocksDBKeyValueStorage( - config(), new NoOpMetricsSystem(), RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); - } - - @Test - public void createStoreMustCreateMetrics() throws Exception { - // Prepare mocks - when(labelledMetricOperationTimerMock.labels(any())).thenReturn(operationTimerMock); - when(metricsSystemMock.createLabelledTimer( - eq(BesuMetricCategory.KVSTORE_ROCKSDB), anyString(), anyString(), any())) - .thenReturn(labelledMetricOperationTimerMock); - when(metricsSystemMock.createLabelledCounter( - eq(BesuMetricCategory.KVSTORE_ROCKSDB), anyString(), anyString(), any())) - .thenReturn(labelledMetricCounterMock); - // Prepare argument captors - final ArgumentCaptor labelledTimersMetricsNameArgs = - ArgumentCaptor.forClass(String.class); - final ArgumentCaptor labelledTimersHelpArgs = ArgumentCaptor.forClass(String.class); - final ArgumentCaptor labelledCountersMetricsNameArgs = - ArgumentCaptor.forClass(String.class); - final ArgumentCaptor labelledCountersHelpArgs = ArgumentCaptor.forClass(String.class); - final ArgumentCaptor longGaugesMetricsNameArgs = ArgumentCaptor.forClass(String.class); - final ArgumentCaptor longGaugesHelpArgs = ArgumentCaptor.forClass(String.class); - - // Actual call - final KeyValueStorage keyValueStorage = - new RocksDBKeyValueStorage( - config(), metricsSystemMock, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); - - // Assertions - assertThat(keyValueStorage).isNotNull(); - verify(metricsSystemMock, times(4)) - .createLabelledTimer( - eq(BesuMetricCategory.KVSTORE_ROCKSDB), - labelledTimersMetricsNameArgs.capture(), - labelledTimersHelpArgs.capture(), - any()); - assertThat(labelledTimersMetricsNameArgs.getAllValues()) - .containsExactly( - "read_latency_seconds", - "remove_latency_seconds", - "write_latency_seconds", - "commit_latency_seconds"); - assertThat(labelledTimersHelpArgs.getAllValues()) - .containsExactly( - "Latency for read from RocksDB.", - "Latency of remove requests from RocksDB.", - "Latency for write to RocksDB.", - "Latency for commits to RocksDB."); - - verify(metricsSystemMock, times(2)) - .createLongGauge( - eq(BesuMetricCategory.KVSTORE_ROCKSDB), - longGaugesMetricsNameArgs.capture(), - longGaugesHelpArgs.capture(), - any(LongSupplier.class)); - assertThat(longGaugesMetricsNameArgs.getAllValues()) - .containsExactly("rocks_db_table_readers_memory_bytes", "rocks_db_files_size_bytes"); - assertThat(longGaugesHelpArgs.getAllValues()) - .containsExactly( - "Estimated memory used for RocksDB index and filter blocks in bytes", - "Estimated database size in bytes"); - - verify(metricsSystemMock) - .createLabelledCounter( - eq(BesuMetricCategory.KVSTORE_ROCKSDB), - labelledCountersMetricsNameArgs.capture(), - labelledCountersHelpArgs.capture(), - any()); - assertThat(labelledCountersMetricsNameArgs.getValue()).isEqualTo("rollback_count"); - assertThat(labelledCountersHelpArgs.getValue()) - .isEqualTo("Number of RocksDB transactions rolled back."); - } - - private RocksDBConfiguration config() throws Exception { - return new RocksDBConfigurationBuilder().databaseDir(getTempSubFolder(folder)).build(); - } -} diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorageTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorageTest.java index d7d4e12da7d..5633de159d8 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorageTest.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorageTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.plugin.services.storage.rocksdb.segmented; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbSegmentIdentifier; @@ -25,6 +26,10 @@ import java.util.Arrays; import java.util.List; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) public class TransactionDBRocksDBColumnarKeyValueStorageTest extends RocksDBColumnarKeyValueStorageTest { @@ -51,4 +56,18 @@ protected SegmentedKeyValueStorage createSegmentedStor new NoOpMetricsSystem(), RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); } + + @Override + protected SegmentedKeyValueStorage createSegmentedStore( + final Path path, + final MetricsSystem metricsSystem, + final List segments, + final List ignorableSegments) { + return new TransactionDBRocksDBColumnarKeyValueStorage( + new RocksDBConfigurationBuilder().databaseDir(path).build(), + segments, + ignorableSegments, + metricsSystem, + RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); + } }