Skip to content

Commit d6ad738

Browse files
authored
refactor(db): unify database engine initialization (#6421)
- Consolidate duplicate engine initialization logic from two separate classes into a single unified method - Enhance LevelDB/RocksDB compatibility detection with clearer error messages - Improve error handling for directory/file creation failures
1 parent b3ffa43 commit d6ad738

File tree

10 files changed

+340
-104
lines changed

10 files changed

+340
-104
lines changed

chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@
1818
import static org.fusesource.leveldbjni.JniDBFactory.factory;
1919

2020
import com.google.common.annotations.VisibleForTesting;
21-
import com.google.common.base.Strings;
2221
import com.google.common.collect.Sets;
2322
import com.google.common.primitives.Bytes;
24-
import java.io.File;
2523
import java.io.IOException;
2624
import java.nio.file.Files;
2725
import java.nio.file.Path;
@@ -53,7 +51,6 @@
5351
import org.tron.common.storage.WriteOptionsWrapper;
5452
import org.tron.common.storage.metric.DbStat;
5553
import org.tron.common.utils.FileUtil;
56-
import org.tron.common.utils.PropUtil;
5754
import org.tron.common.utils.StorageUtils;
5855
import org.tron.core.db.common.DbSourceInter;
5956
import org.tron.core.db.common.iterator.StoreIterator;
@@ -73,9 +70,7 @@ public class LevelDbDataSourceImpl extends DbStat implements DbSourceInter<byte[
7370
private Options options;
7471
private WriteOptions writeOptions;
7572
private ReadWriteLock resetDbLock = new ReentrantReadWriteLock();
76-
private static final String LEVELDB = "LEVELDB";
7773
private static final org.slf4j.Logger innerLogger = LoggerFactory.getLogger(LEVELDB);
78-
private static final String KEY_ENGINE = "ENGINE";
7974
private Logger leveldbLogger = new Logger() {
8075
@Override
8176
public void log(String message) {
@@ -111,11 +106,6 @@ public LevelDbDataSourceImpl(String parentPath, String dataBaseName) {
111106

112107
@Override
113108
public void initDB() {
114-
if (!checkOrInitEngine()) {
115-
throw new RuntimeException(String.format(
116-
"Cannot open RocksDB database '%s' with LevelDB engine."
117-
+ " Set db.engine=ROCKSDB or use LevelDB database. ", dataBaseName));
118-
}
119109
resetDbLock.writeLock().lock();
120110
try {
121111
logger.debug("Init DB: {}.", dataBaseName);
@@ -141,28 +131,6 @@ public void initDB() {
141131
}
142132
}
143133

144-
private boolean checkOrInitEngine() {
145-
String dir = getDbPath().toString();
146-
String enginePath = dir + File.separator + "engine.properties";
147-
148-
if (FileUtil.createDirIfNotExists(dir)) {
149-
if (!FileUtil.createFileIfNotExists(enginePath)) {
150-
return false;
151-
}
152-
} else {
153-
return false;
154-
}
155-
156-
// for the first init engine
157-
String engine = PropUtil.readProperty(enginePath, KEY_ENGINE);
158-
if (Strings.isNullOrEmpty(engine) && !PropUtil.writeProperty(enginePath, KEY_ENGINE, LEVELDB)) {
159-
return false;
160-
}
161-
engine = PropUtil.readProperty(enginePath, KEY_ENGINE);
162-
163-
return LEVELDB.equals(engine);
164-
}
165-
166134
private void openDatabase(Options dbOptions) throws IOException {
167135
final Path dbPath = getDbPath();
168136
if (dbPath == null || dbPath.getParent() == null) {
@@ -172,6 +140,8 @@ private void openDatabase(Options dbOptions) throws IOException {
172140
Files.createDirectories(dbPath.getParent());
173141
}
174142
try {
143+
DbSourceInter.checkOrInitEngine(getEngine(), dbPath.toString(),
144+
TronError.ErrCode.LEVELDB_INIT);
175145
database = factory.open(dbPath.toFile(), dbOptions);
176146
if (!this.getDBName().startsWith("checkpoint")) {
177147
logger

chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.tron.common.storage.rocksdb;
22

33
import com.google.common.annotations.VisibleForTesting;
4-
import com.google.common.base.Strings;
54
import com.google.common.collect.Sets;
65
import com.google.common.primitives.Bytes;
76
import java.io.File;
@@ -39,7 +38,6 @@
3938
import org.tron.common.storage.WriteOptionsWrapper;
4039
import org.tron.common.storage.metric.DbStat;
4140
import org.tron.common.utils.FileUtil;
42-
import org.tron.common.utils.PropUtil;
4341
import org.tron.core.db.common.DbSourceInter;
4442
import org.tron.core.db.common.iterator.RockStoreIterator;
4543
import org.tron.core.db2.common.Instance;
@@ -58,8 +56,6 @@ public class RocksDbDataSourceImpl extends DbStat implements DbSourceInter<byte[
5856
private volatile boolean alive;
5957
private String parentPath;
6058
private ReadWriteLock resetDbLock = new ReentrantReadWriteLock();
61-
private static final String KEY_ENGINE = "ENGINE";
62-
private static final String ROCKSDB = "ROCKSDB";
6359
private static final org.slf4j.Logger rocksDbLogger = LoggerFactory.getLogger(ROCKSDB);
6460

6561
public RocksDbDataSourceImpl(String parentPath, String name, Options options) {
@@ -187,39 +183,7 @@ public void setDBName(String name) {
187183
this.dataBaseName = name;
188184
}
189185

190-
public boolean checkOrInitEngine() {
191-
String dir = getDbPath().toString();
192-
String enginePath = dir + File.separator + "engine.properties";
193-
File currentFile = new File(dir, "CURRENT");
194-
if (currentFile.exists() && !Paths.get(enginePath).toFile().exists()) {
195-
// if the CURRENT file exists, but the engine.properties file does not exist, it is LevelDB
196-
logger.error(" You are trying to open a LevelDB database with RocksDB engine.");
197-
return false;
198-
}
199-
if (FileUtil.createDirIfNotExists(dir)) {
200-
if (!FileUtil.createFileIfNotExists(enginePath)) {
201-
return false;
202-
}
203-
} else {
204-
return false;
205-
}
206-
207-
// for the first init engine
208-
String engine = PropUtil.readProperty(enginePath, KEY_ENGINE);
209-
if (Strings.isNullOrEmpty(engine) && !PropUtil.writeProperty(enginePath, KEY_ENGINE, ROCKSDB)) {
210-
return false;
211-
}
212-
engine = PropUtil.readProperty(enginePath, KEY_ENGINE);
213-
214-
return ROCKSDB.equals(engine);
215-
}
216-
217186
public void initDB() {
218-
if (!checkOrInitEngine()) {
219-
throw new RuntimeException(String.format(
220-
"Cannot open LevelDB database '%s' with RocksDB engine."
221-
+ " Set db.engine=LEVELDB or use RocksDB database. ", dataBaseName));
222-
}
223187
resetDbLock.writeLock().lock();
224188
try {
225189
if (isAlive()) {
@@ -244,6 +208,8 @@ protected void log(InfoLogLevel infoLogLevel, String logMsg) {
244208
}
245209

246210
try {
211+
DbSourceInter.checkOrInitEngine(getEngine(), dbPath.toString(),
212+
TronError.ErrCode.ROCKSDB_INIT);
247213
database = RocksDB.open(options, dbPath.toString());
248214
} catch (RocksDBException e) {
249215
if (Objects.equals(e.getStatus().getCode(), Status.Code.Corruption)) {

chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,28 @@
1515
* You should have received a copy of the GNU Lesser General Public License
1616
* along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>.
1717
*/
18+
1819
package org.tron.core.db.common;
1920

2021
import com.google.common.annotations.VisibleForTesting;
22+
import com.google.common.base.Strings;
23+
import java.io.File;
24+
import java.nio.file.Paths;
2125
import java.util.Map;
2226
import java.util.Set;
27+
import org.tron.common.utils.FileUtil;
28+
import org.tron.common.utils.PropUtil;
2329
import org.tron.core.db2.common.WrappedByteArray;
30+
import org.tron.core.exception.TronError;
2431

2532
public interface DbSourceInter<V> extends BatchSourceInter<byte[], V>,
2633
Iterable<Map.Entry<byte[], V>> {
2734

35+
String ENGINE_KEY = "ENGINE";
36+
String ENGINE_FILE = "engine.properties";
37+
String ROCKSDB = "ROCKSDB";
38+
String LEVELDB = "LEVELDB";
39+
2840
String getDBName();
2941

3042
void setDBName(String name);
@@ -53,4 +65,34 @@ public interface DbSourceInter<V> extends BatchSourceInter<byte[], V>,
5365

5466
Map<WrappedByteArray, byte[]> prefixQuery(byte[] key);
5567

68+
static void checkOrInitEngine(String expectedEngine, String dir, TronError.ErrCode errCode) {
69+
String engineFile = Paths.get(dir, ENGINE_FILE).toString();
70+
File currentFile = new File(dir, "CURRENT");
71+
if (ROCKSDB.equals(expectedEngine) && currentFile.exists()
72+
&& !Paths.get(engineFile).toFile().exists()) {
73+
// if the CURRENT file exists, but the engine.properties file does not exist, it is LevelDB
74+
// 000003.log CURRENT LOCK MANIFEST-000002
75+
throw new TronError(
76+
String.format("Cannot open %s database with %s engine.", LEVELDB, ROCKSDB), errCode);
77+
}
78+
if (FileUtil.createDirIfNotExists(dir)) {
79+
if (!FileUtil.createFileIfNotExists(engineFile)) {
80+
throw new TronError(String.format("Cannot create file: %s.", engineFile), errCode);
81+
}
82+
} else {
83+
throw new TronError(String.format("Cannot create dir: %s.", dir), errCode);
84+
}
85+
String actualEngine = PropUtil.readProperty(engineFile, ENGINE_KEY);
86+
// engine init
87+
if (Strings.isNullOrEmpty(actualEngine)
88+
&& !PropUtil.writeProperty(engineFile, ENGINE_KEY, expectedEngine)) {
89+
throw new TronError(String.format("Cannot write file: %s.", engineFile), errCode);
90+
}
91+
actualEngine = PropUtil.readProperty(engineFile, ENGINE_KEY);
92+
if (!expectedEngine.equals(actualEngine)) {
93+
throw new TronError(String.format(
94+
"Cannot open %s database with %s engine.",
95+
actualEngine, expectedEngine), errCode);
96+
}
97+
}
5698
}

framework/src/main/java/org/tron/core/config/args/Args.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ private static Map<String, String[]> getOptionGroup() {
372372
* set parameters.
373373
*/
374374
public static void setParam(final String[] args, final String confFileName) {
375-
Arch.throwUnsupportedJavaException();
375+
Arch.throwIfUnsupportedJavaVersion();
376376
clearParam(); // reset all parameters to avoid the influence in test
377377
JCommander.newBuilder().addObject(PARAMETER).build().parse(args);
378378
if (PARAMETER.version) {

0 commit comments

Comments
 (0)