remove v0 version of the database (#5698)

Signed-off-by: Karim TAAM <karim.t2am@gmail.com>
pull/5701/head
matkt 1 year ago committed by GitHub
parent 86b2b600a0
commit 9f42a3f261
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 10
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java
  3. 10
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java
  4. BIN
      acceptance-tests/tests/src/test/resources/org/hyperledger/besu/tests/acceptance/database/version0/besu-db-archive.tar.gz
  5. 15
      ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java
  6. 4
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactory.java
  7. 19
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java
  8. 2
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/DatabaseMetadata.java
  9. 223
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java
  10. 112
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBTransaction.java
  11. 7
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactoryTest.java
  12. 8
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java
  13. 18
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest.java
  14. 100
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java
  15. 136
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBKeyValueStorageTest.java
  16. 19
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorageTest.java

@ -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)

@ -80,16 +80,6 @@ public class BackupRoundTripAcceptanceTest extends AbstractPreexistingNodeTest {
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",

@ -56,16 +56,6 @@ public class 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",

@ -24,16 +24,19 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
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 @@ public class 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();

@ -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<Integer> SUPPORTED_VERSIONS = Set.of(0, 1);
private static final Set<Integer> SUPPORTED_VERSIONS = Set.of(1);
private static final String PRIVATE_DATABASE_PATH = "private";
private final RocksDBKeyValueStorageFactory publicFactory;
@ -96,7 +96,7 @@ public class RocksDBKeyValuePrivacyStorageFactory implements PrivacyKeyValueStor
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 {

@ -30,7 +30,6 @@ import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksD
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<Integer> SUPPORTED_VERSIONS = Set.of(0, 1, 2);
private static final Set<Integer> 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<RocksDBFactoryConfiguration> configuration;
@ -163,17 +161,7 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
// 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<SegmentIdentifier> segmentsForVersion =
segments.stream()
@ -249,7 +237,7 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
}
private boolean requiresInit() {
return segmentedStorage == null && unsegmentedStorage == null;
return segmentedStorage == null;
}
private int readDatabaseVersion(final BesuConfiguration commonConfiguration) throws IOException {
@ -283,9 +271,6 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
@Override
public void close() throws IOException {
if (unsegmentedStorage != null) {
unsegmentedStorage.close();
}
if (segmentedStorage != null) {
segmentedStorage.close();
}

@ -151,7 +151,7 @@ public class DatabaseMetadata {
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);

@ -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<byte[]> 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<byte[]> getAllKeysThat(final Predicate<byte[]> returnCondition) {
return stream()
.filter(pair -> returnCondition.test(pair.getKey()))
.map(Pair::getKey)
.collect(toUnmodifiableSet());
}
@Override
public Stream<Pair<byte[], byte[]>> stream() {
throwIfClosed();
final RocksIterator rocksIterator = db.newIterator();
rocksIterator.seekToFirst();
return RocksDbIterator.create(rocksIterator).toStream();
}
@Override
public Stream<Pair<byte[], byte[]>> streamFromKey(final byte[] startKey) {
return stream().filter(e -> Bytes.wrap(startKey).compareTo(Bytes.wrap(e.getKey())) <= 0);
}
@Override
public Stream<byte[]> streamKeys() {
throwIfClosed();
final RocksIterator rocksIterator = db.newIterator();
rocksIterator.seekToFirst();
return RocksDbIterator.create(rocksIterator).toStreamKeys();
}
@Override
public Set<byte[]> getAllValuesFromKeysThat(final Predicate<byte[]> 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");
}
}
}

@ -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();
}
}

@ -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 class RocksDBKeyValuePrivacyStorageFactoryTest {
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

@ -71,7 +71,7 @@ public class RocksDBKeyValueStorageFactoryTest {
}
@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 class RocksDBKeyValueStorageFactoryTest {
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 class RocksDBKeyValueStorageFactoryTest {
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);
}

@ -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.Arrays;
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 @@ public class OptimisticTransactionDBRocksDBColumnarKeyValueStorageTest
new NoOpMetricsSystem(),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
}
@Override
protected SegmentedKeyValueStorage<RocksDbSegmentIdentifier> createSegmentedStore(
final Path path,
final MetricsSystem metricsSystem,
final List<SegmentIdentifier> segments,
final List<SegmentIdentifier> ignorableSegments) {
return new OptimisticRocksDBColumnarKeyValueStorage(
new RocksDBConfigurationBuilder().databaseDir(path).build(),
segments,
ignorableSegments,
metricsSystem,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
}
}

@ -16,9 +16,21 @@ package org.hyperledger.besu.plugin.services.storage.rocksdb.segmented;
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.List;
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<OperationTimer> labelledMetricOperationTimerMock;
@Mock private LabelledMetric<Counter> labelledMetricCounterMock;
@Mock private OperationTimer operationTimerMock;
@TempDir public Path folder;
@Test
@ -257,6 +277,80 @@ public abstract class RocksDBColumnarKeyValueStorageTest extends AbstractKeyValu
}
}
@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<String> labelledTimersMetricsNameArgs =
ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> labelledTimersHelpArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> labelledCountersMetricsNameArgs =
ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> labelledCountersHelpArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> longGaugesMetricsNameArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> longGaugesHelpArgs = ArgumentCaptor.forClass(String.class);
// Actual call
final SegmentedKeyValueStorage<RocksDbSegmentIdentifier> 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 @@ public abstract class RocksDBColumnarKeyValueStorageTest extends AbstractKeyValu
final List<SegmentIdentifier> segments,
final List<SegmentIdentifier> ignorableSegments);
protected abstract SegmentedKeyValueStorage<RocksDbSegmentIdentifier> createSegmentedStore(
final Path path,
final MetricsSystem metricsSystem,
final List<SegmentIdentifier> segments,
final List<SegmentIdentifier> ignorableSegments);
@Override
protected KeyValueStorage createStore() throws Exception {
return new SnappableSegmentedKeyValueStorageAdapter<>(TestSegment.FOO, createSegmentedStore());

@ -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<OperationTimer> labelledMetricOperationTimerMock;
@Mock private LabelledMetric<Counter> 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<String> labelledTimersMetricsNameArgs =
ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> labelledTimersHelpArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> labelledCountersMetricsNameArgs =
ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> labelledCountersHelpArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> longGaugesMetricsNameArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> 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();
}
}

@ -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.nio.file.Path;
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 @@ public class TransactionDBRocksDBColumnarKeyValueStorageTest
new NoOpMetricsSystem(),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
}
@Override
protected SegmentedKeyValueStorage<RocksDbSegmentIdentifier> createSegmentedStore(
final Path path,
final MetricsSystem metricsSystem,
final List<SegmentIdentifier> segments,
final List<SegmentIdentifier> ignorableSegments) {
return new TransactionDBRocksDBColumnarKeyValueStorage(
new RocksDBConfigurationBuilder().databaseDir(path).build(),
segments,
ignorableSegments,
metricsSystem,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
}
}

Loading…
Cancel
Save