From 3daccebc1219b14ec0b41b14536465e5a37eef06 Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Fri, 28 Jul 2023 18:44:23 +0800 Subject: [PATCH 1/2] feat(log): optimize open db log Add suggestion when open db fail. --- .../leveldb/LevelDbDataSourceImpl.java | 21 ++++++++++++++----- .../rocksdb/RocksDbDataSourceImpl.java | 10 +++++++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 2292f974c4b..43a24ff4416 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -142,11 +142,22 @@ private void openDatabase(Options dbOptions) throws IOException { if (!Files.isSymbolicLink(dbPath.getParent())) { Files.createDirectories(dbPath.getParent()); } - database = factory.open(dbPath.toFile(), dbOptions); - if (!this.getDBName().startsWith("checkpoint")) { - logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", - this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, - dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); + try { + database = factory.open(dbPath.toFile(), dbOptions); + if (!this.getDBName().startsWith("checkpoint")) { + logger + .info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", + this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, + dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); + } + } catch (IOException e) { + if (e.getMessage().contains("Corruption:")) { + logger.error("Database {} corrupted, please delete database directory({}) and restart.", + dataBaseName, parentPath, e); + } else { + logger.error("Open Database {} failed", dataBaseName, e); + } + System.exit(1); } } diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index a561ed1fa11..6c5d8018487 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -32,6 +32,7 @@ import org.rocksdb.RocksDBException; import org.rocksdb.RocksIterator; import org.rocksdb.Statistics; +import org.rocksdb.Status; import org.rocksdb.WriteBatch; import org.rocksdb.WriteOptions; import org.slf4j.LoggerFactory; @@ -265,8 +266,13 @@ protected void log(InfoLogLevel infoLogLevel, String logMsg) { try { database = RocksDB.open(options, dbPath.toString()); } catch (RocksDBException e) { - throw new RuntimeException( - String.format("failed to open database: %s", dataBaseName), e); + if (Objects.equals(e.getStatus().getCode(), Status.Code.Corruption)) { + logger.error("Database {} corrupted, please delete database directory({}) " + + "and restart.", dataBaseName, parentPath, e); + } else { + logger.error("Open Database {} failed", dataBaseName, e); + } + System.exit(1); } alive = true; From 6f082a8332ed2dd5990e430161ecc865d0f59fc4 Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Wed, 9 Aug 2023 23:31:02 +0800 Subject: [PATCH 2/2] feat(test): add db test --- framework/build.gradle | 1 + .../leveldb/LevelDbDataSourceImplTest.java | 25 +++++++++++++++++++ .../leveldb/RocksDbDataSourceImplTest.java | 24 ++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/framework/build.gradle b/framework/build.gradle index d3e13ac0a7e..063d320d477 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -43,6 +43,7 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' + testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.16.0' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index eed995f12b5..b4ac2b4aebf 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -37,7 +37,9 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; @@ -65,6 +67,9 @@ public class LevelDbDataSourceImplTest { private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + /** * Release resources. */ @@ -332,4 +337,24 @@ public void prefixQueryTest() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void initDbTest() { + exit.expectSystemExitWithStatus(1); + makeExceptionDb("test_initDb"); + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + } + + private void makeExceptionDb(String dbName) { + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + FileUtil.saveData(dataSource.getDbPath().toString() + "/CURRENT", + "...", Boolean.FALSE); + } + } diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index f0ceb7fcac4..62630014b23 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -20,7 +20,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -48,6 +50,9 @@ public class RocksDbDataSourceImplTest { private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + /** * Release resources. */ @@ -382,4 +387,23 @@ public void prefixQueryTest() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void initDbTest() { + exit.expectSystemExitWithStatus(1); + makeExceptionDb("test_initDb"); + RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + } + + private void makeExceptionDb(String dbName) { + RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + FileUtil.saveData(dataSource.getDbPath().toString() + "/CURRENT", + "...", Boolean.FALSE); + } }