You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by sy...@apache.org on 2015/09/26 01:28:52 UTC

hbase git commit: HBASE-14212 Add IT test for procedure-v2-based namespace DDL (Stephen Yuan Jiang)

Repository: hbase
Updated Branches:
  refs/heads/master eeefc3d58 -> daccb1c0c


HBASE-14212 Add IT test for procedure-v2-based namespace DDL (Stephen Yuan Jiang)


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

Branch: refs/heads/master
Commit: daccb1c0c22849444cd040f8dfdbb75e49b48807
Parents: eeefc3d
Author: Stephen Yuan Jiang <sy...@gmail.com>
Authored: Fri Sep 25 16:23:48 2015 -0700
Committer: Stephen Yuan Jiang <sy...@gmail.com>
Committed: Fri Sep 25 16:28:29 2015 -0700

----------------------------------------------------------------------
 .../hbase/IntegrationTestDDLMasterFailover.java | 189 ++++++++++++++++++-
 1 file changed, 188 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/daccb1c0/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.java
index 75910c6..3ba7818 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.java
@@ -58,13 +58,19 @@ import org.junit.experimental.categories.Category;
  *     <li>DeleteTableAction</li>
  *     <li>AddRowAction</li>
  * </ul>
- * Actions performing DDL operations:
+ * Actions performing column family DDL operations:
  * <ul>
  *     <li>AddColumnFamilyAction</li>
  *     <li>AlterColumnFamilyVersionsAction</li>
  *     <li>AlterColumnFamilyEncodingAction</li>
  *     <li>DeleteColumnFamilyAction</li>
  * </ul>
+ * Actions performing namespace DDL operations:
+ * <ul>
+ *     <li>AddNamespaceAction</li>
+ *     <li>AlterNamespaceAction</li>
+ *     <li>DeleteNamespaceAction</li>
+ * </ul>
  * <br/>
  *
  * The threads run for a period of time (default 20 minutes) then are stopped at the end of
@@ -115,6 +121,9 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
 
   protected int numThreads, numRegions;
 
+  ConcurrentHashMap<String, NamespaceDescriptor> namespaceMap =
+      new ConcurrentHashMap<String, NamespaceDescriptor>();
+
   ConcurrentHashMap<TableName, HTableDescriptor> enabledTables =
       new ConcurrentHashMap<TableName, HTableDescriptor>();
 
@@ -140,6 +149,11 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
       admin.disableTables("ittable-\\d+");
       admin.deleteTables("ittable-\\d+");
     }
+    enabledTables.clear();
+    disabledTables.clear();
+    deletedTables.clear();
+    namespaceMap.clear();
+
     Connection connection = getConnection();
     connection.close();
     super.cleanUpCluster();
@@ -165,6 +179,23 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
     return connection;
   }
 
+  protected void verifyNamespaces() throws  IOException{
+    Connection connection = getConnection();
+    Admin admin = connection.getAdmin();
+    // iterating concurrent map
+    for (String nsName : namespaceMap.keySet()){
+      try {
+        Assert.assertTrue(
+          "Namespace: " + nsName + " in namespaceMap does not exist",
+          admin.getNamespaceDescriptor(nsName) != null);
+      } catch (NamespaceNotFoundException nsnfe) {
+        Assert.fail(
+          "Namespace: " + nsName + " in namespaceMap does not exist: " + nsnfe.getMessage());
+      }
+    }
+    admin.close();
+  }
+
   protected void verifyTables() throws  IOException{
     Connection connection = getConnection();
     Admin admin = connection.getAdmin();
@@ -201,6 +232,148 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
     abstract void perform() throws IOException;
   }
 
+  private abstract class NamespaceAction extends MasterAction {
+    final String nsTestConfigKey = "hbase.namespace.testKey";
+
+    // NamespaceAction has implemented selectNamespace() shared by multiple namespace Actions
+    protected NamespaceDescriptor selectNamespace(
+        ConcurrentHashMap<String, NamespaceDescriptor> namespaceMap) {
+      // randomly select namespace from namespaceMap
+      if (namespaceMap.isEmpty()) {
+        return null;
+      }
+      // synchronization to prevent removal from multiple threads
+      synchronized (namespaceMap) {
+        ArrayList<String> namespaceList = new ArrayList<String>(namespaceMap.keySet());
+        String randomKey = namespaceList.get(RandomUtils.nextInt(namespaceList.size()));
+        NamespaceDescriptor randomNsd = namespaceMap.get(randomKey);
+        // remove from namespaceMap
+        namespaceMap.remove(randomKey);
+        return randomNsd;
+      }
+    }
+  }
+
+  private class CreateNamespaceAction extends NamespaceAction {
+    @Override
+    void perform() throws IOException {
+      Admin admin = connection.getAdmin();
+      try {
+        NamespaceDescriptor nsd;
+        while (true) {
+          nsd = createNamespaceDesc();
+          try {
+            if (admin.getNamespaceDescriptor(nsd.getName()) != null) {
+              // the namespace has already existed.
+              continue;
+            } else {
+              // currently, the code never return null - always throws exception if
+              // namespace is not found - this just a defensive programming to make
+              // sure null situation is handled in case the method changes in the
+              // future.
+              break;
+            }
+          } catch (NamespaceNotFoundException nsnfe) {
+            // This is expected for a random generated NamespaceDescriptor
+            break;
+          }
+        }
+        LOG.info("Creating namespace:" + nsd);
+        admin.createNamespace(nsd);
+        NamespaceDescriptor freshNamespaceDesc = admin.getNamespaceDescriptor(nsd.getName());
+        Assert.assertTrue("Namespace: " + nsd + " was not created", freshNamespaceDesc != null);
+        LOG.info("Created namespace:" + freshNamespaceDesc);
+        namespaceMap.put(nsd.getName(), freshNamespaceDesc);
+      } catch (Exception e){
+        LOG.warn("Caught exception in action: " + this.getClass());
+        throw e;
+      } finally {
+        admin.close();
+      }
+      verifyNamespaces();
+    }
+
+    private NamespaceDescriptor createNamespaceDesc() {
+      String namespaceName = "itnamespace" + String.format("%010d",
+        RandomUtils.nextInt(Integer.MAX_VALUE));
+      NamespaceDescriptor nsd = NamespaceDescriptor.create(namespaceName).build();
+
+      nsd.setConfiguration(
+        nsTestConfigKey,
+        String.format("%010d", RandomUtils.nextInt(Integer.MAX_VALUE)));
+      return nsd;
+    }
+  }
+
+  private class ModifyNamespaceAction extends NamespaceAction {
+    @Override
+    void perform() throws IOException {
+      NamespaceDescriptor selected = selectNamespace(namespaceMap);
+      if (selected == null) {
+        return;
+      }
+
+      Admin admin = connection.getAdmin();
+      try {
+        String namespaceName = selected.getName();
+        LOG.info("Modifying namespace :" + selected);
+        NamespaceDescriptor modifiedNsd = NamespaceDescriptor.create(namespaceName).build();
+        String nsValueNew;
+        do {
+          nsValueNew = String.format("%010d", RandomUtils.nextInt(Integer.MAX_VALUE));
+        } while (selected.getConfigurationValue(nsTestConfigKey).equals(nsValueNew));
+        modifiedNsd.setConfiguration(nsTestConfigKey, nsValueNew);
+        admin.modifyNamespace(modifiedNsd);
+        NamespaceDescriptor freshNamespaceDesc = admin.getNamespaceDescriptor(namespaceName);
+        Assert.assertTrue(
+          "Namespace: " + selected + " was not modified",
+          freshNamespaceDesc.getConfigurationValue(nsTestConfigKey).equals(nsValueNew));
+        LOG.info("Modified namespace :" + freshNamespaceDesc);
+        namespaceMap.put(namespaceName, freshNamespaceDesc);
+      } catch (Exception e){
+        LOG.warn("Caught exception in action: " + this.getClass());
+        throw e;
+      } finally {
+        admin.close();
+      }
+      verifyNamespaces();
+    }
+  }
+
+  private class DeleteNamespaceAction extends NamespaceAction {
+    @Override
+    void perform() throws IOException {
+      NamespaceDescriptor selected = selectNamespace(namespaceMap);
+      if (selected == null) {
+        return;
+      }
+
+      Admin admin = connection.getAdmin();
+      try {
+        String namespaceName = selected.getName();
+        LOG.info("Deleting namespace :" + selected);
+        admin.deleteNamespace(namespaceName);
+        try {
+          if (admin.getNamespaceDescriptor(namespaceName) != null) {
+            // the namespace still exists.
+            Assert.assertTrue("Namespace: " + selected + " was not deleted", false);
+          } else {
+            LOG.info("Deleted namespace :" + selected);
+          }
+        } catch (NamespaceNotFoundException nsnfe) {
+          // This is expected result
+          LOG.info("Deleted namespace :" + selected);
+        }
+      } catch (Exception e){
+        LOG.warn("Caught exception in action: " + this.getClass());
+        throw e;
+      } finally {
+        admin.close();
+      }
+      verifyNamespaces();
+    }
+  }
+
   private abstract class TableAction extends  MasterAction{
     // TableAction has implemented selectTable() shared by multiple table Actions
     protected HTableDescriptor selectTable(ConcurrentHashMap<TableName, HTableDescriptor> tableMap)
@@ -610,6 +783,9 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
   }
 
   private enum ACTION {
+    CREATE_NAMESPACE,
+    MODIFY_NAMESPACE,
+    DELETE_NAMESPACE,
     CREATE_TABLE,
     DISABLE_TABLE,
     ENABLE_TABLE,
@@ -637,6 +813,15 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
 
         try {
           switch (selectedAction) {
+          case CREATE_NAMESPACE:
+            new CreateNamespaceAction().perform();
+            break;
+          case MODIFY_NAMESPACE:
+            new ModifyNamespaceAction().perform();
+            break;
+          case DELETE_NAMESPACE:
+            new DeleteNamespaceAction().perform();
+            break;
           case CREATE_TABLE:
             // stop creating new tables in the later stage of the test to avoid too many empty
             // tables
@@ -741,6 +926,8 @@ public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
     // verify
     LOG.info("Verify actions of all threads succeeded");
     checkException(workers);
+    LOG.info("Verify namespaces");
+    verifyNamespaces();
     LOG.info("Verify states of all tables");
     verifyTables();