assertNoErrors(hbck);
ServerName mockName = ServerName.valueOf("localhost", 60000, 1);
// obtain one lock
final TableLockManager tableLockManager = TableLockManager.createTableLockManager(conf, TEST_UTIL.getZooKeeperWatcher(), mockName);
TableLock writeLock = tableLockManager.writeLock(TableName.valueOf("foo"),
"testCheckTableLocks");
writeLock.acquire();
hbck = doFsck(conf, false);
assertNoErrors(hbck); // should not have expired, no problems
edge.incrementTime(conf.getLong(TableLockManager.TABLE_LOCK_EXPIRE_TIMEOUT,
TableLockManager.DEFAULT_TABLE_LOCK_EXPIRE_TIMEOUT_MS)); // let table lock expire
hbck = doFsck(conf, false);
assertErrors(hbck, new ERROR_CODE[] {ERROR_CODE.EXPIRED_TABLE_LOCK});
final CountDownLatch latch = new CountDownLatch(1);
new Thread() {
@Override
public void run() {
TableLock readLock = tableLockManager.writeLock(TableName.valueOf("foo"),
"testCheckTableLocks");
try {
latch.countDown();
readLock.acquire();
} catch (IOException ex) {
fail();
} catch (IllegalStateException ex) {
return; // expected, since this will be reaped under us.
}
fail("should not have come here");
};
}.start();
latch.await(); // wait until thread starts
Threads.sleep(300); // wait some more to ensure writeLock.acquire() is called
hbck = doFsck(conf, false);
assertErrors(hbck, new ERROR_CODE[] {ERROR_CODE.EXPIRED_TABLE_LOCK}); // still one expired, one not-expired
edge.incrementTime(conf.getLong(TableLockManager.TABLE_LOCK_EXPIRE_TIMEOUT,
TableLockManager.DEFAULT_TABLE_LOCK_EXPIRE_TIMEOUT_MS)); // let table lock expire
hbck = doFsck(conf, false);
assertErrors(hbck, new ERROR_CODE[] {ERROR_CODE.EXPIRED_TABLE_LOCK, ERROR_CODE.EXPIRED_TABLE_LOCK}); // both are expired
conf.setLong(TableLockManager.TABLE_LOCK_EXPIRE_TIMEOUT, 1); // reaping from ZKInterProcessWriteLock uses znode cTime,
// which is not injectable through EnvironmentEdge
Threads.sleep(10);
hbck = doFsck(conf, true); // now fix both cases
hbck = doFsck(conf, false);
assertNoErrors(hbck);
// ensure that locks are deleted
writeLock = tableLockManager.writeLock(TableName.valueOf("foo"),
"should acquire without blocking");
writeLock.acquire(); // this should not block.
writeLock.release(); // release for clean state
}