use of org.apache.bookkeeper.util.SafeRunnable in project distributedlog by twitter.
the class TestZKSessionLock method testLockWhenSiblingUseSameLockId.
private void testLockWhenSiblingUseSameLockId(long timeout, final boolean isUnlock) throws Exception {
String lockPath = "/test-lock-when-sibling-use-same-lock-id-" + timeout + "-" + isUnlock + "-" + System.currentTimeMillis();
String clientId = "client-id";
createLockPath(zkc.get(), lockPath);
final ZKSessionLock lock0 = new ZKSessionLock(zkc0, lockPath, clientId, lockStateExecutor);
final ZKSessionLock lock1 = new ZKSessionLock(zkc0, lockPath, clientId, lockStateExecutor);
lock0.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
List<String> children = getLockWaiters(zkc0, lockPath);
assertEquals(1, children.size());
assertEquals(State.CLAIMED, lock0.getLockState());
assertEquals(lock0.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
lock1.tryLock(timeout, TimeUnit.MILLISECONDS);
children = getLockWaiters(zkc0, lockPath);
assertEquals(2, children.size());
assertEquals(State.CLAIMED, lock0.getLockState());
assertEquals(lock0.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
assertEquals(State.CLAIMED, lock1.getLockState());
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(1))));
if (isUnlock) {
lock0.unlock();
assertEquals(State.CLOSED, lock0.getLockState());
children = getLockWaiters(zkc0, lockPath);
assertEquals(1, children.size());
assertEquals(State.CLAIMED, lock1.getLockState());
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
lock1.unlock();
} else {
ZooKeeperClientUtils.expireSession(zkc0, zkServers, sessionTimeoutMs);
final CountDownLatch latch = new CountDownLatch(1);
lockStateExecutor.submit(lockPath, new SafeRunnable() {
@Override
public void safeRun() {
latch.countDown();
}
});
latch.await();
children = getLockWaiters(zkc, lockPath);
assertEquals(0, children.size());
assertEquals(State.EXPIRED, lock0.getLockState());
assertEquals(State.EXPIRED, lock1.getLockState());
}
}
use of org.apache.bookkeeper.util.SafeRunnable in project distributedlog by twitter.
the class ZKSessionLock method checkOrClaimLockOwner.
private boolean checkOrClaimLockOwner(final Pair<String, Long> currentOwner, final Promise<String> result) {
if (lockId.compareTo(currentOwner) != 0 && !lockContext.hasLockId(currentOwner)) {
lockStateExecutor.submit(lockPath, new SafeRunnable() {
@Override
public void safeRun() {
result.setValue(currentOwner.getLeft());
}
});
return false;
}
// current owner is itself
final int curEpoch = epoch.incrementAndGet();
executeLockAction(curEpoch, new LockAction() {
@Override
public void execute() {
if (!lockState.inState(State.INIT)) {
result.setException(new LockStateChangedException(lockPath, lockId, State.INIT, lockState.getState()));
return;
}
asyncTryLock(false, result);
}
@Override
public String getActionName() {
return "claimOwnership(owner=" + currentOwner + ")";
}
}, result);
return true;
}
use of org.apache.bookkeeper.util.SafeRunnable in project distributedlog by twitter.
the class ZKSessionLock method asyncTryLock.
@Override
public Future<LockWaiter> asyncTryLock(final long timeout, final TimeUnit unit) {
final Promise<String> result = new Promise<String>();
final boolean wait = DistributedLogConstants.LOCK_IMMEDIATE != timeout;
if (wait) {
asyncTryLock(wait, result);
} else {
// try to check locks first
zk.getChildren(lockPath, null, new AsyncCallback.Children2Callback() {
@Override
public void processResult(final int rc, String path, Object ctx, final List<String> children, Stat stat) {
lockStateExecutor.submit(lockPath, new SafeRunnable() {
@Override
public void safeRun() {
if (!lockState.inState(State.INIT)) {
result.setException(new LockStateChangedException(lockPath, lockId, State.INIT, lockState.getState()));
return;
}
if (KeeperException.Code.OK.intValue() != rc) {
result.setException(KeeperException.create(KeeperException.Code.get(rc)));
return;
}
FailpointUtils.checkFailPointNoThrow(FailpointUtils.FailPointName.FP_LockTryAcquire);
Collections.sort(children, MEMBER_COMPARATOR);
if (children.size() > 0) {
asyncParseClientID(zk, lockPath, children.get(0)).addEventListener(new FutureEventListener<Pair<String, Long>>() {
@Override
public void onSuccess(Pair<String, Long> owner) {
if (!checkOrClaimLockOwner(owner, result)) {
acquireFuture.updateIfEmpty(new Return<Boolean>(false));
}
}
@Override
public void onFailure(final Throwable cause) {
lockStateExecutor.submit(lockPath, new SafeRunnable() {
@Override
public void safeRun() {
result.setException(cause);
}
});
}
});
} else {
asyncTryLock(wait, result);
}
}
});
}
}, null);
}
final Promise<Boolean> waiterAcquireFuture = new Promise<Boolean>(new com.twitter.util.Function<Throwable, BoxedUnit>() {
@Override
public BoxedUnit apply(Throwable t) {
acquireFuture.raise(t);
return BoxedUnit.UNIT;
}
});
return result.map(new AbstractFunction1<String, LockWaiter>() {
@Override
public LockWaiter apply(final String currentOwner) {
final Exception acquireException = new OwnershipAcquireFailedException(lockPath, currentOwner);
FutureUtils.within(acquireFuture, timeout, unit, acquireException, lockStateExecutor, lockPath).addEventListener(new FutureEventListener<Boolean>() {
@Override
public void onSuccess(Boolean acquired) {
completeOrFail(acquireException);
}
@Override
public void onFailure(final Throwable acquireCause) {
completeOrFail(acquireException);
}
private void completeOrFail(final Throwable acquireCause) {
if (isLockHeld()) {
waiterAcquireFuture.setValue(true);
} else {
asyncUnlock().addEventListener(new FutureEventListener<BoxedUnit>() {
@Override
public void onSuccess(BoxedUnit value) {
waiterAcquireFuture.setException(acquireCause);
}
@Override
public void onFailure(Throwable cause) {
waiterAcquireFuture.setException(acquireCause);
}
});
}
}
});
;
return new LockWaiter(lockId.getLeft(), currentOwner, waiterAcquireFuture);
}
});
}
use of org.apache.bookkeeper.util.SafeRunnable in project distributedlog by twitter.
the class ZKSessionLock method asyncUnlock.
Future<BoxedUnit> asyncUnlock(final Throwable cause) {
final Promise<BoxedUnit> promise = new Promise<BoxedUnit>();
// Use lock executor here rather than lock action, because we want this opertaion to be applied
// whether the epoch has changed or not. The member node is EPHEMERAL_SEQUENTIAL so there's no
// risk of an ABA problem where we delete and recreate a node and then delete it again here.
lockStateExecutor.submit(lockPath, new SafeRunnable() {
@Override
public void safeRun() {
acquireFuture.updateIfEmpty(new Throw<Boolean>(cause));
unlockInternal(promise);
promise.addEventListener(new OpStatsListener<BoxedUnit>(unlockStats));
}
});
return promise;
}
use of org.apache.bookkeeper.util.SafeRunnable in project distributedlog by twitter.
the class TestZKSessionLock method testSessionExpiredBeforeLock.
/**
* Test Session Expired Before Lock does locking. The lock should be closed since
* all zookeeper operations would be failed.
*
* @param timeout
* timeout to wait for the lock
* @throws Exception
*/
private void testSessionExpiredBeforeLock(long timeout) throws Exception {
String lockPath = "/test-session-expired-before-lock-" + timeout + "-" + System.currentTimeMillis();
String clientId = "test-session-expired-before-lock-" + System.currentTimeMillis();
createLockPath(zkc.get(), lockPath);
final AtomicInteger expireCounter = new AtomicInteger(0);
final CountDownLatch expiredLatch = new CountDownLatch(1);
LockListener listener = new LockListener() {
@Override
public void onExpired() {
expireCounter.incrementAndGet();
}
};
final ZKSessionLock lock = new ZKSessionLock(zkc, lockPath, clientId, lockStateExecutor).setLockListener(listener);
// expire session
ZooKeeperClientUtils.expireSession(zkc, zkServers, sessionTimeoutMs);
// submit a runnable to lock state executor to ensure any state changes happened when session expired
lockStateExecutor.submit(lockPath, new SafeRunnable() {
@Override
public void safeRun() {
expiredLatch.countDown();
}
});
expiredLatch.await();
// no watcher was registered if never acquired lock successfully
assertEquals(State.INIT, lock.getLockState());
try {
lock.tryLock(timeout, TimeUnit.MILLISECONDS);
fail("Should fail locking using an expired lock");
} catch (LockingException le) {
assertTrue(le.getCause() instanceof KeeperException.SessionExpiredException);
}
assertEquals(State.CLOSED, lock.getLockState());
List<String> children = getLockWaiters(zkc, lockPath);
assertEquals(0, children.size());
}
Aggregations