HBASE-18091 Added API for getting who currently holds a lock on namespace/ table/ region/ server and log messages when procedure needs to wait to acquire lock

Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
Umesh Agashe 2017-05-23 11:08:33 -07:00 committed by Michael Stack
parent 64c701768b
commit 837bb9ece7
3 changed files with 64 additions and 1 deletions

View File

@ -127,6 +127,10 @@ public interface ProcedureScheduler {
*/
List<LockInfo> listLocks();
/**
* @return {@link LockInfo} for resource of specified type & name. null if resource is not locked.
*/
LockInfo getLockInfoForResource(LockInfo.ResourceType resourceType, String resourceName);
/**
* Returns the number of elements in this queue.
* @return the number of elements in this queue.

View File

@ -81,4 +81,9 @@ public class SimpleProcedureScheduler extends AbstractProcedureScheduler {
public List<LockInfo> listLocks() {
return Collections.emptyList();
}
@Override
public LockInfo getLockInfoForResource(LockInfo.ResourceType resourceType, String resourceName) {
return null;
}
}

View File

@ -338,6 +338,32 @@ public class MasterProcedureScheduler extends AbstractProcedureScheduler {
}
}
@Override
public LockInfo getLockInfoForResource(LockInfo.ResourceType resourceType, String resourceName) {
LockAndQueue queue = null;
schedLock();
try {
switch (resourceType) {
case SERVER:
queue = locking.serverLocks.get(ServerName.valueOf(resourceName));
break;
case NAMESPACE:
queue = locking.namespaceLocks.get(resourceName);
break;
case TABLE:
queue = locking.tableLocks.get(TableName.valueOf(resourceName));
break;
case REGION:
queue = locking.regionLocks.get(resourceName);
break;
}
return queue != null ? createLockInfo(resourceType, resourceName, queue) : null;
} finally {
schedUnlock();
}
}
@Override
public void clear() {
schedLock();
@ -585,6 +611,27 @@ public class MasterProcedureScheduler extends AbstractProcedureScheduler {
proc.getTableOperationType());
}
/**
* Get lock info for a resource of specified type and name and log details
*/
protected void logLockInfoForResource(LockInfo.ResourceType resourceType, String resourceName) {
if (!LOG.isDebugEnabled()) {
return;
}
LockInfo lockInfo = getLockInfoForResource(resourceType, resourceName);
if (lockInfo != null) {
String msg = resourceType.toString() + " '" + resourceName + "', shared lock count=" +
lockInfo.getSharedLockCount();
ProcedureInfo proc = lockInfo.getExclusiveLockOwnerProcedure();
if (proc != null) {
msg += ", exclusively locked by procId=" + proc.getProcId();
}
LOG.debug(msg);
}
}
/**
* Suspend the procedure if the specified table is already locked.
* Other operations in the table-queue will be executed after the lock is released.
@ -595,15 +642,18 @@ public class MasterProcedureScheduler extends AbstractProcedureScheduler {
public boolean waitTableExclusiveLock(final Procedure procedure, final TableName table) {
schedLock();
try {
final LockAndQueue namespaceLock = locking.getNamespaceLock(table.getNamespaceAsString());
final String namespace = table.getNamespaceAsString();
final LockAndQueue namespaceLock = locking.getNamespaceLock(namespace);
final LockAndQueue tableLock = locking.getTableLock(table);
if (!namespaceLock.trySharedLock()) {
waitProcedure(namespaceLock, procedure);
logLockInfoForResource(LockInfo.ResourceType.NAMESPACE, namespace);
return true;
}
if (!tableLock.tryExclusiveLock(procedure)) {
namespaceLock.releaseSharedLock();
waitProcedure(tableLock, procedure);
logLockInfoForResource(LockInfo.ResourceType.TABLE, table.getNameAsString());
return true;
}
removeFromRunQueue(tableRunQueue, getTableQueue(table));
@ -856,6 +906,8 @@ public class MasterProcedureScheduler extends AbstractProcedureScheduler {
locking.getTableLock(TableName.NAMESPACE_TABLE_NAME);
if (!systemNamespaceTableLock.trySharedLock()) {
waitProcedure(systemNamespaceTableLock, procedure);
logLockInfoForResource(LockInfo.ResourceType.TABLE,
TableName.NAMESPACE_TABLE_NAME.getNameAsString());
return true;
}
@ -863,6 +915,7 @@ public class MasterProcedureScheduler extends AbstractProcedureScheduler {
if (!namespaceLock.tryExclusiveLock(procedure)) {
systemNamespaceTableLock.releaseSharedLock();
waitProcedure(namespaceLock, procedure);
logLockInfoForResource(LockInfo.ResourceType.NAMESPACE, namespace);
return true;
}
return false;
@ -915,6 +968,7 @@ public class MasterProcedureScheduler extends AbstractProcedureScheduler {
return false;
}
waitProcedure(lock, procedure);
logLockInfoForResource(LockInfo.ResourceType.SERVER, serverName.getServerName());
return true;
} finally {
schedUnlock();