Skip to content

Commit

Permalink
Merge pull request #4545 from halibobo1205/feat/db_transfer_tool
Browse files Browse the repository at this point in the history
tool(db):add db path move function.
  • Loading branch information
halibobo1205 committed Jul 28, 2022
2 parents c5acd14 + aee957f commit f899621
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 20 deletions.
3 changes: 2 additions & 1 deletion framework/src/main/java/org/tron/tool/litefullnode/Util.java
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.nio.file.FileSystemException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand Down Expand Up @@ -31,7 +32,7 @@ public static void copyDatabases(Path src, Path dest, List<String> subDirs)
subDirs.forEach(dir -> {
if (FileUtil.isExists(Paths.get(src.toString(), dir).toString())) {
try {
Files.walk(Paths.get(src.toString(), dir))
Files.walk(Paths.get(src.toString(), dir), FileVisitOption.FOLLOW_LINKS)
.forEach(source -> copy(source, dest.resolve(src.relativize(source))));
} catch (IOException e) {
logger.error("copy database failed, src: {}, dest: {}, error: {}",
Expand Down
11 changes: 8 additions & 3 deletions plugins/build.gradle
Expand Up @@ -30,8 +30,10 @@ dependencies {
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: 'org.testng', name: 'testng', version: '6.14.3'
// https://mvnrepository.com/artifact/com.beust/jcommander
compile group: 'com.beust', name: 'jcommander', version: '1.78'
compile group: 'info.picocli', name: 'picocli', version: '4.6.3'
compile group: 'com.typesafe', name: 'config', version: '1.3.2'
compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3'


compile 'com.github.halibobo1205.leveldb-java:leveldb:v0.12.5'
compile 'com.github.halibobo1205.leveldb-java:leveldb-api:v0.12.5'
Expand Down Expand Up @@ -127,11 +129,14 @@ applicationDistribution.from("../gradle/java-tron.vmoptions") {
into "bin"
}
createScript(project, 'org.tron.plugins.ArchiveManifest', 'ArchiveManifest')
createScript(project, 'org.tron.plugins.Toolkit', 'Toolkit')

def releaseBinary = hasProperty('binaryRelease') ? getProperty('binaryRelease') : 'true'
if (releaseBinary == 'true') {
artifacts {
archives(binaryRelease('buildArchiveManifestJar', 'ArchiveManifest', 'org.tron.plugins.ArchiveManifest'))
archives(
binaryRelease('buildArchiveManifestJar', 'ArchiveManifest', 'org.tron.plugins.ArchiveManifest'),
binaryRelease('buildToolkitJar', 'Toolkit', 'org.tron.plugins.Toolkit'))
}
}

Expand Down
34 changes: 18 additions & 16 deletions plugins/src/main/java/org/tron/plugins/ArchiveManifest.java
Expand Up @@ -3,8 +3,6 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
Expand Down Expand Up @@ -37,6 +35,8 @@
import org.iq80.leveldb.DB;
import org.iq80.leveldb.Options;
import org.iq80.leveldb.impl.Filename;
import picocli.CommandLine;
import picocli.CommandLine.Option;

@Slf4j(topic = "archive")
/*
Expand Down Expand Up @@ -95,12 +95,10 @@ public static void main(String[] args) {

public static int run(String[] args) {
Args parameters = new Args();
JCommander jc = JCommander.newBuilder()
.addObject(parameters)
.build();
jc.parse(args);
CommandLine commandLine = new CommandLine(parameters);
commandLine.parseArgs(args);
if (parameters.help) {
jc.usage();
commandLine.usage(System.out);
return 0;
}

Expand Down Expand Up @@ -247,19 +245,23 @@ public static boolean writeProperty(String file, String key, String value) {
}

public static class Args {
@Parameter
private List<String> parameters = new ArrayList<>();

@Parameter(names = {"-d", "--database-directory"}, description = "java-tron database directory")
private String databaseDirectory = "output-directory/database";
@Option(names = {"-d", "--database-directory"},
defaultValue = "output-directory/database",
description = "java-tron database directory. Default: ${DEFAULT-VALUE}")
private String databaseDirectory;

@Parameter(names = {"-b", "--batch-size" }, description = "deal manifest batch size")
private int maxBatchSize = 80_000;
@Option(names = {"-b", "--batch-size" },
defaultValue = "80000",
description = "deal manifest batch size. Default: ${DEFAULT-VALUE}")
private int maxBatchSize;

@Parameter(names = {"-m", "--manifest-size" }, description = "manifest min size(M) to archive")
private int maxManifestSize = 0;
@Option(names = {"-m", "--manifest-size" },
defaultValue = "0",
description = "manifest min size(M) to archive. Default: ${DEFAULT-VALUE}")
private int maxManifestSize;

@Parameter(names = {"-h", "--help"}, help = true)
@Option(names = {"-h", "--help"}, help = true)
private boolean help;
}
}
25 changes: 25 additions & 0 deletions plugins/src/main/java/org/tron/plugins/Db.java
@@ -0,0 +1,25 @@
package org.tron.plugins;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import java.nio.file.Paths;
import picocli.CommandLine;

@CommandLine.Command(name = "db",
mixinStandardHelpOptions = true,
version = "db command 1.0",
description = "An rich command set that provides high-level operations for dbs.",
subcommands = {CommandLine.HelpCommand.class, DbMove.class},
commandListHeading = "%nCommands:%n%nThe most commonly used git commands are:%n"
)
public class Db {

static class ConfigConverter implements CommandLine.ITypeConverter<Config> {
ConfigConverter() {
}

public Config convert(String value) {
return ConfigFactory.parseFile(Paths.get(value).toFile());
}
}
}
163 changes: 163 additions & 0 deletions plugins/src/main/java/org/tron/plugins/DbMove.java
@@ -0,0 +1,163 @@
package org.tron.plugins;

import com.typesafe.config.Config;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import me.tongfei.progressbar.ProgressBar;
import picocli.CommandLine;
import picocli.CommandLine.Command;

@Command(name = "mv", aliases = "move",
description = "mv db to pre-set new path . For example HDD,reduce storage expenses.")
public class DbMove implements Callable<Integer> {

private static final String PROPERTIES_CONFIG_KEY = "storage.properties";
private static final String DB_DIRECTORY_CONFIG_KEY = "storage.db.directory";
private static final String DEFAULT_DB_DIRECTORY = "database";
private static final String NAME_CONFIG_KEY = "name";
private static final String PATH_CONFIG_KEY = "path";
private static final String NOT_FIND = "The database to be moved cannot be found.";

@CommandLine.Spec
CommandLine.Model.CommandSpec spec;

@CommandLine.Option(names = {"-d", "--database-directory"},
defaultValue = "output-directory",
description = "database directory path. Default: ${DEFAULT-VALUE}")
String database;

@CommandLine.Option(names = {"-c", "--config"},
defaultValue = "config.conf",
converter = Db.ConfigConverter.class,
description = " config file. Default: ${DEFAULT-VALUE}")
Config config;

@CommandLine.Option(names = {"-h", "--help"}, help = true, description = "display a help message")
boolean help;

@Override
public Integer call() throws Exception {
if (help) {
spec.commandLine().usage(System.out);
return 0;
}
if (config.hasPath(PROPERTIES_CONFIG_KEY)) {
List<? extends Config> dbs = config.getConfigList(PROPERTIES_CONFIG_KEY);
if (dbs.isEmpty()) {
spec.commandLine().getOut().println(NOT_FIND);
return 0;
}
String dbPath = config.hasPath(DB_DIRECTORY_CONFIG_KEY)
? config.getString(DB_DIRECTORY_CONFIG_KEY) : DEFAULT_DB_DIRECTORY;

dbs = dbs.stream()
.filter(c -> c.hasPath(NAME_CONFIG_KEY) && c.hasPath(PATH_CONFIG_KEY))
.collect(Collectors.toList());

if (dbs.isEmpty()) {
spec.commandLine().getOut().println(NOT_FIND);
return 0;
}
List<Property> toBeMove = dbs.stream()
.map(c -> {
try {
return new Property(c.getString(NAME_CONFIG_KEY),
Paths.get(database, dbPath, c.getString(NAME_CONFIG_KEY)),
Paths.get(c.getString(PATH_CONFIG_KEY), dbPath, c.getString(NAME_CONFIG_KEY)));
} catch (IOException e) {
spec.commandLine().getErr().println(e);
}
return null;
}).filter(Objects::nonNull)
.filter(p -> !p.destination.equals(p.original)).collect(Collectors.toList());

if (toBeMove.isEmpty()) {
spec.commandLine().getOut().println(NOT_FIND);
return 0;
}
toBeMove = toBeMove.stream()
.filter(property -> {
if (property.destination.toFile().exists()) {
spec.commandLine().getOut().println(String.format("%s already exist,skip.",
property.destination));
return false;
} else {
return true;
}
}).collect(Collectors.toList());

if (toBeMove.isEmpty()) {
spec.commandLine().getOut().println(NOT_FIND);
return 0;
}
ProgressBar.wrap(toBeMove.stream(), "mv task").forEach(this::run);
spec.commandLine().getOut().println("move db done.");

} else {
spec.commandLine().getOut().println(NOT_FIND);
}
return 0;
}

private void run(Property p) {
if (p.destination.toFile().mkdirs()) {
ProgressBar.wrap(Arrays.stream(Objects.requireNonNull(p.original.toFile().listFiles()))
.filter(File::isFile).map(File::getName).parallel(), p.name).forEach(file -> {
Path original = Paths.get(p.original.toString(), file);
Path destination = Paths.get(p.destination.toString(), file);
try {
Files.copy(original, destination,
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
spec.commandLine().getErr().println(e);
}
});
try {
if (deleteDir(p.original.toFile())) {
Files.createSymbolicLink(p.original, p.destination);
}
} catch (IOException | UnsupportedOperationException x) {
spec.commandLine().getErr().println(x);
}
} else {
spec.commandLine().getErr().println(String.format("%s create failed.", p.destination));
}
}

/**
* delete directory.
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
if (children != null) {
for (String child : children) {
deleteDir(new File(dir, child));
}
}
}
return dir.delete();
}

static class Property {

private final String name;
private final Path original;
final Path destination;

public Property(String name, Path original, Path destination) throws IOException {
this.name = name;
this.original = original.toFile().getCanonicalFile().toPath();
this.destination = destination.toFile().getCanonicalFile().toPath();
}
}
}
19 changes: 19 additions & 0 deletions plugins/src/main/java/org/tron/plugins/Toolkit.java
@@ -0,0 +1,19 @@
package org.tron.plugins;

import java.util.concurrent.Callable;
import picocli.CommandLine;

@CommandLine.Command(name = "tron", subcommands = { CommandLine.HelpCommand.class, Db.class})
public class Toolkit implements Callable<Integer> {


public static void main(String[] args) {
int exitCode = new CommandLine(new Toolkit()).execute(args);
System.exit(exitCode);
}

@Override
public Integer call() throws Exception {
return 0;
}
}

0 comments on commit f899621

Please sign in to comment.