2727import java .util .Date ;
2828import java .util .List ;
2929import java .util .Map ;
30+ import java .util .Properties ;
3031import java .util .concurrent .ConcurrentHashMap ;
3132import java .util .concurrent .ExecutorService ;
3233import java .util .concurrent .atomic .AtomicInteger ;
4344import org .apache .hadoop .hbase .util .AbstractHBaseTool ;
4445import org .apache .hadoop .hbase .util .CommonFSUtils ;
4546import org .apache .hadoop .util .StringUtils ;
47+ import org .apache .hbase .thirdparty .org .apache .commons .cli .AlreadySelectedException ;
48+ import org .apache .hbase .thirdparty .org .apache .commons .cli .CommandLineParser ;
49+ import org .apache .hbase .thirdparty .org .apache .commons .cli .DefaultParser ;
50+ import org .apache .hbase .thirdparty .org .apache .commons .cli .MissingOptionException ;
51+ import org .apache .hbase .thirdparty .org .apache .commons .cli .Options ;
52+ import org .apache .hbase .thirdparty .org .apache .commons .cli .ParseException ;
4653import org .apache .yetus .audience .InterfaceAudience ;
4754import org .slf4j .Logger ;
4855import org .slf4j .LoggerFactory ;
@@ -68,17 +75,25 @@ public final class SnapshotInfo extends AbstractHBaseTool {
6875 private static final Logger LOG = LoggerFactory .getLogger (SnapshotInfo .class );
6976
7077 static final class Options {
71- static final Option SNAPSHOT = new Option (null , "snapshot" , true , "Snapshot to examine." );
78+ static final Option SNAPSHOT = new Option (null , "snapshot" , true ,
79+ "The name of the snapshot to be detailed." );
7280 static final Option REMOTE_DIR = new Option (null , "remote-dir" , true ,
73- "Root directory that contains the snapshots." );
81+ "A custom root directory where snapshots are stored. "
82+ + "Use it together with the --snapshot option." );
7483 static final Option LIST_SNAPSHOTS = new Option (null , "list-snapshots" , false ,
7584 "List all the available snapshots and exit." );
76- static final Option FILES = new Option (null , "files" , false , "Files and logs list." );
77- static final Option STATS = new Option (null , "stats" , false , "Files and logs stats." );
85+ static final Option FILES = new Option (null , "files" , false ,
86+ "The list of files retained by the specified snapshot. "
87+ + "Use it together with the --snapshot option." );
88+ static final Option STATS = new Option (null , "stats" , false ,
89+ "Additional information about the specified snapshot. "
90+ + "Use it together with the --snapshot option." );
7891 static final Option SCHEMA = new Option (null , "schema" , false ,
79- "Describe the snapshotted table." );
92+ "Show the descriptor of the table for the specified snapshot. "
93+ + "Use it together with the --snapshot option." );
8094 static final Option SIZE_IN_BYTES = new Option (null , "size-in-bytes" , false ,
81- "Print the size of the files in bytes." );
95+ "Print the size of the files in bytes. "
96+ + "Use it together with the --snapshot and --files options." );
8297 }
8398
8499 /**
@@ -396,7 +411,9 @@ public int doWork() throws IOException, InterruptedException {
396411 }
397412
398413 printInfo ();
399- if (showSchema ) printSchema ();
414+ if (showSchema ) {
415+ printSchema ();
416+ }
400417 printFiles (showFiles , showStats );
401418
402419 return 0 ;
@@ -516,7 +533,7 @@ private String fileSizeToString(long size) {
516533
517534 @ Override
518535 protected void addOptions () {
519- addRequiredOption (Options .SNAPSHOT );
536+ addOption (Options .SNAPSHOT );
520537 addOption (Options .REMOTE_DIR );
521538 addOption (Options .LIST_SNAPSHOTS );
522539 addOption (Options .FILES );
@@ -525,6 +542,24 @@ protected void addOptions() {
525542 addOption (Options .SIZE_IN_BYTES );
526543 }
527544
545+
546+ @ Override
547+ protected CommandLineParser newParser () {
548+ // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves
549+ // Validate in parse() to get helpful error messages instead of exploding in processOptions()
550+ return new DefaultParser () {
551+ @ Override
552+ public CommandLine parse (org .apache .hbase .thirdparty .org .apache .commons .cli .Options opts , String [] args , Properties props , boolean stop )
553+ throws ParseException {
554+ CommandLine cl = super .parse (opts , args , props , stop );
555+ if (!cmd .hasOption (Options .LIST_SNAPSHOTS ) && !cmd .hasOption (Options .SNAPSHOT )) {
556+ throw new ParseException ("Missing required snapshot option!" );
557+ }
558+ return cl ;
559+ }
560+ };
561+ }
562+
528563 @ Override
529564 protected void processOptions (CommandLine cmd ) {
530565 snapshotName = cmd .getOptionValue (Options .SNAPSHOT .getLongOpt ());
0 commit comments