Merge branch '1.6' into 1.7

Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/4678cf92
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/4678cf92
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/4678cf92

Branch: refs/heads/1.7
Commit: 4678cf928a623467cd7cf678bb43b7f92967943d
Parents: 09ddfd4 eb0f9b4
Author: Christopher Tubbs <ctubb...@apache.org>
Authored: Fri Feb 19 21:45:39 2016 -0500
Committer: Christopher Tubbs <ctubb...@apache.org>
Committed: Fri Feb 19 21:45:39 2016 -0500

----------------------------------------------------------------------
 .../core/client/admin/TableOperations.java      |  4 +--
 .../shell/commands/DeleteRowsCommand.java       |  4 +--
 .../accumulo/shell/commands/MergeCommand.java   |  4 +--
 .../apache/accumulo/shell/commands/OptUtil.java |  2 +-
 .../accumulo/shell/commands/ScanCommand.java    |  5 +++-
 .../shell/commands/CompactCommandTest.java      | 29 ++++++++++++++++++++
 .../shell/commands/DeleteManyCommandTest.java   | 29 ++++++++++++++++++++
 .../shell/commands/DeleteRowsCommandTest.java   | 29 ++++++++++++++++++++
 .../shell/commands/FlushCommandTest.java        | 29 ++++++++++++++++++++
 .../shell/commands/MergeCommandTest.java        | 29 ++++++++++++++++++++
 .../shell/commands/ScanCommandTest.java         | 29 ++++++++++++++++++++
 11 files changed, 183 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperations.java
----------------------------------------------------------------------
diff --cc 
core/src/main/java/org/apache/accumulo/core/client/admin/TableOperations.java
index 2e15d26,bcad3a3..45b94a5
--- 
a/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperations.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperations.java
@@@ -297,10 -276,9 +297,10 @@@ public interface TableOperations 
     * @param start
     *          first tablet to be compacted contains the row after this row, 
null means the first tablet in table
     * @param end
-    *          last tablet to be merged contains this row, null means the last 
tablet in table
+    *          last tablet to be compacted contains this row, null means the 
last tablet in table
     * @param iterators
 -   *          A set of iterators that will be applied to each tablet compacted
 +   *          A set of iterators that will be applied to each tablet 
compacted. If two or more concurrent calls to compact pass iterators, then only 
one will
 +   *          succeed and the others will fail.
     * @param flush
     *          when true, table memory is flushed before compaction starts
     * @param wait

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteRowsCommand.java
----------------------------------------------------------------------
diff --cc 
shell/src/main/java/org/apache/accumulo/shell/commands/DeleteRowsCommand.java
index af7eb9a,0000000..527efe6
mode 100644,000000..100644
--- 
a/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteRowsCommand.java
+++ 
b/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteRowsCommand.java
@@@ -1,65 -1,0 +1,63 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.accumulo.shell.commands;
 +
 +import org.apache.accumulo.shell.Shell;
 +import org.apache.accumulo.shell.Shell.Command;
 +import org.apache.commons.cli.CommandLine;
 +import org.apache.commons.cli.Option;
 +import org.apache.commons.cli.Options;
 +import org.apache.hadoop.io.Text;
 +
 +public class DeleteRowsCommand extends Command {
 +  private Option forceOpt;
 +  private Option startRowOptExclusive;
 +
 +  @Override
 +  public int execute(final String fullCommand, final CommandLine cl, final 
Shell shellState) throws Exception {
 +    final String tableName = OptUtil.getTableOpt(cl, shellState);
 +    final Text startRow = OptUtil.getStartRow(cl);
 +    final Text endRow = OptUtil.getEndRow(cl);
 +    if (!cl.hasOption(forceOpt.getOpt()) && (startRow == null || endRow == 
null)) {
 +      shellState.getReader().println("Not deleting unbounded range. Specify 
both ends, or use --force");
 +      return 1;
 +    }
 +    shellState.getConnector().tableOperations().deleteRows(tableName, 
startRow, endRow);
 +    return 0;
 +  }
 +
 +  @Override
 +  public String description() {
 +    return "deletes a range of rows in a table.  Note that rows matching the 
start row ARE NOT deleted, but rows matching the end row ARE deleted.";
 +  }
 +
 +  @Override
 +  public int numArgs() {
 +    return 0;
 +  }
 +
 +  @Override
 +  public Options getOptions() {
 +    final Options o = new Options();
 +    forceOpt = new Option("f", "force", false, "delete data even if start or 
end are not specified");
-     startRowOptExclusive = new Option(OptUtil.START_ROW_OPT, "begin-row", 
true, "begin row (exclusive)");
-     startRowOptExclusive.setArgName("begin-row");
-     o.addOption(startRowOptExclusive);
++    o.addOption(OptUtil.startRowOpt());
 +    o.addOption(OptUtil.endRowOpt());
 +    o.addOption(OptUtil.tableOpt("table to delete a row range from"));
 +    o.addOption(forceOpt);
 +    return o;
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/main/java/org/apache/accumulo/shell/commands/MergeCommand.java
----------------------------------------------------------------------
diff --cc 
shell/src/main/java/org/apache/accumulo/shell/commands/MergeCommand.java
index 90fcace,0000000..0da53c0
mode 100644,000000..100644
--- a/shell/src/main/java/org/apache/accumulo/shell/commands/MergeCommand.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/commands/MergeCommand.java
@@@ -1,112 -1,0 +1,110 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.accumulo.shell.commands;
 +
 +import java.io.IOException;
 +
 +import org.apache.accumulo.core.conf.AccumuloConfiguration;
 +import org.apache.accumulo.core.util.Merge;
 +import org.apache.accumulo.shell.Shell;
 +import org.apache.accumulo.shell.Shell.Command;
 +import org.apache.commons.cli.CommandLine;
 +import org.apache.commons.cli.Option;
 +import org.apache.commons.cli.Options;
 +import org.apache.hadoop.io.Text;
 +
 +public class MergeCommand extends Command {
 +  private Option verboseOpt, forceOpt, sizeOpt, allOpt;
 +
 +  @Override
 +  public int execute(final String fullCommand, final CommandLine cl, final 
Shell shellState) throws Exception {
 +    boolean verbose = shellState.isVerbose();
 +    boolean force = false;
 +    boolean all = false;
 +    long size = -1;
 +    final String tableName = OptUtil.getTableOpt(cl, shellState);
 +    final Text startRow = OptUtil.getStartRow(cl);
 +    final Text endRow = OptUtil.getEndRow(cl);
 +    if (cl.hasOption(verboseOpt.getOpt())) {
 +      verbose = true;
 +    }
 +    if (cl.hasOption(forceOpt.getOpt())) {
 +      force = true;
 +    }
 +    if (cl.hasOption(allOpt.getOpt())) {
 +      all = true;
 +    }
 +    if (cl.hasOption(sizeOpt.getOpt())) {
 +      size = 
AccumuloConfiguration.getMemoryInBytes(cl.getOptionValue(sizeOpt.getOpt()));
 +    }
 +    if (startRow == null && endRow == null && size < 0 && !all) {
 +      shellState.getReader().flush();
 +      String line = shellState.getReader().readLine("Merge the entire table { 
" + tableName + " } into one tablet (yes|no)? ");
 +      if (line == null)
 +        return 0;
 +      if (!line.equalsIgnoreCase("y") && !line.equalsIgnoreCase("yes"))
 +        return 0;
 +    }
 +    if (size < 0) {
 +      shellState.getConnector().tableOperations().merge(tableName, startRow, 
endRow);
 +    } else {
 +      final boolean finalVerbose = verbose;
 +      final Merge merge = new Merge() {
 +        @Override
 +        protected void message(String fmt, Object... args) {
 +          if (finalVerbose) {
 +            try {
 +              shellState.getReader().println(String.format(fmt, args));
 +            } catch (IOException ex) {
 +              throw new RuntimeException(ex);
 +            }
 +          }
 +        }
 +      };
 +      merge.mergomatic(shellState.getConnector(), tableName, startRow, 
endRow, size, force);
 +    }
 +    return 0;
 +  }
 +
 +  @Override
 +  public String description() {
 +    return "merges tablets in a table";
 +  }
 +
 +  @Override
 +  public int numArgs() {
 +    return 0;
 +  }
 +
 +  @Override
 +  public Options getOptions() {
 +    final Options o = new Options();
 +    verboseOpt = new Option("v", "verbose", false, "verbose output during 
merge");
 +    sizeOpt = new Option("s", "size", true, "merge tablets to the given size 
over the entire table");
 +    forceOpt = new Option("f", "force", false, "merge small tablets to large 
tablets, even if it goes over the given size");
 +    allOpt = new Option("", "all", false, "allow an entire table to be merged 
into one tablet without prompting the user for confirmation");
-     Option startRowOpt = OptUtil.startRowOpt();
-     startRowOpt.setDescription("begin row (NOT inclusive)");
-     o.addOption(startRowOpt);
++    o.addOption(OptUtil.startRowOpt());
 +    o.addOption(OptUtil.endRowOpt());
 +    o.addOption(OptUtil.tableOpt("table to be merged"));
 +    o.addOption(verboseOpt);
 +    o.addOption(sizeOpt);
 +    o.addOption(forceOpt);
 +    o.addOption(allOpt);
 +    return o;
 +  }
 +
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/main/java/org/apache/accumulo/shell/commands/OptUtil.java
----------------------------------------------------------------------
diff --cc shell/src/main/java/org/apache/accumulo/shell/commands/OptUtil.java
index 16d7220,0000000..eb8833f
mode 100644,000000..100644
--- a/shell/src/main/java/org/apache/accumulo/shell/commands/OptUtil.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/commands/OptUtil.java
@@@ -1,147 -1,0 +1,147 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.accumulo.shell.commands;
 +
 +import java.io.UnsupportedEncodingException;
 +
 +import org.apache.accumulo.core.client.AccumuloException;
 +import org.apache.accumulo.core.client.AccumuloSecurityException;
 +import org.apache.accumulo.core.client.NamespaceNotFoundException;
 +import org.apache.accumulo.core.client.TableNotFoundException;
 +import org.apache.accumulo.shell.Shell;
 +import org.apache.accumulo.shell.ShellOptions;
 +import org.apache.commons.cli.CommandLine;
 +import org.apache.commons.cli.Option;
 +import org.apache.commons.cli.OptionGroup;
 +import org.apache.hadoop.io.Text;
 +
 +public abstract class OptUtil {
 +  public static final String START_ROW_OPT = "b";
 +  public static final String END_ROW_OPT = "e";
 +
 +  public static String getTableOpt(final CommandLine cl, final Shell 
shellState) throws TableNotFoundException {
 +    String tableName;
 +
 +    if (cl.hasOption(ShellOptions.tableOption)) {
 +      tableName = cl.getOptionValue(ShellOptions.tableOption);
 +      if (!shellState.getConnector().tableOperations().exists(tableName)) {
 +        throw new TableNotFoundException(tableName, tableName, "specified 
table that doesn't exist");
 +      }
 +    } else {
 +      shellState.checkTableState();
 +      tableName = shellState.getTableName();
 +    }
 +
 +    return tableName;
 +  }
 +
 +  public static String getNamespaceOpt(final CommandLine cl, final Shell 
shellState) throws NamespaceNotFoundException, AccumuloException,
 +      AccumuloSecurityException {
 +    String namespace = null;
 +    if (cl.hasOption(ShellOptions.namespaceOption)) {
 +      namespace = cl.getOptionValue(ShellOptions.namespaceOption);
 +      if (!shellState.getConnector().namespaceOperations().exists(namespace)) 
{
 +        throw new NamespaceNotFoundException(namespace, namespace, "specified 
namespace that doesn't exist");
 +      }
 +    } else {
 +      throw new NamespaceNotFoundException(null, null, "no namespace 
specified");
 +    }
 +    return namespace;
 +  }
 +
 +  public static Option tableOpt() {
 +    return tableOpt("tableName");
 +  }
 +
 +  public static Option tableOpt(final String description) {
 +    final Option tableOpt = new Option(ShellOptions.tableOption, "table", 
true, description);
 +    tableOpt.setArgName("table");
 +    tableOpt.setRequired(false);
 +    return tableOpt;
 +  }
 +
 +  public static Option namespaceOpt() {
 +    return namespaceOpt("namespace");
 +  }
 +
 +  public static Option namespaceOpt(final String description) {
 +    final Option namespaceOpt = new Option(ShellOptions.namespaceOption, 
"namespace", true, description);
 +    namespaceOpt.setArgName("namespace");
 +    namespaceOpt.setRequired(false);
 +    return namespaceOpt;
 +  }
 +
 +  public static enum AdlOpt {
 +    ADD("a"), DELETE("d"), LIST("l");
 +
 +    public final String opt;
 +
 +    private AdlOpt(String opt) {
 +      this.opt = opt;
 +    }
 +  }
 +
 +  public static AdlOpt getAldOpt(final CommandLine cl) {
 +    if (cl.hasOption(AdlOpt.ADD.opt)) {
 +      return AdlOpt.ADD;
 +    } else if (cl.hasOption(AdlOpt.DELETE.opt)) {
 +      return AdlOpt.DELETE;
 +    } else {
 +      return AdlOpt.LIST;
 +    }
 +  }
 +
 +  public static OptionGroup addListDeleteGroup(final String name) {
 +    final Option addOpt = new Option(AdlOpt.ADD.opt, "add", false, "add " + 
name);
 +    final Option deleteOpt = new Option(AdlOpt.DELETE.opt, "delete", false, 
"delete " + name);
 +    final Option listOpt = new Option(AdlOpt.LIST.opt, "list", false, "list " 
+ name + "(s)");
 +    final OptionGroup og = new OptionGroup();
 +    og.addOption(addOpt);
 +    og.addOption(deleteOpt);
 +    og.addOption(listOpt);
 +    og.setRequired(true);
 +    return og;
 +  }
 +
 +  public static Option startRowOpt() {
-     final Option o = new Option(START_ROW_OPT, "begin-row", true, "begin row 
(inclusive)");
++    final Option o = new Option(START_ROW_OPT, "begin-row", true, "begin row 
(exclusive)");
 +    o.setArgName("begin-row");
 +    return o;
 +  }
 +
 +  public static Option endRowOpt() {
 +    final Option o = new Option(END_ROW_OPT, "end-row", true, "end row 
(inclusive)");
 +    o.setArgName("end-row");
 +    return o;
 +  }
 +
 +  public static Text getStartRow(final CommandLine cl) throws 
UnsupportedEncodingException {
 +    if (cl.hasOption(START_ROW_OPT)) {
 +      return new 
Text(cl.getOptionValue(START_ROW_OPT).getBytes(Shell.CHARSET));
 +    } else {
 +      return null;
 +    }
 +  }
 +
 +  public static Text getEndRow(final CommandLine cl) throws 
UnsupportedEncodingException {
 +    if (cl.hasOption(END_ROW_OPT)) {
 +      return new Text(cl.getOptionValue(END_ROW_OPT).getBytes(Shell.CHARSET));
 +    } else {
 +      return null;
 +    }
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java
----------------------------------------------------------------------
diff --cc 
shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java
index 3531fe9,0000000..6f1ddd3
mode 100644,000000..100644
--- a/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java
@@@ -1,340 -1,0 +1,343 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.accumulo.shell.commands;
 +
 +import java.io.FileNotFoundException;
 +import java.io.IOException;
 +import java.io.UnsupportedEncodingException;
 +import java.util.List;
 +import java.util.Map.Entry;
 +import java.util.concurrent.TimeUnit;
 +
 +import org.apache.accumulo.core.client.AccumuloException;
 +import org.apache.accumulo.core.client.AccumuloSecurityException;
 +import org.apache.accumulo.core.client.IteratorSetting;
 +import org.apache.accumulo.core.client.Scanner;
 +import org.apache.accumulo.core.client.ScannerBase;
 +import org.apache.accumulo.core.client.TableNotFoundException;
 +import org.apache.accumulo.core.conf.AccumuloConfiguration;
 +import org.apache.accumulo.core.data.Key;
 +import org.apache.accumulo.core.data.Range;
 +import org.apache.accumulo.core.data.Value;
 +import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
 +import org.apache.accumulo.core.security.Authorizations;
 +import org.apache.accumulo.core.util.format.BinaryFormatter;
 +import org.apache.accumulo.core.util.format.Formatter;
 +import org.apache.accumulo.core.util.interpret.DefaultScanInterpreter;
 +import org.apache.accumulo.core.util.interpret.ScanInterpreter;
 +import org.apache.accumulo.shell.Shell;
 +import org.apache.accumulo.shell.Shell.Command;
 +import org.apache.accumulo.shell.Shell.PrintFile;
 +import org.apache.accumulo.shell.ShellCommandException;
 +import org.apache.accumulo.shell.ShellCommandException.ErrorCode;
 +import org.apache.accumulo.start.classloader.vfs.AccumuloVFSClassLoader;
 +import org.apache.commons.cli.CommandLine;
 +import org.apache.commons.cli.Option;
 +import org.apache.commons.cli.Options;
 +import org.apache.hadoop.io.Text;
 +
 +public class ScanCommand extends Command {
 +
 +  private Option scanOptAuths, scanOptRow, scanOptColumns, 
disablePaginationOpt, showFewOpt, formatterOpt, interpreterOpt, 
formatterInterpeterOpt,
 +      outputFileOpt;
 +
 +  protected Option timestampOpt;
 +  private Option optStartRowExclusive;
++  private Option optStartRowInclusive;
 +  private Option optEndRowExclusive;
 +  private Option timeoutOption;
 +  private Option profileOpt;
 +
 +  @Override
 +  public int execute(final String fullCommand, final CommandLine cl, final 
Shell shellState) throws Exception {
 +    final PrintFile printFile = getOutputFile(cl);
 +    final String tableName = OptUtil.getTableOpt(cl, shellState);
 +
 +    final Class<? extends Formatter> formatter = getFormatter(cl, tableName, 
shellState);
 +    final ScanInterpreter interpeter = getInterpreter(cl, tableName, 
shellState);
 +
 +    // handle first argument, if present, the authorizations list to
 +    // scan with
 +    final Authorizations auths = getAuths(cl, shellState);
 +    final Scanner scanner = 
shellState.getConnector().createScanner(tableName, auths);
 +
 +    // handle session-specific scan iterators
 +    addScanIterators(shellState, cl, scanner, tableName);
 +
 +    // handle remaining optional arguments
 +    scanner.setRange(getRange(cl, interpeter));
 +
 +    // handle columns
 +    fetchColumns(cl, scanner, interpeter);
 +
 +    // set timeout
 +    scanner.setTimeout(getTimeout(cl), TimeUnit.MILLISECONDS);
 +
 +    // output the records
 +    if (cl.hasOption(showFewOpt.getOpt())) {
 +      final String showLength = cl.getOptionValue(showFewOpt.getOpt());
 +      try {
 +        final int length = Integer.parseInt(showLength);
 +        if (length < 1) {
 +          throw new IllegalArgumentException();
 +        }
 +        BinaryFormatter.getlength(length);
 +        printBinaryRecords(cl, shellState, scanner, printFile);
 +      } catch (NumberFormatException nfe) {
 +        shellState.getReader().println("Arg must be an integer.");
 +      } catch (IllegalArgumentException iae) {
 +        shellState.getReader().println("Arg must be greater than one.");
 +      }
 +
 +    } else {
 +      printRecords(cl, shellState, scanner, formatter, printFile);
 +    }
 +    if (printFile != null) {
 +      printFile.close();
 +    }
 +
 +    return 0;
 +  }
 +
 +  protected long getTimeout(final CommandLine cl) {
 +    if (cl.hasOption(timeoutOption.getLongOpt())) {
 +      return 
AccumuloConfiguration.getTimeInMillis(cl.getOptionValue(timeoutOption.getLongOpt()));
 +    }
 +
 +    return Long.MAX_VALUE;
 +  }
 +
 +  static void ensureTserversCanLoadIterator(final Shell shellState, String 
tableName, String classname) throws AccumuloException, 
AccumuloSecurityException,
 +      TableNotFoundException, ShellCommandException {
 +    if (!shellState.getConnector().tableOperations().testClassLoad(tableName, 
classname, SortedKeyValueIterator.class.getName())) {
 +      throw new ShellCommandException(ErrorCode.INITIALIZATION_FAILURE, 
"Servers are unable to load " + classname + " as type "
 +          + SortedKeyValueIterator.class.getName());
 +    }
 +  }
 +
 +  protected void addScanIterators(final Shell shellState, CommandLine cl, 
final Scanner scanner, final String tableName) throws Exception {
 +
 +    List<IteratorSetting> tableScanIterators;
 +    if (cl.hasOption(profileOpt.getOpt())) {
 +      String profile = cl.getOptionValue(profileOpt.getOpt());
 +      tableScanIterators = shellState.iteratorProfiles.get(profile);
 +
 +      if (tableScanIterators == null) {
 +        throw new IllegalArgumentException("Profile " + profile + " does not 
exist");
 +      }
 +
 +      for (IteratorSetting iteratorSetting : tableScanIterators) {
 +        ensureTserversCanLoadIterator(shellState, tableName, 
iteratorSetting.getIteratorClass());
 +      }
 +    } else {
 +      tableScanIterators = shellState.scanIteratorOptions.get(tableName);
 +      if (tableScanIterators == null) {
 +        Shell.log.debug("Found no scan iterators to set");
 +        return;
 +      }
 +    }
 +
 +    Shell.log.debug("Found " + tableScanIterators.size() + " scan iterators 
to set");
 +
 +    for (IteratorSetting setting : tableScanIterators) {
 +      Shell.log.debug("Setting scan iterator " + setting.getName() + " at 
priority " + setting.getPriority() + " using class name "
 +          + setting.getIteratorClass());
 +      for (Entry<String,String> option : setting.getOptions().entrySet()) {
 +        Shell.log.debug("Setting option for " + setting.getName() + ": " + 
option.getKey() + "=" + option.getValue());
 +      }
 +      scanner.addScanIterator(setting);
 +    }
 +  }
 +
 +  protected void printRecords(final CommandLine cl, final Shell shellState, 
final Iterable<Entry<Key,Value>> scanner,
 +      final Class<? extends Formatter> formatter, PrintFile outFile) throws 
IOException {
 +    if (outFile == null) {
 +      shellState.printRecords(scanner, cl.hasOption(timestampOpt.getOpt()), 
!cl.hasOption(disablePaginationOpt.getOpt()), formatter);
 +    } else {
 +      shellState.printRecords(scanner, cl.hasOption(timestampOpt.getOpt()), 
!cl.hasOption(disablePaginationOpt.getOpt()), formatter, outFile);
 +    }
 +  }
 +
 +  protected void printBinaryRecords(final CommandLine cl, final Shell 
shellState, final Iterable<Entry<Key,Value>> scanner, PrintFile outFile)
 +      throws IOException {
 +    if (outFile == null) {
 +      shellState.printBinaryRecords(scanner, 
cl.hasOption(timestampOpt.getOpt()), 
!cl.hasOption(disablePaginationOpt.getOpt()));
 +    } else {
 +      shellState.printBinaryRecords(scanner, 
cl.hasOption(timestampOpt.getOpt()), 
!cl.hasOption(disablePaginationOpt.getOpt()), outFile);
 +    }
 +  }
 +
 +  protected ScanInterpreter getInterpreter(final CommandLine cl, final String 
tableName, final Shell shellState) throws Exception {
 +
 +    Class<? extends ScanInterpreter> clazz = null;
 +    try {
 +      if (cl.hasOption(interpreterOpt.getOpt())) {
 +        clazz = 
AccumuloVFSClassLoader.loadClass(cl.getOptionValue(interpreterOpt.getOpt()), 
ScanInterpreter.class);
 +      } else if (cl.hasOption(formatterInterpeterOpt.getOpt())) {
 +        clazz = 
AccumuloVFSClassLoader.loadClass(cl.getOptionValue(formatterInterpeterOpt.getOpt()),
 ScanInterpreter.class);
 +      }
 +    } catch (ClassNotFoundException e) {
 +      shellState.getReader().println("Interpreter class could not be 
loaded.\n" + e.getMessage());
 +    }
 +
 +    if (clazz == null)
 +      clazz = InterpreterCommand.getCurrentInterpreter(tableName, shellState);
 +
 +    if (clazz == null)
 +      clazz = DefaultScanInterpreter.class;
 +
 +    return clazz.newInstance();
 +  }
 +
 +  protected Class<? extends Formatter> getFormatter(final CommandLine cl, 
final String tableName, final Shell shellState) throws IOException {
 +
 +    try {
 +      if (cl.hasOption(formatterOpt.getOpt())) {
 +        return shellState.getClassLoader(cl, 
shellState).loadClass(cl.getOptionValue(formatterOpt.getOpt())).asSubclass(Formatter.class);
 +      } else if (cl.hasOption(formatterInterpeterOpt.getOpt())) {
 +        return shellState.getClassLoader(cl, 
shellState).loadClass(cl.getOptionValue(formatterInterpeterOpt.getOpt())).asSubclass(Formatter.class);
 +      }
 +    } catch (Exception e) {
 +      shellState.getReader().println("Formatter class could not be loaded.\n" 
+ e.getMessage());
 +    }
 +
 +    return shellState.getFormatter(tableName);
 +  }
 +
 +  protected void fetchColumns(final CommandLine cl, final ScannerBase 
scanner, final ScanInterpreter formatter) throws UnsupportedEncodingException {
 +    if (cl.hasOption(scanOptColumns.getOpt())) {
 +      for (String a : cl.getOptionValue(scanOptColumns.getOpt()).split(",")) {
 +        final String sa[] = a.split(":", 2);
 +        if (sa.length == 1) {
 +          scanner.fetchColumnFamily(formatter.interpretColumnFamily(new 
Text(a.getBytes(Shell.CHARSET))));
 +        } else {
 +          scanner.fetchColumn(formatter.interpretColumnFamily(new 
Text(sa[0].getBytes(Shell.CHARSET))),
 +              formatter.interpretColumnQualifier(new 
Text(sa[1].getBytes(Shell.CHARSET))));
 +        }
 +      }
 +    }
 +  }
 +
 +  protected Range getRange(final CommandLine cl, final ScanInterpreter 
formatter) throws UnsupportedEncodingException {
 +    if ((cl.hasOption(OptUtil.START_ROW_OPT) || 
cl.hasOption(OptUtil.END_ROW_OPT)) && cl.hasOption(scanOptRow.getOpt())) {
 +      // did not see a way to make commons cli do this check... it has 
mutually exclusive options but does not support the or
 +      throw new IllegalArgumentException("Options -" + scanOptRow.getOpt() + 
" AND (-" + OptUtil.START_ROW_OPT + " OR -" + OptUtil.END_ROW_OPT
 +          + ") are mutally exclusive ");
 +    }
 +
 +    if (cl.hasOption(scanOptRow.getOpt())) {
 +      return new Range(formatter.interpretRow(new 
Text(cl.getOptionValue(scanOptRow.getOpt()).getBytes(Shell.CHARSET))));
 +    } else {
 +      Text startRow = OptUtil.getStartRow(cl);
 +      if (startRow != null)
 +        startRow = formatter.interpretBeginRow(startRow);
 +      Text endRow = OptUtil.getEndRow(cl);
 +      if (endRow != null)
 +        endRow = formatter.interpretEndRow(endRow);
 +      final boolean startInclusive = 
!cl.hasOption(optStartRowExclusive.getOpt());
 +      final boolean endInclusive = !cl.hasOption(optEndRowExclusive.getOpt());
 +      return new Range(startRow, startInclusive, endRow, endInclusive);
 +    }
 +  }
 +
 +  protected Authorizations getAuths(final CommandLine cl, final Shell 
shellState) throws AccumuloSecurityException, AccumuloException {
 +    final String user = shellState.getConnector().whoami();
 +    Authorizations auths = 
shellState.getConnector().securityOperations().getUserAuthorizations(user);
 +    if (cl.hasOption(scanOptAuths.getOpt())) {
 +      auths = 
ScanCommand.parseAuthorizations(cl.getOptionValue(scanOptAuths.getOpt()));
 +    }
 +    return auths;
 +  }
 +
 +  static Authorizations parseAuthorizations(final String field) {
 +    if (field == null || field.isEmpty()) {
 +      return Authorizations.EMPTY;
 +    }
 +    return new Authorizations(field.split(","));
 +  }
 +
 +  @Override
 +  public String description() {
 +    return "scans the table, and displays the resulting records";
 +  }
 +
 +  @Override
 +  public Options getOptions() {
 +    final Options o = new Options();
 +
 +    scanOptAuths = new Option("s", "scan-authorizations", true, "scan 
authorizations (all user auths are used if this argument is not specified)");
 +    optStartRowExclusive = new Option("be", "begin-exclusive", false, "make 
start row exclusive (by default it's inclusive)");
 +    optStartRowExclusive.setArgName("begin-exclusive");
 +    optEndRowExclusive = new Option("ee", "end-exclusive", false, "make end 
row exclusive (by default it's inclusive)");
 +    optEndRowExclusive.setArgName("end-exclusive");
 +    scanOptRow = new Option("r", "row", true, "row to scan");
 +    scanOptColumns = new Option("c", "columns", true, "comma-separated 
columns");
 +    timestampOpt = new Option("st", "show-timestamps", false, "display 
timestamps");
 +    disablePaginationOpt = new Option("np", "no-pagination", false, "disable 
pagination of output");
 +    showFewOpt = new Option("f", "show-few", true, "show only a specified 
number of characters");
 +    formatterOpt = new Option("fm", "formatter", true, "fully qualified name 
of the formatter class to use");
 +    interpreterOpt = new Option("i", "interpreter", true, "fully qualified 
name of the interpreter class to use");
 +    formatterInterpeterOpt = new Option("fi", "fmt-interpreter", true, "fully 
qualified name of a class that is a formatter and interpreter");
 +    timeoutOption = new Option(null, "timeout", true,
 +        "time before scan should fail if no data is returned. If no unit is 
given assumes seconds.  Units d,h,m,s,and ms are supported.  e.g. 30s or 
100ms");
 +    outputFileOpt = new Option("o", "output", true, "local file to write the 
scan output to");
 +
 +    scanOptAuths.setArgName("comma-separated-authorizations");
 +    scanOptRow.setArgName("row");
 +    
scanOptColumns.setArgName("<columnfamily>[:<columnqualifier>]{,<columnfamily>[:<columnqualifier>]}");
 +    showFewOpt.setRequired(false);
 +    showFewOpt.setArgName("int");
 +    formatterOpt.setArgName("className");
 +    timeoutOption.setArgName("timeout");
 +    outputFileOpt.setArgName("file");
 +
 +    profileOpt = new Option("pn", "profile", true, "iterator profile name");
 +    profileOpt.setArgName("profile");
 +
 +    o.addOption(scanOptAuths);
 +    o.addOption(scanOptRow);
-     o.addOption(OptUtil.startRowOpt());
++    optStartRowInclusive = new Option(OptUtil.START_ROW_OPT, "begin-row", 
true, "begin row (inclusive)");
++    optStartRowInclusive.setArgName("begin-row");
++    o.addOption(optStartRowInclusive);
 +    o.addOption(OptUtil.endRowOpt());
 +    o.addOption(optStartRowExclusive);
 +    o.addOption(optEndRowExclusive);
 +    o.addOption(scanOptColumns);
 +    o.addOption(timestampOpt);
 +    o.addOption(disablePaginationOpt);
 +    o.addOption(OptUtil.tableOpt("table to be scanned"));
 +    o.addOption(showFewOpt);
 +    o.addOption(formatterOpt);
 +    o.addOption(interpreterOpt);
 +    o.addOption(formatterInterpeterOpt);
 +    o.addOption(timeoutOption);
 +    o.addOption(outputFileOpt);
 +    o.addOption(profileOpt);
 +
 +    return o;
 +  }
 +
 +  @Override
 +  public int numArgs() {
 +    return 0;
 +  }
 +
 +  protected PrintFile getOutputFile(final CommandLine cl) throws 
FileNotFoundException {
 +    final String outputFile = cl.getOptionValue(outputFileOpt.getOpt());
 +    return (outputFile == null ? null : new PrintFile(outputFile));
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/test/java/org/apache/accumulo/shell/commands/CompactCommandTest.java
----------------------------------------------------------------------
diff --cc 
shell/src/test/java/org/apache/accumulo/shell/commands/CompactCommandTest.java
index 0000000,0000000..928f7f2
new file mode 100644
--- /dev/null
+++ 
b/shell/src/test/java/org/apache/accumulo/shell/commands/CompactCommandTest.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.accumulo.shell.commands;
++
++import static org.junit.Assert.assertTrue;
++import org.junit.Test;
++
++public class CompactCommandTest {
++
++  @Test
++  public void testBeginRowHelp() {
++    assertTrue("-b should say it is exclusive", new 
CompactCommand().getOptions().getOption("b").getDescription().contains("(exclusive)"));
++  }
++
++}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/test/java/org/apache/accumulo/shell/commands/DeleteManyCommandTest.java
----------------------------------------------------------------------
diff --cc 
shell/src/test/java/org/apache/accumulo/shell/commands/DeleteManyCommandTest.java
index 0000000,0000000..bfe370b
new file mode 100644
--- /dev/null
+++ 
b/shell/src/test/java/org/apache/accumulo/shell/commands/DeleteManyCommandTest.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.accumulo.shell.commands;
++
++import static org.junit.Assert.assertTrue;
++import org.junit.Test;
++
++public class DeleteManyCommandTest {
++
++  @Test
++  public void testBeginRowHelp() {
++    assertTrue("-b should say it is inclusive", new 
DeleteManyCommand().getOptions().getOption("b").getDescription().contains("row 
(inclusive)"));
++  }
++
++}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/test/java/org/apache/accumulo/shell/commands/DeleteRowsCommandTest.java
----------------------------------------------------------------------
diff --cc 
shell/src/test/java/org/apache/accumulo/shell/commands/DeleteRowsCommandTest.java
index 0000000,0000000..0cf8c11
new file mode 100644
--- /dev/null
+++ 
b/shell/src/test/java/org/apache/accumulo/shell/commands/DeleteRowsCommandTest.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.accumulo.shell.commands;
++
++import static org.junit.Assert.assertTrue;
++import org.junit.Test;
++
++public class DeleteRowsCommandTest {
++
++  @Test
++  public void testBeginRowHelp() {
++    assertTrue("-b should say it is exclusive", new 
DeleteRowsCommand().getOptions().getOption("b").getDescription().contains("(exclusive)"));
++  }
++
++}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/test/java/org/apache/accumulo/shell/commands/FlushCommandTest.java
----------------------------------------------------------------------
diff --cc 
shell/src/test/java/org/apache/accumulo/shell/commands/FlushCommandTest.java
index 0000000,0000000..7250427
new file mode 100644
--- /dev/null
+++ 
b/shell/src/test/java/org/apache/accumulo/shell/commands/FlushCommandTest.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.accumulo.shell.commands;
++
++import static org.junit.Assert.assertTrue;
++import org.junit.Test;
++
++public class FlushCommandTest {
++
++  @Test
++  public void testBeginRowHelp() {
++    assertTrue("-b should say it is exclusive", new 
FlushCommand().getOptions().getOption("b").getDescription().contains("(exclusive)"));
++  }
++
++}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/test/java/org/apache/accumulo/shell/commands/MergeCommandTest.java
----------------------------------------------------------------------
diff --cc 
shell/src/test/java/org/apache/accumulo/shell/commands/MergeCommandTest.java
index 0000000,0000000..5cd2f2e
new file mode 100644
--- /dev/null
+++ 
b/shell/src/test/java/org/apache/accumulo/shell/commands/MergeCommandTest.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.accumulo.shell.commands;
++
++import static org.junit.Assert.assertTrue;
++import org.junit.Test;
++
++public class MergeCommandTest {
++
++  @Test
++  public void testBeginRowHelp() {
++    assertTrue("-b should say it is exclusive", new 
MergeCommand().getOptions().getOption("b").getDescription().contains("(exclusive)"));
++  }
++
++}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4678cf92/shell/src/test/java/org/apache/accumulo/shell/commands/ScanCommandTest.java
----------------------------------------------------------------------
diff --cc 
shell/src/test/java/org/apache/accumulo/shell/commands/ScanCommandTest.java
index 0000000,0000000..173d8a1
new file mode 100644
--- /dev/null
+++ 
b/shell/src/test/java/org/apache/accumulo/shell/commands/ScanCommandTest.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.accumulo.shell.commands;
++
++import static org.junit.Assert.assertTrue;
++import org.junit.Test;
++
++public class ScanCommandTest {
++
++  @Test
++  public void testBeginRowHelp() {
++    assertTrue("-b should say it is inclusive", new 
ScanCommand().getOptions().getOption("b").getDescription().contains("row 
(inclusive)"));
++  }
++
++}

Reply via email to