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();