accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [02/54] ACCUMULO-802 Apply Sean Hickey's patch (v5)
Date Fri, 01 Nov 2013 02:00:03 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java b/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
index 52e1d04..cdb86f1 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
@@ -73,6 +73,7 @@ import org.apache.accumulo.core.util.shell.commands.ClsCommand;
 import org.apache.accumulo.core.util.shell.commands.CompactCommand;
 import org.apache.accumulo.core.util.shell.commands.ConfigCommand;
 import org.apache.accumulo.core.util.shell.commands.ConstraintCommand;
+import org.apache.accumulo.core.util.shell.commands.CreateNamespaceCommand;
 import org.apache.accumulo.core.util.shell.commands.CreateTableCommand;
 import org.apache.accumulo.core.util.shell.commands.CreateUserCommand;
 import org.apache.accumulo.core.util.shell.commands.DUCommand;
@@ -80,6 +81,7 @@ import org.apache.accumulo.core.util.shell.commands.DebugCommand;
 import org.apache.accumulo.core.util.shell.commands.DeleteCommand;
 import org.apache.accumulo.core.util.shell.commands.DeleteIterCommand;
 import org.apache.accumulo.core.util.shell.commands.DeleteManyCommand;
+import org.apache.accumulo.core.util.shell.commands.DeleteNamespaceCommand;
 import org.apache.accumulo.core.util.shell.commands.DeleteRowsCommand;
 import org.apache.accumulo.core.util.shell.commands.DeleteScanIterCommand;
 import org.apache.accumulo.core.util.shell.commands.DeleteShellIterCommand;
@@ -114,6 +116,7 @@ import org.apache.accumulo.core.util.shell.commands.ListScansCommand;
 import org.apache.accumulo.core.util.shell.commands.ListShellIterCommand;
 import org.apache.accumulo.core.util.shell.commands.MaxRowCommand;
 import org.apache.accumulo.core.util.shell.commands.MergeCommand;
+import org.apache.accumulo.core.util.shell.commands.NamespacesCommand;
 import org.apache.accumulo.core.util.shell.commands.NoTableCommand;
 import org.apache.accumulo.core.util.shell.commands.OfflineCommand;
 import org.apache.accumulo.core.util.shell.commands.OnlineCommand;
@@ -122,6 +125,7 @@ import org.apache.accumulo.core.util.shell.commands.PingCommand;
 import org.apache.accumulo.core.util.shell.commands.QuestionCommand;
 import org.apache.accumulo.core.util.shell.commands.QuitCommand;
 import org.apache.accumulo.core.util.shell.commands.QuotedStringTokenizer;
+import org.apache.accumulo.core.util.shell.commands.RenameNamespaceCommand;
 import org.apache.accumulo.core.util.shell.commands.RenameTableCommand;
 import org.apache.accumulo.core.util.shell.commands.RevokeCommand;
 import org.apache.accumulo.core.util.shell.commands.ScanCommand;
@@ -349,7 +353,7 @@ public class Shell extends ShellOptions {
         new TableCommand(), new UserCommand(), new WhoAmICommand()};
     Command[] tableCommands = {new CloneTableCommand(), new ConfigCommand(), new CreateTableCommand(), new DeleteTableCommand(), new DropTableCommand(),
         new DUCommand(), new ExportTableCommand(), new ImportTableCommand(), new OfflineCommand(), new OnlineCommand(), new RenameTableCommand(),
-        new TablesCommand()};
+        new TablesCommand(), new NamespacesCommand(), new CreateNamespaceCommand(), new DeleteNamespaceCommand(), new RenameNamespaceCommand()};
     Command[] tableControlCommands = {new AddSplitsCommand(), new CompactCommand(), new ConstraintCommand(), new FlushCommand(), new GetGroupsCommand(),
         new GetSplitsCommand(), new MergeCommand(), new SetGroupsCommand()};
     Command[] userCommands = {new AddAuthsCommand(), new CreateUserCommand(), new DeleteUserCommand(), new DropUserCommand(), new GetAuthsCommand(),
@@ -705,6 +709,14 @@ public class Shell extends ShellOptions {
       userlist = Collections.emptySet();
     }
     
+    Set<String> tableNamespaces = null;
+    try {
+      tableNamespaces = connector.tableNamespaceOperations().list();
+    } catch (Exception e) {
+      log.debug("Unable to obtain list of table namespaces", e);
+      tableNamespaces = Collections.emptySet();
+    }
+    
     Map<Command.CompletionSet,Set<String>> options = new HashMap<Command.CompletionSet,Set<String>>();
     
     Set<String> commands = new HashSet<String>();
@@ -713,14 +725,18 @@ public class Shell extends ShellOptions {
     
     Set<String> modifiedUserlist = new HashSet<String>();
     Set<String> modifiedTablenames = new HashSet<String>();
+    Set<String> modifiedTableNamespaces = new HashSet<String>();
     
     for (String a : tableNames)
       modifiedTablenames.add(a.replaceAll("([\\s'\"])", "\\\\$1"));
     for (String a : userlist)
       modifiedUserlist.add(a.replaceAll("([\\s'\"])", "\\\\$1"));
+    for (String a : tableNamespaces)
+      modifiedTableNamespaces.add(a.replaceAll("([\\s'\"])", "\\\\$1"));
     
     options.put(Command.CompletionSet.USERNAMES, modifiedUserlist);
     options.put(Command.CompletionSet.TABLENAMES, modifiedTablenames);
+    options.put(Command.CompletionSet.TABLENAMESPACES, modifiedTableNamespaces);
     options.put(Command.CompletionSet.COMMANDS, commands);
     
     for (Command[] cmdGroup : commandGrouping.values()) {
@@ -741,7 +757,7 @@ public class Shell extends ShellOptions {
   public static abstract class Command {
     // Helper methods for completion
     public enum CompletionSet {
-      TABLENAMES, USERNAMES, COMMANDS
+      TABLENAMES, USERNAMES, COMMANDS, TABLENAMESPACES
     }
     
     static Set<String> getCommandNames(Map<CompletionSet,Set<String>> objects) {
@@ -756,6 +772,10 @@ public class Shell extends ShellOptions {
       return objects.get(CompletionSet.USERNAMES);
     }
     
+    static Set<String> getTableNamespaces(Map<CompletionSet,Set<String>> objects) {
+      return objects.get(CompletionSet.TABLENAMESPACES);
+    }
+    
     public void registerCompletionGeneral(Token root, Set<String> args, boolean caseSens) {
       Token t = new Token(args);
       t.setCaseSensitive(caseSens);
@@ -778,6 +798,10 @@ public class Shell extends ShellOptions {
       registerCompletionGeneral(root, completionSet.get(CompletionSet.COMMANDS), false);
     }
     
+    public void registerCompletionForTableNamespaces(Token root, Map<CompletionSet,Set<String>> completionSet) {
+      registerCompletionGeneral(root, completionSet.get(CompletionSet.TABLENAMESPACES), true);
+    }
+    
     // abstract methods to override
     public abstract int execute(String fullCommand, CommandLine cl, Shell shellState) throws Exception;
     

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateNamespaceCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateNamespaceCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateNamespaceCommand.java
new file mode 100644
index 0000000..4e35fcb
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateNamespaceCommand.java
@@ -0,0 +1,95 @@
+/*
+ * 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.core.util.shell.commands;
+
+import java.io.IOException;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableExistsException;
+import org.apache.accumulo.core.client.TableNamespaceExistsException;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class CreateNamespaceCommand extends Command {
+  private Option createTableOptCopyConfig;
+  private Option base64Opt;
+  
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
+      TableExistsException, TableNotFoundException, IOException, ClassNotFoundException, TableNamespaceExistsException, TableNamespaceNotFoundException {
+    
+    if (createTableOptCopyConfig == null) {
+      getOptions();
+    }
+    
+    String namespace = cl.getArgs()[0];
+    
+    shellState.getConnector().tableNamespaceOperations().create(namespace);
+    
+    // Copy options if flag was set
+    if (cl.hasOption(createTableOptCopyConfig.getOpt())) {
+      String copy = cl.getOptionValue(createTableOptCopyConfig.getOpt());
+      if (shellState.getConnector().tableNamespaceOperations().exists(namespace)) {
+        Iterable<Entry<String,String>> configuration = shellState.getConnector().tableNamespaceOperations().getProperties(copy);
+        for (Entry<String,String> entry : configuration) {
+          if (Property.isValidTablePropertyKey(entry.getKey())) {
+            shellState.getConnector().tableNamespaceOperations().setProperty(namespace, entry.getKey(), entry.getValue());
+          }
+        }
+      }
+    }
+    
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "creates a new table namespace";
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <namespaceName>";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    
+    createTableOptCopyConfig = new Option("cc", "copy-config", true, "table namespace to copy configuration from");
+    
+    createTableOptCopyConfig.setArgName("tableNamespace");
+    
+    base64Opt = new Option("b64", "base64encoded", false, "decode encoded split points");
+    o.addOption(base64Opt);
+    o.addOption(createTableOptCopyConfig);
+    
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
index 189458a..356cfed 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
@@ -21,8 +21,11 @@ import java.util.Arrays;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.admin.DiskUsage;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
 import org.apache.accumulo.core.util.NumUtil;
 import org.apache.accumulo.core.util.shell.Shell;
 import org.apache.accumulo.core.util.shell.Shell.Command;
@@ -32,10 +35,10 @@ import org.apache.commons.cli.Options;
 
 public class DUCommand extends Command {
   
-  private Option optTablePattern, optHumanReadble;
-
-  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws IOException, TableNotFoundException {
-
+  private Option optTablePattern, optHumanReadble, optTableNamespace;
+  
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws IOException, TableNotFoundException, TableNamespaceNotFoundException {
+    
     final SortedSet<String> tables = new TreeSet<String>(Arrays.asList(cl.getArgs()));
     
     if (cl.hasOption(Shell.tableOption)) {
@@ -45,9 +48,15 @@ public class DUCommand extends Command {
       }
       tables.add(tableName);
     }
-
+    
+    if (cl.hasOption(optTableNamespace.getOpt())) {
+      Instance instance = shellState.getInstance();
+      String namespaceId = TableNamespaces.getNamespaceId(instance, cl.getOptionValue(optTableNamespace.getOpt()));
+      tables.addAll(TableNamespaces.getTableNames(instance, namespaceId));
+    }
+    
     boolean prettyPrint = cl.hasOption(optHumanReadble.getOpt()) ? true : false;
-
+    
     if (cl.hasOption(optTablePattern.getOpt())) {
       for (String table : shellState.getConnector().tableOperations().list()) {
         if (table.matches(cl.getOptionValue(optTablePattern.getOpt()))) {
@@ -83,14 +92,18 @@ public class DUCommand extends Command {
     
     optTablePattern = new Option("p", "pattern", true, "regex pattern of table names");
     optTablePattern.setArgName("pattern");
-
+    
     optHumanReadble = new Option("h", "human-readable", false, "format large sizes to human readable units");
     optHumanReadble.setArgName("human readable output");
     
+    optTableNamespace = new Option("tn", "table-namespace", true, "name of a table namespace");
+    optTableNamespace.setArgName("table-namespace");
+    
     o.addOption(OptUtil.tableOpt("table to examine"));
-
+    
     o.addOption(optTablePattern);
     o.addOption(optHumanReadble);
+    o.addOption(optTableNamespace);
     
     return o;
   }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java
new file mode 100644
index 0000000..27d669b
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java
@@ -0,0 +1,104 @@
+/*
+ * 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.core.util.shell.commands;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Token;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class DeleteNamespaceCommand extends Command {
+  private Option forceOpt;
+  
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    boolean force = false;
+    boolean operate = true;
+    if (cl.hasOption(forceOpt.getOpt())) {
+      force = true;
+    }
+    String namespace = cl.getArgs()[0];
+    
+    if (!force) {
+      shellState.getReader().flush();
+      String line = shellState.getReader().readLine(getName() + " { " + namespace + " } (yes|no)? ");
+      operate = line != null && (line.equalsIgnoreCase("y") || line.equalsIgnoreCase("yes"));
+    }
+    if (operate) {
+      doTableOp(shellState, namespace, force);
+    }
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "deletes a table namespace";
+  }
+  
+  protected void doTableOp(final Shell shellState, final String namespace, boolean force) throws Exception {
+    boolean resetContext = false;
+    String currentTable = shellState.getTableName();
+    if (!TableNamespaces.getNameToIdMap(shellState.getInstance()).containsKey(namespace)) {
+      throw new TableNamespaceNotFoundException(null, namespace, null);
+    }
+    
+    String namespaceId = TableNamespaces.getNamespaceId(shellState.getInstance(), namespace);
+    List<String> tables = TableNamespaces.getTableNames(shellState.getInstance(), namespaceId);
+    resetContext = tables.contains(currentTable);
+
+    if (force) {
+      shellState.getConnector().tableNamespaceOperations().delete(namespace, true);
+    } else {
+      shellState.getConnector().tableNamespaceOperations().delete(namespace);
+    }
+    if (namespace.equals(Constants.SYSTEM_TABLE_NAMESPACE)) {
+      shellState.getReader().println("Table namespace: [" + namespace + "], can't delete system or default namespace.");
+    } else {
+      shellState.getReader().println("Table namespace: [" + namespace + "] has been deleted.");
+    }
+    if (resetContext) {
+      shellState.setTableName("");
+    }
+  }
+  
+  @Override
+  public Options getOptions() {
+    forceOpt = new Option("f", "force", false, "force deletion without prompting");
+    final Options opts = super.getOptions();
+    
+    opts.addOption(forceOpt);
+    return opts;
+  }
+
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+  
+  @Override
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> special) {
+    registerCompletionForTableNamespaces(root, special);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacesCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacesCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacesCommand.java
new file mode 100644
index 0000000..dcb4bd7
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacesCommand.java
@@ -0,0 +1,55 @@
+/*
+ * 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.core.util.shell.commands;
+
+import java.io.IOException;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class NamespacesCommand extends Command {
+  private Option disablePaginationOpt;
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException, IOException {
+    shellState.printLines(shellState.getConnector().tableNamespaceOperations().list().iterator(), !cl.hasOption(disablePaginationOpt.getOpt()));
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "displays a list of all existing table namespaces";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    disablePaginationOpt = new Option("np", "no-pagination", false, "disable pagination of output");
+    o.addOption(disablePaginationOpt);
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/commands/RenameNamespaceCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/RenameNamespaceCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/RenameNamespaceCommand.java
new file mode 100644
index 0000000..9f4596a
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/RenameNamespaceCommand.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.util.shell.commands;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableExistsException;
+import org.apache.accumulo.core.client.TableNamespaceExistsException;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
+import org.apache.accumulo.core.client.impl.Tables;
+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.commons.cli.CommandLine;
+
+public class RenameNamespaceCommand extends Command {
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
+      TableNotFoundException, TableExistsException, TableNamespaceNotFoundException, TableNamespaceExistsException {
+    String old = cl.getArgs()[0];
+    String newer = cl.getArgs()[1];
+    boolean resetContext = false;
+    String currentTableId = "";
+    if (!(shellState.getTableName() == null) && !shellState.getTableName().isEmpty()) {
+      String namespaceId = TableNamespaces.getNamespaceId(shellState.getInstance(), old);
+      List<String> tableIds = TableNamespaces.getTableIds(shellState.getInstance(), namespaceId);
+      currentTableId = Tables.getTableId(shellState.getInstance(), shellState.getTableName());
+      resetContext = tableIds.contains(currentTableId);
+    }
+    
+    shellState.getConnector().tableNamespaceOperations().rename(old, newer);
+    
+    if (resetContext) {
+      shellState.setTableName(Tables.getTableName(shellState.getInstance(), currentTableId));
+    }
+    
+    return 0;
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <current table namespace> <new table namespace>";
+  }
+  
+  @Override
+  public String description() {
+    return "renames a table namespace";
+  }
+  
+  @Override
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> special) {
+    registerCompletionForTableNamespaces(root, special);
+  }
+  
+  @Override
+  public int numArgs() {
+    return 2;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java
index 2bec526..8c73674 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java
@@ -21,7 +21,10 @@ import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
+import org.apache.accumulo.core.client.impl.Tables;
 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;
@@ -32,7 +35,7 @@ import org.apache.commons.cli.Options;
 
 public abstract class TableOperation extends Command {
   
-  protected Option optTablePattern, optTableName;
+  protected Option optTablePattern, optTableName, optTableNamespace;
   private boolean force = true;
   private boolean useCommandLine = true;
   
@@ -46,6 +49,12 @@ public abstract class TableOperation extends Command {
         }
     } else if (cl.hasOption(optTableName.getOpt())) {
       tableSet.add(cl.getOptionValue(optTableName.getOpt()));
+    } else if (cl.hasOption(optTableNamespace.getOpt())) {
+      Instance instance = shellState.getInstance();
+      String namespaceId = TableNamespaces.getNamespaceId(instance, optTableNamespace.getValue());
+      for (String tableId : TableNamespaces.getTableIds(instance, namespaceId)) {
+        tableSet.add(Tables.getTableName(instance, tableId));
+      }
     } else if (useCommandLine && cl.getArgs().length > 0) {
       for (String tableName : cl.getArgs()) {
         tableSet.add(tableName);
@@ -99,10 +108,14 @@ public abstract class TableOperation extends Command {
     optTableName = new Option(Shell.tableOption, "table", true, "name of a table to operate on");
     optTableName.setArgName("tableName");
     
+    optTableNamespace = new Option("tn", "table-namespace", true, "name of a table namespace to operate on");
+    optTableName.setArgName("table-namespace");
+    
     final OptionGroup opg = new OptionGroup();
     
     opg.addOption(optTablePattern);
     opg.addOption(optTableName);
+    opg.addOption(optTableNamespace);
     
     o.addOptionGroup(opg);
     

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/thrift/client.thrift
----------------------------------------------------------------------
diff --git a/core/src/main/thrift/client.thrift b/core/src/main/thrift/client.thrift
index 2f5e9d1..1e6a145 100644
--- a/core/src/main/thrift/client.thrift
+++ b/core/src/main/thrift/client.thrift
@@ -135,6 +135,7 @@ service ClientService {
     // configuration methods
     map<string, string> getConfiguration(2:trace.TInfo tinfo, 3:security.TCredentials credentials, 1:ConfigurationType type);
     map<string, string> getTableConfiguration(1:trace.TInfo tinfo, 3:security.TCredentials credentials, 2:string tableName) throws (1:ThriftTableOperationException tope);
+    map<string, string> getTableNamespaceConfiguration(1:trace.TInfo tinfo, 3:security.TCredentials credentials, 2:string ns) throws (1:ThriftTableOperationException tope);
     bool checkClass(1:trace.TInfo tinfo, 4:security.TCredentials credentials, 2:string className, 3:string interfaceMatch);
     bool checkTableClass(1:trace.TInfo tinfo, 5:security.TCredentials credentials, 2:string tableId, 3:string className, 4:string interfaceMatch) throws (1:ThriftSecurityException sec, 2:ThriftTableOperationException tope);
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/thrift/master.thrift
----------------------------------------------------------------------
diff --git a/core/src/main/thrift/master.thrift b/core/src/main/thrift/master.thrift
index 19960c8..6270f33 100644
--- a/core/src/main/thrift/master.thrift
+++ b/core/src/main/thrift/master.thrift
@@ -137,6 +137,9 @@ service MasterClientService {
     
     void setTableProperty(5:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:string tableName, 3:string property, 4:string value) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
     void removeTableProperty(4:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:string tableName, 3:string property) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
+    
+    void setTableNamespaceProperty(5:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:string ns, 3:string property, 4:string value) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
+    void removeTableNamespaceProperty(4:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:string ns, 3:string property) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
 
     // system management methods
     void setMasterGoalState(3:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:MasterGoalState state) throws (1:client.ThriftSecurityException sec);
@@ -154,7 +157,14 @@ service MasterClientService {
 
    //table operations
    i64 beginTableOperation(2:trace.TInfo tinfo, 1:security.TCredentials credentials) throws (1:client.ThriftSecurityException sec)
-   void executeTableOperation(7:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:i64 opid, 3:TableOperation op, 4:list<binary> arguments, 5:map<string, string> options, 6:bool autoClean)throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
+   void executeTableOperation(7:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:i64 opid, 3:TableOperation op, 4:list<binary> arguments, 5:map<string, string> options, 6:bool autoClean) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
    string waitForTableOperation(3:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:i64 opid) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
    void finishTableOperation(3:trace.TInfo tinfo, 1:security.TCredentials credentials, 2:i64 opid) throws (1:client.ThriftSecurityException sec)
+
+   //table namespace operations
+   i64 beginTableNamespaceOperation(1:trace.TInfo tinfo, 2:security.TCredentials credentials) throws (1:client.ThriftSecurityException sec)
+   void executeTableNamespaceOperation(1:trace.TInfo tinfo, 2:security.TCredentials credentials, 3:i64 opid, 4:TableOperation op, 5:list<binary> arguments, 6:map<string, string> options, 7:bool autoClean) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
+   string waitForTableNamespaceOperation(1:trace.TInfo tinfo, 2:security.TCredentials credentials, 3:i64 opid) throws (1:client.ThriftSecurityException sec, 2:client.ThriftTableOperationException tope)
+   void finishTableNamespaceOperation(1:trace.TInfo tinfo, 2:security.TCredentials credentials, 3:i64 opid) throws (1:client.ThriftSecurityException sec)
+   
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java b/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
new file mode 100644
index 0000000..d15b3e5
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
@@ -0,0 +1,265 @@
+/*
+ * 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.core.client.mock;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Map.Entry;
+import java.util.Random;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.TableNamespaceNotEmptyException;
+import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.Property;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class MockTableNamespacesTest {
+  
+  Random random = new Random();
+  public static TemporaryFolder folder = new TemporaryFolder();
+  
+  /**
+   * This test creates a table without specifying a namespace. In this case, it puts the table into the default namespace.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void testDefaultNamespace() throws Exception {
+    String tableName = "test";
+    Instance instance = new MockInstance("default");
+    Connector c = instance.getConnector("user", new PasswordToken("pass"));
+    
+    assertTrue(c.tableNamespaceOperations().exists(Constants.DEFAULT_TABLE_NAMESPACE));
+    c.tableOperations().create(tableName);
+    assertTrue(c.tableOperations().exists(tableName));
+  }
+  
+  /**
+   * This test creates a new namespace "testing" and a table "testing.table1" which puts "table1" into the "testing" namespace.
+   * Then we create "testing.table2" which creates "table2" and puts it into "testing" as well. 
+   * Then we make sure that you can't delete a namespace with tables in it, and then we delete the tables and delete the namespace.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void testCreateAndDeleteNamespace() throws Exception {
+    String namespace = "testing";
+    String tableName1 = namespace + ".table1";
+    String tableName2 = namespace + ".table2";
+    
+    Instance instance = new MockInstance("createdelete");
+    Connector c = instance.getConnector("user", new PasswordToken("pass"));
+    
+    c.tableNamespaceOperations().create(namespace);
+    assertTrue(c.tableNamespaceOperations().exists(namespace));
+    
+    c.tableOperations().create(tableName1);
+    assertTrue(c.tableOperations().exists(tableName1));
+    
+    c.tableOperations().create(tableName2);
+    assertTrue(c.tableOperations().exists(tableName2));
+    
+    // deleting
+    try {
+      // can't delete a namespace with tables in it
+      c.tableNamespaceOperations().delete(namespace);
+      fail();
+    } catch (TableNamespaceNotEmptyException e) {
+      // ignore, supposed to happen
+    }
+    assertTrue(c.tableNamespaceOperations().exists(namespace));
+    assertTrue(c.tableOperations().exists(tableName1));
+    assertTrue(c.tableOperations().exists(tableName2));
+    
+    c.tableOperations().delete(tableName2);
+    assertTrue(!c.tableOperations().exists(tableName2));
+    assertTrue(c.tableNamespaceOperations().exists(namespace));
+
+    c.tableOperations().delete(tableName1);
+    assertTrue(!c.tableOperations().exists(tableName1));
+    c.tableNamespaceOperations().delete(namespace);
+    assertTrue(!c.tableNamespaceOperations().exists(namespace));
+  }
+  
+  /**
+   * This test creates a namespace, modifies it's properties, and checks to make sure that those properties are applied to its tables. To do something on a
+   * namespace-wide level, use TableNamespaceOperations.
+   * 
+   * Checks to make sure namespace-level properties are overridden by table-level properties.
+   * 
+   * Checks to see if the default namespace's properties work as well.
+   * 
+   * @throws Exception
+   */
+  
+  @Test
+  public void testNamespaceProperties() throws Exception {
+    String namespace = "propchange";
+    String tableName1 = namespace + ".table1";
+    String tableName2 = namespace + ".table2";
+    
+    String propKey = Property.TABLE_SCAN_MAXMEM.getKey();
+    String propVal = "42K";
+    
+    Instance instance = new MockInstance("props");
+    Connector c = instance.getConnector("user", new PasswordToken("pass"));
+    
+    c.tableNamespaceOperations().create(namespace);
+    c.tableOperations().create(tableName1);
+    c.tableNamespaceOperations().setProperty(namespace, propKey, propVal);
+    
+    // check the namespace has the property
+    boolean itWorked = false;
+    for (Entry<String,String> prop : c.tableNamespaceOperations().getProperties(namespace)) {
+      if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
+        itWorked = true;
+        break;
+      }
+    }
+    
+    assertTrue(itWorked);
+    
+    // check that the table gets it from the namespace
+    itWorked = false;
+    for (Entry<String,String> prop : c.tableOperations().getProperties(tableName1)) {
+      if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
+        itWorked = true;
+        break;
+      }
+    }
+    assertTrue(itWorked);
+    
+    // test a second table to be sure the first wasn't magical
+    // (also, changed the order, the namespace already exists with the property)
+    itWorked = false;
+    c.tableOperations().create(tableName2);
+    for (Entry<String,String> prop : c.tableOperations().getProperties(tableName2)) {
+      if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
+        itWorked = true;
+        break;
+      }
+    }
+    assertTrue(itWorked);
+    
+    // test that table properties override namespace properties
+    String propKey2 = Property.TABLE_FILE_MAX.getKey();
+    String propVal2 = "42";
+    String tablePropVal = "13";
+    
+    c.tableOperations().setProperty(tableName2, propKey2, tablePropVal);
+    c.tableNamespaceOperations().setProperty("propchange", propKey2, propVal2);
+    
+    itWorked = false;
+    for (Entry<String,String> prop : c.tableOperations().getProperties(tableName2)) {
+      if (prop.getKey().equals(propKey2) && prop.getValue().equals(tablePropVal)) {
+        itWorked = true;
+        break;
+      }
+    }
+    assertTrue(itWorked);
+    
+    // now check that you can change the default namespace's properties
+    propVal = "13K";
+    propVal2 = "44";
+    String tableName = "some_table";
+    c.tableOperations().create(tableName);
+    c.tableNamespaceOperations().setProperty(Constants.DEFAULT_TABLE_NAMESPACE, propKey, propVal);
+    
+    itWorked = false;
+    for (Entry<String,String> prop : c.tableOperations().getProperties(tableName)) {
+      if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
+        itWorked = true;
+        break;
+      }
+    }
+    assertTrue(itWorked);
+  }
+  
+  /**
+   * This test creates a new user and a namespace. It checks to make sure the user can't modify anything in the namespace at first, then it grants the user
+   * permissions and makes sure that they can modify the namespace. Then it also checks if the user has the correct permissions on tables both already existing
+   * in the namespace and ones they create.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void testNamespacePermissions() throws Exception {
+    // TODO make the test once namespace-level permissions are implemented. (ACCUMULO-1479)
+  }
+  
+  /**
+   * This test renames and clones two separate table into different namespaces.
+   * different namespace.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void testRenameAndCloneTableToNewNamespace() throws Exception {
+    String namespace1 = "renamed";
+    String namespace2 = "cloned";
+    String tableName = "table";
+    String tableName1 = "renamed.table1";
+    //String tableName2 = "cloned.table2";
+    
+    Instance instance = new MockInstance("renameclone");
+    Connector c = instance.getConnector("user", new PasswordToken("pass"));
+
+    c.tableOperations().create(tableName);
+    c.tableNamespaceOperations().create(namespace1);
+    c.tableNamespaceOperations().create(namespace2);
+    
+    c.tableOperations().rename(tableName, tableName1);
+    
+    assertTrue(c.tableOperations().exists(tableName1));
+    assertTrue(!c.tableOperations().exists(tableName));
+    
+    // TODO implement clone in mock
+    /*c.tableOperations().clone(tableName1, tableName2, false, null, null);
+    
+    assertTrue(c.tableOperations().exists(tableName1));
+    assertTrue(c.tableOperations().exists(tableName2));*/
+    return;
+  }
+  
+  /**
+   * This test renames a table namespace and ensures that its tables are still correct
+   */
+  @Test
+  public void testNamespaceRename() throws Exception {
+    String namespace1 = "n1";
+    String namespace2 = "n2";
+    String table = "t";
+    
+    Instance instance = new MockInstance("rename");
+    Connector c = instance.getConnector("user", new PasswordToken("pass"));
+    
+    c.tableNamespaceOperations().create(namespace1);
+    c.tableOperations().create(namespace1 + "." + table);
+    
+    c.tableNamespaceOperations().rename(namespace1, namespace2);
+    
+    assertTrue(!c.tableNamespaceOperations().exists(namespace1));
+    assertTrue(c.tableNamespaceOperations().exists(namespace2));
+    assertTrue(!c.tableOperations().exists(namespace1 + "." + table));
+    assertTrue(c.tableOperations().exists(namespace2 + "." + table));
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/ServerConstants.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/ServerConstants.java b/server/base/src/main/java/org/apache/accumulo/server/ServerConstants.java
index 9e0ac39..04b51b8 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/ServerConstants.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/ServerConstants.java
@@ -29,11 +29,14 @@ import org.apache.hadoop.fs.Path;
 
 public class ServerConstants {
   
-  // versions should never be negative
-  public static final Integer WIRE_VERSION = 2;
+  /**
+   * current version (3) reflects additional namespace operations (ACCUMULO-802) in version 1.6.0 <br />
+   * (versions should never be negative)
+   */
+  public static final Integer WIRE_VERSION = 3;
   
   /**
-   * current version reflects the addition of a separate root table (ACCUMULO-1481)
+   * current version (6) reflects the addition of a separate root table (ACCUMULO-1481) in version 1.6.0
    */
   public static final int DATA_VERSION = 6;
   public static final int PREV_DATA_VERSION = 5;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/client/ClientServiceHandler.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/client/ClientServiceHandler.java b/server/base/src/main/java/org/apache/accumulo/server/client/ClientServiceHandler.java
index 3f1aaa2..e061f99 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/client/ClientServiceHandler.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/client/ClientServiceHandler.java
@@ -33,6 +33,8 @@ import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.impl.thrift.ClientService;
 import org.apache.accumulo.core.client.impl.thrift.ConfigurationType;
@@ -228,7 +230,8 @@ public class ClientServiceHandler implements ClientService.Iface {
   @Override
   public Map<String,String> getTableConfiguration(TInfo tinfo, TCredentials credentials, String tableName) throws TException, ThriftTableOperationException {
     String tableId = checkTableId(tableName, null);
-    return conf(credentials, new ServerConfiguration(instance).getTableConfiguration(tableId));
+    AccumuloConfiguration config = new ServerConfiguration(instance).getTableConfiguration(tableId);
+    return conf(credentials, config);
   }
   
   @Override
@@ -349,4 +352,17 @@ public class ClientServiceHandler implements ClientService.Iface {
       throw new TException(e);
     }
   }
+  
+  @Override
+  public Map<String,String> getTableNamespaceConfiguration(TInfo tinfo, TCredentials credentials, String ns) throws ThriftTableOperationException, TException {
+    String namespaceId;
+    try {
+      namespaceId = TableNamespaces.getNamespaceId(instance, ns);
+    } catch (TableNamespaceNotFoundException e) {
+      String why = "Could not find table namespace while getting configuration.";
+      throw new ThriftTableOperationException(null, ns, null, null, why);
+    }
+    AccumuloConfiguration config = new ServerConfiguration(instance).getTableNamespaceConfiguration(namespaceId);
+    return conf(credentials, config);
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfiguration.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfiguration.java b/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfiguration.java
index c9fd5a1..7897093 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfiguration.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfiguration.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.conf.AccumuloConfiguration;
 import org.apache.accumulo.core.conf.ConfigSanityCheck;
 import org.apache.accumulo.core.conf.DefaultConfiguration;
@@ -29,55 +30,69 @@ import org.apache.accumulo.core.conf.SiteConfiguration;
 import org.apache.accumulo.core.data.KeyExtent;
 
 public class ServerConfiguration {
-  
+
   private static final Map<String,TableConfiguration> tableInstances = new HashMap<String,TableConfiguration>(1);
+  private static final Map<String,TableNamespaceConfiguration> tableNamespaceInstances = new HashMap<String,TableNamespaceConfiguration>(1);
   private static SecurityPermission CONFIGURATION_PERMISSION = new SecurityPermission("configurationPermission");
-  
+
   public static synchronized SiteConfiguration getSiteConfiguration() {
     checkPermissions();
     return SiteConfiguration.getInstance(getDefaultConfiguration());
   }
-  
+
   private static void checkPermissions() {
     SecurityManager sm = System.getSecurityManager();
     if (sm != null) {
       sm.checkPermission(CONFIGURATION_PERMISSION);
     }
   }
-  
+
   private static synchronized ZooConfiguration getZooConfiguration(Instance instance) {
     checkPermissions();
     return ZooConfiguration.getInstance(instance, getSiteConfiguration());
   }
-  
+
   public static synchronized DefaultConfiguration getDefaultConfiguration() {
     checkPermissions();
     return DefaultConfiguration.getInstance();
   }
-  
+
   public static synchronized AccumuloConfiguration getSystemConfiguration(Instance instance) {
     return getZooConfiguration(instance);
   }
-  
+
+  public static TableNamespaceConfiguration getTableNamespaceConfiguration(Instance instance, String namespaceId) {
+    checkPermissions();
+    synchronized (tableNamespaceInstances) {
+      TableNamespaceConfiguration conf = tableNamespaceInstances.get(namespaceId);
+      if (conf == null) {
+        conf = new TableNamespaceConfiguration(instance, namespaceId, getSystemConfiguration(instance));
+        ConfigSanityCheck.validate(conf);
+        tableNamespaceInstances.put(namespaceId, conf);
+      }
+      return conf;
+    }
+  }
+
   public static TableConfiguration getTableConfiguration(Instance instance, String tableId) {
     checkPermissions();
     synchronized (tableInstances) {
       TableConfiguration conf = tableInstances.get(tableId);
-      if (conf == null) {
-        conf = new TableConfiguration(instance.getInstanceID(), tableId, getSystemConfiguration(instance));
+      if (conf == null && Tables.exists(instance, tableId)) {
+        conf = new TableConfiguration(instance.getInstanceID(), tableId, getTableNamespaceConfiguration(instance, Tables.getNamespace(instance, tableId)));
         ConfigSanityCheck.validate(conf);
         tableInstances.put(tableId, conf);
       }
       return conf;
     }
   }
-  
+
   static void removeTableIdInstance(String tableId) {
     synchronized (tableInstances) {
       tableInstances.remove(tableId);
     }
   }
-  
+
   static void expireAllTableObservers() {
     synchronized (tableInstances) {
       for (Entry<String,TableConfiguration> entry : tableInstances.entrySet()) {
@@ -85,27 +100,31 @@ public class ServerConfiguration {
       }
     }
   }
-  
+
   private final Instance instance;
-  
+
   public ServerConfiguration(Instance instance) {
     this.instance = instance;
   }
-  
+
   public TableConfiguration getTableConfiguration(String tableId) {
     return getTableConfiguration(instance, tableId);
   }
-  
+
   public TableConfiguration getTableConfiguration(KeyExtent extent) {
     return getTableConfiguration(extent.getTableId().toString());
   }
-  
+
+  public TableNamespaceConfiguration getTableNamespaceConfiguration(String namespaceId) {
+    return getTableNamespaceConfiguration(instance, namespaceId);
+  }
+
   public synchronized AccumuloConfiguration getConfiguration() {
     return getZooConfiguration(instance);
   }
-  
+
   public Instance getInstance() {
     return instance;
   }
-  
+
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/conf/TableNamespaceConfiguration.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/conf/TableNamespaceConfiguration.java b/server/base/src/main/java/org/apache/accumulo/server/conf/TableNamespaceConfiguration.java
new file mode 100644
index 0000000..a5c3437
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/TableNamespaceConfiguration.java
@@ -0,0 +1,103 @@
+/*
+ * 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.server.conf;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.zookeeper.ZooCache;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.log4j.Logger;
+
+public class TableNamespaceConfiguration extends AccumuloConfiguration {
+  private static final Logger log = Logger.getLogger(TableNamespaceConfiguration.class);
+  
+  private final AccumuloConfiguration parent;
+  private final String instanceId;
+  private static ZooCache propCache = null;
+  private String namespaceId = null;
+  
+  public TableNamespaceConfiguration (Instance inst, String namespaceId, AccumuloConfiguration parent) {
+      propCache = new ZooCache(inst.getZooKeepers(), inst.getZooKeepersSessionTimeOut());
+      this.instanceId = inst.getInstanceID();
+      this.parent = parent;
+      this.namespaceId = namespaceId;
+  }
+
+  public void invalidateCache() {
+    if (propCache != null)
+      propCache.clear();
+  }
+  
+  @Override
+  public String get(Property property) {
+    String key = property.getKey();
+    String value = get(key);
+    
+    if (value == null || !property.getType().isValidFormat(value)) {
+      if (value != null)
+        log.error("Using default value for " + key + " due to improperly formatted " + property.getType() + ": " + value);
+      value = parent.get(property);
+    }
+    return value;
+  }
+  
+  private String get(String key) {
+    String zPath = ZooUtil.getRoot(instanceId) + Constants.ZNAMESPACES + "/" + namespaceId + Constants.ZNAMESPACE_CONF + "/" + key;
+    byte[] v = getPropCache().get(zPath);
+    String value = null;
+    if (v != null)
+      value = new String(v);
+    return value;
+  }
+  
+  private static ZooCache getPropCache() {
+    Instance inst = HdfsZooInstance.getInstance();
+    if (propCache == null)
+      synchronized (TableNamespaceConfiguration.class) {
+        if (propCache == null)
+          propCache = new ZooCache(inst.getZooKeepers(), inst.getZooKeepersSessionTimeOut(), new TableConfWatcher(inst));
+      }
+    return propCache;
+  }
+  
+  @Override
+  public Iterator<Entry<String,String>> iterator() {
+    TreeMap<String,String> entries = new TreeMap<String,String>();
+    
+    for (Entry<String,String> parentEntry : parent)
+      entries.put(parentEntry.getKey(), parentEntry.getValue());
+    
+    List<String> children = getPropCache().getChildren(ZooUtil.getRoot(instanceId) + Constants.ZNAMESPACES + "/" + namespaceId + Constants.ZNAMESPACE_CONF);
+    if (children != null) {
+      for (String child : children) {
+        String value = get(child);
+        if (child != null && value != null)
+          entries.put(child, value);
+      }
+    }
+    
+    return entries.entrySet().iterator();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/init/Initialize.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/init/Initialize.java b/server/base/src/main/java/org/apache/accumulo/server/init/Initialize.java
index 0477a44..47179fc 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/init/Initialize.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/init/Initialize.java
@@ -376,6 +376,22 @@ public class Initialize {
     zoo.putPersistentData(zkInstanceRoot + Constants.ZHDFS_RESERVATIONS, new byte[0], NodeExistsPolicy.FAIL);
     zoo.putPersistentData(zkInstanceRoot + Constants.ZNEXT_FILE, new byte[] {'0'}, NodeExistsPolicy.FAIL);
     zoo.putPersistentData(zkInstanceRoot + Constants.ZRECOVERY, new byte[] {'0'}, NodeExistsPolicy.FAIL);
+    zoo.putPersistentData(zkInstanceRoot + Constants.ZNAMESPACES, new byte[0], NodeExistsPolicy.FAIL);
+    
+    createInitialTableNamespace(zoo, zkInstanceRoot, Constants.DEFAULT_TABLE_NAMESPACE_ID, Constants.DEFAULT_TABLE_NAMESPACE);
+    createInitialTableNamespace(zoo, zkInstanceRoot, Constants.SYSTEM_TABLE_NAMESPACE_ID, Constants.SYSTEM_TABLE_NAMESPACE);
+    
+    zoo.putPersistentData(zkInstanceRoot + Constants.ZTABLES + "/" + MetadataTable.ID + Constants.ZTABLE_NAMESPACE,
+        Constants.SYSTEM_TABLE_NAMESPACE_ID.getBytes(Constants.UTF8), NodeExistsPolicy.FAIL);
+    zoo.putPersistentData(zkInstanceRoot + Constants.ZTABLES + "/" + RootTable.ID + Constants.ZTABLE_NAMESPACE,
+        Constants.SYSTEM_TABLE_NAMESPACE_ID.getBytes(Constants.UTF8), NodeExistsPolicy.FAIL);
+  }
+  
+  private static void createInitialTableNamespace(IZooReaderWriter zoo, String root, String id, String namespace) throws KeeperException, InterruptedException {
+    String zPath = root + Constants.ZNAMESPACES + "/" + id;
+    zoo.putPersistentData(zPath, new byte[0], NodeExistsPolicy.FAIL);
+    zoo.putPersistentData(zPath + Constants.ZNAMESPACE_NAME, namespace.getBytes(Constants.UTF8), NodeExistsPolicy.FAIL);
+    zoo.putPersistentData(zPath + Constants.ZNAMESPACE_CONF, new byte[0], NodeExistsPolicy.FAIL);
   }
   
   private static String getInstanceNamePath(Opts opts) throws IOException, KeeperException, InterruptedException {
@@ -494,7 +510,6 @@ public class Initialize {
   public static void main(String[] args) {
     Opts opts = new Opts();
     opts.parseArgs(Initialize.class.getName(), args);
-    
     try {
       SecurityUtil.serverLogin();
       Configuration conf = CachedConfiguration.getInstance();

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/tables/TableManager.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/tables/TableManager.java b/server/base/src/main/java/org/apache/accumulo/server/tables/TableManager.java
index 8a74d0b..aed6321 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/tables/TableManager.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/tables/TableManager.java
@@ -26,6 +26,7 @@ import java.util.Set;
 
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.master.state.tables.TableState;
 import org.apache.accumulo.core.zookeeper.ZooUtil;
 import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
@@ -57,15 +58,16 @@ public class TableManager {
   public static void prepareNewTableState(String instanceId, String tableId, String tableName, TableState state, NodeExistsPolicy existsPolicy)
       throws KeeperException, InterruptedException {
     // state gets created last
+    tableName = Tables.extractTableName(tableName);
     String zTablePath = Constants.ZROOT + "/" + instanceId + Constants.ZTABLES + "/" + tableId;
     IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
     zoo.putPersistentData(zTablePath, new byte[0], existsPolicy);
     zoo.putPersistentData(zTablePath + Constants.ZTABLE_CONF, new byte[0], existsPolicy);
-    zoo.putPersistentData(zTablePath + Constants.ZTABLE_NAME, tableName.getBytes(), existsPolicy);
-    zoo.putPersistentData(zTablePath + Constants.ZTABLE_STATE, state.name().getBytes(), existsPolicy);
-    zoo.putPersistentData(zTablePath + Constants.ZTABLE_FLUSH_ID, "0".getBytes(), existsPolicy);
-    zoo.putPersistentData(zTablePath + Constants.ZTABLE_COMPACT_ID, "0".getBytes(), existsPolicy);
-    zoo.putPersistentData(zTablePath + Constants.ZTABLE_COMPACT_CANCEL_ID, "0".getBytes(), existsPolicy);
+    zoo.putPersistentData(zTablePath + Constants.ZTABLE_NAME, tableName.getBytes(Constants.UTF8), existsPolicy);
+    zoo.putPersistentData(zTablePath + Constants.ZTABLE_STATE, state.name().getBytes(Constants.UTF8), existsPolicy);
+    zoo.putPersistentData(zTablePath + Constants.ZTABLE_FLUSH_ID, "0".getBytes(Constants.UTF8), existsPolicy);
+    zoo.putPersistentData(zTablePath + Constants.ZTABLE_COMPACT_ID, "0".getBytes(Constants.UTF8), existsPolicy);
+    zoo.putPersistentData(zTablePath + Constants.ZTABLE_COMPACT_CANCEL_ID, "0".getBytes(Constants.UTF8), existsPolicy);
   }
   
   public synchronized static TableManager getInstance() {
@@ -290,6 +292,33 @@ public class TableManager {
     }
   }
   
+  public void addNamespace(String namespaceId, String namespace, NodeExistsPolicy existsPolicy) throws KeeperException, InterruptedException {
+    // state gets created last
+    String zPath = Constants.ZROOT + "/" + instance.getInstanceID() + Constants.ZNAMESPACES + "/" + namespaceId;
+    
+    IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
+
+    zoo.putPersistentData(zPath, new byte[0], existsPolicy);
+    zoo.putPersistentData(zPath + Constants.ZNAMESPACE_NAME, namespace.getBytes(Constants.UTF8), existsPolicy);
+    zoo.putPersistentData(zPath + Constants.ZNAMESPACE_CONF, new byte[0], existsPolicy);
+  }
+  
+  public void removeNamespace(String namespaceId) throws KeeperException, InterruptedException {
+    ZooReaderWriter.getRetryingInstance().recursiveDelete(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + namespaceId, NodeMissingPolicy.SKIP);
+  }
+  
+  public void addNamespaceToTable(String tableId, String namespaceId) throws KeeperException, InterruptedException {
+    String zPath = Constants.ZROOT + "/" + instance.getInstanceID() + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE;
+    ZooReaderWriter.getRetryingInstance().putPersistentData(zPath, namespaceId.getBytes(Constants.UTF8), NodeExistsPolicy.OVERWRITE);
+  }
+  
+  public void removeNamespaceFromTable(String tableId, String namespaceId) throws KeeperException, InterruptedException {
+    // actually, revert it to the default namespace.
+    String zPath = Constants.ZROOT + "/" + instance.getInstanceID() + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE;
+    ZooReaderWriter.getRetryingInstance().putPersistentData(zPath, Constants.DEFAULT_TABLE_NAMESPACE.getBytes(Constants.UTF8), NodeExistsPolicy.OVERWRITE);
+  }
+  
+  
   /*
    * private static boolean verifyTabletAssignments(String tableId) { log.info( "Sending message to load balancer to verify assignment of tablets with tableId="
    * + tableId); // Return true only if transitions to other states did not interrupt // this process. (like deleting the table) return true; }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/base/src/main/java/org/apache/accumulo/server/util/NamespacePropUtil.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/util/NamespacePropUtil.java b/server/base/src/main/java/org/apache/accumulo/server/util/NamespacePropUtil.java
new file mode 100644
index 0000000..a3ff33a
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/util/NamespacePropUtil.java
@@ -0,0 +1,60 @@
+/*
+ * 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.server.util;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
+import org.apache.zookeeper.KeeperException;
+
+public class NamespacePropUtil {
+  public static boolean setNamespaceProperty(String namespaceId, String property, String value) throws KeeperException, InterruptedException {
+    if (!isPropertyValid(property, value))
+      return false;
+    
+    // create the zk node for per-namespace properties for this namespace if it doesn't already exist
+    String zkNamespacePath = getPath(namespaceId);
+    ZooReaderWriter.getInstance().putPersistentData(zkNamespacePath, new byte[0], NodeExistsPolicy.SKIP);
+    
+    // create the zk node for this property and set it's data to the specified value
+    String zPath = zkNamespacePath + "/" + property;
+    ZooReaderWriter.getInstance().putPersistentData(zPath, value.getBytes(), NodeExistsPolicy.OVERWRITE);
+    
+    return true;
+  }
+  
+  public static boolean isPropertyValid(String property, String value) {
+    Property p = Property.getPropertyByKey(property);
+    if ((p != null && !p.getType().isValidFormat(value)) || !Property.isValidTablePropertyKey(property))
+      return false;
+    
+    return true;
+  }
+  
+  public static void removeNamespaceProperty(String namespaceId, String property) throws InterruptedException, KeeperException {
+    String zPath = getPath(namespaceId) + "/" + property;
+    ZooReaderWriter.getInstance().recursiveDelete(zPath, NodeMissingPolicy.SKIP);
+  }
+  
+  private static String getPath(String namespaceId) {
+    return ZooUtil.getRoot(HdfsZooInstance.getInstance()) + Constants.ZNAMESPACES + "/" + namespaceId + Constants.ZNAMESPACE_CONF;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/Master.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/Master.java b/server/master/src/main/java/org/apache/accumulo/master/Master.java
index 8a1a9b2..e9910d5 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/Master.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/Master.java
@@ -44,6 +44,8 @@ import org.apache.accumulo.core.client.RowIterator;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.admin.TableOperationsImpl;
+import org.apache.accumulo.core.client.admin.TimeType;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.impl.ThriftTransportPool;
 import org.apache.accumulo.core.client.impl.thrift.SecurityErrorCode;
@@ -97,10 +99,13 @@ import org.apache.accumulo.master.tableOps.ChangeTableState;
 import org.apache.accumulo.master.tableOps.CloneTable;
 import org.apache.accumulo.master.tableOps.CompactRange;
 import org.apache.accumulo.master.tableOps.CreateTable;
+import org.apache.accumulo.master.tableOps.CreateTableNamespace;
 import org.apache.accumulo.master.tableOps.DeleteTable;
+import org.apache.accumulo.master.tableOps.DeleteTableNamespace;
 import org.apache.accumulo.master.tableOps.ExportTable;
 import org.apache.accumulo.master.tableOps.ImportTable;
 import org.apache.accumulo.master.tableOps.RenameTable;
+import org.apache.accumulo.master.tableOps.RenameTableNamespace;
 import org.apache.accumulo.master.tableOps.TableRangeOp;
 import org.apache.accumulo.master.tableOps.TraceRepo;
 import org.apache.accumulo.master.tserverOps.ShutdownTServer;
@@ -138,6 +143,7 @@ import org.apache.accumulo.server.tables.TableObserver;
 import org.apache.accumulo.server.util.DefaultMap;
 import org.apache.accumulo.server.util.Halt;
 import org.apache.accumulo.server.util.MetadataTableUtil;
+import org.apache.accumulo.server.util.NamespacePropUtil;
 import org.apache.accumulo.server.util.SystemPropUtil;
 import org.apache.accumulo.server.util.TServerUtils;
 import org.apache.accumulo.server.util.TServerUtils.ServerAddress;
@@ -321,6 +327,33 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
           zoo.putPersistentData(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + id + Constants.ZTABLE_COMPACT_CANCEL_ID, "0".getBytes(),
               NodeExistsPolicy.SKIP);
         }
+
+        // setup default and system table namespaces if not already there
+        String tableNamespaces = ZooUtil.getRoot(instance) + Constants.ZNAMESPACES;
+        String defaultTableNamespace = ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + Constants.DEFAULT_TABLE_NAMESPACE_ID;
+        String systemTableNamespace = ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + Constants.SYSTEM_TABLE_NAMESPACE_ID;
+        String tables = ZooUtil.getRoot(instance) + Constants.ZTABLES;
+        zoo.putPersistentData(tableNamespaces, new byte[0], NodeExistsPolicy.SKIP);
+
+        zoo.putPersistentData(defaultTableNamespace, new byte[0], NodeExistsPolicy.SKIP);
+        zoo.putPersistentData(defaultTableNamespace + Constants.ZNAMESPACE_CONF, new byte[0], NodeExistsPolicy.SKIP);
+        zoo.putPersistentData(defaultTableNamespace + Constants.ZNAMESPACE_NAME, Constants.DEFAULT_TABLE_NAMESPACE.getBytes(Constants.UTF8),
+            NodeExistsPolicy.SKIP);
+
+        zoo.putPersistentData(systemTableNamespace, new byte[0], NodeExistsPolicy.SKIP);
+        zoo.putPersistentData(systemTableNamespace + Constants.ZNAMESPACE_CONF, new byte[0], NodeExistsPolicy.SKIP);
+        zoo.putPersistentData(systemTableNamespace + Constants.ZNAMESPACE_NAME, Constants.SYSTEM_TABLE_NAMESPACE.getBytes(Constants.UTF8),
+            NodeExistsPolicy.SKIP);
+
+        for (Entry<String,String> table : Tables.getIdToNameMap(instance).entrySet()) {
+          if (table.getValue().equals(MetadataTable.NAME) || table.getValue().equals(RootTable.NAME)) {
+            zoo.putPersistentData(tables + "/" + table.getKey() + Constants.ZTABLE_NAMESPACE, Constants.SYSTEM_TABLE_NAMESPACE_ID.getBytes(Constants.UTF8),
+                NodeExistsPolicy.SKIP);
+          } else {
+            zoo.putPersistentData(tables + "/" + table.getKey() + Constants.ZTABLE_NAMESPACE, Constants.DEFAULT_TABLE_NAMESPACE_ID.getBytes(Constants.UTF8),
+                NodeExistsPolicy.SKIP);
+          }
+        }
       } catch (Exception ex) {
         log.fatal("Error performing upgrade", ex);
         System.exit(1);
@@ -697,6 +730,24 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
       }
     }
 
+    private void alterTableNamespaceProperty(TCredentials c, String namespace, String property, String value, TableOperation op)
+        throws ThriftSecurityException, ThriftTableOperationException {
+
+      String namespaceId = null;
+      try {
+        namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+        // TODO insert a permission check here once namespace-level permissions exist. (ACCUMULO-1479)
+        if (value == null) {
+          NamespacePropUtil.removeNamespaceProperty(namespaceId, property);
+        } else {
+          NamespacePropUtil.setNamespaceProperty(namespaceId, property, value);
+        }
+      } catch (Exception e) {
+        log.error("Problem altering table namespace property", e);
+        throw new ThriftTableOperationException(namespaceId, namespace, op, TableOperationExceptionType.OTHER, "Problem altering table namespace property");
+      }
+    }
+
     @Override
     public void removeTableProperty(TInfo info, TCredentials credentials, String tableName, String property) throws ThriftSecurityException,
         ThriftTableOperationException, TException {
@@ -845,10 +896,9 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
           checkNotMetadataTable(tableName, TableOperation.CREATE);
           checkTableName(tableName, TableOperation.CREATE);
 
-          org.apache.accumulo.core.client.admin.TimeType timeType = org.apache.accumulo.core.client.admin.TimeType.valueOf(ByteBufferUtil.toString(arguments
-              .get(1)));
-          fate.seedTransaction(opid, new TraceRepo<Master>(new CreateTable(c.getPrincipal(), tableName, timeType, options)), autoCleanup);
+          TimeType timeType = TimeType.valueOf(ByteBufferUtil.toString(arguments.get(1)));
 
+          fate.seedTransaction(opid, new TraceRepo<Master>(new CreateTable(c.getPrincipal(), tableName, timeType, options)), autoCleanup);
           break;
         }
         case RENAME: {
@@ -902,7 +952,6 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
           checkNotMetadataTable(tableName, TableOperation.DELETE);
           if (!security.canDeleteTable(c, tableId))
             throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
-
           fate.seedTransaction(opid, new TraceRepo<Master>(new DeleteTable(tableId)), autoCleanup);
           break;
         }
@@ -1052,6 +1101,85 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
       authenticate(credentials);
       fate.delete(opid);
     }
+
+    @Override
+    public long beginTableNamespaceOperation(TInfo tinfo, TCredentials credentials) throws ThriftSecurityException, TException {
+      return beginTableOperation(tinfo, credentials);
+    }
+
+    @Override
+    public void executeTableNamespaceOperation(TInfo tinfo, TCredentials c, long opid, org.apache.accumulo.core.master.thrift.TableOperation op,
+        List<ByteBuffer> arguments, Map<String,String> options, boolean autoCleanup) throws ThriftSecurityException, ThriftTableOperationException, TException {
+      authenticate(c);
+
+      switch (op) {
+        case CREATE: {
+          String namespace = ByteBufferUtil.toString(arguments.get(0));
+          // TODO security check once namespace permissions exist (ACCUMULO-1479)
+
+          checkTableNamespaceName(namespace);
+          fate.seedTransaction(opid, new TraceRepo<Master>(new CreateTableNamespace(c.getPrincipal(), namespace, options)), autoCleanup);
+          break;
+        }
+        case RENAME: {
+
+          String oldName = ByteBufferUtil.toString(arguments.get(0));
+          String newName = ByteBufferUtil.toString(arguments.get(1));
+          // TODO security check (ACCUMULO-1479)
+          String namespaceId = checkNamespaceId(oldName, TableOperation.RENAME);
+          checkTableNamespaceName(newName);
+          fate.seedTransaction(opid, new TraceRepo<Master>(new RenameTableNamespace(namespaceId, oldName, newName)), autoCleanup);
+          break;
+        }
+        case DELETE: {
+          String namespace = ByteBufferUtil.toString(arguments.get(0));
+          String namespaceId = checkNamespaceId(namespace, TableOperation.DELETE);
+          // TODO security check (ACCUMULO-1479)
+          fate.seedTransaction(opid, new TraceRepo<Master>(new DeleteTableNamespace(namespaceId)), autoCleanup);
+          break;
+        }
+        default:
+          throw new UnsupportedOperationException();
+      }
+
+    }
+
+    protected void checkTableNamespaceName(String namespace) throws ThriftTableOperationException {
+      if (TableNamespaces.getNameToIdMap(instance).containsKey(namespace)) {
+        String why = "Table namespace already exists: " + namespace;
+        throw new ThriftTableOperationException(null, namespace, TableOperation.CREATE, TableOperationExceptionType.EXISTS, why);
+      }
+    }
+
+    protected String checkNamespaceId(String namespace, TableOperation operation) throws ThriftTableOperationException {
+      final String namespaceId = TableNamespaces.getNameToIdMap(getConfiguration().getInstance()).get(namespace);
+      if (namespaceId == null)
+        throw new ThriftTableOperationException(null, namespace, operation, TableOperationExceptionType.NOTFOUND, null);
+      return namespaceId;
+    }
+
+    @Override
+    public String waitForTableNamespaceOperation(TInfo tinfo, TCredentials credentials, long opid) throws ThriftSecurityException,
+        ThriftTableOperationException, TException {
+      return waitForTableOperation(tinfo, credentials, opid);
+    }
+
+    @Override
+    public void finishTableNamespaceOperation(TInfo tinfo, TCredentials credentials, long opid) throws ThriftSecurityException, TException {
+      finishTableOperation(tinfo, credentials, opid);
+    }
+
+    @Override
+    public void setTableNamespaceProperty(TInfo tinfo, TCredentials credentials, String ns, String property, String value) throws ThriftSecurityException,
+        ThriftTableOperationException, TException {
+      alterTableNamespaceProperty(credentials, ns, property, value, TableOperation.SET_PROPERTY);
+    }
+
+    @Override
+    public void removeTableNamespaceProperty(TInfo tinfo, TCredentials credentials, String ns, String property) throws ThriftSecurityException,
+        ThriftTableOperationException, TException {
+      alterTableNamespaceProperty(credentials, ns, property, null, TableOperation.REMOVE_PROPERTY);
+    }
   }
 
   public MergeInfo getMergeInfo(KeyExtent tablet) {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTable.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTable.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTable.java
index 8d906d6..b4c8aa2 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTable.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTable.java
@@ -21,6 +21,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.impl.thrift.TableOperation;
 import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
@@ -147,6 +148,15 @@ class CloneZookeeper extends MasterRepo {
       TableManager.getInstance().cloneTable(cloneInfo.srcTableId, cloneInfo.tableId, cloneInfo.tableName, cloneInfo.propertiesToSet,
           cloneInfo.propertiesToExclude, NodeExistsPolicy.OVERWRITE);
       Tables.clearCache(instance);
+      
+      String namespace = Tables.extractNamespace(cloneInfo.tableName);
+      String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+      TableManager tm = TableManager.getInstance();
+      if (!TableNamespaces.getNameToIdMap(instance).containsKey(namespace)) {
+        tm.addNamespace(namespaceId, namespace, NodeExistsPolicy.SKIP);
+      }
+      tm.addNamespaceToTable(cloneInfo.tableId, namespaceId);
+      
       return new CloneMetadata(cloneInfo);
     } finally {
       Utils.tableNameLock.unlock();

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTable.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTable.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTable.java
index df2e028..d425fe8 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTable.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTable.java
@@ -23,6 +23,7 @@ import java.util.Map.Entry;
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.admin.TimeType;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.impl.thrift.TableOperation;
 import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
@@ -212,6 +213,11 @@ class PopulateZookeeper extends MasterRepo {
       
       TableManager.getInstance().addTable(tableInfo.tableId, tableInfo.tableName, NodeExistsPolicy.OVERWRITE);
       
+      String namespace = Tables.extractNamespace(tableInfo.tableName);
+      String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+      
+      TableManager.getInstance().addNamespaceToTable(tableInfo.tableId, namespaceId);
+      
       for (Entry<String,String> entry : tableInfo.props.entrySet())
         TablePropUtil.setTableProperty(tableInfo.tableId, entry.getKey(), entry.getValue());
       
@@ -288,7 +294,7 @@ public class CreateTable extends MasterRepo {
   }
   
   @Override
-  public Repo<Master> call(long tid, Master master) throws Exception {
+  public Repo<Master> call(long tid, Master master) throws Exception {   
     // first step is to reserve a table id.. if the machine fails during this step
     // it is ok to retry... the only side effect is that a table id may not be used
     // or skipped


Mime
View raw message