diff --git a/bin/hbase b/bin/hbase index b371ffc2ec0..5087e599342 100755 --- a/bin/hbase +++ b/bin/hbase @@ -103,6 +103,7 @@ if [ $# = 0 ]; then echo " ltt Run LoadTestTool" echo " canary Run the Canary tool" echo " version Print the version" + echo " regionsplitter Run RegionSplitter tool" echo " CLASSNAME Run the class named CLASSNAME" exit 1 fi @@ -456,6 +457,8 @@ elif [ "$COMMAND" = "canary" ] ; then HBASE_OPTS="$HBASE_OPTS $HBASE_CANARY_OPTS" elif [ "$COMMAND" = "version" ] ; then CLASS='org.apache.hadoop.hbase.util.VersionInfo' +elif [ "$COMMAND" = "regionsplitter" ] ; then + CLASS='org.apache.hadoop.hbase.util.RegionSplitter' else CLASS=$COMMAND fi diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java index d2d8dac4311..1dd720143ad 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java @@ -137,7 +137,7 @@ public abstract class AbstractHBaseTool implements Tool, Configurable { } String[] remainingArgs = new String[argsList.size()]; argsList.toArray(remainingArgs); - cmd = new DefaultParser().parse(options, remainingArgs); + cmd = newParser().parse(options, remainingArgs); } catch (MissingOptionException e) { LOG.error(e.getMessage()); LOG.error("Use -h or --help for usage instructions."); @@ -160,6 +160,16 @@ public abstract class AbstractHBaseTool implements Tool, Configurable { return ret; } + /** + * Create the parser to use for parsing and validating the command line. Since commons-cli lacks + * the capability to validate arbitrary combination of options, it may be helpful to bake custom + * logic into a specialized parser implementation. See LoadTestTool for examples. + * @return a new parser specific to the current tool + */ + protected CommandLineParser newParser() { + return new DefaultParser(); + } + private boolean isHelpCommand(String[] args) throws ParseException { Options helpOption = new Options().addOption(HELP_OPTION); // this parses the command line but doesn't throw an exception on unknown options diff --git a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java index 51b2cf3ad1f..0f7c5c00469 100644 --- a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java +++ b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java @@ -58,7 +58,14 @@ import org.apache.hadoop.hbase.security.access.Permission; import org.apache.hadoop.hbase.util.test.LoadTestDataGenerator; import org.apache.hadoop.hbase.util.test.LoadTestDataGeneratorWithACL; import org.apache.hadoop.util.ToolRunner; + +import org.apache.hbase.thirdparty.org.apache.commons.cli.AlreadySelectedException; import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine; +import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser; +import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser; +import org.apache.hbase.thirdparty.org.apache.commons.cli.MissingOptionException; +import org.apache.hbase.thirdparty.org.apache.commons.cli.Options; +import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException; /** * A command-line utility that reads, writes, and verifies data. Unlike @@ -358,6 +365,40 @@ public class LoadTestTool extends AbstractHBaseTool { addOptWithArg(OPT_MOB_THRESHOLD, OPT_MOB_THRESHOLD_USAGE); } + @Override + protected CommandLineParser newParser() { + // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves + // Validate in parse() to get helpful error messages instead of exploding in processOptions() + return new DefaultParser() { + @Override + public CommandLine parse(Options opts, String[] args, Properties props, boolean stop) + throws ParseException { + CommandLine cl = super.parse(opts, args, props, stop); + + boolean isReadWriteUpdate = cmd.hasOption(OPT_READ) + || cmd.hasOption(OPT_WRITE) + || cmd.hasOption(OPT_UPDATE); + boolean isInitOnly = cmd.hasOption(OPT_INIT_ONLY); + + if (!isInitOnly && !isReadWriteUpdate) { + throw new MissingOptionException("Must specify either -" + OPT_INIT_ONLY + + " or at least one of -" + OPT_READ + ", -" + OPT_WRITE + ", -" + OPT_UPDATE); + } + + if (isInitOnly && isReadWriteUpdate) { + throw new AlreadySelectedException(OPT_INIT_ONLY + " cannot be specified with any of -" + + OPT_READ + ", -" + OPT_WRITE + ", -" + OPT_UPDATE); + } + + if (isReadWriteUpdate && !cmd.hasOption(OPT_NUM_KEYS)) { + throw new MissingOptionException(OPT_NUM_KEYS + " must be specified in read/write mode."); + } + + return cl; + } + }; + } + @Override protected void processOptions(CommandLine cmd) { this.cmd = cmd; @@ -381,21 +422,7 @@ public class LoadTestTool extends AbstractHBaseTool { isInitOnly = cmd.hasOption(OPT_INIT_ONLY); deferredLogFlush = cmd.hasOption(OPT_DEFERRED_LOG_FLUSH); - if (!isWrite && !isRead && !isUpdate && !isInitOnly) { - throw new IllegalArgumentException("Either -" + OPT_WRITE + " or " + - "-" + OPT_UPDATE + " or -" + OPT_READ + " has to be specified"); - } - - if (isInitOnly && (isRead || isWrite || isUpdate)) { - throw new IllegalArgumentException(OPT_INIT_ONLY + " cannot be specified with" - + " either -" + OPT_WRITE + " or -" + OPT_UPDATE + " or -" + OPT_READ); - } - if (!isInitOnly) { - if (!cmd.hasOption(OPT_NUM_KEYS)) { - throw new IllegalArgumentException(OPT_NUM_KEYS + " must be specified in " - + "read or write mode"); - } startKey = parseLong(cmd.getOptionValue(OPT_START_KEY, String.valueOf(DEFAULT_START_KEY)), 0, Long.MAX_VALUE); long numKeys = parseLong(cmd.getOptionValue(OPT_NUM_KEYS), 1, diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/Canary.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/Canary.java index 31208c1361a..8875862f1d9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/Canary.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/Canary.java @@ -837,9 +837,8 @@ public final class Canary implements Tool { } private void printUsageAndExit() { - System.err.printf( - "Usage: hbase %s [opts] [table1 [table2]...] | [regionserver1 [regionserver2]..]%n", - getClass().getName()); + System.err.println( + "Usage: hbase canary [opts] [table1 [table2]...] | [regionserver1 [regionserver2]..]"); System.err.println(" where [opts] are:"); System.err.println(" -help Show this help and exit."); System.err.println(" -regionserver replace the table argument to regionserver,"); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/RegionSplitter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/RegionSplitter.java index ff7e2552386..1b586348075 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/RegionSplitter.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/RegionSplitter.java @@ -331,7 +331,7 @@ public class RegionSplitter { opt.addOption(null, "lastrow", true, "Last Row in Table for Split Algorithm"); opt.addOption(null, "risky", false, - "Skip verification steps to complete quickly." + "Skip verification steps to complete quickly. " + "STRONGLY DISCOURAGED for production systems. "); CommandLine cmd = new GnuParser().parse(opt, args); @@ -356,8 +356,8 @@ public class RegionSplitter { boolean oneOperOnly = createTable ^ rollingSplit; if (2 != cmd.getArgList().size() || !oneOperOnly || cmd.hasOption("h")) { - new HelpFormatter().printHelp("RegionSplitter \n"+ - "SPLITALGORITHM is a java class name of a class implementing " + + new HelpFormatter().printHelp("bin/hbase regionsplitter
\n"+ + "SPLITALGORITHM is the java class name of a class implementing " + "SplitAlgorithm, or one of the special strings HexStringSplit or " + "DecimalStringSplit or UniformSplit, which are built-in split algorithms. " + "HexStringSplit treats keys as hexadecimal ASCII, and " + diff --git a/src/main/asciidoc/_chapters/ops_mgt.adoc b/src/main/asciidoc/_chapters/ops_mgt.adoc index 33b6c5ea734..23d1485fbad 100644 --- a/src/main/asciidoc/_chapters/ops_mgt.adoc +++ b/src/main/asciidoc/_chapters/ops_mgt.adoc @@ -68,6 +68,7 @@ Some commands take arguments. Pass no args or -h for usage. pe Run PerformanceEvaluation ltt Run LoadTestTool canary Run the Canary tool + regionsplitter Run the RegionSplitter tool version Print the version CLASSNAME Run the class named CLASSNAME ---- @@ -83,7 +84,7 @@ To see the usage, use the `--help` parameter. ---- $ ${HBASE_HOME}/bin/hbase canary -help -Usage: hbase org.apache.hadoop.hbase.tool.Canary [opts] [table1 [table2]...] | [regionserver1 [regionserver2]..] +Usage: hbase canary [opts] [table1 [table2]...] | [regionserver1 [regionserver2]..] where [opts] are: -help Show this help and exit. -regionserver replace the table argument to regionserver, @@ -276,6 +277,35 @@ property> ---- ==== +=== RegionSplitter + +---- +usage: bin/hbase regionsplitter
+SPLITALGORITHM is the java class name of a class implementing + SplitAlgorithm, or one of the special strings + HexStringSplit or DecimalStringSplit or + UniformSplit, which are built-in split algorithms. + HexStringSplit treats keys as hexadecimal ASCII, and + DecimalStringSplit treats keys as decimal ASCII, and + UniformSplit treats keys as arbitrary bytes. + -c Create a new table with a pre-split number of + regions + -D Override HBase Configuration Settings + -f Column Families to create with new table. + Required with -c + --firstrow First Row in Table for Split Algorithm + -h Print this usage help + --lastrow Last Row in Table for Split Algorithm + -o Max outstanding splits that have unfinished + major compactions + -r Perform a rolling split of an existing region + --risky Skip verification steps to complete + quickly. STRONGLY DISCOURAGED for production + systems. +---- + +For additional detail, see <>. + [[health.check]] === Health Checker @@ -758,7 +788,7 @@ The PerformanceEvaluation tool has received many updates in recent HBase release The `hbase ltt` command runs the LoadTestTool utility, which is used for testing. -You must specify one of `-write`, `-update`, or `-read` as the first option. +You must specify either `-init_only` or at least one of `-write`, `-update`, or `-read`. For general usage instructions, pass the `-h` option. The LoadTestTool has received many updates in recent HBase releases, including support for namespaces, support for tags, cell-level ACLS and visibility labels, testing security-related features, ability to specify the number of regions per server, tests for multi-get RPC calls, and tests relating to replication.