accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [05/54] git commit: ACCUMULO-802 Apply Sean Hickey's patch (v5)
Date Fri, 01 Nov 2013 02:00:06 GMT
ACCUMULO-802 Apply Sean Hickey's patch (v5)


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

Branch: refs/heads/ACCUMULO-802
Commit: d4c3e6a9d9abd5cd300dd60a3302439f4feec52b
Parents: 05d5921
Author: Christopher Tubbs <ctubbsii@apache.org>
Authored: Mon Jul 8 15:30:10 2013 -0400
Committer: Christopher Tubbs <ctubbsii@apache.org>
Committed: Thu Oct 31 21:11:24 2013 -0400

----------------------------------------------------------------------
 .../org/apache/accumulo/core/Constants.java     |    12 +-
 .../apache/accumulo/core/client/Connector.java  |     8 +
 .../client/TableNamespaceExistsException.java   |    66 +
 .../client/TableNamespaceNotEmptyException.java |    76 +
 .../client/TableNamespaceNotFoundException.java |    76 +
 .../client/admin/TableNamespaceOperations.java  |   234 +
 .../admin/TableNamespaceOperationsImpl.java     |   534 +
 .../core/client/admin/TableOperationsImpl.java  |    32 +-
 .../core/client/impl/ConnectorImpl.java         |    10 +
 .../core/client/impl/TableNamespaces.java       |   107 +
 .../accumulo/core/client/impl/Tables.java       |    55 +-
 .../core/client/impl/thrift/ClientService.java  |  1178 ++
 .../accumulo/core/client/mock/MockAccumulo.java |    28 +-
 .../core/client/mock/MockConnector.java         |     6 +
 .../accumulo/core/client/mock/MockTable.java    |    36 +-
 .../core/client/mock/MockTableNamespace.java    |    59 +
 .../mock/MockTableNamespaceOperations.java      |   176 +
 .../core/client/mock/MockTableOperations.java   |    47 +-
 .../core/master/thrift/MasterClientService.java | 11700 ++++++++++++++---
 .../apache/accumulo/core/util/shell/Shell.java  |    28 +-
 .../shell/commands/CreateNamespaceCommand.java  |    95 +
 .../core/util/shell/commands/DUCommand.java     |    29 +-
 .../shell/commands/DeleteNamespaceCommand.java  |   104 +
 .../util/shell/commands/NamespacesCommand.java  |    55 +
 .../shell/commands/RenameNamespaceCommand.java  |    79 +
 .../util/shell/commands/TableOperation.java     |    15 +-
 core/src/main/thrift/client.thrift              |     1 +
 core/src/main/thrift/master.thrift              |    12 +-
 .../client/mock/MockTableNamespacesTest.java    |   265 +
 .../apache/accumulo/server/ServerConstants.java |     9 +-
 .../server/client/ClientServiceHandler.java     |    18 +-
 .../server/conf/ServerConfiguration.java        |    55 +-
 .../conf/TableNamespaceConfiguration.java       |   103 +
 .../apache/accumulo/server/init/Initialize.java |    17 +-
 .../accumulo/server/tables/TableManager.java    |    39 +-
 .../accumulo/server/util/NamespacePropUtil.java |    60 +
 .../java/org/apache/accumulo/master/Master.java |   136 +-
 .../accumulo/master/tableOps/CloneTable.java    |    10 +
 .../accumulo/master/tableOps/CreateTable.java   |     8 +-
 .../master/tableOps/CreateTableNamespace.java   |   188 +
 .../master/tableOps/DeleteTableNamespace.java   |   100 +
 .../accumulo/master/tableOps/ImportTable.java   |     5 +
 .../accumulo/master/tableOps/RenameTable.java   |    41 +-
 .../master/tableOps/RenameTableNamespace.java   |    91 +
 .../apache/accumulo/master/tableOps/Utils.java  |    30 +-
 .../org/apache/accumulo/test/ShellServerIT.java |    23 +
 .../accumulo/test/TableNamespacesTest.java      |   281 +
 47 files changed, 14141 insertions(+), 2196 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/Constants.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/Constants.java b/core/src/main/java/org/apache/accumulo/core/Constants.java
index 9db0c40..d85e5d0 100644
--- a/core/src/main/java/org/apache/accumulo/core/Constants.java
+++ b/core/src/main/java/org/apache/accumulo/core/Constants.java
@@ -36,6 +36,11 @@ public class Constants {
   public static final String ZTABLE_FLUSH_ID = "/flush-id";
   public static final String ZTABLE_COMPACT_ID = "/compact-id";
   public static final String ZTABLE_COMPACT_CANCEL_ID = "/compact-cancel-id";
+  public static final String ZTABLE_NAMESPACE = "/namespace";
+
+  public static final String ZNAMESPACES = "/namespaces";
+  public static final String ZNAMESPACE_NAME = "/name";
+  public static final String ZNAMESPACE_CONF = "/conf";
 
   public static final String ZMASTERS = "/masters";
   public static final String ZMASTER_LOCK = ZMASTERS + "/lock";
@@ -96,7 +101,8 @@ public class Constants {
   
   public static final int MAX_DATA_TO_PRINT = 64;
   public static final String CORE_PACKAGE_NAME = "org.apache.accumulo.core";
-  public static final String VALID_TABLE_NAME_REGEX = "^\\w+$";
+  public static final String VALID_TABLE_NAME_REGEX = "^(\\w+\\.)?(\\w+)$";
+  public static final String VALID_TABLE_NAMESPACE_REGEX = "^\\w+$";
   public static final String MAPFILE_EXTENSION = "map";
   public static final String GENERATED_TABLET_DIRECTORY_PREFIX = "t-";
   
@@ -105,4 +111,8 @@ public class Constants {
   public static final String EXPORT_FILE = "exportMetadata.zip";
   public static final String EXPORT_INFO_FILE = "accumulo_export_info.txt";
   
+  public static final String DEFAULT_TABLE_NAMESPACE = "_default_";
+  public static final String SYSTEM_TABLE_NAMESPACE = "_system_";
+  public static final String DEFAULT_TABLE_NAMESPACE_ID = "!DEF";
+  public static final String SYSTEM_TABLE_NAMESPACE_ID = "!SYS";
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/Connector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/Connector.java b/core/src/main/java/org/apache/accumulo/core/client/Connector.java
index bbfa55f..06b74a8 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/Connector.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/Connector.java
@@ -18,6 +18,7 @@ package org.apache.accumulo.core.client;
 
 import org.apache.accumulo.core.client.admin.InstanceOperations;
 import org.apache.accumulo.core.client.admin.SecurityOperations;
+import org.apache.accumulo.core.client.admin.TableNamespaceOperations;
 import org.apache.accumulo.core.client.admin.TableOperations;
 import org.apache.accumulo.core.security.Authorizations;
 
@@ -210,6 +211,13 @@ public abstract class Connector {
   public abstract TableOperations tableOperations();
   
   /**
+   * Retrieves a TableNamespaceOperations object to perform table namespace functions, such as create and delete.
+   * 
+   * @return an object to manipulate table namespaces
+   */
+  public abstract TableNamespaceOperations tableNamespaceOperations();
+  
+  /**
    * Retrieves a SecurityOperations object to perform user security operations, such as creating users.
    * 
    * @return an object to modify users and permissions

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceExistsException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceExistsException.java b/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceExistsException.java
new file mode 100644
index 0000000..ddddc4f
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceExistsException.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+
+/**
+ * Thrown when the table namespace specified already exists, and it was expected that it didn't
+ */
+public class TableNamespaceExistsException extends Exception {
+  /**
+   * Exception to throw if an operation is attempted on a table namespace that already exists.
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+  
+  /**
+   * @param namespaceId
+   *          the internal id of the table namespace that exists
+   * @param namespaceName
+   *          the visible name of the table namespace that exists
+   * @param description
+   *          the specific reason why it failed
+   */
+  public TableNamespaceExistsException(String namespaceId, String namespaceName, String description) {
+    super("Table namespace" + (namespaceName != null && !namespaceName.isEmpty() ? " " + namespaceName : "") + (namespaceId != null && !namespaceId.isEmpty() ? " (Id=" + namespaceId + ")" : "")
+        + " exists" + (description != null && !description.isEmpty() ? " (" + description + ")" : ""));
+  }
+  
+  /**
+   * @param namespaceId
+   *          the internal id of the table namespace that exists
+   * @param namespaceName
+   *          the visible name of the table namespace that exists
+   * @param description
+   *          the specific reason why it failed
+   * @param cause
+   *          the exception that caused this failure
+   */
+  public TableNamespaceExistsException(String namespaceId, String namespaceName, String description, Throwable cause) {
+    this(namespaceId, namespaceName, description);
+    super.initCause(cause);
+  }
+  
+  /**
+   * @param e
+   *          constructs an exception from a thrift exception
+   */
+  public TableNamespaceExistsException(ThriftTableOperationException e) {
+    this(e.getTableId(), e.getTableName(), e.getDescription(), e);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotEmptyException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotEmptyException.java b/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotEmptyException.java
new file mode 100644
index 0000000..81ef03a
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotEmptyException.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+
+/**
+ * Thrown when the table namespace specified contains tables
+ */
+public class TableNamespaceNotEmptyException extends Exception {
+  /**
+   * Exception to throw if an operation is attempted on a table that doesn't exist.
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+  
+  private String namespace;
+  
+  /**
+   * @param namespaceId
+   *          the internal id of the table namespace that was sought
+   * @param namespaceName
+   *          the visible name of the table namespace that was sought
+   * @param description
+   *          the specific reason why it failed
+   */
+  public TableNamespaceNotEmptyException(String namespaceId, String namespaceName, String description) {
+    super("Table namespace" + (namespaceName != null && !namespaceName.isEmpty() ? " " + namespaceName : "") + (namespaceId != null && !namespaceId.isEmpty() ? " (Id=" + namespaceId + ")" : "")
+        + " it not empty, contains at least one table" + (description != null && !description.isEmpty() ? " (" + description + ")" : ""));
+    this.namespace = namespaceName;
+  }
+  
+  /**
+   * @param namespaceId
+   *          the internal id of the table namespace that was sought
+   * @param namespaceName
+   *          the visible name of the table namespace that was sought
+   * @param description
+   *          the specific reason why it failed
+   * @param cause
+   *          the exception that caused this failure
+   */
+  public TableNamespaceNotEmptyException(String namespaceId, String namespaceName, String description, Throwable cause) {
+    this(namespaceId, namespaceName, description);
+    super.initCause(cause);
+  }
+  
+  /**
+   * @param e
+   *          constructs an exception from a thrift exception
+   */
+  public TableNamespaceNotEmptyException(ThriftTableOperationException e) {
+    this(e.getTableId(), e.getTableName(), e.getDescription(), e);
+  }
+  
+  /**
+   * @return the name of the table namespace sought
+   */
+  public String getNamespaceName() {
+    return namespace;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotFoundException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotFoundException.java b/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotFoundException.java
new file mode 100644
index 0000000..3dd0740
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/TableNamespaceNotFoundException.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+
+/**
+ * Thrown when the table namespace specified doesn't exist when it was expected to
+ */
+public class TableNamespaceNotFoundException extends Exception {
+  /**
+   * Exception to throw if an operation is attempted on a table that doesn't exist.
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+  
+  private String namespace;
+  
+  /**
+   * @param namespaceId
+   *          the internal id of the table namespace that was sought
+   * @param namespaceName
+   *          the visible name of the table namespace that was sought
+   * @param description
+   *          the specific reason why it failed
+   */
+  public TableNamespaceNotFoundException(String namespaceId, String namespaceName, String description) {
+    super("Table namespace" + (namespaceName != null && !namespaceName.isEmpty() ? " " + namespaceName : "") + (namespaceId != null && !namespaceId.isEmpty() ? " (Id=" + namespaceId + ")" : "")
+        + " does not exist" + (description != null && !description.isEmpty() ? " (" + description + ")" : ""));
+    this.namespace = namespaceName;
+  }
+  
+  /**
+   * @param namespaceId
+   *          the internal id of the table namespace that was sought
+   * @param namespaceName
+   *          the visible name of the table namespace that was sought
+   * @param description
+   *          the specific reason why it failed
+   * @param cause
+   *          the exception that caused this failure
+   */
+  public TableNamespaceNotFoundException(String namespaceId, String namespaceName, String description, Throwable cause) {
+    this(namespaceId, namespaceName, description);
+    super.initCause(cause);
+  }
+  
+  /**
+   * @param e
+   *          constructs an exception from a thrift exception
+   */
+  public TableNamespaceNotFoundException(ThriftTableOperationException e) {
+    this(e.getTableId(), e.getTableName(), e.getDescription(), e);
+  }
+  
+  /**
+   * @return the name of the table namespace sought
+   */
+  public String getNamespaceName() {
+    return namespace;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java
new file mode 100644
index 0000000..24793f0
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperations.java
@@ -0,0 +1,234 @@
+/*
+ * 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.admin;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedSet;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableNamespaceExistsException;
+import org.apache.accumulo.core.client.TableNamespaceNotEmptyException;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+
+/**
+ * Provides a class for administering table namespaces
+ * 
+ */
+
+public interface TableNamespaceOperations {
+  
+  /**
+   * Retrieve a list of table namespaces in Accumulo.
+   * 
+   * @return List of table namespaces in accumulo
+   */
+  public SortedSet<String> list();
+  
+  /**
+   * A method to check if a table namespace exists in Accumulo.
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @return true if the table namespace exists
+   */
+  public boolean exists(String namespace);
+  
+  /**
+   * Create a table namespace with no special configuration
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceExistsException
+   *           if the table namespace already exists
+   */
+  public void create(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceExistsException;
+  
+  /**
+   * @param namespace
+   *          the name of the table namespace
+   * @param limitVersion
+   *          Enables/disables the versioning iterator, which will limit the number of Key versions kept.
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceExistsException
+   *           if the table namespace already exists
+   */
+  public void create(String namespace, boolean limitVersion) throws AccumuloException, AccumuloSecurityException, TableNamespaceExistsException;
+  
+  /**
+   * @param namespace
+   *          the name of the table namespace
+   * @param versioningIter
+   *          Enables/disables the versioning iterator, which will limit the number of Key versions kept.
+   * @param timeType
+   *          specifies logical or real-time based time recording for entries in the table
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceExistsException
+   *           if the table namespace already exists
+   */
+  public void create(String namespace, boolean versioningIter, TimeType timeType) throws AccumuloException, AccumuloSecurityException, TableNamespaceExistsException;
+  
+  /**
+   * Delete a table namespace if it is empty
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceNotFoundException
+   *           if the table namespace does not exist
+   * @throws TableNamespaceNotEmptyException 
+   *           if the table namespaces still contains tables
+   */
+  public void delete(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, TableNamespaceNotEmptyException;
+  
+  /**
+   * Delete a table namespace
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @param deleteTables
+   *          boolean, if true deletes all the tables in the namespace in addition to deleting the namespace.
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceNotFoundException
+   *           if the table namespace does not exist
+   * @throws TableNamespaceNotEmptyException 
+   *           if the table namespaces still contains tables
+   */
+  public void delete(String namespace, boolean deleteTables) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, TableNamespaceNotEmptyException;
+  
+  /**
+   * Rename a table namespace
+   * 
+   * @param oldNamespaceName
+   *          the old table namespace name
+   * @param newNamespaceName
+   *          the new table namespace name
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceNotFoundException
+   *           if the old table namespace does not exist
+   * @throws TableNamespaceExistsException
+   *           if the new table namespace already exists
+   */
+  public void rename(String oldNamespaceName, String newNamespaceName) throws AccumuloSecurityException, TableNamespaceNotFoundException, AccumuloException,
+      TableNamespaceExistsException;
+    
+  /**
+   * Sets a property on a table namespace. Note that it may take a short period of time (a second) to propagate the change everywhere.
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @param property
+   *          the name of a per-table property
+   * @param value
+   *          the value to set a per-table property to
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   */
+  public void setProperty(String namespace, String property, String value) throws AccumuloException, AccumuloSecurityException;
+  
+  /**
+   * Removes a property from a table namespace.  Note that it may take a short period of time (a second) to propagate the change everywhere.
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @param property
+   *          the name of a per-table property
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   */
+  public void removeProperty(String namespace, String property) throws AccumuloException, AccumuloSecurityException;
+  
+  /**
+   * Gets properties of a table namespace.  Note that recently changed properties may not be available immediately.
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @return all properties visible by this table (system and per-table properties).  Note that recently changed 
+   *         properties may not be visible immediately. 
+   * @throws TableNamespaceNotFoundException
+   *           if the table does not exist
+   */
+  public Iterable<Entry<String,String>> getProperties(String namespace) throws AccumuloException, TableNamespaceNotFoundException;
+  
+  /**
+   * 
+   * @param namespace
+   *          the table namespace to take offline
+   * @throws AccumuloException
+   *           when there is a general accumulo error
+   * @throws AccumuloSecurityException
+   *           when the user does not have the proper permissions
+   * @throws TableNamespaceNotFoundException
+   */
+  public void offline(String namespace) throws AccumuloSecurityException, AccumuloException, TableNamespaceNotFoundException;
+  
+  /**
+   * 
+   * @param namespace
+   *          the table namespace to take online
+   * @throws AccumuloException
+   *           when there is a general accumulo error
+   * @throws AccumuloSecurityException
+   *           when the user does not have the proper permissions
+   * @throws TableNamespaceNotFoundException
+   */
+  public void online(String namespace) throws AccumuloSecurityException, AccumuloException, TableNamespaceNotFoundException;
+  
+  /**
+   * Get a mapping of table namespace name to internal table namespace id.
+   * 
+   * @return the map from table namespace name to internal table namespace id
+   */
+  public Map<String,String> namespaceIdMap();
+
+  /**
+   * Gets the number of bytes being used in the files for the set of tables in this namespace
+   *
+   * @param namespace
+   *          the table namespace to get the set of tables from
+   *
+   * @return  a list of disk usage objects containing linked table names and sizes
+   * @throws AccumuloException
+   * @throws AccumuloSecurityException
+   */
+  public List<DiskUsage> getDiskUsage(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException;
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java
new file mode 100644
index 0000000..a80dcf6
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/admin/TableNamespaceOperationsImpl.java
@@ -0,0 +1,534 @@
+/*
+ * 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.admin;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import jline.internal.Log;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.TableNamespaceExistsException;
+import org.apache.accumulo.core.client.TableNamespaceNotEmptyException;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.TableOfflineException;
+import org.apache.accumulo.core.client.impl.ClientExec;
+import org.apache.accumulo.core.client.impl.ClientExecReturn;
+import org.apache.accumulo.core.client.impl.MasterClient;
+import org.apache.accumulo.core.client.impl.ServerClient;
+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.ThriftSecurityException;
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+import org.apache.accumulo.core.iterators.IteratorUtil;
+import org.apache.accumulo.core.master.thrift.MasterClientService;
+import org.apache.accumulo.core.master.thrift.TableOperation;
+import org.apache.accumulo.core.security.thrift.TCredentials;
+import org.apache.accumulo.core.util.ArgumentChecker;
+import org.apache.accumulo.core.util.ByteBufferUtil;
+import org.apache.accumulo.core.util.OpTimer;
+import org.apache.accumulo.core.util.UtilWaitThread;
+import org.apache.accumulo.trace.instrument.Tracer;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.thrift.TException;
+import org.apache.thrift.transport.TTransportException;
+
+/**
+ * Provides a class for administering table namespaces
+ * 
+ */
+public class TableNamespaceOperationsImpl implements TableNamespaceOperations {
+  private Instance instance;
+  private TCredentials credentials;
+  
+  private static final Logger log = Logger.getLogger(TableOperations.class);
+  
+  /**
+   * @param instance
+   *          the connection information for this instance
+   * @param credentials
+   *          the username/password for this connection
+   */
+  public TableNamespaceOperationsImpl(Instance instance, TCredentials credentials) {
+    ArgumentChecker.notNull(instance, credentials);
+    this.instance = instance;
+    this.credentials = credentials;
+  }
+  
+  /**
+   * Retrieve a list of table namespaces in Accumulo.
+   * 
+   * @return List of table namespaces in accumulo
+   */
+  @Override
+  public SortedSet<String> list() {
+    OpTimer opTimer = new OpTimer(log, Level.TRACE).start("Fetching list of table namespaces...");
+    TreeSet<String> namespaces = new TreeSet<String>(TableNamespaces.getNameToIdMap(instance).keySet());
+    opTimer.stop("Fetched " + namespaces.size() + " table namespaces in %DURATION%");
+    return namespaces;
+  }
+  
+  /**
+   * A method to check if a table namespace exists in Accumulo.
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @return true if the table namespace exists
+   */
+  @Override
+  public boolean exists(String namespace) {
+    ArgumentChecker.notNull(namespace);
+    
+    OpTimer opTimer = new OpTimer(log, Level.TRACE).start("Checking if table namespace " + namespace + " exists...");
+    boolean exists = TableNamespaces.getNameToIdMap(instance).containsKey(namespace);
+    opTimer.stop("Checked existance of " + exists + " in %DURATION%");
+    return exists;
+  }
+  
+  /**
+   * Create a table namespace with no special configuration
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceExistsException
+   *           if the table namespace already exists
+   */
+  @Override
+  public void create(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceExistsException {
+    create(namespace, true, TimeType.MILLIS);
+  }
+  
+  /**
+   * @param namespace
+   *          the name of the table namespace
+   * @param limitVersion
+   *          Enables/disables the versioning iterator, which will limit the number of Key versions kept.
+   */
+  @Override
+  public void create(String namespace, boolean limitVersion) throws AccumuloException, AccumuloSecurityException, TableNamespaceExistsException {
+    create(namespace, limitVersion, TimeType.MILLIS);
+  }
+  
+  /**
+   * @param namespace
+   *          the name of the table namespace
+   * @param timeType
+   *          specifies logical or real-time based time recording for entries in the table
+   * @param limitVersion
+   *          Enables/disables the versioning iterator, which will limit the number of Key versions kept.
+   */
+  @Override
+  public void create(String namespace, boolean limitVersion, TimeType timeType) throws AccumuloException, AccumuloSecurityException,
+      TableNamespaceExistsException {
+    ArgumentChecker.notNull(namespace, timeType);
+    
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(namespace.getBytes()), ByteBuffer.wrap(timeType.name().getBytes()));
+    
+    Map<String,String> opts = IteratorUtil.generateInitialTableProperties(limitVersion);
+    
+    try {
+      doTableNamespaceOperation(TableOperation.CREATE, args, opts);
+    } catch (TableNamespaceNotFoundException e1) {
+      // should not happen
+      throw new RuntimeException(e1);
+    }
+  }
+  
+  private long beginTableNamespaceOperation() throws ThriftSecurityException, TException {
+    while (true) {
+      MasterClientService.Iface client = null;
+      try {
+        client = MasterClient.getConnectionWithRetry(instance);
+        return client.beginTableNamespaceOperation(Tracer.traceInfo(), credentials);
+      } catch (TTransportException tte) {
+        log.debug("Failed to call beginTableOperation(), retrying ... ", tte);
+        UtilWaitThread.sleep(100);
+      } finally {
+        MasterClient.close(client);
+      }
+    }
+  }
+  
+  private void executeTableNamespaceOperation(long opid, TableOperation op, List<ByteBuffer> args, Map<String,String> opts, boolean autoCleanUp)
+      throws ThriftSecurityException, TException, ThriftTableOperationException {
+    while (true) {
+      MasterClientService.Iface client = null;
+      try {
+        client = MasterClient.getConnectionWithRetry(instance);
+        client.executeTableNamespaceOperation(Tracer.traceInfo(), credentials, opid, op, args, opts, autoCleanUp);
+        break;
+      } catch (TTransportException tte) {
+        log.debug("Failed to call executeTableOperation(), retrying ... ", tte);
+        UtilWaitThread.sleep(100);
+      } finally {
+        MasterClient.close(client);
+      }
+    }
+  }
+  
+  private String waitForTableNamespaceOperation(long opid) throws ThriftSecurityException, TException, ThriftTableOperationException {
+    while (true) {
+      MasterClientService.Iface client = null;
+      try {
+        client = MasterClient.getConnectionWithRetry(instance);
+        return client.waitForTableNamespaceOperation(Tracer.traceInfo(), credentials, opid);
+      } catch (TTransportException tte) {
+        log.debug("Failed to call waitForTableOperation(), retrying ... ", tte);
+        UtilWaitThread.sleep(100);
+      } finally {
+        MasterClient.close(client);
+      }
+    }
+  }
+  
+  private void finishTableNamespaceOperation(long opid) throws ThriftSecurityException, TException {
+    while (true) {
+      MasterClientService.Iface client = null;
+      try {
+        client = MasterClient.getConnectionWithRetry(instance);
+        client.finishTableNamespaceOperation(Tracer.traceInfo(), credentials, opid);
+        break;
+      } catch (TTransportException tte) {
+        log.debug("Failed to call finishTableOperation(), retrying ... ", tte);
+        UtilWaitThread.sleep(100);
+      } finally {
+        MasterClient.close(client);
+      }
+    }
+  }
+  
+  private String doTableNamespaceOperation(TableOperation op, List<ByteBuffer> args, Map<String,String> opts) throws AccumuloSecurityException,
+      TableNamespaceExistsException, TableNamespaceNotFoundException, AccumuloException {
+    return doTableNamespaceOperation(op, args, opts, true);
+  }
+  
+  private String doTableNamespaceOperation(TableOperation op, List<ByteBuffer> args, Map<String,String> opts, boolean wait) throws AccumuloSecurityException,
+      TableNamespaceExistsException, TableNamespaceNotFoundException, AccumuloException {
+    Long opid = null;
+    
+    try {
+      opid = beginTableNamespaceOperation();
+      executeTableNamespaceOperation(opid, op, args, opts, !wait);
+      if (!wait) {
+        opid = null;
+        return null;
+      }
+      String ret = waitForTableNamespaceOperation(opid);
+      Tables.clearCache(instance);
+      return ret;
+    } catch (ThriftSecurityException e) {
+      String tableName = ByteBufferUtil.toString(args.get(0));
+      String tableInfo = Tables.getPrintableTableInfoFromName(instance, tableName);
+      throw new AccumuloSecurityException(e.user, e.code, tableInfo, e);
+    } catch (ThriftTableOperationException e) {
+      switch (e.getType()) {
+        case EXISTS:
+          throw new TableNamespaceExistsException(e);
+        case NOTFOUND:
+          throw new TableNamespaceNotFoundException(e);
+        case OFFLINE:
+          throw new TableOfflineException(instance, null);
+        case OTHER:
+        default:
+          throw new AccumuloException(e.description, e);
+      }
+    } catch (Exception e) {
+      throw new AccumuloException(e.getMessage(), e);
+    } finally {
+      // always finish table op, even when exception
+      if (opid != null)
+        try {
+          finishTableNamespaceOperation(opid);
+        } catch (Exception e) {
+          log.warn(e.getMessage(), e);
+        }
+    }
+  }
+  
+  /**
+   * Delete a table namespace if empty
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceNotFoundException
+   *           if the table namespace does not exist
+   * @throws TableNamespaceNotEmptyException 
+   *           if the table namespaces still contains tables
+   */
+  @Override
+  public void delete(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, TableNamespaceNotEmptyException {
+    delete(namespace, false);
+  }
+  
+  /**
+   * Delete a table namespace
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @param deleteTables
+   *          boolean, if true deletes all the tables in the namespace in addition to deleting the namespace.
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceNotFoundException
+   *           if the table namespace does not exist
+   * @throws TableNamespaceNotEmptyException 
+   */
+  @Override
+  public void delete(String namespace, boolean deleteTables) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException, TableNamespaceNotEmptyException {
+    ArgumentChecker.notNull(namespace);
+    String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+    
+    if (namespaceId.equals(Constants.SYSTEM_TABLE_NAMESPACE_ID) || namespaceId.equals(Constants.DEFAULT_TABLE_NAMESPACE_ID)) {
+      String why = "Can't delete the system or default table namespace";
+      throw new RuntimeException(why);
+    }
+    
+    if (TableNamespaces.getTableIds(instance, namespaceId).size() > 0) {
+      if (!deleteTables) {
+        throw new TableNamespaceNotEmptyException(namespaceId, namespace, null);
+      }
+      for (String table : TableNamespaces.getTableNames(instance, namespaceId)) {
+        try {
+          getTableOperations().delete(table);
+        } catch (TableNotFoundException e) {
+          throw new RuntimeException("Table (" + table + ") was found in ZooKeeper, but now doesn't exist. (while deleting namespace)");
+        }
+      }
+    }
+    
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(namespace.getBytes()));
+    Map<String,String> opts = new HashMap<String,String>();
+    
+    try {
+      doTableNamespaceOperation(TableOperation.DELETE, args, opts);
+    } catch (TableNamespaceExistsException e) {
+      // should not happen
+      throw new RuntimeException(e);
+    }
+    
+  }
+  
+  /**
+   * Rename a table namespace
+   * 
+   * @param oldNamespaceName
+   *          the old table namespace
+   * @param newNamespaceName
+   *          the new table namespace
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   * @throws TableNamespaceNotFoundException
+   *           if the old table namespace name does not exist
+   * @throws TableNamespaceExistsException
+   *           if the new table namespace name already exists
+   */
+  @Override
+  public void rename(String oldNamespaceName, String newNamespaceName) throws AccumuloSecurityException, TableNamespaceNotFoundException, AccumuloException,
+      TableNamespaceExistsException {
+    
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(oldNamespaceName.getBytes()), ByteBuffer.wrap(newNamespaceName.getBytes()));
+    Map<String,String> opts = new HashMap<String,String>();
+    doTableNamespaceOperation(TableOperation.RENAME, args, opts);
+  }
+  
+  /**
+   * Sets a property on a table namespace
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @param property
+   *          the name of a per-table property
+   * @param value
+   *          the value to set a per-table property to
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   */
+  @Override
+  public void setProperty(final String namespace, final String property, final String value) throws AccumuloException, AccumuloSecurityException {
+    ArgumentChecker.notNull(namespace, property, value);
+    
+    MasterClient.execute(instance, new ClientExec<MasterClientService.Client>() {
+      @Override
+      public void execute(MasterClientService.Client client) throws Exception {
+        client.setTableNamespaceProperty(Tracer.traceInfo(), credentials, namespace, property, value);
+      }
+    });
+  }
+  
+  /**
+   * Removes a property from a table namespace
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @param property
+   *          the name of a per-table property
+   * @throws AccumuloException
+   *           if a general error occurs
+   * @throws AccumuloSecurityException
+   *           if the user does not have permission
+   */
+  @Override
+  public void removeProperty(final String namespace, final String property) throws AccumuloException, AccumuloSecurityException {
+    ArgumentChecker.notNull(namespace, property);
+    
+    MasterClient.execute(instance, new ClientExec<MasterClientService.Client>() {
+      @Override
+      public void execute(MasterClientService.Client client) throws Exception {
+        client.removeTableNamespaceProperty(Tracer.traceInfo(), credentials, namespace, property);
+      }
+    });
+  }
+  
+  /**
+   * Gets properties of a table namespace
+   * 
+   * @param namespace
+   *          the name of the table namespace
+   * @return all properties visible by this table namespace (system and per-namespace properties)
+   * @throws TableNamespaceNotFoundException
+   *           if the table namespace does not exist
+   */
+  @Override
+  public Iterable<Entry<String,String>> getProperties(final String namespace) throws AccumuloException, TableNamespaceNotFoundException {
+    ArgumentChecker.notNull(namespace);
+    try {
+      return ServerClient.executeRaw(instance, new ClientExecReturn<Map<String,String>,ClientService.Client>() {
+        @Override
+        public Map<String,String> execute(ClientService.Client client) throws Exception {
+          return client.getTableNamespaceConfiguration(Tracer.traceInfo(), credentials, namespace);
+        }
+      }).entrySet();
+    } catch (ThriftTableOperationException e) {
+      switch (e.getType()) {
+        case NOTFOUND:
+          throw new TableNamespaceNotFoundException(e);
+        case OTHER:
+        default:
+          throw new AccumuloException(e.description, e);
+      }
+    } catch (AccumuloException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new AccumuloException(e);
+    }
+    
+  }
+  
+  /**
+   * 
+   * @param namespace
+   *          the table namespace to take offline
+   * @throws AccumuloException
+   *           when there is a general accumulo error
+   * @throws AccumuloSecurityException
+   *           when the user does not have the proper permissions
+   * @throws TableNamespaceNotFoundException
+   */
+  @Override
+  public void offline(String namespace) throws AccumuloSecurityException, AccumuloException, TableNamespaceNotFoundException {
+    
+    ArgumentChecker.notNull(namespace);
+    String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+    try {
+      for (String table : TableNamespaces.getTableNames(instance, namespaceId)) {
+        getTableOperations().offline(table);
+      }
+    } catch (TableNotFoundException e) {
+      Log.error("Table namespace (" + namespaceId + ") contains reference to table that doesn't exist");
+    }
+  }
+  
+  /**
+   * 
+   * @param namespace
+   *          the table namespace to take online
+   * @throws AccumuloException
+   *           when there is a general accumulo error
+   * @throws AccumuloSecurityException
+   *           when the user does not have the proper permissions
+   * @throws TableNamespaceNotFoundException
+   */
+  @Override
+  public void online(String namespace) throws AccumuloSecurityException, AccumuloException, TableNamespaceNotFoundException {
+    ArgumentChecker.notNull(namespace);
+    String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+    try {
+      for (String table : TableNamespaces.getTableNames(instance, namespaceId)) {
+        getTableOperations().online(table);
+      }
+    } catch (TableNotFoundException e) {
+      Log.warn("Table namespace (" + namespaceId + ") contains a reference to a table that doesn't exist");
+    }
+  }
+  
+  /**
+   * Get a mapping of table namespace name to internal table namespace id.
+   * 
+   * @return the map from table namespace name to internal table namespace id
+   */
+  @Override
+  public Map<String,String> namespaceIdMap() {
+    return TableNamespaces.getNameToIdMap(instance);
+  }
+  
+  @Override
+  public List<DiskUsage> getDiskUsage(String namespace) throws AccumuloException, AccumuloSecurityException, TableNamespaceNotFoundException {
+    Set<String> tables = new HashSet<String>();
+    String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+    tables.addAll(TableNamespaces.getTableNames(instance, namespaceId));
+    List<DiskUsage> du = null;
+    try {
+      du = getTableOperations().getDiskUsage(tables);
+    } catch (TableNotFoundException e) {
+      log.warn("Could not find table (" + e.getTableName() + ") reference in namespace (" + namespace + ")");
+    }
+    return du;
+  }
+  
+  private TableOperations getTableOperations() throws AccumuloException, AccumuloSecurityException {
+    return new TableOperationsImpl(instance, credentials);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperationsImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperationsImpl.java
index 1b652f9..a3cf190 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperationsImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/admin/TableOperationsImpl.java
@@ -54,6 +54,7 @@ import org.apache.accumulo.core.client.RowIterator;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableDeletedException;
 import org.apache.accumulo.core.client.TableExistsException;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.TableOfflineException;
 import org.apache.accumulo.core.client.impl.AccumuloServerException;
@@ -61,6 +62,7 @@ import org.apache.accumulo.core.client.impl.ClientExec;
 import org.apache.accumulo.core.client.impl.ClientExecReturn;
 import org.apache.accumulo.core.client.impl.MasterClient;
 import org.apache.accumulo.core.client.impl.ServerClient;
+import org.apache.accumulo.core.client.impl.TableNamespaces;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.impl.TabletLocator;
 import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocation;
@@ -167,7 +169,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
     if (tableName.equals(MetadataTable.NAME) || tableName.equals(RootTable.NAME))
       return true;
     
-    OpTimer opTimer = new OpTimer(log, Level.TRACE).start("Checking if table " + tableName + "exists...");
+    OpTimer opTimer = new OpTimer(log, Level.TRACE).start("Checking if table " + tableName + " exists...");
     boolean exists = Tables.getNameToIdMap(instance).containsKey(tableName);
     opTimer.stop("Checked existance of " + exists + " in %DURATION%");
     return exists;
@@ -217,6 +219,12 @@ public class TableOperationsImpl extends TableOperationsHelper {
     
     Map<String,String> opts = IteratorUtil.generateInitialTableProperties(limitVersion);
     
+    String namespace = Tables.extractNamespace(tableName);
+    if (!namespaceExists(namespace)) {
+      String info = "Table namespace not found while trying to create table";
+      throw new RuntimeException(new TableNamespaceNotFoundException(null, namespace, info));
+    }
+    
     try {
       doTableOperation(TableOperation.CREATE, args, opts);
     } catch (TableNotFoundException e1) {
@@ -673,6 +681,12 @@ public class TableOperationsImpl extends TableOperationsHelper {
     
     ArgumentChecker.notNull(srcTableName, newTableName);
     
+    String namespace = Tables.extractNamespace(newTableName);
+    if (!namespaceExists(namespace)) {
+      String info = "Table namespace not found while cloning table";
+      throw new RuntimeException(new TableNamespaceNotFoundException(null, namespace, info));
+    }
+    
     String srcTableId = Tables.getTableId(instance, srcTableName);
     
     if (flush)
@@ -722,6 +736,12 @@ public class TableOperationsImpl extends TableOperationsHelper {
   public void rename(String oldTableName, String newTableName) throws AccumuloSecurityException, TableNotFoundException, AccumuloException,
       TableExistsException {
     
+    String namespace = Tables.extractNamespace(newTableName);
+    if (!namespaceExists(namespace)) {
+      String info = "Table namespace not found while renaming table";
+      throw new RuntimeException(new TableNamespaceNotFoundException(null, namespace, info));
+    }
+    
     List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(oldTableName.getBytes()), ByteBuffer.wrap(newTableName.getBytes()));
     Map<String,String> opts = new HashMap<String,String>();
     doTableOperation(TableOperation.RENAME, args, opts);
@@ -1459,6 +1479,12 @@ public class TableOperationsImpl extends TableOperationsHelper {
       Logger.getLogger(this.getClass()).warn("Failed to check if imported table references external java classes : " + ioe.getMessage());
     }
     
+    String namespace = Tables.extractNamespace(tableName);
+    if (!namespaceExists(namespace)) {
+      String info = "Table namespace not found while importing to table";
+      throw new RuntimeException(new TableNamespaceNotFoundException(null, namespace, info));
+    }
+    
     List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableName.getBytes()), ByteBuffer.wrap(importDir.getBytes()));
     
     Map<String,String> opts = Collections.emptyMap();
@@ -1529,4 +1555,8 @@ public class TableOperationsImpl extends TableOperationsHelper {
     testClassLoad(tableName, constraintClassName, Constraint.class.getName());
     return super.addConstraint(tableName, constraintClassName);
   }
+  
+  private boolean namespaceExists(String namespace) {
+    return TableNamespaces.getNameToIdMap(instance).containsKey(namespace);
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
index bd11569..bc3f39a 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
@@ -36,6 +36,8 @@ import org.apache.accumulo.core.client.admin.InstanceOperations;
 import org.apache.accumulo.core.client.admin.InstanceOperationsImpl;
 import org.apache.accumulo.core.client.admin.SecurityOperations;
 import org.apache.accumulo.core.client.admin.SecurityOperationsImpl;
+import org.apache.accumulo.core.client.admin.TableNamespaceOperations;
+import org.apache.accumulo.core.client.admin.TableNamespaceOperationsImpl;
 import org.apache.accumulo.core.client.admin.TableOperations;
 import org.apache.accumulo.core.client.admin.TableOperationsImpl;
 import org.apache.accumulo.core.client.impl.thrift.ClientService;
@@ -51,6 +53,7 @@ public class ConnectorImpl extends Connector {
   private final Credentials credentials;
   private SecurityOperations secops = null;
   private TableOperations tableops = null;
+  private TableNamespaceOperations namespaceops = null;
   private InstanceOperations instanceops = null;
   
   public ConnectorImpl(final Instance instance, Credentials cred) throws AccumuloException, AccumuloSecurityException {
@@ -158,6 +161,13 @@ public class ConnectorImpl extends Connector {
   }
   
   @Override
+  public synchronized TableNamespaceOperations tableNamespaceOperations() {
+    if (namespaceops == null)
+      namespaceops = new TableNamespaceOperationsImpl(instance, credentials);
+    return namespaceops;
+  }
+  
+  @Override
   public synchronized SecurityOperations securityOperations() {
     if (secops == null)
       secops = new SecurityOperationsImpl(instance, credentials);

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/impl/TableNamespaces.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TableNamespaces.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TableNamespaces.java
new file mode 100644
index 0000000..e3de9db
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TableNamespaces.java
@@ -0,0 +1,107 @@
+/*
+ * 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.impl;
+
+import java.security.SecurityPermission;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.zookeeper.ZooCache;
+
+public class TableNamespaces {
+  private static SecurityPermission TABLES_PERMISSION = new SecurityPermission("tablesPermission");
+  
+  private static ZooCache getZooCache(Instance instance) {
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null) {
+      sm.checkPermission(TABLES_PERMISSION);
+    }
+    return ZooCache.getInstance(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut());
+  }
+  
+  private static SortedMap<String,String> getMap(Instance instance, boolean nameAsKey) {
+    ZooCache zc = getZooCache(instance);
+    
+    List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES);
+    
+    TreeMap<String,String> namespaceMap = new TreeMap<String,String>();
+    
+    for (String id : namespaceIds) {
+      byte[] path = zc.get(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + id + Constants.ZNAMESPACE_NAME);
+      if (path != null) {
+        if (nameAsKey)
+          namespaceMap.put(new String(path, Constants.UTF8), id);
+        else
+          namespaceMap.put(id, new String(path, Constants.UTF8));
+      }
+    }
+    return namespaceMap;
+  }
+  
+  public static String getNamespaceId(Instance instance, String namespace) throws TableNamespaceNotFoundException {
+    String id = getNameToIdMap(instance).get(namespace);
+    if (id == null)
+      throw new TableNamespaceNotFoundException(null, namespace, "getNamespaceId() failed to find namespace");
+    return id;
+  }
+  
+  public static String getNamespaceName(Instance instance, String namespaceId) throws TableNamespaceNotFoundException {
+    String namespaceName = getIdToNameMap(instance).get(namespaceId);
+    if (namespaceName == null)
+      throw new TableNamespaceNotFoundException(namespaceId, null, "getNamespaceName() failed to find namespace");
+    return namespaceName;
+  }
+  
+  public static SortedMap<String,String> getNameToIdMap(Instance instance) {
+    return getMap(instance, true);
+  }
+  
+  public static SortedMap<String,String> getIdToNameMap(Instance instance) {
+    return getMap(instance, false);
+  }
+  
+  public static List<String> getTableIds(Instance instance, String namespaceId) throws TableNamespaceNotFoundException {
+    List<String> l = new LinkedList<String>();
+    for (String id : Tables.getIdToNameMap(instance).keySet()) {
+      if (Tables.getNamespace(instance, id).equals(namespaceId)) {
+        l.add(id);
+      }
+    }
+    return l;
+  }
+  
+  public static List<String> getTableNames(Instance instance, String namespaceId) throws TableNamespaceNotFoundException {
+    ZooCache zc = getZooCache(instance);
+    List<String> ids = getTableIds(instance, namespaceId);
+    List<String> names = new LinkedList<String>();
+    String namespace = getNamespaceName(instance, namespaceId) + ".";
+    if (namespaceId.equals(Constants.DEFAULT_TABLE_NAMESPACE_ID) || namespaceId.equals(Constants.SYSTEM_TABLE_NAMESPACE_ID)) {
+      // default and system namespaces aren't displayed for backwards compatibility
+      namespace = "";
+    }
+    for (String id : ids) {
+      names.add(namespace + new String(zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + id + Constants.ZTABLE_NAME), Constants.UTF8));
+    }
+    return names;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
index 8bc725a..1573303 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
@@ -22,10 +22,15 @@ import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import jline.internal.Log;
+
 import org.apache.accumulo.core.Constants;
 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.master.state.tables.TableState;
+import org.apache.accumulo.core.metadata.MetadataTable;
+import org.apache.accumulo.core.metadata.RootTable;
 import org.apache.accumulo.core.zookeeper.ZooUtil;
 import org.apache.accumulo.fate.zookeeper.ZooCache;
 
@@ -49,11 +54,26 @@ public class Tables {
     
     for (String tableId : tableIds) {
       byte[] tblPath = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAME);
+      byte[] nId = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE);
+      String name = "";
+      // create fully qualified table name if it's in a namespace other than default or system.
+      if (nId != null) {
+        String namespaceId = new String(nId, Constants.UTF8);
+        if (!namespaceId.equals(Constants.DEFAULT_TABLE_NAMESPACE_ID) && !namespaceId.equals(Constants.SYSTEM_TABLE_NAMESPACE_ID)) {
+          try {
+            name += TableNamespaces.getNamespaceName(instance, new String(namespaceId)) + ".";
+          } catch (TableNamespaceNotFoundException e) {
+            Log.error("Table (" + tableId + ") contains reference to namespace (" + namespaceId + ") that doesn't exist");
+            continue;
+          }
+        }
+      }
       if (tblPath != null) {
+        name += new String(tblPath, Constants.UTF8);
         if (nameAsKey)
-          tableMap.put(new String(tblPath), tableId);
+          tableMap.put(name, tableId);
         else
-          tableMap.put(tableId, new String(tblPath));
+          tableMap.put(tableId, name);
       }
     }
     
@@ -107,7 +127,7 @@ public class Tables {
     try {
       tableName = getTableName(instance, tableId);
     } catch (TableNotFoundException e) {
-      //handled in the string formatting
+      // handled in the string formatting
     }
     return tableName == null ? String.format("?(ID:%s)", tableId) : String.format("%s(ID:%s)", tableName, tableId);
   }
@@ -117,7 +137,7 @@ public class Tables {
     try {
       tableId = getTableId(instance, tableName);
     } catch (TableNotFoundException e) {
-      //handled in the string formatting
+      // handled in the string formatting
     }
     return tableId == null ? String.format("%s(?)", tableName) : String.format("%s(ID:%s)", tableName, tableId);
   }
@@ -131,4 +151,31 @@ public class Tables {
     
     return TableState.valueOf(new String(state));
   }
+  
+  public static String extractNamespace(String tableName) {
+    String[] s = tableName.split("\\.");
+    if (tableName.equals(MetadataTable.NAME) || tableName.equals(RootTable.NAME)) {
+      return Constants.SYSTEM_TABLE_NAMESPACE;
+    } else if (s.length == 2 && !s[0].isEmpty()) {
+      return s[0];
+    } else {
+      return Constants.DEFAULT_TABLE_NAMESPACE;
+    }
+  }
+  
+  public static String extractTableName(String tableName) {
+    String[] s = tableName.split("\\.");
+    if (s.length == 2 && !s[1].isEmpty() && !s[0].isEmpty()) {
+      return s[1];
+    } else {
+      return tableName;
+    }
+  }
+  
+  public static String getNamespace(Instance instance, String tableId) {
+    ZooCache zc = getZooCache(instance);
+    zc.clear();
+    byte[] n = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE);
+    return new String(n, Constants.UTF8);
+  }
 }


Mime
View raw message