Skip to content

Commit

Permalink
[MINOR] Detect DB version mismatch on Startup and gracefully exit hyp…
Browse files Browse the repository at this point in the history
…erledger#6511 (hyperledger#6513)

* Halt besu if database mismatches configuration

Signed-off-by: Gabriel-Trintinalia <[email protected]>

---------

Signed-off-by: Gabriel-Trintinalia <[email protected]>
Co-authored-by: Sally MacFarlane <[email protected]>
  • Loading branch information
Gabriel-Trintinalia and macfarla authored Feb 4, 2024
1 parent 03dd7f1 commit a64ad2b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ private int readDatabaseVersion(final BesuConfiguration commonConfiguration) thr
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public void shouldDetectVersion1DatabaseIfNoMetadataFileFound() throws Exception
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);

final RocksDBKeyValuePrivacyStorageFactory storageFactory =
new RocksDBKeyValuePrivacyStorageFactory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -70,14 +68,19 @@ public void shouldCreateCorrectMetadataFileForLatestVersion() throws Exception {
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(
Expand All @@ -93,9 +96,7 @@ public void shouldDetectCorrectVersionIfMetadataFileExists() throws Exception {
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(
Expand All @@ -113,8 +114,7 @@ public void shouldDetectCorrectVersionInCaseOfRollback() throws Exception {
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(
Expand All @@ -135,8 +135,8 @@ public void shouldThrowExceptionWhenVersionNumberIsInvalid() throws Exception {
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(
() ->
Expand All @@ -148,14 +148,42 @@ public void shouldThrowExceptionWhenVersionNumberIsInvalid() throws Exception {
.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(
Expand All @@ -170,8 +198,7 @@ public void shouldThrowExceptionWhenMetaDataFileIsCorrupted() throws Exception {
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(
Expand Down Expand Up @@ -206,9 +233,7 @@ public void shouldCreateDBCorrectlyIfSymlink() throws Exception {
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(
Expand Down

0 comments on commit a64ad2b

Please sign in to comment.