You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2015/04/27 23:02:08 UTC

[1/3] hbase git commit: HBASE-13394 Failed to recreate a table when quota is enabled

Repository: hbase
Updated Branches:
  refs/heads/branch-1 51177c48a -> f86241259
  refs/heads/branch-1.1 8e1e46576 -> e8fb9cb16
  refs/heads/master 79db62932 -> b96952bee


HBASE-13394 Failed to recreate a table when quota is enabled


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

Branch: refs/heads/master
Commit: b96952beef41226a051fec8add2ff2c803cf1abc
Parents: 79db629
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Mon Apr 27 21:43:39 2015 +0100
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Mon Apr 27 21:43:39 2015 +0100

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/master/HMaster.java |  3 +-
 .../master/procedure/CreateTableProcedure.java  |  5 ++
 .../master/procedure/DeleteTableProcedure.java  | 14 +----
 .../master/procedure/ProcedureSyncWait.java     | 12 ++++
 .../hbase/namespace/TestNamespaceAuditor.java   | 64 ++++++++++++++++++++
 5 files changed, 83 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/b96952be/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 9bd1dbb..98006ec 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -1344,8 +1344,7 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
     HRegionInfo[] newRegions = ModifyRegionUtils.createHRegionInfos(hTableDescriptor, splitKeys);
     checkInitialized();
     sanityCheckTableDescriptor(hTableDescriptor);
-    this.quotaManager.checkNamespaceTableAndRegionQuota(hTableDescriptor.getTableName(),
-      newRegions.length);
+
     if (cpHost != null) {
       cpHost.preCreateTable(hTableDescriptor, newRegions);
     }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b96952be/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
index dd6d387..edaf7fb 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
@@ -284,6 +284,11 @@ public class CreateTableProcedure
 
   private void preCreate(final MasterProcedureEnv env)
       throws IOException, InterruptedException {
+    if (!getTableName().isSystemTable()) {
+      ProcedureSyncWait.getMasterQuotaManager(env)
+        .checkNamespaceTableAndRegionQuota(getTableName(), newRegions.size());
+    }
+
     final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost();
     if (cpHost != null) {
       final HRegionInfo[] regions = newRegions == null ? null :

http://git-wip-us.apache.org/repos/asf/hbase/blob/b96952be/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
index 2582a1e..dfe70c7 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
@@ -53,7 +53,6 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.DeleteTableState;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
-import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.security.UserGroupInformation;
 
@@ -406,17 +405,6 @@ public class DeleteTableProcedure
 
   protected static void deleteTableStates(final MasterProcedureEnv env, final TableName tableName)
       throws IOException {
-    getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
-  }
-
-  private static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
-      throws IOException {
-    return ProcedureSyncWait.waitFor(env, "quota manager to be available",
-        new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
-      @Override
-      public MasterQuotaManager evaluate() throws IOException {
-        return env.getMasterServices().getMasterQuotaManager();
-      }
-    });
+    ProcedureSyncWait.getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b96952be/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
index 903dbd3..1eb0073 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
@@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.master.ServerManager;
 import org.apache.hadoop.hbase.procedure2.Procedure;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.procedure2.ProcedureResult;
+import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.Threads;
 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
@@ -176,4 +177,15 @@ public final class ProcedureSyncWait {
       });
     }
   }
+
+  protected static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
+      throws IOException {
+    return ProcedureSyncWait.waitFor(env, "quota manager to be available",
+        new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
+      @Override
+      public MasterQuotaManager evaluate() throws IOException {
+        return env.getMasterServices().getMasterQuotaManager();
+      }
+    });
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b96952be/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
index c86e0ff..cccdace 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -41,6 +42,7 @@ import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.DoNotRetryIOException;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.MiniHBaseCluster;
@@ -100,6 +102,7 @@ public class TestNamespaceAuditor {
     UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
       MasterSyncObserver.class.getName());
     Configuration conf = UTIL.getConfiguration();
+    conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 5);
     conf.setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
     conf.setClass("hbase.coprocessor.regionserver.classes", CPRegionServerObserver.class,
       RegionServerObserver.class);
@@ -470,6 +473,58 @@ public class TestNamespaceAuditor {
     htable.close();
   }
 
+  /*
+   * Create a table and make sure that the table creation fails after adding this table entry into
+   * namespace quota cache. Now correct the failure and recreate the table with same name.
+   * HBASE-13394
+   */
+  @Test(timeout = 180000)
+  public void testRecreateTableWithSameNameAfterFirstTimeFailure() throws Exception {
+    String nsp1 = prefix + "_testRecreateTable";
+    NamespaceDescriptor nspDesc =
+        NamespaceDescriptor.create(nsp1)
+            .addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "20")
+            .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "1").build();
+    ADMIN.createNamespace(nspDesc);
+    final TableName tableOne = TableName.valueOf(nsp1 + TableName.NAMESPACE_DELIM + "table1");
+    byte[] columnFamily = Bytes.toBytes("info");
+    HTableDescriptor tableDescOne = new HTableDescriptor(tableOne);
+    tableDescOne.addFamily(new HColumnDescriptor(columnFamily));
+    MasterSyncObserver.throwExceptionInPreCreateTableHandler = true;
+    try {
+      try {
+        ADMIN.createTable(tableDescOne);
+        fail("Table " + tableOne.toString() + "creation should fail.");
+      } catch (Exception exp) {
+        LOG.error(exp);
+      }
+      assertFalse(ADMIN.tableExists(tableOne));
+
+      NamespaceTableAndRegionInfo nstate = getNamespaceState(nsp1);
+      assertEquals("First table creation failed in namespace so number of tables in namespace "
+          + "should be 0.", 0, nstate.getTables().size());
+
+      MasterSyncObserver.throwExceptionInPreCreateTableHandler = false;
+      try {
+        ADMIN.createTable(tableDescOne);
+      } catch (Exception e) {
+        fail("Table " + tableOne.toString() + "creation should succeed.");
+        LOG.error(e);
+      }
+      assertTrue(ADMIN.tableExists(tableOne));
+      nstate = getNamespaceState(nsp1);
+      assertEquals("First table was created successfully so table size in namespace should "
+          + "be one now.", 1, nstate.getTables().size());
+    } finally {
+      MasterSyncObserver.throwExceptionInPreCreateTableHandler = false;
+      if (ADMIN.tableExists(tableOne)) {
+        ADMIN.disableTable(tableOne);
+        deleteTable(tableOne);
+      }
+      ADMIN.deleteNamespace(nsp1);
+    }
+  }
+
   private NamespaceTableAndRegionInfo getNamespaceState(String namespace) throws KeeperException,
       IOException {
     return getQuotaManager().getState(namespace);
@@ -569,6 +624,7 @@ public class TestNamespaceAuditor {
 
   public static class MasterSyncObserver extends BaseMasterObserver {
     volatile CountDownLatch tableDeletionLatch;
+    static boolean throwExceptionInPreCreateTableHandler;
 
     @Override
     public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
@@ -582,6 +638,14 @@ public class TestNamespaceAuditor {
         throws IOException {
       tableDeletionLatch.countDown();
     }
+
+    @Override
+    public void preCreateTableHandler(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
+      if (throwExceptionInPreCreateTableHandler) {
+        throw new IOException("Throw exception as it is demanded.");
+      }
+    }
   }
 
   private void deleteTable(final TableName tableName) throws Exception {


[3/3] hbase git commit: HBASE-13394 Failed to recreate a table when quota is enabled

Posted by mb...@apache.org.
HBASE-13394 Failed to recreate a table when quota is enabled

Signed-off-by: Matteo Bertozzi <ma...@cloudera.com>


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

Branch: refs/heads/branch-1.1
Commit: e8fb9cb16c78618a10fbc6bba71431284a872a82
Parents: 8e1e465
Author: Ashish Singhi <as...@huawei.com>
Authored: Mon Apr 27 11:28:21 2015 +0530
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Mon Apr 27 22:01:24 2015 +0100

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/master/HMaster.java | 16 +++--
 .../master/procedure/CreateTableProcedure.java  |  4 ++
 .../master/procedure/DeleteTableProcedure.java  | 14 +----
 .../master/procedure/ProcedureSyncWait.java     | 12 ++++
 .../hbase/namespace/TestNamespaceAuditor.java   | 64 ++++++++++++++++++++
 5 files changed, 92 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/e8fb9cb1/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 7ecfd8d..63a6e49 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -1428,14 +1428,13 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
       throw new MasterNotRunningException();
     }
 
-    String namespace = hTableDescriptor.getTableName().getNamespaceAsString();
+    TableName tableName = hTableDescriptor.getTableName();
+    String namespace = tableName.getNamespaceAsString();
     ensureNamespaceExists(namespace);
 
     HRegionInfo[] newRegions = ModifyRegionUtils.createHRegionInfos(hTableDescriptor, splitKeys);
     checkInitialized();
     sanityCheckTableDescriptor(hTableDescriptor);
-    this.quotaManager.checkNamespaceTableAndRegionQuota(hTableDescriptor.getTableName(),
-      newRegions.length);
     if (cpHost != null) {
       cpHost.preCreateTable(hTableDescriptor, newRegions);
     }
@@ -1451,8 +1450,15 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
           hTableDescriptor, newRegions, latch));
       latch.await();
     } else {
-      this.service.submit(new CreateTableHandler(this, this.fileSystemManager, hTableDescriptor,
-        conf, newRegions, this).prepare());
+      try {
+        this.quotaManager.checkNamespaceTableAndRegionQuota(tableName, newRegions.length);
+        this.service.submit(new CreateTableHandler(this, this.fileSystemManager, hTableDescriptor,
+            conf, newRegions, this).prepare());
+      } catch (IOException e) {
+        this.quotaManager.removeTableFromNamespaceQuota(tableName);
+        LOG.error("Exception occurred while creating the table " + tableName.getNameAsString(), e);
+        throw e;
+      }
     }
 
     if (cpHost != null) {

http://git-wip-us.apache.org/repos/asf/hbase/blob/e8fb9cb1/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
index 2db04f3..ecea171 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
@@ -296,6 +296,10 @@ public class CreateTableProcedure
 
   private void preCreate(final MasterProcedureEnv env)
       throws IOException, InterruptedException {
+    if (!getTableName().isSystemTable()) {
+      ProcedureSyncWait.getMasterQuotaManager(env).checkNamespaceTableAndRegionQuota(
+        getTableName(), newRegions.size());
+    }
     final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost();
     if (cpHost != null) {
       final HRegionInfo[] regions = newRegions == null ? null :

http://git-wip-us.apache.org/repos/asf/hbase/blob/e8fb9cb1/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
index b61c850..2ba7b42 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
@@ -53,7 +53,6 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.DeleteTableState;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
-import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.security.UserGroupInformation;
 
@@ -406,17 +405,6 @@ public class DeleteTableProcedure
 
   protected static void deleteTableStates(final MasterProcedureEnv env, final TableName tableName)
       throws IOException {
-    getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
-  }
-
-  private static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
-      throws IOException {
-    return ProcedureSyncWait.waitFor(env, "quota manager to be available",
-        new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
-      @Override
-      public MasterQuotaManager evaluate() throws IOException {
-        return env.getMasterServices().getMasterQuotaManager();
-      }
-    });
+    ProcedureSyncWait.getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/e8fb9cb1/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
index a57fa59..63d8a1e 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
@@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.master.ServerManager;
 import org.apache.hadoop.hbase.procedure2.Procedure;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.procedure2.ProcedureResult;
+import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.Threads;
 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
@@ -177,4 +178,15 @@ public final class ProcedureSyncWait {
       });
     }
   }
+
+  protected static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
+      throws IOException {
+    return ProcedureSyncWait.waitFor(env, "quota manager to be available",
+      new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
+        @Override
+        public MasterQuotaManager evaluate() throws IOException {
+          return env.getMasterServices().getMasterQuotaManager();
+        }
+      });
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/e8fb9cb1/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
index 1f0a827..05a0294 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
@@ -15,6 +15,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -33,6 +34,7 @@ import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.DoNotRetryIOException;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.MiniHBaseCluster;
@@ -93,6 +95,7 @@ public class TestNamespaceAuditor {
 
   public static void setupOnce() throws Exception, IOException {
     Configuration conf = UTIL.getConfiguration();
+    conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 5);
     conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, CustomObserver.class.getName());
     conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, MasterSyncObserver.class.getName());
     conf.setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
@@ -476,6 +479,58 @@ public class TestNamespaceAuditor {
     htable.close();
   }
 
+  /*
+   * Create a table and make sure that the table creation fails after adding this table entry into
+   * namespace quota cache. Now correct the failure and recreate the table with same name.
+   * HBASE-13394
+   */
+  @Test(timeout = 180000)
+  public void testRecreateTableWithSameNameAfterFirstTimeFailure() throws Exception {
+    String nsp1 = prefix + "_testRecreateTable";
+    NamespaceDescriptor nspDesc =
+        NamespaceDescriptor.create(nsp1)
+            .addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "20")
+            .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "1").build();
+    ADMIN.createNamespace(nspDesc);
+    final TableName tableOne = TableName.valueOf(nsp1 + TableName.NAMESPACE_DELIM + "table1");
+    byte[] columnFamily = Bytes.toBytes("info");
+    HTableDescriptor tableDescOne = new HTableDescriptor(tableOne);
+    tableDescOne.addFamily(new HColumnDescriptor(columnFamily));
+    MasterSyncObserver.throwExceptionInPreCreateTable = true;
+    try {
+      try {
+        ADMIN.createTable(tableDescOne);
+        fail("Table " + tableOne.toString() + "creation should fail.");
+      } catch (Exception exp) {
+        LOG.error(exp);
+      }
+      assertFalse(ADMIN.tableExists(tableOne));
+
+      NamespaceTableAndRegionInfo nstate = getNamespaceState(nsp1);
+      assertEquals("First table creation failed in namespace so number of tables in namespace "
+          + "should be 0.", 0, nstate.getTables().size());
+
+      MasterSyncObserver.throwExceptionInPreCreateTable = false;
+      try {
+        ADMIN.createTable(tableDescOne);
+      } catch (Exception e) {
+        fail("Table " + tableOne.toString() + "creation should succeed.");
+        LOG.error(e);
+      }
+      assertTrue(ADMIN.tableExists(tableOne));
+      nstate = getNamespaceState(nsp1);
+      assertEquals("First table was created successfully so table size in namespace should "
+          + "be one now.", 1, nstate.getTables().size());
+    } finally {
+      MasterSyncObserver.throwExceptionInPreCreateTable = false;
+      if (ADMIN.tableExists(tableOne)) {
+        ADMIN.disableTable(tableOne);
+        deleteTable(tableOne);
+      }
+      ADMIN.deleteNamespace(nsp1);
+    }
+  }
+
   private NamespaceTableAndRegionInfo getNamespaceState(String namespace) throws KeeperException,
       IOException {
     return getQuotaManager().getState(namespace);
@@ -575,6 +630,7 @@ public class TestNamespaceAuditor {
 
   public static class MasterSyncObserver extends BaseMasterObserver {
     volatile CountDownLatch tableDeletionLatch;
+    static boolean throwExceptionInPreCreateTable;
 
     @Override
     public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
@@ -587,6 +643,14 @@ public class TestNamespaceAuditor {
         TableName tableName) throws IOException {
       tableDeletionLatch.countDown();
     }
+
+    @Override
+    public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
+      if (throwExceptionInPreCreateTable) {
+        throw new IOException("Throw exception as it is demanded.");
+      }
+    }
   }
 
   private void deleteTable(final TableName tableName) throws Exception {


[2/3] hbase git commit: HBASE-13394 Failed to recreate a table when quota is enabled

Posted by mb...@apache.org.
HBASE-13394 Failed to recreate a table when quota is enabled


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

Branch: refs/heads/branch-1
Commit: f862412592fc4654a827b7594098b3373a6bb1a2
Parents: 51177c4
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Mon Apr 27 21:43:39 2015 +0100
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Mon Apr 27 21:49:58 2015 +0100

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/master/HMaster.java |  3 +-
 .../master/procedure/CreateTableProcedure.java  |  5 ++
 .../master/procedure/DeleteTableProcedure.java  | 14 +----
 .../master/procedure/ProcedureSyncWait.java     | 12 ++++
 .../hbase/namespace/TestNamespaceAuditor.java   | 64 ++++++++++++++++++++
 5 files changed, 83 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/f8624125/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 530dcea..4886f59 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -1376,8 +1376,7 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
     HRegionInfo[] newRegions = ModifyRegionUtils.createHRegionInfos(hTableDescriptor, splitKeys);
     checkInitialized();
     sanityCheckTableDescriptor(hTableDescriptor);
-    this.quotaManager.checkNamespaceTableAndRegionQuota(hTableDescriptor.getTableName(),
-      newRegions.length);
+
     if (cpHost != null) {
       cpHost.preCreateTable(hTableDescriptor, newRegions);
     }

http://git-wip-us.apache.org/repos/asf/hbase/blob/f8624125/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
index 2db04f3..360637f 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
@@ -296,6 +296,11 @@ public class CreateTableProcedure
 
   private void preCreate(final MasterProcedureEnv env)
       throws IOException, InterruptedException {
+    if (!getTableName().isSystemTable()) {
+      ProcedureSyncWait.getMasterQuotaManager(env)
+        .checkNamespaceTableAndRegionQuota(getTableName(), newRegions.size());
+    }
+
     final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost();
     if (cpHost != null) {
       final HRegionInfo[] regions = newRegions == null ? null :

http://git-wip-us.apache.org/repos/asf/hbase/blob/f8624125/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
index b61c850..2ba7b42 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
@@ -53,7 +53,6 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.DeleteTableState;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
-import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.security.UserGroupInformation;
 
@@ -406,17 +405,6 @@ public class DeleteTableProcedure
 
   protected static void deleteTableStates(final MasterProcedureEnv env, final TableName tableName)
       throws IOException {
-    getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
-  }
-
-  private static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
-      throws IOException {
-    return ProcedureSyncWait.waitFor(env, "quota manager to be available",
-        new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
-      @Override
-      public MasterQuotaManager evaluate() throws IOException {
-        return env.getMasterServices().getMasterQuotaManager();
-      }
-    });
+    ProcedureSyncWait.getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/f8624125/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
index a57fa59..1e94744 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java
@@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.master.ServerManager;
 import org.apache.hadoop.hbase.procedure2.Procedure;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.procedure2.ProcedureResult;
+import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.Threads;
 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
@@ -177,4 +178,15 @@ public final class ProcedureSyncWait {
       });
     }
   }
+
+  protected static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
+      throws IOException {
+    return ProcedureSyncWait.waitFor(env, "quota manager to be available",
+        new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
+      @Override
+      public MasterQuotaManager evaluate() throws IOException {
+        return env.getMasterServices().getMasterQuotaManager();
+      }
+    });
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/f8624125/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
index 1f0a827..8540dcf 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/namespace/TestNamespaceAuditor.java
@@ -15,6 +15,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -33,6 +34,7 @@ import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.DoNotRetryIOException;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.MiniHBaseCluster;
@@ -95,6 +97,7 @@ public class TestNamespaceAuditor {
     Configuration conf = UTIL.getConfiguration();
     conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, CustomObserver.class.getName());
     conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, MasterSyncObserver.class.getName());
+    conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 5);
     conf.setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
     conf.setClass("hbase.coprocessor.regionserver.classes", CPRegionServerObserver.class,
       RegionServerObserver.class);
@@ -476,6 +479,58 @@ public class TestNamespaceAuditor {
     htable.close();
   }
 
+  /*
+   * Create a table and make sure that the table creation fails after adding this table entry into
+   * namespace quota cache. Now correct the failure and recreate the table with same name.
+   * HBASE-13394
+   */
+  @Test(timeout = 180000)
+  public void testRecreateTableWithSameNameAfterFirstTimeFailure() throws Exception {
+    String nsp1 = prefix + "_testRecreateTable";
+    NamespaceDescriptor nspDesc =
+        NamespaceDescriptor.create(nsp1)
+            .addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "20")
+            .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "1").build();
+    ADMIN.createNamespace(nspDesc);
+    final TableName tableOne = TableName.valueOf(nsp1 + TableName.NAMESPACE_DELIM + "table1");
+    byte[] columnFamily = Bytes.toBytes("info");
+    HTableDescriptor tableDescOne = new HTableDescriptor(tableOne);
+    tableDescOne.addFamily(new HColumnDescriptor(columnFamily));
+    MasterSyncObserver.throwExceptionInPreCreateTableHandler = true;
+    try {
+      try {
+        ADMIN.createTable(tableDescOne);
+        fail("Table " + tableOne.toString() + "creation should fail.");
+      } catch (Exception exp) {
+        LOG.error(exp);
+      }
+      assertFalse(ADMIN.tableExists(tableOne));
+
+      NamespaceTableAndRegionInfo nstate = getNamespaceState(nsp1);
+      assertEquals("First table creation failed in namespace so number of tables in namespace "
+          + "should be 0.", 0, nstate.getTables().size());
+
+      MasterSyncObserver.throwExceptionInPreCreateTableHandler = false;
+      try {
+        ADMIN.createTable(tableDescOne);
+      } catch (Exception e) {
+        fail("Table " + tableOne.toString() + "creation should succeed.");
+        LOG.error(e);
+      }
+      assertTrue(ADMIN.tableExists(tableOne));
+      nstate = getNamespaceState(nsp1);
+      assertEquals("First table was created successfully so table size in namespace should "
+          + "be one now.", 1, nstate.getTables().size());
+    } finally {
+      MasterSyncObserver.throwExceptionInPreCreateTableHandler = false;
+      if (ADMIN.tableExists(tableOne)) {
+        ADMIN.disableTable(tableOne);
+        deleteTable(tableOne);
+      }
+      ADMIN.deleteNamespace(nsp1);
+    }
+  }
+
   private NamespaceTableAndRegionInfo getNamespaceState(String namespace) throws KeeperException,
       IOException {
     return getQuotaManager().getState(namespace);
@@ -575,6 +630,7 @@ public class TestNamespaceAuditor {
 
   public static class MasterSyncObserver extends BaseMasterObserver {
     volatile CountDownLatch tableDeletionLatch;
+    static boolean throwExceptionInPreCreateTableHandler;
 
     @Override
     public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
@@ -587,6 +643,14 @@ public class TestNamespaceAuditor {
         TableName tableName) throws IOException {
       tableDeletionLatch.countDown();
     }
+
+    @Override
+    public void preCreateTableHandler(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
+      if (throwExceptionInPreCreateTableHandler) {
+        throw new IOException("Throw exception as it is demanded.");
+      }
+    }
   }
 
   private void deleteTable(final TableName tableName) throws Exception {