You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2017/04/25 17:20:00 UTC

[4/4] hbase git commit: HBASE-15143 Procedure v2 - Web UI displaying queues

HBASE-15143 Procedure v2 - Web UI displaying queues

Signed-off-by: Michael Stack <st...@apache.org>


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

Branch: refs/heads/master
Commit: 25575064154fe1cc7ff8970e8f15a3cff648f37a
Parents: 1367519
Author: Balazs Meszaros <ba...@cloudera.com>
Authored: Mon Feb 13 13:50:56 2017 -0800
Committer: Michael Stack <st...@apache.org>
Committed: Tue Apr 25 09:39:28 2017 -0700

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/client/Admin.java   |    9 +
 .../hbase/client/ConnectionImplementation.java  |   11 +-
 .../apache/hadoop/hbase/client/HBaseAdmin.java  |   42 +-
 .../client/ShortCircuitMasterConnection.java    |    6 +
 .../hbase/shaded/protobuf/ProtobufUtil.java     |  183 +-
 .../hadoop/hbase/procedure2/LockInfo.java       |  128 +
 .../hadoop/hbase/procedure2/LockAndQueue.java   |   21 +-
 .../hadoop/hbase/procedure2/LockStatus.java     |    1 +
 .../hbase/procedure2/ProcedureScheduler.java    |    7 +
 .../hadoop/hbase/procedure2/ProcedureUtil.java  |    4 +-
 .../procedure2/SimpleProcedureScheduler.java    |   10 +-
 .../protobuf/generated/LockServiceProtos.java   | 2423 +++++++++++++++++-
 .../shaded/protobuf/generated/MasterProtos.java | 2152 ++++++++++++----
 .../src/main/protobuf/LockService.proto         |   22 +
 .../src/main/protobuf/Master.proto              |   11 +
 .../hbase/tmpl/master/MasterStatusTmpl.jamon    |    2 +-
 .../hbase/coprocessor/MasterObserver.java       |   19 +
 .../org/apache/hadoop/hbase/master/HMaster.java |   37 +-
 .../hbase/master/MasterCoprocessorHost.java     |   21 +
 .../hadoop/hbase/master/MasterRpcServices.java  |  147 +-
 .../hadoop/hbase/master/MasterServices.java     |    9 +-
 .../hbase/master/locking/LockProcedure.java     |    8 +-
 .../procedure/MasterProcedureScheduler.java     |  119 +-
 .../hbase-webapps/master/procedures.jsp         |  127 +-
 .../resources/hbase-webapps/master/snapshot.jsp |    2 +-
 .../hbase-webapps/master/snapshotsStats.jsp     |    2 +-
 .../resources/hbase-webapps/master/table.jsp    |    2 +-
 .../hbase-webapps/master/tablesDetailed.jsp     |    2 +-
 .../main/resources/hbase-webapps/master/zk.jsp  |    2 +-
 .../hbase/coprocessor/TestMasterObserver.java   |   38 +
 .../hbase/master/MockNoopMasterServices.java    |    9 +-
 .../procedure/TestMasterProcedureScheduler.java |  169 +-
 .../hadoop/hbase/protobuf/TestProtobufUtil.java |   41 +-
 .../hbase/shaded/protobuf/TestProtobufUtil.java |  151 ++
 hbase-shell/src/main/ruby/hbase/admin.rb        |    5 +
 hbase-shell/src/main/ruby/shell.rb              |    3 +-
 hbase-shell/src/main/ruby/shell/commands.rb     |    5 +
 .../src/main/ruby/shell/commands/list_locks.rb  |   60 +
 hbase-shell/src/main/ruby/shell/formatter.rb    |    9 +-
 .../src/test/ruby/shell/list_locks_test.rb      |  152 ++
 40 files changed, 5409 insertions(+), 762 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
index f2fc9a5..3e767d2 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
@@ -45,6 +45,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.client.replication.TableCFs;
 import org.apache.hadoop.hbase.client.security.SecurityCapability;
 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
+import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.quotas.QuotaFilter;
 import org.apache.hadoop.hbase.quotas.QuotaRetriever;
 import org.apache.hadoop.hbase.quotas.QuotaSettings;
@@ -1250,6 +1251,14 @@ public interface Admin extends Abortable, Closeable {
       throws IOException;
 
   /**
+   * List locks.
+   * @return lock list
+   * @throws IOException if a remote or network exception occurs
+   */
+  LockInfo[] listLocks()
+      throws IOException;
+
+  /**
    * Roll the log writer. I.e. for filesystem based write ahead logs, start writing to a new file.
    *
    * Note that the actual rolling of the log writer is asynchronous and may not be complete when

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
index 99feb14..6859cb3 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
@@ -25,8 +25,6 @@ import static org.apache.hadoop.hbase.client.MetricsConnection.CLIENT_SIDE_METRI
 import static org.apache.hadoop.hbase.util.CollectionUtils.computeIfAbsent;
 import static org.apache.hadoop.hbase.util.CollectionUtils.computeIfAbsentEx;
 
-import com.google.common.annotations.VisibleForTesting;
-
 import java.io.Closeable;
 import java.io.IOException;
 import java.io.InterruptedIOException;
@@ -120,6 +118,8 @@ import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
 import org.apache.hadoop.ipc.RemoteException;
 import org.apache.zookeeper.KeeperException;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import edu.umd.cs.findbugs.annotations.Nullable;
 
 /**
@@ -1283,6 +1283,13 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
       }
 
       @Override
+      public MasterProtos.ListLocksResponse listLocks(
+          RpcController controller,
+          MasterProtos.ListLocksRequest request) throws ServiceException {
+        return stub.listLocks(controller, request);
+      }
+
+      @Override
       public MasterProtos.AddColumnResponse addColumn(
           RpcController controller,
           MasterProtos.AddColumnRequest request) throws ServiceException {

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
index e55a95d..7e79c20 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -80,6 +79,7 @@ import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
 import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
 import org.apache.hadoop.hbase.ipc.HBaseRpcController;
 import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
+import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.quotas.QuotaFilter;
 import org.apache.hadoop.hbase.quotas.QuotaRetriever;
 import org.apache.hadoop.hbase.quotas.QuotaSettings;
@@ -110,6 +110,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameStringP
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureResponse;
@@ -151,6 +152,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedur
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDrainingRegionServersRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListLocksRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListLocksResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListProceduresRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
@@ -191,7 +194,6 @@ import org.apache.hadoop.hbase.util.Addressing;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
-import org.apache.hadoop.hbase.util.NonceKey;
 import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
@@ -201,7 +203,6 @@ import org.apache.hadoop.util.StringUtils;
 import org.apache.zookeeper.KeeperException;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
 import com.google.protobuf.Descriptors;
 import com.google.protobuf.Message;
 import com.google.protobuf.RpcController;
@@ -2096,26 +2097,33 @@ public class HBaseAdmin implements Admin {
             getRpcController(), ListProceduresRequest.newBuilder().build()).getProcedureList();
         ProcedureInfo[] procInfoList = new ProcedureInfo[procList.size()];
         for (int i = 0; i < procList.size(); i++) {
-          procInfoList[i] = convert(procList.get(i));
+          procInfoList[i] = ProtobufUtil.toProcedureInfo(procList.get(i));
         }
         return procInfoList;
       }
     });
   }
 
-  private static ProcedureInfo convert(final ProcedureProtos.Procedure procProto) {
-    NonceKey nonceKey = null;
-    if (procProto.getNonce() != HConstants.NO_NONCE) {
-      nonceKey = new NonceKey(procProto.getNonceGroup(), procProto.getNonce());
-    }
-    org.apache.hadoop.hbase.ProcedureState procedureState =
-        org.apache.hadoop.hbase.ProcedureState.valueOf(procProto.getState().name());
-    return new ProcedureInfo(procProto.getProcId(), procProto.getClassName(), procProto.getOwner(),
-        procedureState, procProto.hasParentId() ? procProto.getParentId() : -1, nonceKey,
-            procProto.hasException()?
-                ForeignExceptionUtil.toIOException(procProto.getException()): null,
-            procProto.getLastUpdate(), procProto.getSubmittedTime(),
-            procProto.hasResult()? procProto.getResult().toByteArray() : null);
+  @Override
+  public LockInfo[] listLocks() throws IOException {
+    return executeCallable(new MasterCallable<LockInfo[]>(getConnection(),
+        getRpcControllerFactory()) {
+      @Override
+      protected LockInfo[] rpcCall() throws Exception {
+        ListLocksRequest request = ListLocksRequest.newBuilder().build();
+        ListLocksResponse response = master.listLocks(getRpcController(), request);
+        List<LockServiceProtos.LockInfo> locksProto = response.getLockList();
+
+        LockInfo[] locks = new LockInfo[locksProto.size()];
+
+        for (int i = 0; i < locks.length; i++) {
+          LockServiceProtos.LockInfo lockProto = locksProto.get(i);
+          locks[i] = ProtobufUtil.toLockInfo(lockProto);
+        }
+
+        return locks;
+      }
+    });
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java
index 72b2a15..e3b5b12 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java
@@ -191,6 +191,12 @@ public class ShortCircuitMasterConnection implements MasterKeepAliveConnection {
   }
 
   @Override
+  public ListLocksResponse listLocks(RpcController controller,
+      ListLocksRequest request) throws ServiceException {
+    return stub.listLocks(controller, request);
+  }
+
+  @Override
   public ListNamespaceDescriptorsResponse listNamespaceDescriptors(RpcController controller,
       ListNamespaceDescriptorsRequest request) throws ServiceException {
     return stub.listNamespaceDescriptors(controller, request);

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
index e969ded..04ce040 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
@@ -53,6 +53,8 @@ import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.NamespaceDescriptor;
+import org.apache.hadoop.hbase.ProcedureInfo;
+import org.apache.hadoop.hbase.ProcedureState;
 import org.apache.hadoop.hbase.ServerLoad;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
@@ -82,6 +84,7 @@ import org.apache.hadoop.hbase.filter.Filter;
 import org.apache.hadoop.hbase.io.LimitInputStream;
 import org.apache.hadoop.hbase.io.TimeRange;
 import org.apache.hadoop.hbase.master.RegionState;
+import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.protobuf.ProtobufMagic;
 import org.apache.hadoop.hbase.quotas.QuotaScope;
 import org.apache.hadoop.hbase.quotas.QuotaType;
@@ -145,11 +148,14 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionInfo;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.Procedure;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
@@ -166,7 +172,9 @@ import org.apache.hadoop.hbase.util.Addressing;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.DynamicClassLoader;
 import org.apache.hadoop.hbase.util.ExceptionUtil;
+import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
 import org.apache.hadoop.hbase.util.Methods;
+import org.apache.hadoop.hbase.util.NonceKey;
 import org.apache.hadoop.hbase.util.VersionInfo;
 import org.apache.hadoop.ipc.RemoteException;
 
@@ -3262,4 +3270,177 @@ public final class ProtobufUtil {
     int port = Addressing.parsePort(str);
     return ServerName.valueOf(hostname, port, -1L);
   }
-}
\ No newline at end of file
+
+  /**
+   * @return Convert the current {@link ProcedureInfo} into a Protocol Buffers Procedure
+   * instance.
+   */
+  public static ProcedureProtos.Procedure toProtoProcedure(ProcedureInfo procedure) {
+    ProcedureProtos.Procedure.Builder builder = ProcedureProtos.Procedure.newBuilder();
+
+    builder.setClassName(procedure.getProcName());
+    builder.setProcId(procedure.getProcId());
+    builder.setSubmittedTime(procedure.getSubmittedTime());
+    builder.setState(ProcedureProtos.ProcedureState.valueOf(procedure.getProcState().name()));
+    builder.setLastUpdate(procedure.getLastUpdate());
+
+    if (procedure.hasParentId()) {
+      builder.setParentId(procedure.getParentId());
+    }
+
+    if (procedure.hasOwner()) {
+      builder.setOwner(procedure.getProcOwner());
+    }
+
+    if (procedure.isFailed()) {
+      builder.setException(ForeignExceptionUtil.toProtoForeignException(procedure.getException()));
+    }
+
+    if (procedure.hasResultData()) {
+      builder.setResult(UnsafeByteOperations.unsafeWrap(procedure.getResult()));
+    }
+
+    return builder.build();
+  }
+
+  /**
+   * Helper to convert the protobuf object.
+   * @return Convert the current Protocol Buffers Procedure to {@link ProcedureInfo}
+   * instance.
+   */
+  public static ProcedureInfo toProcedureInfo(ProcedureProtos.Procedure procedureProto) {
+    NonceKey nonceKey = null;
+
+    if (procedureProto.getNonce() != HConstants.NO_NONCE) {
+      nonceKey = new NonceKey(procedureProto.getNonceGroup(), procedureProto.getNonce());
+    }
+
+    return new ProcedureInfo(procedureProto.getProcId(), procedureProto.getClassName(),
+        procedureProto.hasOwner() ? procedureProto.getOwner() : null,
+        ProcedureState.valueOf(procedureProto.getState().name()),
+        procedureProto.hasParentId() ? procedureProto.getParentId() : -1, nonceKey,
+        procedureProto.hasException() ?
+          ForeignExceptionUtil.toIOException(procedureProto.getException()) : null,
+        procedureProto.getLastUpdate(), procedureProto.getSubmittedTime(),
+        procedureProto.hasResult() ? procedureProto.getResult().toByteArray() : null);
+  }
+
+  public static LockServiceProtos.ResourceType toProtoResourceType(
+      LockInfo.ResourceType resourceType) {
+    switch (resourceType) {
+    case SERVER:
+      return LockServiceProtos.ResourceType.RESOURCE_TYPE_SERVER;
+    case NAMESPACE:
+      return LockServiceProtos.ResourceType.RESOURCE_TYPE_NAMESPACE;
+    case TABLE:
+      return LockServiceProtos.ResourceType.RESOURCE_TYPE_TABLE;
+    case REGION:
+      return LockServiceProtos.ResourceType.RESOURCE_TYPE_REGION;
+    default:
+      throw new IllegalArgumentException("Unknown resource type: " + resourceType);
+    }
+  }
+
+  public static LockInfo.ResourceType toResourceType(
+      LockServiceProtos.ResourceType resourceTypeProto) {
+    switch (resourceTypeProto) {
+    case RESOURCE_TYPE_SERVER:
+      return LockInfo.ResourceType.SERVER;
+    case RESOURCE_TYPE_NAMESPACE:
+      return LockInfo.ResourceType.NAMESPACE;
+    case RESOURCE_TYPE_TABLE:
+      return LockInfo.ResourceType.TABLE;
+    case RESOURCE_TYPE_REGION:
+      return LockInfo.ResourceType.REGION;
+    default:
+      throw new IllegalArgumentException("Unknown resource type: " + resourceTypeProto);
+    }
+  }
+
+  public static LockServiceProtos.LockType toProtoLockType(
+      LockInfo.LockType lockType) {
+    return LockServiceProtos.LockType.valueOf(lockType.name());
+  }
+
+  public static LockInfo.LockType toLockType(
+      LockServiceProtos.LockType lockTypeProto) {
+    return LockInfo.LockType.valueOf(lockTypeProto.name());
+  }
+
+  public static LockServiceProtos.WaitingProcedure toProtoWaitingProcedure(
+      LockInfo.WaitingProcedure waitingProcedure) {
+    LockServiceProtos.WaitingProcedure.Builder builder = LockServiceProtos.WaitingProcedure.newBuilder();
+
+    ProcedureProtos.Procedure procedureProto =
+        toProtoProcedure(waitingProcedure.getProcedure());
+
+    builder
+        .setLockType(toProtoLockType(waitingProcedure.getLockType()))
+        .setProcedure(procedureProto);
+
+    return builder.build();
+  }
+
+  public static LockInfo.WaitingProcedure toWaitingProcedure(
+      LockServiceProtos.WaitingProcedure waitingProcedureProto) {
+    LockInfo.WaitingProcedure waiting = new LockInfo.WaitingProcedure();
+
+    waiting.setLockType(toLockType(waitingProcedureProto.getLockType()));
+
+    ProcedureInfo procedure =
+        toProcedureInfo(waitingProcedureProto.getProcedure());
+    waiting.setProcedure(procedure);
+
+    return waiting;
+  }
+
+  public static LockServiceProtos.LockInfo toProtoLockInfo(LockInfo lock)
+  {
+    LockServiceProtos.LockInfo.Builder builder = LockServiceProtos.LockInfo.newBuilder();
+
+    builder
+        .setResourceType(toProtoResourceType(lock.getResourceType()))
+        .setResourceName(lock.getResourceName())
+        .setLockType(toProtoLockType(lock.getLockType()));
+
+    ProcedureInfo exclusiveLockOwnerProcedure = lock.getExclusiveLockOwnerProcedure();
+
+    if (exclusiveLockOwnerProcedure != null) {
+      Procedure exclusiveLockOwnerProcedureProto =
+          toProtoProcedure(lock.getExclusiveLockOwnerProcedure());
+      builder.setExclusiveLockOwnerProcedure(exclusiveLockOwnerProcedureProto);
+    }
+
+    builder.setSharedLockCount(lock.getSharedLockCount());
+
+    for (LockInfo.WaitingProcedure waitingProcedure : lock.getWaitingProcedures()) {
+      builder.addWaitingProcedures(toProtoWaitingProcedure(waitingProcedure));
+    }
+
+    return builder.build();
+  }
+
+  public static LockInfo toLockInfo(LockServiceProtos.LockInfo lockProto)
+  {
+    LockInfo lock = new LockInfo();
+
+    lock.setResourceType(toResourceType(lockProto.getResourceType()));
+    lock.setResourceName(lockProto.getResourceName());
+    lock.setLockType(toLockType(lockProto.getLockType()));
+
+    if (lockProto.hasExclusiveLockOwnerProcedure()) {
+      ProcedureInfo exclusiveLockOwnerProcedureProto =
+          toProcedureInfo(lockProto.getExclusiveLockOwnerProcedure());
+
+      lock.setExclusiveLockOwnerProcedure(exclusiveLockOwnerProcedureProto);
+    }
+
+    lock.setSharedLockCount(lockProto.getSharedLockCount());
+
+    for (LockServiceProtos.WaitingProcedure waitingProcedureProto : lockProto.getWaitingProceduresList()) {
+      lock.addWaitingProcedure(toWaitingProcedure(waitingProcedureProto));
+    }
+
+    return lock;
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-common/src/main/java/org/apache/hadoop/hbase/procedure2/LockInfo.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/procedure2/LockInfo.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/procedure2/LockInfo.java
new file mode 100644
index 0000000..30ecee8
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/procedure2/LockInfo.java
@@ -0,0 +1,128 @@
+/*
+ * 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.hadoop.hbase.procedure2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.hbase.ProcedureInfo;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+
+@InterfaceAudience.Public
+public class LockInfo {
+  @InterfaceAudience.Public
+  public enum ResourceType {
+    SERVER, NAMESPACE, TABLE, REGION
+  }
+
+  @InterfaceAudience.Public
+  public enum LockType {
+    EXCLUSIVE, SHARED
+  }
+
+  @InterfaceAudience.Public
+  public static class WaitingProcedure {
+    private LockType lockType;
+    private ProcedureInfo procedure;
+
+    public WaitingProcedure() {
+    }
+
+    public LockType getLockType() {
+      return lockType;
+    }
+
+    public void setLockType(LockType lockType) {
+      this.lockType = lockType;
+    }
+
+    public ProcedureInfo getProcedure() {
+      return procedure;
+    }
+
+    public void setProcedure(ProcedureInfo procedure) {
+      this.procedure = procedure;
+    }
+  }
+
+  private ResourceType resourceType;
+  private String resourceName;
+  private LockType lockType;
+  private ProcedureInfo exclusiveLockOwnerProcedure;
+  private int sharedLockCount;
+  private final List<WaitingProcedure> waitingProcedures;
+
+  public LockInfo() {
+    waitingProcedures = new ArrayList<>();
+  }
+
+  public ResourceType getResourceType() {
+    return resourceType;
+  }
+
+  public void setResourceType(ResourceType resourceType) {
+    this.resourceType = resourceType;
+  }
+
+  public String getResourceName() {
+    return resourceName;
+  }
+
+  public void setResourceName(String resourceName) {
+    this.resourceName = resourceName;
+  }
+
+  public LockType getLockType() {
+    return lockType;
+  }
+
+  public void setLockType(LockType lockType) {
+    this.lockType = lockType;
+  }
+
+  public ProcedureInfo getExclusiveLockOwnerProcedure() {
+    return exclusiveLockOwnerProcedure;
+  }
+
+  public void setExclusiveLockOwnerProcedure(
+      ProcedureInfo exclusiveLockOwnerProcedure) {
+    this.exclusiveLockOwnerProcedure = exclusiveLockOwnerProcedure;
+  }
+
+  public int getSharedLockCount() {
+    return sharedLockCount;
+  }
+
+  public void setSharedLockCount(int sharedLockCount) {
+    this.sharedLockCount = sharedLockCount;
+  }
+
+  public List<WaitingProcedure> getWaitingProcedures() {
+    return waitingProcedures;
+  }
+
+  public void setWaitingProcedures(List<WaitingProcedure> waitingProcedures) {
+    this.waitingProcedures.clear();
+    this.waitingProcedures.addAll(waitingProcedures);
+  }
+
+  public void addWaitingProcedure(WaitingProcedure waitingProcedure) {
+    waitingProcedures.add(waitingProcedure);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockAndQueue.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockAndQueue.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockAndQueue.java
index e11c23c..2c307b7 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockAndQueue.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockAndQueue.java
@@ -43,7 +43,7 @@ package org.apache.hadoop.hbase.procedure2;
  * We do not use ReentrantReadWriteLock directly because of its high memory overhead.
  */
 public class LockAndQueue extends ProcedureDeque implements LockStatus {
-  private long exclusiveLockProcIdOwner = Long.MIN_VALUE;
+  private Procedure<?> exclusiveLockOwnerProcedure = null;
   private int sharedLock = 0;
 
   // ======================================================================
@@ -57,12 +57,12 @@ public class LockAndQueue extends ProcedureDeque implements LockStatus {
 
   @Override
   public boolean hasExclusiveLock() {
-    return this.exclusiveLockProcIdOwner != Long.MIN_VALUE;
+    return this.exclusiveLockOwnerProcedure != null;
   }
 
   @Override
   public boolean isLockOwner(long procId) {
-    return exclusiveLockProcIdOwner == procId;
+    return getExclusiveLockProcIdOwner() == procId;
   }
 
   @Override
@@ -76,8 +76,17 @@ public class LockAndQueue extends ProcedureDeque implements LockStatus {
   }
 
   @Override
+  public Procedure<?> getExclusiveLockOwnerProcedure() {
+    return exclusiveLockOwnerProcedure;
+  }
+
+  @Override
   public long getExclusiveLockProcIdOwner() {
-    return exclusiveLockProcIdOwner;
+    if (exclusiveLockOwnerProcedure == null) {
+      return Long.MIN_VALUE;
+    } else {
+      return exclusiveLockOwnerProcedure.getProcId();
+    }
   }
 
   @Override
@@ -101,7 +110,7 @@ public class LockAndQueue extends ProcedureDeque implements LockStatus {
 
   public boolean tryExclusiveLock(final Procedure proc) {
     if (isLocked()) return hasLockAccess(proc);
-    exclusiveLockProcIdOwner = proc.getProcId();
+    exclusiveLockOwnerProcedure = proc;
     return true;
   }
 
@@ -110,7 +119,7 @@ public class LockAndQueue extends ProcedureDeque implements LockStatus {
    */
   public boolean releaseExclusiveLock(final Procedure proc) {
     if (isLockOwner(proc.getProcId())) {
-      exclusiveLockProcIdOwner = Long.MIN_VALUE;
+      exclusiveLockOwnerProcedure = null;
       return true;
     }
     return false;

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockStatus.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockStatus.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockStatus.java
index 9f2aae7..f32ef76 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockStatus.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/LockStatus.java
@@ -29,6 +29,7 @@ public interface LockStatus {
   boolean isLockOwner(long procId);
   boolean hasParentLock(final Procedure proc);
   boolean hasLockAccess(final Procedure proc);
+  Procedure<?> getExclusiveLockOwnerProcedure();
   long getExclusiveLockProcIdOwner();
   int getSharedLockCount();
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureScheduler.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureScheduler.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureScheduler.java
index 617532b..b5295e7 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureScheduler.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureScheduler.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.procedure2;
 
 import com.google.common.annotations.VisibleForTesting;
 
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
@@ -121,6 +122,12 @@ public interface ProcedureScheduler {
   boolean waitEvent(ProcedureEvent event, Procedure procedure);
 
   /**
+   * List lock queues.
+   * @return the locks
+   */
+  List<LockInfo> listLocks();
+
+  /**
    * Returns the number of elements in this queue.
    * @return the number of elements in this queue.
    */

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureUtil.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureUtil.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureUtil.java
index b4222c7..7ce7568 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureUtil.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureUtil.java
@@ -17,8 +17,6 @@
  */
 package org.apache.hadoop.hbase.procedure2;
 
-import com.google.common.base.Preconditions;
-
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
@@ -33,6 +31,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;
 import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
 import org.apache.hadoop.hbase.util.NonceKey;
 
+import com.google.common.base.Preconditions;
+
 /**
  * Helper to convert to/from ProcedureProtos
  */

http://git-wip-us.apache.org/repos/asf/hbase/blob/25575064/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SimpleProcedureScheduler.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SimpleProcedureScheduler.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SimpleProcedureScheduler.java
index 788f4ff..176a900 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SimpleProcedureScheduler.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SimpleProcedureScheduler.java
@@ -18,10 +18,13 @@
 
 package org.apache.hadoop.hbase.procedure2;
 
-import com.google.common.annotations.VisibleForTesting;
+import java.util.Collections;
+import java.util.List;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
 
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * Simple scheduler for procedures
  */
@@ -73,4 +76,9 @@ public class SimpleProcedureScheduler extends AbstractProcedureScheduler {
   @Override
   public void completionCleanup(Procedure proc) {
   }
+
+  @Override
+  public List<LockInfo> listLocks() {
+    return Collections.emptyList();
+  }
 }
\ No newline at end of file