accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [01/54] ACCUMULO-802 Apply Sean Hickey's patch (v5)
Date Fri, 01 Nov 2013 02:00:02 GMT
Updated Branches:
  refs/heads/ACCUMULO-802 [created] 2f2ba30b2


http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
new file mode 100644
index 0000000..d6c6fc4
--- /dev/null
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
@@ -0,0 +1,188 @@
+/*
+ * 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.master.tableOps;
+
+import java.io.Serializable;
+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.client.impl.thrift.TableOperation;
+import org.apache.accumulo.fate.Repo;
+import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.master.Master;
+import org.apache.accumulo.server.tables.TableManager;
+import org.apache.accumulo.server.util.NamespacePropUtil;
+import org.apache.log4j.Logger;
+
+class TableNamespaceInfo implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  String namespaceName;
+  String namespaceId;
+  String user;
+
+  public Map<String,String> props;
+}
+
+class FinishCreateTableNamespace extends MasterRepo {
+
+  private static final long serialVersionUID = 1L;
+
+  private TableNamespaceInfo tableNamespaceInfo;
+
+  public FinishCreateTableNamespace(TableNamespaceInfo ti) {
+    this.tableNamespaceInfo = ti;
+  }
+
+  @Override
+  public long isReady(long tid, Master environment) throws Exception {
+    return 0;
+  }
+
+  @Override
+  public Repo<Master> call(long id, Master env) throws Exception {
+
+    Utils.unreserveTableNamespace(tableNamespaceInfo.namespaceId, id, true);
+
+    env.getEventCoordinator().event("Created table namespace %s ", tableNamespaceInfo.namespaceName);
+
+    Logger.getLogger(FinishCreateTableNamespace.class).debug("Created table " + tableNamespaceInfo.namespaceId
+ " " + tableNamespaceInfo.namespaceName);
+
+    return null;
+  }
+
+  @Override
+  public String getReturn() {
+    return tableNamespaceInfo.namespaceId;
+  }
+
+  @Override
+  public void undo(long tid, Master env) throws Exception {}
+
+}
+
+class PopulateZookeeperWithNamespace extends MasterRepo {
+
+  private static final long serialVersionUID = 1L;
+
+  private TableNamespaceInfo tableNamespaceInfo;
+
+  PopulateZookeeperWithNamespace(TableNamespaceInfo ti) {
+    this.tableNamespaceInfo = ti;
+  }
+
+  @Override
+  public long isReady(long id, Master environment) throws Exception {
+    return Utils.reserveTableNamespace(tableNamespaceInfo.namespaceId, id, true, false, TableOperation.CREATE);
+  }
+
+  @Override
+  public Repo<Master> call(long tid, Master master) throws Exception {
+
+    Utils.tableNameLock.lock();
+    try {
+      Instance instance = master.getInstance();
+
+      Utils.checkTableNamespaceDoesNotExist(instance, tableNamespaceInfo.namespaceName, tableNamespaceInfo.namespaceId,
TableOperation.CREATE);
+
+      TableManager.getInstance().addNamespace(tableNamespaceInfo.namespaceId, tableNamespaceInfo.namespaceName,
NodeExistsPolicy.OVERWRITE);
+
+      for (Entry<String,String> entry : tableNamespaceInfo.props.entrySet())
+        NamespacePropUtil.setNamespaceProperty(tableNamespaceInfo.namespaceId, entry.getKey(),
entry.getValue());
+
+      Tables.clearCache(instance);
+
+      return new FinishCreateTableNamespace(tableNamespaceInfo);
+    } finally {
+      Utils.tableNameLock.unlock();
+    }
+  }
+
+  @Override
+  public void undo(long tid, Master master) throws Exception {
+    TableManager.getInstance().removeNamespace(tableNamespaceInfo.namespaceId);
+    Tables.clearCache(master.getInstance());
+  }
+
+}
+
+class SetupNamespacePermissions extends MasterRepo {
+
+  private static final long serialVersionUID = 1L;
+
+  private TableNamespaceInfo tableNamespaceInfo;
+
+  public SetupNamespacePermissions(TableNamespaceInfo ti) {
+    this.tableNamespaceInfo = ti;
+  }
+
+  @Override
+  public Repo<Master> call(long tid, Master env) throws Exception {
+    // TODO implement once namespace permissions exist (ACCUMULO-1479)
+
+    // give all table permissions to the creator
+    /*
+     * SecurityOperation security = AuditedSecurityOperation.getInstance(); for (TableNamespacePermission
permission : TableNamespacePermission.values()) { try
+     * { security.grantTableNamespacePermission(SecurityConstants.getSystemCredentials(),
tableNamespaceInfo.user, tableNamespaceInfo.tableId, permission); }
+     * catch (ThriftSecurityException e) { Logger.getLogger(FinishCreateTableNamespace.class).error(e.getMessage(),
e); throw e; } }
+     */
+
+    // setup permissions in zookeeper before table info in zookeeper
+    // this way concurrent users will not get a spurious permission denied
+    // error
+    return new PopulateZookeeperWithNamespace(tableNamespaceInfo);
+  }
+}
+
+public class CreateTableNamespace extends MasterRepo {
+  private static final long serialVersionUID = 1L;
+
+  private TableNamespaceInfo tableNamespaceInfo;
+
+  public CreateTableNamespace(String user, String namespaceName, Map<String,String>
props) {
+    tableNamespaceInfo = new TableNamespaceInfo();
+    tableNamespaceInfo.namespaceName = namespaceName;
+    tableNamespaceInfo.user = user;
+    tableNamespaceInfo.props = props;
+  }
+
+  @Override
+  public long isReady(long tid, Master environment) throws Exception {
+    return 0;
+  }
+
+  @Override
+  public Repo<Master> call(long tid, Master master) throws Exception {
+    Utils.idLock.lock();
+    try {
+      tableNamespaceInfo.namespaceId = Utils.getNextTableId(tableNamespaceInfo.namespaceName,
master.getInstance());
+      return new SetupNamespacePermissions(tableNamespaceInfo);
+    } finally {
+      Utils.idLock.unlock();
+    }
+
+  }
+
+  @Override
+  public void undo(long tid, Master env) throws Exception {
+    // nothing to do, the namespace id was allocated!
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
b/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
new file mode 100644
index 0000000..5013a2f
--- /dev/null
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
@@ -0,0 +1,100 @@
+/*
+ * 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.master.tableOps;
+
+import org.apache.accumulo.core.client.impl.Tables;
+import org.apache.accumulo.core.client.impl.thrift.TableOperation;
+import org.apache.accumulo.fate.Repo;
+import org.apache.accumulo.master.Master;
+import org.apache.accumulo.server.tables.TableManager;
+import org.apache.log4j.Logger;
+
+class NamespaceCleanUp extends MasterRepo {
+
+  final private static Logger log = Logger.getLogger(CleanUp.class);
+
+  private static final long serialVersionUID = 1L;
+
+  private String namespaceId;
+
+  public NamespaceCleanUp(String namespaceId) {
+    this.namespaceId = namespaceId;
+  }
+
+  @Override
+  public long isReady(long tid, Master master) throws Exception {
+    return 0;
+  }
+
+  @Override
+  public Repo<Master> call(long id, Master master) throws Exception {
+
+    // remove from zookeeper
+    try {
+      TableManager.getInstance().removeNamespace(namespaceId);
+    } catch (Exception e) {
+      log.error("Failed to find table namespace in zookeeper", e);
+    }
+    Tables.clearCache(master.getInstance());
+
+    // TODO remove any permissions associated with this once they exist (ACCUMULO-1479)
+    /*
+     * try { AuditedSecurityOperation.getInstance().deleteTable(SecurityConstants.getSystemCredentials(),
namespaceName); } catch (ThriftSecurityException e) {
+     * log.error(e.getMessage(), e); }
+     */
+
+    Utils.unreserveTableNamespace(namespaceId, id, true);
+
+    Logger.getLogger(CleanUp.class).debug("Deleted table namespace " + namespaceId);
+
+    return null;
+  }
+
+  @Override
+  public void undo(long tid, Master environment) throws Exception {
+    // nothing to do
+  }
+
+}
+
+public class DeleteTableNamespace extends MasterRepo {
+
+  private static final long serialVersionUID = 1L;
+
+  private String namespaceId;
+
+  public DeleteTableNamespace(String namespaceId) {
+    this.namespaceId = namespaceId;
+  }
+
+  @Override
+  public long isReady(long id, Master environment) throws Exception {
+    return Utils.reserveTableNamespace(namespaceId, id, true, true, TableOperation.DELETE);
+  }
+
+  @Override
+  public Repo<Master> call(long tid, Master environment) throws Exception {
+    environment.getEventCoordinator().event("deleting table namespace %s ", namespaceId);
+    return new NamespaceCleanUp(namespaceId);
+  }
+
+  @Override
+  public void undo(long id, Master environment) throws Exception {
+    Utils.unreserveTableNamespace(namespaceId, id, true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/ImportTable.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/ImportTable.java
b/server/master/src/main/java/org/apache/accumulo/master/tableOps/ImportTable.java
index b91da52..4032ce5 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/ImportTable.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/ImportTable.java
@@ -35,6 +35,7 @@ import org.apache.accumulo.core.client.BatchWriter;
 import org.apache.accumulo.core.client.BatchWriterConfig;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.admin.TableOperationsImpl;
+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.TableOperationExceptionType;
@@ -445,6 +446,10 @@ class ImportPopulateZookeeper 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);
+      
       Tables.clearCache(instance);
     } 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/RenameTable.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
b/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
index 3069aaf..900d9ea 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
@@ -18,6 +18,7 @@ package org.apache.accumulo.master.tableOps;
 
 import org.apache.accumulo.core.Constants;
 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.TableOperationExceptionType;
@@ -27,40 +28,56 @@ import org.apache.accumulo.fate.Repo;
 import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
 import org.apache.accumulo.fate.zookeeper.IZooReaderWriter.Mutator;
 import org.apache.accumulo.master.Master;
+import org.apache.accumulo.server.tables.TableManager;
 import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
 import org.apache.log4j.Logger;
 
 public class RenameTable extends MasterRepo {
-  
+
   private static final long serialVersionUID = 1L;
   private String tableId;
   private String oldTableName;
   private String newTableName;
-  
+
   @Override
   public long isReady(long tid, Master environment) throws Exception {
     return Utils.reserveTable(tableId, tid, true, true, TableOperation.RENAME);
   }
-  
+
   public RenameTable(String tableId, String oldTableName, String newTableName) {
     this.tableId = tableId;
     this.oldTableName = oldTableName;
     this.newTableName = newTableName;
   }
-  
+
   @Override
   public Repo<Master> call(long tid, Master master) throws Exception {
-    
+
     Instance instance = master.getInstance();
-    
+
+    final String namespace = Tables.extractNamespace(newTableName);
+    String namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
+    final String oldNamespace = Tables.extractNamespace(oldTableName);
+    String oldNamespaceId = TableNamespaces.getNamespaceId(instance, oldNamespace);
+
+    if (!namespaceId.equals(oldNamespaceId)) {
+      TableManager tm = TableManager.getInstance();
+      tm.addNamespaceToTable(tableId, namespaceId);
+    }
+
+    newTableName = Tables.extractTableName(newTableName);
+    oldTableName = Tables.extractTableName(oldTableName);
+
     IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
+
     Utils.tableNameLock.lock();
     try {
       Utils.checkTableDoesNotExist(instance, newTableName, tableId, TableOperation.RENAME);
-      
+
       final String tap = ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId +
Constants.ZTABLE_NAME;
-      
+
       zoo.mutate(tap, null, null, new Mutator() {
+        @Override
         public byte[] mutate(byte[] current) throws Exception {
           final String currentName = new String(current);
           if (currentName.equals(newTableName))
@@ -77,15 +94,15 @@ public class RenameTable extends MasterRepo {
       Utils.tableNameLock.unlock();
       Utils.unreserveTable(tableId, tid, true);
     }
-    
+
     Logger.getLogger(RenameTable.class).debug("Renamed table " + tableId + " " + oldTableName
+ " " + newTableName);
-    
+
     return null;
   }
-  
+
   @Override
   public void undo(long tid, Master env) throws Exception {
     Utils.unreserveTable(tableId, tid, true);
   }
-  
+
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTableNamespace.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTableNamespace.java
b/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTableNamespace.java
new file mode 100644
index 0000000..2da5d9f
--- /dev/null
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTableNamespace.java
@@ -0,0 +1,91 @@
+/*
+ * 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.master.tableOps;
+
+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.client.impl.thrift.TableOperation;
+import org.apache.accumulo.core.client.impl.thrift.TableOperationExceptionType;
+import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.Repo;
+import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
+import org.apache.accumulo.fate.zookeeper.IZooReaderWriter.Mutator;
+import org.apache.accumulo.master.Master;
+import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
+import org.apache.log4j.Logger;
+
+public class RenameTableNamespace extends MasterRepo {
+
+  private static final long serialVersionUID = 1L;
+  private String namespaceId;
+  private String oldName;
+  private String newName;
+
+  @Override
+  public long isReady(long id, Master environment) throws Exception {
+    return Utils.reserveTableNamespace(namespaceId, id, true, true, TableOperation.RENAME);
+  }
+
+  public RenameTableNamespace(String namespaceId, String oldName, String newName) {
+    this.namespaceId = namespaceId;
+    this.oldName = oldName;
+    this.newName = newName;
+  }
+
+  @Override
+  public Repo<Master> call(long id, Master master) throws Exception {
+
+    Instance instance = master.getInstance();
+
+    IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
+
+    Utils.tableNameLock.lock();
+    try {
+      Utils.checkTableNamespaceDoesNotExist(instance, newName, namespaceId, TableOperation.RENAME);
+
+      final String tap = ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + namespaceId
+ Constants.ZNAMESPACE_NAME;
+
+      zoo.mutate(tap, null, null, new Mutator() {
+        public byte[] mutate(byte[] current) throws Exception {
+          final String currentName = new String(current);
+          if (currentName.equals(newName))
+            return null; // assume in this case the operation is running again, so we are
done
+          if (!currentName.equals(oldName)) {
+            throw new ThriftTableOperationException(null, oldName, TableOperation.RENAME,
TableOperationExceptionType.NOTFOUND, "Name changed while processing");
+          }
+          return newName.getBytes();
+        }
+      });
+      Tables.clearCache(instance);
+    } finally {
+      Utils.tableNameLock.unlock();
+      Utils.unreserveTable(namespaceId, id, true);
+    }
+
+    Logger.getLogger(RenameTableNamespace.class).debug("Renamed table namespace " + namespaceId
+ " " + oldName + " " + newName);
+
+    return null;
+  }
+
+  @Override
+  public void undo(long tid, Master env) throws Exception {
+    Utils.unreserveTableNamespace(namespaceId, tid, true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/server/master/src/main/java/org/apache/accumulo/master/tableOps/Utils.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/Utils.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/Utils.java
index fa14f43..c01b5f0 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/Utils.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/Utils.java
@@ -22,6 +22,7 @@ import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.accumulo.core.Constants;
 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.TableOperationExceptionType;
@@ -79,7 +80,7 @@ public class Utils {
         Instance instance = HdfsZooInstance.getInstance();
         IZooReaderWriter zk = ZooReaderWriter.getRetryingInstance();
         if (!zk.exists(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId))
-          throw new ThriftTableOperationException(tableId, "", op, TableOperationExceptionType.NOTFOUND,
"Table does not exists");
+          throw new ThriftTableOperationException(tableId, "", op, TableOperationExceptionType.NOTFOUND,
"Table does not exist");
       }
       log.info("table " + tableId + " (" + Long.toHexString(tid) + ") locked for " + (writeLock
? "write" : "read") + " operation: " + op);
       return 0;
@@ -87,6 +88,25 @@ public class Utils {
       return 100;
   }
   
+  public static void unreserveTableNamespace(String namespaceId, long id, boolean writeLock)
throws Exception {
+    getLock(namespaceId, id, writeLock).unlock();
+    log.info("table namespace " + namespaceId + " (" + Long.toHexString(id) + ") unlocked
for " + (writeLock ? "write" : "read"));
+  }
+  
+  public static long reserveTableNamespace(String namespaceId, long id, boolean writeLock,
boolean mustExist, TableOperation op) throws Exception {
+    if (getLock(namespaceId, id, writeLock).tryLock()) {
+      if (mustExist) {
+        Instance instance = HdfsZooInstance.getInstance();
+        IZooReaderWriter zk = ZooReaderWriter.getRetryingInstance();
+        if (!zk.exists(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES+ "/" + namespaceId))
+          throw new ThriftTableOperationException(namespaceId, "", op, TableOperationExceptionType.NOTFOUND,
"Table namespace does not exist");
+      }
+      log.info("table namespace " + namespaceId + " (" + Long.toHexString(id) + ") locked
for " + (writeLock ? "write" : "read") + " operation: " + op);
+      return 0;
+    } else
+      return 100;
+  }
+  
   public static void unreserveTable(String tableId, long tid, boolean writeLock) throws Exception
{
     getLock(tableId, tid, writeLock).unlock();
     log.info("table " + tableId + " (" + Long.toHexString(tid) + ") unlocked for " + (writeLock
? "write" : "read"));
@@ -129,4 +149,12 @@ public class Utils {
     return Utils.getLock(tableId, tid, false);
   }
   
+  
+  static void checkTableNamespaceDoesNotExist(Instance instance, String namespace, String
namespaceId, TableOperation operation) throws ThriftTableOperationException {
+    
+    String n = TableNamespaces.getNameToIdMap(instance).get(namespace);
+    
+    if (n != null && !n.equals(namespaceId))
+      throw new ThriftTableOperationException(null, namespace, operation, TableOperationExceptionType.EXISTS,
null);
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java b/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
index 31867f3..7f094c1 100644
--- a/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
+++ b/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
@@ -826,6 +826,29 @@ public class ShellServerIT extends SimpleMacIT {
     assertTrue(err.contains("BAD_CREDENTIALS for user NoSuchUser"));
   }
 
+  @Test(timeout = 30 * 1000)
+  public void tablenamespaces() throws Exception {
+    exec("namespaces", true, Constants.DEFAULT_TABLE_NAMESPACE, true);
+    exec("createnamespace thing1", true);
+    String namespaces = exec("namespaces");
+    assertTrue(namespaces.contains("thing1"));
+    
+    exec("renamenamespace thing1 thing2");
+    namespaces = exec("namespaces");
+    assertTrue(namespaces.contains("thing2"));
+    assertTrue(!namespaces.contains("thing1"));
+    
+    exec("createtable thing2.thingy", true);
+    exec("deletenamespace thing2");
+    exec("y");
+    exec("namespaces", true, "thing2", true);
+    
+    exec("deletenamespace -f thing2", true);
+    namespaces = exec("namespaces");
+    assertTrue(!namespaces.contains("thing2"));
+    exec("tables", true, "thing2.thingy", false);
+  }
+  
   private int countkeys(String table) throws IOException {
     exec("scan -np -t " + table);
     return output.get().split("\n").length - 1;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d4c3e6a9/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java b/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java
new file mode 100644
index 0000000..6685103
--- /dev/null
+++ b/test/src/test/java/org/apache/accumulo/test/TableNamespacesTest.java
@@ -0,0 +1,281 @@
+/*
+ * 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.test;
+
+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.impl.TableNamespaces;
+import org.apache.accumulo.core.client.impl.Tables;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.minicluster.MiniAccumuloCluster;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class TableNamespacesTest {
+  
+  Random random = new Random();
+  public static TemporaryFolder folder = new TemporaryFolder();
+  static private MiniAccumuloCluster accumulo;
+  static private String secret = "secret";
+  
+  @BeforeClass
+  static public void setUp() throws Exception {
+    folder.create();
+    accumulo = new MiniAccumuloCluster(folder.getRoot(), secret);
+    accumulo.start();
+  }
+  
+  @AfterClass
+  static public void tearDown() throws Exception {
+    accumulo.stop();
+    folder.delete();
+  }
+  
+  /**
+   * 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";
+    Connector c = accumulo.getConnector("root", secret);
+    
+    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";
+    
+    Connector c = accumulo.getConnector("root", secret);
+    
+    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";
+    
+    Connector c = accumulo.getConnector("root", secret);
+    
+    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";
+    
+    Connector c = accumulo.getConnector("root", secret);
+    
+    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));
+    
+    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";
+    
+    Connector c = accumulo.getConnector("root", secret);
+    Instance instance = c.getInstance();
+    
+    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(namespace2 + "." + table));
+    String tid = Tables.getTableId(instance, namespace2 + "." + table);
+    String tnid = Tables.getNamespace(instance, tid);
+    String tnamespace = TableNamespaces.getNamespaceName(instance, tnid);
+    assertTrue(namespace2.equals(tnamespace));
+  }
+}


Mime
View raw message