forked from tronprotocol/java-tron
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDbRoot.java
More file actions
121 lines (108 loc) · 4.02 KB
/
DbRoot.java
File metadata and controls
121 lines (108 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package org.tron.plugins;
import com.google.common.collect.Streams;
import com.google.common.primitives.Bytes;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import me.tongfei.progressbar.ProgressBar;
import org.rocksdb.RocksDBException;
import org.tron.plugins.utils.MerkleRoot;
import org.tron.plugins.utils.Sha256Hash;
import org.tron.plugins.utils.db.DBInterface;
import org.tron.plugins.utils.db.DBIterator;
import org.tron.plugins.utils.db.DbTool;
import picocli.CommandLine;
@Slf4j(topic = "db-root")
@CommandLine.Command(name = "root",
description = "compute merkle root for tiny db. NOTE: large db may GC overhead limit exceeded.",
exitCodeListHeading = "Exit Codes:%n",
exitCodeList = {
"0:Successful",
"n:query failed,please check toolkit.log"})
public class DbRoot implements Callable<Integer> {
@CommandLine.Spec
CommandLine.Model.CommandSpec spec;
@CommandLine.Parameters(index = "0", defaultValue = "output-directory/database",
description = "Input path. Default: ${DEFAULT-VALUE}")
private Path db;
@CommandLine.Option(names = { "--db"},
description = "db name for show root")
private List<String> dbs;
@CommandLine.Option(names = {"-h", "--help"}, help = true, description = "display a help message")
private boolean help;
@Override
public Integer call() throws Exception {
if (help) {
spec.commandLine().usage(System.out);
return 0;
}
if (!db.toFile().exists()) {
logger.info(" {} does not exist.", db);
spec.commandLine().getErr().println(spec.commandLine().getColorScheme()
.errorText(String.format("%s does not exist.", db)));
return 404;
}
// remove not exit
if (dbs != null) {
dbs.removeIf(s -> !Paths.get(db.toString(), s).toFile().exists());
}
if (dbs == null || dbs.isEmpty()) {
logger.info("Specify at least one exit database: --db dbName.");
spec.commandLine().getErr().println(spec.commandLine().getColorScheme()
.errorText("Specify at least one exit database: --db dbName."));
return 404;
}
List<Ret> task = ProgressBar.wrap(dbs.stream(), "root task").parallel()
.map(this::calcMerkleRoot).collect(Collectors.toList());
task.forEach(this::printInfo);
int code = (int) task.stream().filter(r -> r.code == 1).count();
if (code > 0) {
spec.commandLine().getErr().println(spec.commandLine().getColorScheme()
.errorText("There are some errors, please check toolkit.log for detail."));
}
spec.commandLine().getOut().println("root task done.");
return code;
}
private Ret calcMerkleRoot(String name) {
Ret info = new Ret();
try (DBInterface database = DbTool.getDB(this.db, name)) {
DBIterator iterator = database.iterator();
iterator.seekToFirst();
ArrayList<Sha256Hash> ids = Streams.stream(iterator)
.map(this::getHash)
.collect(Collectors.toCollection(ArrayList::new));
Sha256Hash root = MerkleRoot.root(ids);
logger.info("db: {},root: {}", database.getName(), root);
info.code = 0;
info.msg = String.format("db: %s,root: %s", database.getName(), root);
} catch (RocksDBException | IOException e) {
logger.error("calc db {} fail", name, e);
info.code = 1;
info.msg = String.format("db: %s,fail: %s",
name, e.getMessage());
}
return info;
}
private Sha256Hash getHash(Map.Entry<byte[], byte[]> entry) {
return Sha256Hash.of(true,
Bytes.concat(entry.getKey(), entry.getValue()));
}
private void printInfo(Ret ret) {
if (ret.code == 0) {
spec.commandLine().getOut().println(ret.msg);
} else {
spec.commandLine().getErr().println(spec.commandLine().getColorScheme()
.errorText(ret.msg));
}
}
private static class Ret {
private int code;
private String msg;
}
}