Skip to content

Commit

Permalink
fix(LiteTool): fix data inconsistency of snapshot generation in the c…
Browse files Browse the repository at this point in the history
…rash scenario
  • Loading branch information
tomatoishealthy committed Jan 26, 2024
1 parent cbf2417 commit d67eef9
Showing 1 changed file with 27 additions and 41 deletions.
68 changes: 27 additions & 41 deletions plugins/src/main/java/org/tron/plugins/DbLite.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
Expand Down Expand Up @@ -353,28 +354,12 @@ private void generateInfoProperties(String propertyfile, long num)
}

private long getLatestBlockHeaderNum(String databaseDir) throws IOException, RocksDBException {
// query latest_block_header_number from checkpoint first
final String latestBlockHeaderNumber = "latest_block_header_number";
DBInterface checkpointDb = getCheckpointDb(databaseDir);
Long blockNumber = getLatestBlockHeaderNumFromCP(checkpointDb,
latestBlockHeaderNumber.getBytes());
if (blockNumber != null) {
return blockNumber;
}
// query from propertiesDb if checkpoint not contains latest_block_header_number
DBInterface propertiesDb = DbTool.getDB(databaseDir, PROPERTIES_DB_NAME);
return Optional.ofNullable(propertiesDb.get(ByteArray.fromString(latestBlockHeaderNumber)))
.map(ByteArray::toLong)
.orElseThrow(
() -> new IllegalArgumentException("not found latest block header number"));
}

private Long getLatestBlockHeaderNumFromCP(DBInterface db, byte[] key) {
byte[] value = db.get(Bytes.concat(simpleEncode(PROPERTIES_DB_NAME), key));
if (value != null && value.length > 1) {
return ByteArray.toLong(Arrays.copyOfRange(value, 1, value.length));
}
return null;
final byte[] latestBlockHeaderNumber = "latest_block_header_number".getBytes();
byte[] value = getDataFromSourceDB(databaseDir, PROPERTIES_DB_NAME, latestBlockHeaderNumber);
return Optional.ofNullable(value)
.map(ByteArray::toLong)
.orElseThrow(
() -> new IllegalArgumentException("not found latest block header number"));
}

/**
Expand Down Expand Up @@ -585,16 +570,30 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws

private byte[] getDataFromSourceDB(String sourceDir, String dbName, byte[] key)
throws IOException, RocksDBException {
byte[] keyInCp = Bytes.concat(simpleEncode(dbName), key);
byte[] valueInCp = null;
DBInterface sourceDb = DbTool.getDB(sourceDir, dbName);
DBInterface checkpointDb = getCheckpointDb(sourceDir);
// get data from tmp first.
byte[] valueFromTmp = checkpointDb.get(Bytes.concat(simpleEncode(dbName), key));
// get data from checkpoint first.
List<String> cpList = getCheckpointV2List(sourceDir);
if (cpList.size() > 0) {
// reverse iteration
Collections.reverse(cpList);
for (String cp: cpList) {
valueInCp = DbTool.getDB(
sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, cp).get(keyInCp);
if (!isEmptyBytes(valueInCp)) {
break;
}
}
} else {
valueInCp = DbTool.getDB(sourceDir, CHECKPOINT_DB).get(keyInCp);
}
byte[] value;
if (isEmptyBytes(valueFromTmp)) {
if (isEmptyBytes(valueInCp)) {
value = sourceDb.get(key);
} else {
value = valueFromTmp.length == 1
? null : Arrays.copyOfRange(valueFromTmp, 1, valueFromTmp.length);
value = valueInCp.length == 1
? null : Arrays.copyOfRange(valueInCp, 1, valueInCp.length);
}
if (isEmptyBytes(value)) {
throw new RuntimeException(String.format("data not found in store, dbName: %s, key: %s",
Expand Down Expand Up @@ -664,19 +663,6 @@ private long getSecondBlock(String databaseDir) throws RocksDBException, IOExcep
return num;
}

private DBInterface getCheckpointDb(String sourceDir) throws IOException, RocksDBException {
List<String> cpList = getCheckpointV2List(sourceDir);
DBInterface checkpointDb;
if (cpList.size() > 0) {
String latestCp = cpList.get(cpList.size() - 1);
checkpointDb = DbTool.getDB(
sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, latestCp);
} else {
checkpointDb = DbTool.getDB(sourceDir, CHECKPOINT_DB);
}
return checkpointDb;
}

@VisibleForTesting
public static void setRecentBlks(long recentBlks) {
RECENT_BLKS = recentBlks;
Expand Down

0 comments on commit d67eef9

Please sign in to comment.