diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..27f7932
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,27 @@
+language: java
+
+jdk:
+ - openjdk8
+
+sudo: required
+
+branches:
+ only:
+ - master
+ - /^release-.*$/
+ - /^test-.*$/
+
+install: mvn compile -Dmaven.javadoc.skip=true | grep -v "Downloading\|Downloaded"
+
+before_script:
+ - $TRAVIS_DIR/install-hugegraph.sh $TRAVIS_BRANCH | grep -v "Downloading\|Downloaded"
+
+script:
+ - mvn test -Dtest=FuncTestSuite
+
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
+
+env:
+ global:
+ - TRAVIS_DIR=assembly/travis
diff --git a/assembly/travis/conf/gremlin-server.yaml b/assembly/travis/conf/gremlin-server.yaml
new file mode 100644
index 0000000..484ee12
--- /dev/null
+++ b/assembly/travis/conf/gremlin-server.yaml
@@ -0,0 +1,110 @@
+# host and port of gremlin server, need to be consistent with host and port in rest-server.properties
+#host: 127.0.0.1
+#port: 8182
+
+# timeout in ms of gremlin query
+scriptEvaluationTimeout: 30000
+
+channelizer: org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer
+graphs: {
+ hugegraph: conf/hugegraph.properties
+}
+scriptEngines: {
+ gremlin-groovy: {
+ plugins: {
+ com.baidu.hugegraph.plugin.HugeGraphGremlinPlugin: {},
+ org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
+ org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {
+ classImports: [
+ java.lang.Math,
+ com.baidu.hugegraph.backend.id.IdGenerator,
+ com.baidu.hugegraph.type.define.Directions,
+ com.baidu.hugegraph.type.define.NodeRole,
+ com.baidu.hugegraph.traversal.algorithm.CollectionPathsTraverser,
+ com.baidu.hugegraph.traversal.algorithm.CountTraverser,
+ com.baidu.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser,
+ com.baidu.hugegraph.traversal.algorithm.CustomizePathsTraverser,
+ com.baidu.hugegraph.traversal.algorithm.FusiformSimilarityTraverser,
+ com.baidu.hugegraph.traversal.algorithm.HugeTraverser,
+ com.baidu.hugegraph.traversal.algorithm.JaccardSimilarTraverser,
+ com.baidu.hugegraph.traversal.algorithm.KneighborTraverser,
+ com.baidu.hugegraph.traversal.algorithm.KoutTraverser,
+ com.baidu.hugegraph.traversal.algorithm.MultiNodeShortestPathTraverser,
+ com.baidu.hugegraph.traversal.algorithm.NeighborRankTraverser,
+ com.baidu.hugegraph.traversal.algorithm.PathsTraverser,
+ com.baidu.hugegraph.traversal.algorithm.PersonalRankTraverser,
+ com.baidu.hugegraph.traversal.algorithm.SameNeighborTraverser,
+ com.baidu.hugegraph.traversal.algorithm.ShortestPathTraverser,
+ com.baidu.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser,
+ com.baidu.hugegraph.traversal.algorithm.SubGraphTraverser,
+ com.baidu.hugegraph.traversal.algorithm.TemplatePathsTraverser,
+ com.baidu.hugegraph.traversal.algorithm.steps.EdgeStep,
+ com.baidu.hugegraph.traversal.algorithm.steps.RepeatEdgeStep,
+ com.baidu.hugegraph.traversal.algorithm.steps.WeightedEdgeStep,
+ com.baidu.hugegraph.traversal.optimize.Text,
+ com.baidu.hugegraph.traversal.optimize.TraversalUtil,
+ com.baidu.hugegraph.util.DateUtil
+ ],
+ methodImports: [java.lang.Math#*]
+ },
+ org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {
+ files: [scripts/empty-sample.groovy]
+ }
+ }
+ }
+}
+serializers:
+ - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0,
+ config: {
+ serializeResultToString: false,
+ ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
+ }
+ }
+ - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1,
+ config: {
+ serializeResultToString: false,
+ ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
+ }
+ }
+ - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
+ config: {
+ serializeResultToString: false,
+ ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
+ }
+ }
+ - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0,
+ config: {
+ serializeResultToString: false,
+ ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
+ }
+ }
+ - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0,
+ config: {
+ serializeResultToString: false,
+ ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
+ }
+ }
+metrics: {
+ consoleReporter: {enabled: false, interval: 180000},
+ csvReporter: {enabled: true, interval: 180000, fileName: /tmp/gremlin-server-metrics.csv},
+ jmxReporter: {enabled: false},
+ slf4jReporter: {enabled: false, interval: 180000},
+ gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
+ graphiteReporter: {enabled: false, interval: 180000}
+}
+maxInitialLineLength: 4096
+maxHeaderSize: 8192
+maxChunkSize: 8192
+maxContentLength: 65536
+maxAccumulationBufferComponents: 1024
+resultIterationBatchSize: 64
+writeBufferLowWaterMark: 32768
+writeBufferHighWaterMark: 65536
+ssl: {
+ enabled: false
+}
+authentication: {
+ authenticator: com.baidu.hugegraph.auth.StandardAuthenticator,
+ authenticationHandler: com.baidu.hugegraph.auth.WsAndHttpBasicAuthHandler,
+ config: {tokens: conf/rest-server.properties}
+}
diff --git a/assembly/travis/conf/hugegraph.properties b/assembly/travis/conf/hugegraph.properties
new file mode 100644
index 0000000..c66d0a7
--- /dev/null
+++ b/assembly/travis/conf/hugegraph.properties
@@ -0,0 +1,68 @@
+# gremlin entrence to create graph
+gremlin.graph=com.baidu.hugegraph.auth.HugeFactoryAuthProxy
+
+# cache config
+#schema.cache_capacity=100000
+# vertex-cache default is 1000w, 10min expired
+#vertex.cache_capacity=10000000
+#vertex.cache_expire=600
+# edge-cache default is 100w, 10min expired
+#edge.cache_capacity=1000000
+#edge.cache_expire=600
+
+
+# schema illegal name template
+#schema.illegal_name_regex=\s+|~.*
+
+#vertex.default_label=vertex
+
+backend=rocksdb
+serializer=binary
+
+store=hugegraph
+
+search.text_analyzer=jieba
+search.text_analyzer_mode=INDEX
+
+# rocksdb backend config
+#rocksdb.data_path=/path/to/disk
+#rocksdb.wal_path=/path/to/disk
+
+
+# cassandra backend config
+cassandra.host=localhost
+cassandra.port=9042
+cassandra.username=
+cassandra.password=
+#cassandra.connect_timeout=5
+#cassandra.read_timeout=20
+#cassandra.keyspace.strategy=SimpleStrategy
+#cassandra.keyspace.replication=3
+
+# hbase backend config
+#hbase.hosts=localhost
+#hbase.port=2181
+#hbase.znode_parent=/hbase
+#hbase.threads_max=64
+
+# mysql backend config
+#jdbc.driver=com.mysql.jdbc.Driver
+#jdbc.url=jdbc:mysql://127.0.0.1:3306
+#jdbc.username=root
+#jdbc.password=
+#jdbc.reconnect_max_times=3
+#jdbc.reconnect_interval=3
+#jdbc.sslmode=false
+
+# palo backend config
+#palo.host=127.0.0.1
+#palo.poll_interval=10
+#palo.temp_dir=./palo-data
+#palo.file_limit_size=32
+
+# postgresql & cockroachdb backend config
+#jdbc.driver=org.postgresql.Driver
+#jdbc.url=jdbc:postgresql://localhost:5432/
+#jdbc.username=postgres
+#jdbc.password=
+#jdbc.postgresql.connect_database=template1
diff --git a/assembly/travis/conf/rest-server.properties b/assembly/travis/conf/rest-server.properties
new file mode 100644
index 0000000..a9ea865
--- /dev/null
+++ b/assembly/travis/conf/rest-server.properties
@@ -0,0 +1,12 @@
+# bind url
+restserver.url=http://127.0.0.1:8080
+# gremlin server url, need to be consistent with host and port in gremlin-server.yaml
+#gremlinserver.url=http://127.0.0.1:8182
+
+# graphs list with pair NAME:CONF_PATH
+graphs=[hugegraph:conf/hugegraph.properties]
+
+# authentication
+auth.authenticator=com.baidu.hugegraph.auth.StandardAuthenticator
+#auth.admin_token=
+#auth.user_tokens=[]
diff --git a/assembly/travis/install-hugegraph.sh b/assembly/travis/install-hugegraph.sh
new file mode 100755
index 0000000..3c4eedf
--- /dev/null
+++ b/assembly/travis/install-hugegraph.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+set -ev
+
+TRAVIS_DIR=`dirname $0`
+
+if [ $# -ne 1 ]; then
+ echo "Must pass base branch name of pull request"
+ exit 1
+fi
+
+CLIENT_BRANCH=$1
+HUGEGRAPH_BRANCH=$CLIENT_BRANCH
+
+HUGEGRAPH_GIT_URL="https://github.com/hugegraph/hugegraph.git"
+
+git clone $HUGEGRAPH_GIT_URL
+
+cd hugegraph
+
+git checkout $HUGEGRAPH_BRANCH
+
+mvn package -DskipTests
+
+mv hugegraph-*.tar.gz ../
+
+cd ../
+
+rm -rf hugegraph
+
+tar -zxvf hugegraph-*.tar.gz
+
+HTTPS_SERVER_DIR="hugegraph_https"
+
+mkdir $HTTPS_SERVER_DIR
+
+cp -r hugegraph-*/. $HTTPS_SERVER_DIR
+
+cd hugegraph-*
+
+cp ../$TRAVIS_DIR/conf/* conf
+
+echo -e "123456" | bin/init-store.sh
+
+bin/start-hugegraph.sh
diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100644
index 0000000..80c26bf
--- /dev/null
+++ b/checkstyle.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 3d606b6..80a7a97 100644
--- a/pom.xml
+++ b/pom.xml
@@ -238,6 +238,28 @@
release
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.1.0
+
+ checkstyle.xml
+ UTF-8
+ true
+ true
+ false
+ false
+
+
+
+ validate
+ validate
+
+ check
+
+
+
+
maven-source-plugin
diff --git a/src/main/java/com/baidu/hugegraph/base/ToolClient.java b/src/main/java/com/baidu/hugegraph/base/ToolClient.java
index d054e08..8516958 100644
--- a/src/main/java/com/baidu/hugegraph/base/ToolClient.java
+++ b/src/main/java/com/baidu/hugegraph/base/ToolClient.java
@@ -23,6 +23,7 @@
import org.apache.commons.lang3.StringUtils;
+import com.baidu.hugegraph.driver.AuthManager;
import com.baidu.hugegraph.driver.GraphManager;
import com.baidu.hugegraph.driver.GremlinManager;
import com.baidu.hugegraph.driver.HugeClient;
@@ -113,6 +114,16 @@ public static String homePath() {
return homePath;
}
+ public AuthManager authManager() {
+ return this.client.auth();
+ }
+
+ public void close() {
+ if (this.client != null) {
+ this.client.close();
+ }
+ }
+
public static class ConnectionInfo {
private String url;
diff --git a/src/main/java/com/baidu/hugegraph/base/ToolManager.java b/src/main/java/com/baidu/hugegraph/base/ToolManager.java
index f5d00f1..1828d2b 100644
--- a/src/main/java/com/baidu/hugegraph/base/ToolManager.java
+++ b/src/main/java/com/baidu/hugegraph/base/ToolManager.java
@@ -65,4 +65,8 @@ protected List readList(String key, Class clazz,
"Failed to deserialize %s", e, content);
}
}
+
+ public void close () {
+ this.client.close();
+ }
}
diff --git a/src/main/java/com/baidu/hugegraph/cmd/HugeGraphCommand.java b/src/main/java/com/baidu/hugegraph/cmd/HugeGraphCommand.java
index dab5361..2eb5c53 100644
--- a/src/main/java/com/baidu/hugegraph/cmd/HugeGraphCommand.java
+++ b/src/main/java/com/baidu/hugegraph/cmd/HugeGraphCommand.java
@@ -19,15 +19,23 @@
package com.baidu.hugegraph.cmd;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.util.Strings;
+
import com.baidu.hugegraph.base.Printer;
import com.baidu.hugegraph.base.ToolClient;
import com.baidu.hugegraph.base.ToolClient.ConnectionInfo;
import com.baidu.hugegraph.base.ToolManager;
+import com.baidu.hugegraph.constant.Constants;
+import com.baidu.hugegraph.exception.ExitException;
+import com.baidu.hugegraph.manager.AuthBackupRestoreManager;
import com.baidu.hugegraph.manager.BackupManager;
import com.baidu.hugegraph.manager.DumpGraphManager;
import com.baidu.hugegraph.manager.GraphsManager;
@@ -39,9 +47,11 @@
import com.baidu.hugegraph.structure.gremlin.Result;
import com.baidu.hugegraph.structure.gremlin.ResultSet;
import com.baidu.hugegraph.util.E;
+import com.baidu.hugegraph.util.ToolUtil;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.ParametersDelegate;
+import com.google.common.collect.Lists;
import static com.baidu.hugegraph.manager.BackupManager.BACKUP_DEFAULT_TIMEOUT;
@@ -51,6 +61,8 @@ public class HugeGraphCommand {
private SubCommands subCommands;
+ private List taskManagers;
+
@ParametersDelegate
private SubCommands.Url url = new SubCommands.Url();
@@ -74,8 +86,12 @@ public class HugeGraphCommand {
private SubCommands.TrustStorePassword trustStorePassword =
new SubCommands.TrustStorePassword();
+ @ParametersDelegate
+ private SubCommands.ThrowMode throwMode = new SubCommands.ThrowMode();
+
public HugeGraphCommand() {
this.subCommands = new SubCommands();
+ this.taskManagers = Lists.newArrayList();
}
public Map subCommands() {
@@ -143,6 +159,14 @@ public void trustStorePassword(String trustStorePassword) {
this.trustStorePassword.trustStorePassword = trustStorePassword;
}
+ public boolean throwMode() {
+ return this.throwMode.throwMode;
+ }
+
+ private void throwMode(boolean throwMode) {
+ this.throwMode.throwMode = throwMode;
+ }
+
public JCommander jCommander() {
JCommander.Builder builder = JCommander.newBuilder();
@@ -328,8 +352,21 @@ private void execute(String subCmd, JCommander jCommander) {
Printer.print("Tasks are cleared[force=%s]",
taskClear.force());
break;
- case "help":
- jCommander.usage();
+ case "auth-backup":
+ Printer.print("Auth backup start...");
+ SubCommands.AuthBackup authBackup = this.subCommand(subCmd);
+ AuthBackupRestoreManager authBackupManager = manager(AuthBackupRestoreManager.class);
+
+ authBackupManager.init(authBackup);
+ authBackupManager.backup(authBackup.types());
+ break;
+ case "auth-restore":
+ Printer.print("Auth restore start...");
+ SubCommands.AuthRestore authRestore = this.subCommand(subCmd);
+ AuthBackupRestoreManager authRestoreManager = manager(AuthBackupRestoreManager.class);
+
+ authRestoreManager.init(authRestore);
+ authRestoreManager.restore(authRestore.types());
break;
default:
throw new ParameterException(String.format(
@@ -337,6 +374,11 @@ private void execute(String subCmd, JCommander jCommander) {
}
}
+ private void execute(String[] args) {
+ JCommander jCommander = this.parseCommand(args);
+ this.execute(jCommander.getParsedCommand(), jCommander);
+ }
+
private void checkMainParams() {
E.checkArgument(this.url() != null, "Url can't be null");
E.checkArgument(this.username() == null && this.password() == null ||
@@ -353,8 +395,10 @@ private T manager(Class clz) {
this.timeout(),
this.trustStoreFile(),
this.trustStorePassword());
- return clz.getConstructor(ToolClient.ConnectionInfo.class)
- .newInstance(info);
+ T toolManager = clz.getConstructor(ToolClient.ConnectionInfo.class)
+ .newInstance(info);
+ this.taskManagers.add(toolManager);
+ return toolManager;
} catch (Exception e) {
throw new RuntimeException(String.format(
"Construct manager failed for class '%s', please make " +
@@ -402,29 +446,87 @@ private GraphMode mode() {
return mode;
}
- public static void main(String[] args) {
- HugeGraphCommand cmd = new HugeGraphCommand();
- JCommander jCommander = cmd.jCommander();
-
+ public JCommander parseCommand(String[] args) {
+ JCommander jCommander = this.jCommander();
if (args.length == 0) {
- jCommander.usage();
- System.exit(-1);
+ throw ExitException.exception(ToolUtil.commandUsage(jCommander),
+ "No command found, please input" +
+ " command");
}
- try {
+ if (this.parseHelp(args, jCommander)) {
+ assert false;
+ } else {
jCommander.parse(args);
- } catch (ParameterException e) {
- Printer.print(e.getMessage());
- System.exit(-1);
}
-
String subCommand = jCommander.getParsedCommand();
if (subCommand == null) {
- Printer.print("Must provide one sub-command");
- jCommander.usage();
- System.exit(-1);
+ throw ExitException.normal(ToolUtil.commandsCategory(
+ jCommander),
+ "No sub-command found");
+ }
+ return jCommander;
+ }
+
+ public boolean parseHelp(String[] args, JCommander jCommander) {
+ String subCommand = Strings.EMPTY;
+ List list = Arrays.asList(args);
+ if (!list.contains(Constants.COMMAND_HELP)) {
+ return false;
+ }
+ // Parse the '--throw-mode' command
+ if (list.contains(Constants.COMMAND_THROW_MODE)) {
+ int index = list.indexOf(Constants.COMMAND_THROW_MODE) + 1;
+ jCommander.parse(Constants.COMMAND_THROW_MODE,
+ list.get(index));
+ }
+ int index = list.indexOf(Constants.COMMAND_HELP);
+ if (list.size() > index + 1) {
+ subCommand = list.get(index + 1);
+ }
+ if (StringUtils.isEmpty(subCommand)) {
+ throw ExitException.normal(ToolUtil.commandUsage(jCommander),
+ "Command : hugegragh help");
}
- cmd.execute(subCommand, jCommander);
- System.exit(0);
+ Map commands = jCommander.getCommands();
+ if (commands.containsKey(subCommand)) {
+ throw ExitException.normal(ToolUtil.commandUsage(
+ commands.get(subCommand)),
+ "Command : hugegragh help %s",
+ subCommand);
+ } else {
+ throw ExitException.exception(ToolUtil.commandsCategory(jCommander),
+ "Unexpected help sub-command " +
+ "%s", subCommand);
+ }
+ }
+
+ public void shutdown() {
+ if (CollectionUtils.isEmpty(this.taskManagers)) {
+ return;
+ }
+ for (ToolManager toolManager : this.taskManagers) {
+ toolManager.close();
+ }
+ }
+
+ public static void main(String[] args) {
+ HugeGraphCommand cmd = new HugeGraphCommand();
+ int exitCode = Constants.EXIT_CODE_NORMAL;
+ try {
+ cmd.execute(args);
+ } catch (ExitException e) {
+ exitCode = e.exitCode();
+ ToolUtil.exitOrThrow(e, cmd.throwMode());
+ } catch (Throwable e) {
+ exitCode = Constants.EXIT_CODE_ERROR;
+ ToolUtil.printOrThrow(e, cmd.throwMode());
+ } finally {
+ cmd.shutdown();
+ }
+
+ if (exitCode != Constants.EXIT_CODE_NORMAL) {
+ System.exit(exitCode);
+ }
}
}
diff --git a/src/main/java/com/baidu/hugegraph/cmd/SubCommands.java b/src/main/java/com/baidu/hugegraph/cmd/SubCommands.java
index 5a71e38..743a88f 100644
--- a/src/main/java/com/baidu/hugegraph/cmd/SubCommands.java
+++ b/src/main/java/com/baidu/hugegraph/cmd/SubCommands.java
@@ -22,14 +22,17 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
import com.baidu.hugegraph.api.API;
+import com.baidu.hugegraph.constant.AuthRestoreConflictStrategy;
import com.baidu.hugegraph.manager.TasksManager;
import com.baidu.hugegraph.structure.constant.GraphMode;
import com.baidu.hugegraph.structure.constant.HugeType;
@@ -82,6 +85,9 @@ private void initSubCommands() {
this.commands.put("clear", new Clear());
this.commands.put("stop-all", new StopAll());
+ this.commands.put("auth-backup", new AuthBackup());
+ this.commands.put("auth-restore", new AuthRestore());
+
this.commands.put("help", new Help());
}
@@ -135,7 +141,7 @@ public static class Backup extends BackupRestore {
public boolean compress = true;
@Parameter(names = {"--label"}, arity = 1,
- description = "Vertex or edge label, only valid when type " +
+ description = "Vertex label or edge label, only valid when type " +
"is vertex or edge")
public String label;
@@ -668,8 +674,8 @@ public static class Protocol {
public static class TrustStoreFile {
@Parameter(names = {"--trust-store-file"}, arity = 1,
- description = "The path of client truststore file used when https " +
- "protocol is enabled")
+ description = "The path of client truststore file used when " +
+ "https protocol is enabled")
public String trustStoreFile;
}
@@ -681,16 +687,26 @@ public static class TrustStorePassword {
public String trustStorePassword;
}
+ public static class ThrowMode {
+
+ @Parameter(names = {"--throw-mode"}, arity = 1,
+ description = "Whether the hugegraph-tools work " +
+ "to throw an exception")
+ public boolean throwMode = false;
+ }
+
public static class HugeTypes {
@Parameter(names = {"--huge-types", "-t"},
listConverter = HugeTypeListConverter.class,
- description = "Type of schema/data. " +
- "Concat with ',' if more than one. " +
- "'all' means all vertices, edges and schema," +
- " in other words, 'all' equals with " +
- "'vertex,edge,vertex_label," +
- "edge_label,property_key,index_label'")
+ description = "Type of schema/data. Concat with ',' if more " +
+ "than one. Other types include 'all' and " +
+ "'schema'. 'all' means all vertices, edges and " +
+ "schema. In other words, 'all' equals with " +
+ "'vertex, edge, vertex_label, edge_label, " +
+ "property_key, index_label'. 'schema' equals " +
+ "with 'vertex_label, edge_label, property_key, " +
+ "index_label'.")
public List types = HugeTypeListConverter.ALL_TYPES;
}
@@ -812,6 +828,113 @@ public static class TaskId {
private long taskId;
}
+ public static class AuthBackupRestore {
+
+ @ParametersDelegate
+ private AuthTypes types = new AuthTypes();
+
+ @Parameter(names = {"--directory"}, arity = 1,
+ description = "Directory of auth information, default " +
+ "is './{auth-backup-restore}' in local " +
+ "file system or '{fs.default.name}/" +
+ "{auth-backup-restore}' in HDFS")
+ public String directory;
+
+ @DynamicParameter(names = "-D",
+ description = "HDFS config parameters")
+ private Map hdfsConf = new HashMap<>();
+
+ @ParametersDelegate
+ private Retry retry = new Retry();
+
+ public List types() {
+ return this.types.types;
+ }
+
+ public void types(List types) {
+ this.types.types = types;
+ }
+
+ public int retry() {
+ return this.retry.retry;
+ }
+
+ public void retry(int retry) {
+ this.retry.retry = retry;
+ }
+
+ public String directory() {
+ return this.directory;
+ }
+
+ public void directory(String directory) {
+ this.directory = directory;
+ }
+
+ public Map hdfsConf() {
+ return this.hdfsConf;
+ }
+
+ public void hdfsConf(Map hdfsConf) {
+ this.hdfsConf = hdfsConf;
+ }
+ }
+
+ public static class AuthBackup extends AuthBackupRestore {
+ }
+
+ public static class AuthRestore extends AuthBackupRestore {
+
+ @Parameter(names = {"--strategy"},
+ converter = AuthStrategyConverter.class,
+ description = "The strategy needs to be chosen in the event " +
+ "of a conflict when restoring. Valid " +
+ "strategies include 'stop' and 'ignore', " +
+ "default is 'stop'. 'stop' means if there " +
+ "a conflict, stop restore. 'ignore' means if " +
+ "there a conflict, ignore and continue to " +
+ "restore.")
+ public AuthRestoreConflictStrategy strategy = AuthStrategyConverter.strategy;
+
+ @Parameter(names = {"--init-password"}, arity = 1,
+ description = "Init user password, if restore type include " +
+ "'user', please specify the init-password of " +
+ "users.")
+ public String initPassword = StringUtils.EMPTY;
+
+ public AuthRestoreConflictStrategy strategy() {
+ return this.strategy;
+ }
+
+ public void strategy(AuthRestoreConflictStrategy strategy) {
+ this.strategy = strategy;
+ }
+
+ public String initPassword() {
+ return this.initPassword;
+ }
+
+ public void initPassword(String initPassword) {
+ this.initPassword = initPassword;
+ }
+ }
+
+ public static class AuthTypes {
+
+ @Parameter(names = {"--types", "-t"},
+ listConverter = AuthHugeTypeConverter.class,
+ description = "Type of auth data to restore and backup, " +
+ "concat with ',' if more than one. 'all' " +
+ "means all auth information. In other words, " +
+ "'all' equals with 'user, group, target, " +
+ "belong, access'. In addition, 'belong' or " +
+ "'access' can not backup or restore alone, if " +
+ "type contains 'belong' then should contains " +
+ "'user' and 'group'. If type contains 'access' " +
+ "then should contains 'group' and 'target'.")
+ public List types = AuthHugeTypeConverter.AUTH_ALL_TYPES;
+ }
+
public static class GraphModeConverter
implements IStringConverter {
@@ -832,6 +955,11 @@ public static class HugeTypeListConverter
HugeType.VERTEX, HugeType.EDGE
);
+ public static final List SCHEMA_TYPES = ImmutableList.of(
+ HugeType.PROPERTY_KEY, HugeType.VERTEX_LABEL,
+ HugeType.EDGE_LABEL, HugeType.INDEX_LABEL
+ );
+
@Override
public List convert(String value) {
E.checkArgument(value != null && !value.isEmpty(),
@@ -840,6 +968,9 @@ public List convert(String value) {
if (types.length == 1 && types[0].equalsIgnoreCase("all")) {
return ALL_TYPES;
}
+ if (types.length == 1 && types[0].equalsIgnoreCase("schema")) {
+ return SCHEMA_TYPES;
+ }
List hugeTypes = new ArrayList<>();
for (String type : types) {
try {
@@ -855,6 +986,66 @@ public List convert(String value) {
}
}
+ public static class AuthHugeTypeConverter
+ implements IStringConverter> {
+
+ public static final List AUTH_ALL_TYPES = ImmutableList.of(
+ HugeType.TARGET, HugeType.GROUP,
+ HugeType.USER, HugeType.ACCESS,
+ HugeType.BELONG
+ );
+
+ @Override
+ public List convert(String value) {
+ E.checkArgument(value != null && !value.isEmpty(),
+ "HugeType can't be null or empty");
+ String[] types = value.split(",");
+ if (types.length == 1 && types[0].equalsIgnoreCase("all")) {
+ return AUTH_ALL_TYPES;
+ }
+ List typeList = Arrays.asList(types);
+ E.checkArgument(!typeList.contains(HugeType.BELONG.toString().toLowerCase()) ||
+ (typeList.contains(HugeType.USER.toString().toLowerCase()) &&
+ typeList.contains(HugeType.GROUP.toString().toLowerCase())),
+ "Invalid --type '%s', if type contains 'belong'" +
+ " then 'user' and 'group' are required.", value);
+ E.checkArgument(!typeList.contains(HugeType.ACCESS.toString().toLowerCase()) ||
+ (typeList.contains(HugeType.GROUP.toString().toLowerCase()) &&
+ typeList.contains(HugeType.TARGET.toString().toLowerCase())),
+ "Invalid --type '%s', if type contains 'access'" +
+ " then 'group' and 'target' are required.", value);
+ List hugeTypes = new ArrayList<>();
+ for (String type : types) {
+ try {
+ hugeTypes.add(HugeType.valueOf(type.toUpperCase()));
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(String.format(
+ "Invalid --type '%s', valid value is 'all' or " +
+ "combination of [user,group,target," +
+ "belong,access]", type));
+ }
+ }
+ return hugeTypes;
+ }
+ }
+
+ public static class AuthStrategyConverter
+ implements IStringConverter {
+
+ public static final AuthRestoreConflictStrategy strategy =
+ AuthRestoreConflictStrategy.STOP;
+
+ @Override
+ public AuthRestoreConflictStrategy convert(String value) {
+ E.checkArgument(value != null && !value.isEmpty(),
+ "Strategy can't be null or empty");
+ E.checkArgument(AuthRestoreConflictStrategy.matchStrategy(value),
+ "Invalid --strategy '%s', valid value is " +
+ "'stop' or 'ignore", value);
+ return AuthRestoreConflictStrategy.fromName(value);
+ }
+ }
+
public static class MapConverter
implements IStringConverter