Repository: hbase
Updated Branches:
  refs/heads/master 243fe287b -> 28d8609e5


HBASE-16233 Procedure V2: Support acquire/release shared table lock 
concurrently (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/28d8609e
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/28d8609e
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/28d8609e

Branch: refs/heads/master
Commit: 28d8609e5de62de78b6ab7570c7fea2c8f78a856
Parents: 243fe28
Author: Stephen Yuan Jiang <syuanjiang...@gmail.com>
Authored: Thu Jul 14 21:32:59 2016 -0700
Committer: Stephen Yuan Jiang <syuanjiang...@gmail.com>
Committed: Thu Jul 14 21:32:59 2016 -0700

----------------------------------------------------------------------
 .../procedure/MasterProcedureScheduler.java     | 38 +++++++++++-------
 .../procedure/TestMasterProcedureScheduler.java | 42 ++++++++++++++++++--
 2 files changed, 62 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/28d8609e/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
index d4791fe..d368a82 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
@@ -794,21 +794,28 @@ public class MasterProcedureScheduler implements 
ProcedureRunnableSet {
 
     private synchronized boolean tryZkSharedLock(final TableLockManager 
lockManager,
         final String purpose) {
-      // Take zk-read-lock
-      TableName tableName = getKey();
-      tableLock = lockManager.readLock(tableName, purpose);
-      try {
-        tableLock.acquire();
-      } catch (IOException e) {
-        LOG.error("failed acquire read lock on " + tableName, e);
-        tableLock = null;
-        return false;
+      // Since we only have one lock resource.  We should only acquire zk lock 
if the znode
+      // does not exist.
+      //
+      if (isSingleSharedLock()) {
+        // Take zk-read-lock
+        TableName tableName = getKey();
+        tableLock = lockManager.readLock(tableName, purpose);
+        try {
+          tableLock.acquire();
+        } catch (IOException e) {
+          LOG.error("failed acquire read lock on " + tableName, e);
+          tableLock = null;
+          return false;
+        }
       }
       return true;
     }
 
     private synchronized void releaseZkSharedLock(final TableLockManager 
lockManager) {
-      releaseTableLock(lockManager, isSingleSharedLock());
+      if (isSingleSharedLock()) {
+        releaseTableLock(lockManager, true);
+      }
     }
 
     private synchronized boolean tryZkExclusiveLock(final TableLockManager 
lockManager,
@@ -969,16 +976,17 @@ public class MasterProcedureScheduler implements 
ProcedureRunnableSet {
       return null;
     }
 
-    schedLock.unlock();
-
-    // Zk lock is expensive...
+    // TODO: Zk lock is expensive and it would be perf bottleneck.  Long term 
solution is
+    // to remove it.
     if (!queue.tryZkSharedLock(lockManager, procedure.toString())) {
-      schedLock.lock();
       queue.releaseSharedLock();
       queue.getNamespaceQueue().releaseSharedLock();
       schedLock.unlock();
       return null;
     }
+
+    schedLock.unlock();
+
     return queue;
   }
 
@@ -990,10 +998,10 @@ public class MasterProcedureScheduler implements 
ProcedureRunnableSet {
   public void releaseTableSharedLock(final Procedure procedure, final 
TableName table) {
     final TableQueue queue = getTableQueueWithLock(table);
 
+    schedLock.lock();
     // Zk lock is expensive...
     queue.releaseZkSharedLock(lockManager);
 
-    schedLock.lock();
     queue.releaseSharedLock();
     queue.getNamespaceQueue().releaseSharedLock();
     schedLock.unlock();

http://git-wip-us.apache.org/repos/asf/hbase/blob/28d8609e/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
index 9c37404..3de6d36 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.hbase.master.procedure;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -28,16 +29,19 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.master.TableLockManager;
 import 
org.apache.hadoop.hbase.master.procedure.MasterProcedureScheduler.ProcedureEvent;
 import org.apache.hadoop.hbase.procedure2.Procedure;
 import 
org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility.TestProcedure;
-import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
 import org.apache.hadoop.hbase.testclassification.MasterTests;
 import org.apache.hadoop.hbase.util.Bytes;
-
+import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster;
+import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -47,7 +51,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-@Category({MasterTests.class, SmallTests.class})
+@Category({MasterTests.class, MediumTests.class})
 public class TestMasterProcedureScheduler {
   private static final Log LOG = 
LogFactory.getLog(TestMasterProcedureScheduler.class);
 
@@ -350,6 +354,38 @@ public class TestMasterProcedureScheduler {
   }
 
   @Test
+  public void testSharedZkLock() throws Exception {
+    final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+    final String dir = TEST_UTIL.getDataTestDir("TestSharedZkLock").toString();
+    MiniZooKeeperCluster zkCluster = new MiniZooKeeperCluster(conf);
+    int zkPort = zkCluster.startup(new File(dir));
+
+    try {
+      conf.set("hbase.zookeeper.quorum", "localhost:" + zkPort);
+
+      ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "testSchedWithZkLock", 
null, false);
+      ServerName mockName = ServerName.valueOf("localhost", 60000, 1);
+      MasterProcedureScheduler procQueue = new MasterProcedureScheduler(
+        conf,
+        TableLockManager.createTableLockManager(conf, zkw, mockName));
+
+      final TableName tableName = TableName.valueOf("testtb");
+      TestTableProcedure procA =
+          new TestTableProcedure(1, tableName, 
TableProcedureInterface.TableOperationType.READ);
+      TestTableProcedure procB =
+          new TestTableProcedure(2, tableName, 
TableProcedureInterface.TableOperationType.READ);
+
+      assertTrue(procQueue.tryAcquireTableSharedLock(procA, tableName));
+      assertTrue(procQueue.tryAcquireTableSharedLock(procB, tableName));
+
+      procQueue.releaseTableSharedLock(procA, tableName);
+      procQueue.releaseTableSharedLock(procB, tableName);
+    } finally {
+      zkCluster.shutdown();
+    }
+  }
+
+  @Test
   public void testVerifyRegionLocks() throws Exception {
     final TableName tableName = TableName.valueOf("testtb");
     final HRegionInfo regionA = new HRegionInfo(tableName, Bytes.toBytes("a"), 
Bytes.toBytes("b"));

Reply via email to