[MINOR] Detect DB version mismatch on Startup and gracefully exit #6511 (#6513)

* Halt besu if database mismatches configuration

Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>

---------

Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/6526/head
Gabriel-Trintinalia 9 months ago committed by GitHub
parent 03dd7f1d1a
commit a64ad2b60d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java
  2. 1
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactoryTest.java
  3. 63
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java

@ -258,6 +258,13 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
final int databaseVersion;
if (databaseExists) {
databaseVersion = DatabaseMetadata.lookUpFrom(dataDir).getVersion();
if (databaseVersion != commonConfiguration.getDatabaseVersion()) {
String error =
String.format(
"Mismatch detected: Database at %s is version '%s', but configuration expects version '%s'.",
dataDir, databaseVersion, commonConfiguration.getDatabaseVersion());
throw new StorageException(error);
}
LOG.info(
"Existing database detected at {}. Version {}. Compacting database...",
dataDir,

@ -56,6 +56,7 @@ public class RocksDBKeyValuePrivacyStorageFactoryTest {
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
final RocksDBKeyValuePrivacyStorageFactory storageFactory =
new RocksDBKeyValuePrivacyStorageFactory(

@ -56,9 +56,7 @@ public class RocksDBKeyValueStorageFactoryTest {
public void shouldCreateCorrectMetadataFileForLatestVersion() throws Exception {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@ -70,14 +68,19 @@ public class RocksDBKeyValueStorageFactoryTest {
assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).getVersion()).isEqualTo(DEFAULT_VERSION);
}
private void mockCommonConfiguration(final Path tempDataDir, final Path tempDatabaseDir) {
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
}
@Test
public void shouldDetectVersion1DatabaseIfNoMetadataFileFound() throws Exception {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@ -93,9 +96,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@ -113,8 +114,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@ -135,8 +135,8 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
new DatabaseMetadata(-1).writeToDirectory(tempDataDir);
assertThatThrownBy(
() ->
@ -148,14 +148,42 @@ public class RocksDBKeyValueStorageFactoryTest {
.isInstanceOf(StorageException.class);
}
@Test
public void shouldThrowExceptionWhenExistingDatabaseVersionDifferentFromConfig()
throws Exception {
final int actualDatabaseVersion = 1;
final int expectedDatabaseVersion = 2;
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(expectedDatabaseVersion);
new DatabaseMetadata(actualDatabaseVersion).writeToDirectory(tempDataDir);
assertThatThrownBy(
() ->
new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration,
segments,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS)
.create(segment, commonConfiguration, metricsSystem))
.isInstanceOf(StorageException.class)
.hasMessage(
String.format(
"Mismatch detected: Database at %s is version '%s', but configuration expects version '%s'.",
tempDataDir.toAbsolutePath(), actualDatabaseVersion, expectedDatabaseVersion));
}
@Test
public void shouldSetSegmentationFieldDuringCreation() throws Exception {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@ -170,8 +198,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final String badVersion = "{\"🦄\":1}";
Files.write(
@ -206,9 +233,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempSymLinkDataDir =
Files.createSymbolicLink(temporaryFolder.resolve("symlink-data-dir"), tempRealDataDir);
final Path tempDatabaseDir = temporaryFolder.resolve("db");
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempSymLinkDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
mockCommonConfiguration(tempSymLinkDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(

Loading…
Cancel
Save