Skip to content

Commit

Permalink
Merge pull request #1874 from rsksmart/fix-rocksdb-startup
Browse files Browse the repository at this point in the history
Fix node startup when database dir folder is empty
  • Loading branch information
Vovchyk authored Sep 20, 2022
2 parents c3c9f25 + 70a3d1e commit 159d59d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 39 deletions.
2 changes: 2 additions & 0 deletions rskj-core/src/main/java/co/rsk/RskContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ public synchronized NodeRunner getNodeRunner() {
FileUtil.recursiveDelete(rskSystemProperties.databaseDir());
}

KeyValueDataSource.validateDbKind(rskSystemProperties.databaseKind(), rskSystemProperties.databaseDir(), rskSystemProperties.databaseReset() || rskSystemProperties.importEnabled());

if (rskSystemProperties.importEnabled()) {
getBootstrapImporter().importData();
}
Expand Down
5 changes: 0 additions & 5 deletions rskj-core/src/main/java/co/rsk/Start.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
*/
package co.rsk;

import co.rsk.config.RskSystemProperties;
import co.rsk.util.PreflightChecksUtils;
import org.ethereum.datasource.KeyValueDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -39,9 +37,6 @@ public static void main(String[] args) {
try {
ctx = new RskContext(args);

RskSystemProperties rskSystemProperties = ctx.getRskSystemProperties();
KeyValueDataSource.validateDbKind(rskSystemProperties.databaseKind(), rskSystemProperties.databaseDir(), rskSystemProperties.databaseReset() || rskSystemProperties.importEnabled());

runNode(Runtime.getRuntime(), new PreflightChecksUtils(ctx), ctx);
} catch (Exception e) {
logger.error("The RSK node main thread failed, closing program", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
public interface KeyValueDataSource extends DataSource {
String DB_KIND_PROPERTIES_FILE = "dbKind.properties";
String KEYVALUE_DATASOURCE_PROP_NAME = "keyvalue.datasource";
String KEYVALUE_DATASOURCE = "KeyValueDataSource";

@Nullable
byte[] get(byte[] key);
Expand Down Expand Up @@ -129,7 +130,7 @@ static void generatedDbKindFile(DbKind dbKind, String databaseDir) {
try (FileWriter writer = new FileWriter(file)) {
props.store(writer, "Generated dbKind. In order to follow selected db.");

LoggerFactory.getLogger("KeyValueDataSource").info("Generated dbKind.properties file.");
LoggerFactory.getLogger(KEYVALUE_DATASOURCE).info("Generated dbKind.properties file.");
}
} catch (IOException e) {
throw new RuntimeException(e);
Expand All @@ -138,9 +139,15 @@ static void generatedDbKindFile(DbKind dbKind, String databaseDir) {

static void validateDbKind(DbKind currentDbKind, String databaseDir, boolean databaseReset) {
File dir = new File(databaseDir);

if (dir.exists() && !dir.isDirectory()) {
LoggerFactory.getLogger(KEYVALUE_DATASOURCE).error("database.dir should be a folder.");
throw new IllegalStateException("database.dir should be a folder");
}

boolean databaseDirExists = dir.exists() && dir.isDirectory();

if (!databaseDirExists) {
if (!databaseDirExists || dir.list().length == 0) {
KeyValueDataSource.generatedDbKindFile(currentDbKind, databaseDir);
return;
}
Expand All @@ -151,7 +158,7 @@ static void validateDbKind(DbKind currentDbKind, String databaseDir, boolean dat
if (databaseReset) {
KeyValueDataSource.generatedDbKindFile(currentDbKind, databaseDir);
} else {
LoggerFactory.getLogger("KeyValueDataSource").warn("Use the flag --reset when running the application if you are using a different datasource. Also you can use the cli tool DbMigrate, in order to migrate data between databases.");
LoggerFactory.getLogger(KEYVALUE_DATASOURCE).warn("Use the flag --reset when running the application if you are using a different datasource. Also you can use the cli tool DbMigrate, in order to migrate data between databases.");
throw new IllegalStateException("DbKind mismatch. You have selected " + currentDbKind.name() + " when the previous detected DbKind was " + prevDbKind.name() + ".");
}
}
Expand Down
30 changes: 0 additions & 30 deletions rskj-core/src/test/java/co/rsk/cli/tools/CliToolsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -518,36 +518,6 @@ public void dbMigrate() throws IOException {
Assert.assertEquals(dbKindPropsFileLine, "keyvalue.datasource=ROCKS_DB");
}

@Test
public void dbMigrateThrowsExceptionBecauseMigratingToSameDb() throws IOException {
File dbKindPropsFile = new File(tempFolder.getRoot(), KeyValueDataSource.DB_KIND_PROPERTIES_FILE);

RskContext rskContext = mock(RskContext.class);
RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class);

doReturn(DbKind.LEVEL_DB).when(rskSystemProperties).databaseKind();
doReturn(tempFolder.getRoot().getPath()).when(rskSystemProperties).databaseDir();
doReturn(true).when(rskSystemProperties).databaseReset();
doReturn(rskSystemProperties).when(rskContext).getRskSystemProperties();

NodeStopper stopper = mock(NodeStopper.class);

DbMigrate dbMigrateCliTool = new DbMigrate();
dbMigrateCliTool.execute(new String[]{"leveldb"}, () -> rskContext, stopper);

String dbKindPropsFileLine = null;

if (dbKindPropsFile.exists()) {
BufferedReader reader = new BufferedReader(new FileReader(dbKindPropsFile));
reader.readLine();
reader.readLine();
dbKindPropsFileLine = reader.readLine();
reader.close();
}

Assert.assertNull(dbKindPropsFileLine);
}

@Test
public void startBootstrap() throws Exception {
// check thread setup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import co.rsk.rpc.ModuleDescription;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.ethereum.datasource;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class NotParameterizedKeyValueDataSourceTest {

@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();

@Test
public void testShouldValidateKindWithEmptyDbDirAndResetDbFalseSuccessfully() {
KeyValueDataSource.validateDbKind(DbKind.ROCKS_DB, tempFolder.getRoot().getPath(), false);
}

@Test(expected = IllegalStateException.class)
public void testShouldThrowErrorWhenValidatingDifferentKinds() throws IOException {
FileWriter fileWriter = new FileWriter(new File(tempFolder.getRoot(), KeyValueDataSource.DB_KIND_PROPERTIES_FILE));
fileWriter.write("keyvalue.datasource=ROCKS_DB\n");
fileWriter.close();
KeyValueDataSource.validateDbKind(DbKind.LEVEL_DB, tempFolder.getRoot().getPath(), false);
}

@Test(expected = IllegalStateException.class)
public void testShouldThrowErrorWhenDbDirIsAFile() throws IOException {
File file = new File(tempFolder.getRoot(), KeyValueDataSource.DB_KIND_PROPERTIES_FILE);
FileWriter fileWriter = new FileWriter(file);
fileWriter.write("keyvalue.datasource=ROCKS_DB\n");
fileWriter.close();
KeyValueDataSource.validateDbKind(DbKind.LEVEL_DB, file.getPath(), false);
}
}

0 comments on commit 159d59d

Please sign in to comment.