You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ec...@apache.org on 2012/01/11 14:24:43 UTC

svn commit: r1230006 - in /incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core: conf/ util/shell/ util/shell/commands/

Author: ecn
Date: Wed Jan 11 13:24:42 2012
New Revision: 1230006

URL: http://svn.apache.org/viewvc?rev=1230006&view=rev
Log:
ACCUMULO-303: applying patch to allow per-table formatters in the shell

Modified:
    incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/conf/Property.java
    incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
    incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ConfigCommand.java
    incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java
    incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FormatterCommand.java

Modified: incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/conf/Property.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/conf/Property.java?rev=1230006&r1=1230005&r2=1230006&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/conf/Property.java (original)
+++ incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/conf/Property.java Wed Jan 11 13:24:42 2012
@@ -286,7 +286,9 @@ public enum Property {
           + "with the category prefix, followed by a name, followed by a period, and followed by a property for that group.<br />"
           + "For example table.group.group1=x,y,z sets the column families for a group called group1. Once configured, "
           + "group1 can be enabled by adding it to the list of groups in the " + TABLE_LOCALITY_GROUPS.getKey() + " property.<br />"
-          + "Additional group options may be specified for a named group by setting table.group.&lt;name&gt;.opt.&lt;key&gt;=&lt;value&gt;."), ;
+          + "Additional group options may be specified for a named group by setting table.group.&lt;name&gt;.opt.&lt;key&gt;=&lt;value&gt;."),
+  TABLE_FORMATTER_CLASS("table.formatter", "org.apache.accumulo.core.util.format.DefaultFormatter", PropertyType.STRING,
+      "The Formatter class to apply on results in the shell");
   
   private String key, defaultValue, description;
   private PropertyType type;

Modified: incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java?rev=1230006&r1=1230005&r2=1230006&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java (original)
+++ incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java Wed Jan 11 13:24:42 2012
@@ -163,8 +163,9 @@ public class Shell {
   private Connector connector;
   private ConsoleReader reader;
   private AuthInfo credentials;
-  private Class<? extends Formatter> formatterClass = DefaultFormatter.class;
+  private Class<? extends Formatter> defaultFormatterClass = DefaultFormatter.class;
   private Class<? extends Formatter> binaryFormatterClass = BinaryFormatter.class;
+  private Map<String, Class<? extends Formatter>> tableFormatters = new HashMap<String, Class<? extends Formatter>>();
   public Map<String,List<IteratorSetting>> scanIteratorOptions = new HashMap<String,List<IteratorSetting>>();
   
   private Token rootToken;
@@ -217,7 +218,7 @@ public class Shell {
     
     Option execCommandOpt = new Option("e", "execute-command", true, "executes a command, and then exits");
     opts.addOption(execCommandOpt);
-
+    
     OptionGroup execFileGroup = new OptionGroup();
     
     Option execfileOption = new Option("f", "execute-file", true, "executes commands from a file at startup");
@@ -459,8 +460,13 @@ public class Shell {
     else
       sb.append("- Authorization timeout: ").append(String.format("%.2fs\n", authTimeout / 1000.0));
     sb.append("- Debug: ").append(isDebuggingEnabled() ? "on" : "off").append("\n");
-    if (formatterClass != null && formatterClass != DefaultFormatter.class) {
-      sb.append("- Active formatter class: ").append(formatterClass.getSimpleName()).append("\n");
+    if (!tableFormatters.isEmpty()) {
+      sb.append("- Active Formatters");
+      for (Entry<String, Class<? extends Formatter>> entry : tableFormatters.entrySet()) {
+        if (null != entry.getValue()) {
+          sb.append("-    Table: ").append(entry.getKey()).append(", ").append(entry.getValue().getName()).append("\n");
+        }
+      }
     }
     if (!scanIteratorOptions.isEmpty()) {
       for (Entry<String,List<IteratorSetting>> entry : scanIteratorOptions.entrySet()) {
@@ -905,6 +911,8 @@ public class Shell {
   }
   
   public final void printRecords(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps, boolean paginate) throws IOException {
+    Class<? extends Formatter> formatterClass = getFormatterClass(this.tableName);
+    
     printLines(FormatterFactory.getFormatter(formatterClass, scanner, printTimestamps), paginate);
   }
   
@@ -989,12 +997,27 @@ public class Shell {
     return credentials;
   }
   
-  public void setFormatterClass(Class<? extends Formatter> formatterClass) {
-    this.formatterClass = formatterClass;
+  public void setFormatterClass(String tableName, Class<? extends Formatter> formatter) {
+    this.tableFormatters.put(tableName, formatter);
   }
   
-  public Class<? extends Formatter> getFormatterClass() {
-    return formatterClass;
+  /**
+   * Pull the current formatter for the given table and cache it.
+   * @param tableName
+   * @return The formatter class for the given table
+   */
+  public Class<? extends Formatter> getFormatterClass(String tableName) {
+    if (this.tableFormatters.containsKey(tableName) && null != this.tableFormatters.get(tableName)) {
+      return this.tableFormatters.get(tableName);
+    } else {
+      Class<? extends Formatter> formatter = FormatterCommand.getCurrentFormatter(tableName, this);
+      
+      if (null == formatter) {
+        return this.defaultFormatterClass;
+      } else {
+        return formatter;
+      }
+    }
   }
   
 }

Modified: incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ConfigCommand.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ConfigCommand.java?rev=1230006&r1=1230005&r2=1230006&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ConfigCommand.java (original)
+++ incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ConfigCommand.java Wed Jan 11 13:24:42 2012
@@ -32,9 +32,11 @@ import org.apache.accumulo.core.conf.Acc
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.security.ColumnVisibility;
 import org.apache.accumulo.core.util.BadArgumentException;
+import org.apache.accumulo.core.util.format.Formatter;
 import org.apache.accumulo.core.util.shell.Shell;
 import org.apache.accumulo.core.util.shell.Shell.Command;
 import org.apache.accumulo.core.util.shell.Token;
+import org.apache.accumulo.start.classloader.AccumuloClassLoader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionGroup;
@@ -59,7 +61,7 @@ public class ConfigCommand extends Comma
   }
   
   public int execute(String fullCommand, CommandLine cl, Shell shellState) throws AccumuloException, AccumuloSecurityException, TableNotFoundException,
-      IOException {
+  IOException, ClassNotFoundException {
     reader = shellState.getReader();
     
     String tableName = cl.getOptionValue(tableOpt.getOpt());
@@ -74,6 +76,12 @@ public class ConfigCommand extends Comma
       if (tableName != null) {
         if (!Property.isValidTablePropertyKey(property))
           Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if its there.");
+        
+        // Fall back to the default formatter
+        if (property.equals(Property.TABLE_FORMATTER_CLASS.getKey())) {
+          shellState.setFormatterClass(tableName, AccumuloClassLoader.loadClass(Property.TABLE_FORMATTER_CLASS.getDefaultValue(), Formatter.class));
+        }
+        
         shellState.getConnector().tableOperations().removeProperty(tableName, property);
         Shell.log.debug("Successfully deleted table configuration option.");
       } else {
@@ -100,6 +108,11 @@ public class ConfigCommand extends Comma
           new ColumnVisibility(value); // validate that it is a valid
         // expression
         
+        // Load the formatter before setting the parameter
+        if (property.equals(Property.TABLE_FORMATTER_CLASS.getKey())) {
+          shellState.setFormatterClass(tableName, AccumuloClassLoader.loadClass(value, Formatter.class));
+        }
+        
         shellState.getConnector().tableOperations().setProperty(tableName, property, value);
         Shell.log.debug("Successfully set table configuration option.");
       } else {

Modified: incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java?rev=1230006&r1=1230005&r2=1230006&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java (original)
+++ incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java Wed Jan 11 13:24:42 2012
@@ -36,8 +36,11 @@ import org.apache.accumulo.core.iterator
 import org.apache.accumulo.core.iterators.conf.PerColumnIteratorConfig;
 import org.apache.accumulo.core.security.VisibilityConstraint;
 import org.apache.accumulo.core.util.BadArgumentException;
+import org.apache.accumulo.core.util.format.DefaultFormatter;
+import org.apache.accumulo.core.util.format.Formatter;
 import org.apache.accumulo.core.util.shell.Shell;
 import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.start.classloader.AccumuloClassLoader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionGroup;
@@ -56,10 +59,11 @@ public class CreateTableCommand extends 
   private Option createTableNoDefaultIters;
   private Option createTableOptEVC;
   private Option base64Opt;
+  private Option createTableOptFormatter;
   public static String testTable;
   
   public int execute(String fullCommand, CommandLine cl, Shell shellState) throws AccumuloException, AccumuloSecurityException, TableExistsException,
-      TableNotFoundException, IOException {
+      TableNotFoundException, IOException, ClassNotFoundException {
     
     String testTableName = cl.getArgs()[0];
     
@@ -128,11 +132,13 @@ public class CreateTableCommand extends 
     TimeType timeType = TimeType.MILLIS;
     if (cl.hasOption(createTableOptTimeLogical.getOpt()))
       timeType = TimeType.LOGICAL;
+
     
     // create table
     shellState.getConnector().tableOperations().create(tableName, true, timeType);
     shellState.getConnector().tableOperations().addSplits(tableName, partitions);
     shellState.getConnector().tableOperations().addAggregators(tableName, aggregators);
+    
     shellState.setTableName(tableName); // switch shell to new table
     // context
     
@@ -173,6 +179,15 @@ public class CreateTableCommand extends 
         shellState.getConnector().tableOperations()
             .setProperty(tableName, Property.TABLE_CONSTRAINT_PREFIX.getKey() + (max + 1), VisibilityConstraint.class.getName());
     }
+
+    // Load custom formatter if set
+    if (cl.hasOption(createTableOptFormatter.getOpt())) {
+        String formatterClass = cl.getOptionValue(createTableOptFormatter.getOpt());
+        
+        shellState.setFormatterClass(tableName, AccumuloClassLoader.loadClass(formatterClass, Formatter.class));
+        
+        shellState.getConnector().tableOperations().setProperty(tableName, Property.TABLE_FORMATTER_CLASS.toString(), formatterClass);   
+    }    
     
     return 0;
   }
@@ -200,6 +215,7 @@ public class CreateTableCommand extends 
     createTableNoDefaultIters = new Option("ndi", "no-default-iterators", false, "prevents creation of the normal default iterator set");
     createTableOptEVC = new Option("evc", "enable-visibility-constraint", false,
         "prevents users from writing data they can not read.  When enabling this may want to consider disabling bulk import and alter table");
+    createTableOptFormatter = new Option("f", "formatter", false, "default formatter to set");
     
     createTableOptCopyConfig.setArgName("table");
     createTableOptCopySplits.setArgName("table");
@@ -226,6 +242,7 @@ public class CreateTableCommand extends 
     o.addOption(createTableOptCopyConfig);
     o.addOption(createTableNoDefaultIters);
     o.addOption(createTableOptEVC);
+    o.addOption(createTableOptFormatter);
     
     return o;
   }

Modified: incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FormatterCommand.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FormatterCommand.java?rev=1230006&r1=1230005&r2=1230006&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FormatterCommand.java (original)
+++ incubator/accumulo/branches/1.4/src/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FormatterCommand.java Wed Jan 11 13:24:42 2012
@@ -16,7 +16,12 @@
  */
 package org.apache.accumulo.core.util.shell.commands;
 
-import org.apache.accumulo.core.util.format.DefaultFormatter;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.util.format.Formatter;
 import org.apache.accumulo.core.util.shell.Shell;
 import org.apache.accumulo.core.util.shell.Shell.Command;
@@ -27,39 +32,106 @@ import org.apache.commons.cli.OptionGrou
 import org.apache.commons.cli.Options;
 
 public class FormatterCommand extends Command {
-  private Option resetOption, formatterClassOption, listClassOption;
+  private Option removeFormatterOption, formatterClassOption, listClassOption, tableOption;
   
   @Override
   public String description() {
-    return "specifies a formatter to use for displaying database entries";
+    return "specifies a formatter to use for displaying table entries";
   }
   
   @Override
   public int execute(String fullCommand, CommandLine cl, Shell shellState) throws Exception {
-    if (cl.hasOption(resetOption.getOpt()))
-      shellState.setFormatterClass(DefaultFormatter.class);
-    else if (cl.hasOption(formatterClassOption.getOpt()))
-      shellState.setFormatterClass(AccumuloClassLoader.loadClass(cl.getOptionValue(formatterClassOption.getOpt()), Formatter.class));
-    else if (cl.hasOption(listClassOption.getOpt()))
-      shellState.getReader().printString(shellState.getFormatterClass().getName() + "\n");
+    String tableName = shellState.getTableName();
+    
+    if (cl.hasOption(tableOption.getOpt())) {
+      tableName = cl.getOptionValue(tableOption.getOpt());
+    }
+    
+    if (cl.hasOption(removeFormatterOption.getOpt())) {
+      // Remove the property
+      shellState.getConnector().tableOperations().removeProperty(tableName, Property.TABLE_FORMATTER_CLASS.toString());
+      
+      // Reset the shell formatter on this table
+      shellState.setFormatterClass(tableName, AccumuloClassLoader.loadClass(Property.TABLE_FORMATTER_CLASS.getDefaultValue(), Formatter.class));
+      
+      shellState.getReader().printString("Removed formatter on " + tableName + "\n");
+    } else if (cl.hasOption(listClassOption.getOpt())) {
+      // Get the options for this table
+      Iterator<Entry<String,String>> iter = shellState.getConnector().tableOperations().getProperties(tableName).iterator();
+      
+      while (iter.hasNext()) {
+        Entry<String, String> ent = iter.next();
+        
+        // List all parameters with the property name
+        if (ent.getKey().startsWith(Property.TABLE_FORMATTER_CLASS.toString())) {
+          shellState.getReader().printString(ent.getKey() + ": " + ent.getValue() + "\n");
+        }
+      }
+    } else {
+      // Set the formatter with the provided options
+      String className = cl.getOptionValue(formatterClassOption.getOpt());
+      
+      // Update the shell formatter for this table
+      shellState.setFormatterClass(tableName, AccumuloClassLoader.loadClass(className, Formatter.class));
+      
+      shellState.getConnector().tableOperations().setProperty(tableName, Property.TABLE_FORMATTER_CLASS.toString(), className);
+    }
+    
     return 0;
   }
   
+  public static Class<? extends Formatter> getCurrentFormatter(String tableName, Shell shellState) {
+    Iterator<Entry<String, String>> props;
+    try {
+      props = shellState.getConnector().tableOperations().getProperties(tableName).iterator();
+    } catch (AccumuloException e) {
+      return null;
+    } catch (TableNotFoundException e) {
+      return null;
+    }
+    
+    while (props.hasNext()) {
+      Entry<String, String> ent = props.next();
+      if (ent.getKey().equals(Property.TABLE_FORMATTER_CLASS.toString())) {
+        Class<? extends Formatter> formatter;
+        try {
+          formatter = AccumuloClassLoader.loadClass(ent.getValue(), Formatter.class);
+          shellState.setFormatterClass(tableName, formatter);
+        } catch (ClassNotFoundException e) {
+          return null;
+        }
+        
+        return formatter;
+      }
+    }
+    
+    return null;
+  }
+  
   @Override
   public Options getOptions() {
     Options o = new Options();
-    OptionGroup formatGroup = new OptionGroup();
+    OptionGroup actionGroup = new OptionGroup();
+    
+    // Table and formatter class name
+    tableOption = new Option("t", "table", true, "table to set the formatter on");
+    tableOption.setArgName("table");
+    tableOption.setRequired(false);
     
-    resetOption = new Option("r", "reset", false, "reset to default formatter");
-    formatterClassOption = new Option("f", "formatter", true, "fully qualified name of formatter class to use");
+    formatterClassOption = new Option("f", "formatter", true, "fully qualified name of the formatter class to use");
     formatterClassOption.setArgName("className");
+    
+    // Action to take: apply (default), remove, list
+    removeFormatterOption = new Option("r", "remove", false, "remove the current formatter");
     listClassOption = new Option("l", "list", false, "display the current formatter");
-    formatGroup.addOption(resetOption);
-    formatGroup.addOption(formatterClassOption);
-    formatGroup.addOption(listClassOption);
-    formatGroup.setRequired(true);
     
-    o.addOptionGroup(formatGroup);
+    actionGroup.addOption(formatterClassOption);
+    actionGroup.addOption(removeFormatterOption);
+    actionGroup.addOption(listClassOption);
+    actionGroup.setRequired(true);
+    
+    o.addOptionGroup(actionGroup);
+    o.addOption(tableOption);
     
     return o;
   }