use of com.twitter.distributedlog.exceptions.LockingException in project distributedlog by twitter.
the class TestAsyncReaderWriter method testAsyncWriteWithMinDelayBetweenFlushesFlushFailure.
@Test(timeout = 60000)
public void testAsyncWriteWithMinDelayBetweenFlushesFlushFailure() throws Exception {
String name = runtime.getMethodName();
DistributedLogConfiguration confLocal = new DistributedLogConfiguration();
confLocal.loadConf(testConf);
confLocal.setOutputBufferSize(0);
confLocal.setImmediateFlushEnabled(true);
confLocal.setMinDelayBetweenImmediateFlushMs(1);
URI uri = createDLMURI("/" + name);
ensureURICreated(uri);
DistributedLogNamespace namespace = DistributedLogNamespaceBuilder.newBuilder().conf(confLocal).uri(uri).clientId("gabbagoo").build();
DistributedLogManager dlm = namespace.openLog(name);
DistributedLogNamespace namespace1 = DistributedLogNamespaceBuilder.newBuilder().conf(confLocal).uri(uri).clientId("tortellini").build();
DistributedLogManager dlm1 = namespace1.openLog(name);
int txid = 1;
BKAsyncLogWriter writer = (BKAsyncLogWriter) (dlm.startAsyncLogSegmentNonPartitioned());
// First write succeeds since lock isnt checked until transmit, which is scheduled
Await.result(writer.write(DLMTestUtil.getLogRecordInstance(txid++)));
writer.flushAndCommit();
BKLogSegmentWriter perStreamWriter = writer.getCachedLogWriter();
DistributedLock lock = perStreamWriter.getLock();
FutureUtils.result(lock.asyncClose());
// Get second writer, steal lock
BKAsyncLogWriter writer2 = (BKAsyncLogWriter) (dlm1.startAsyncLogSegmentNonPartitioned());
try {
// Succeeds, kicks off scheduked flush
writer.write(DLMTestUtil.getLogRecordInstance(txid++));
// Succeeds, kicks off scheduled flush
Thread.sleep(100);
Await.result(writer.write(DLMTestUtil.getLogRecordInstance(txid++)));
fail("should have thrown");
} catch (LockingException ex) {
LOG.debug("caught exception ", ex);
}
writer.close();
dlm.close();
}
use of com.twitter.distributedlog.exceptions.LockingException in project distributedlog by twitter.
the class TestZKSessionLock method testLockWhenSiblingUseDifferentLockId.
private void testLockWhenSiblingUseDifferentLockId(long timeout, final boolean isUnlock) throws Exception {
String lockPath = "/test-lock-when-sibling-use-different-lock-id-" + timeout + "-" + isUnlock + "-" + System.currentTimeMillis();
String clientId0 = "client-id-0";
String clientId1 = "client-id-1";
createLockPath(zkc.get(), lockPath);
final ZKSessionLock lock0_0 = new ZKSessionLock(zkc0, lockPath, clientId0, lockStateExecutor);
final ZKSessionLock lock0_1 = new ZKSessionLock(zkc0, lockPath, clientId0, lockStateExecutor);
final ZKSessionLock lock1 = new ZKSessionLock(zkc, lockPath, clientId1, lockStateExecutor);
lock0_0.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
// lock1 wait for the lock ownership.
final CountDownLatch lock1DoneLatch = new CountDownLatch(1);
Thread lock1Thread = new Thread(new Runnable() {
@Override
public void run() {
try {
lock1.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
lock1DoneLatch.countDown();
} catch (LockingException e) {
logger.error("Failed on locking lock1 : ", e);
}
}
}, "lock1-thread");
lock1Thread.start();
// check lock1 is waiting for lock0_0
List<String> children = awaitWaiters(2, zkc, lockPath);
assertEquals(2, children.size());
assertEquals(State.CLAIMED, lock0_0.getLockState());
assertEquals(lock0_0.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
awaitState(State.WAITING, lock1);
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(1))));
final CountDownLatch lock0DoneLatch = new CountDownLatch(1);
final AtomicReference<String> ownerFromLock0 = new AtomicReference<String>(null);
Thread lock0Thread = null;
if (timeout == 0) {
try {
lock0_1.tryLock(0, TimeUnit.MILLISECONDS);
fail("Should fail on locking if sibling is using differnt lock id.");
} catch (OwnershipAcquireFailedException oafe) {
assertEquals(clientId0, oafe.getCurrentOwner());
}
assertEquals(State.CLOSED, lock0_1.getLockState());
children = getLockWaiters(zkc, lockPath);
assertEquals(2, children.size());
assertEquals(State.CLAIMED, lock0_0.getLockState());
assertEquals(lock0_0.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
assertEquals(State.WAITING, lock1.getLockState());
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(1))));
} else {
lock0Thread = new Thread(new Runnable() {
@Override
public void run() {
try {
lock0_1.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
if (isUnlock) {
lock0DoneLatch.countDown();
}
} catch (OwnershipAcquireFailedException oafe) {
if (!isUnlock) {
ownerFromLock0.set(oafe.getCurrentOwner());
lock0DoneLatch.countDown();
}
} catch (LockingException le) {
logger.error("Failed on locking lock0_1 : ", le);
}
}
}, "lock0-thread");
lock0Thread.start();
// check lock1 is waiting for lock0_0
children = awaitWaiters(3, zkc, lockPath);
assertEquals(3, children.size());
assertEquals(State.CLAIMED, lock0_0.getLockState());
assertEquals(lock0_0.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
awaitState(State.WAITING, lock1);
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(1))));
awaitState(State.WAITING, lock0_1);
assertEquals(lock0_1.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(2))));
}
if (isUnlock) {
lock0_0.unlock();
} else {
ZooKeeperClientUtils.expireSession(zkc0, zkServers, sessionTimeoutMs);
}
lock1DoneLatch.await();
lock1Thread.join();
// check the state of lock0_0
if (isUnlock) {
assertEquals(State.CLOSED, lock0_0.getLockState());
} else {
assertEquals(State.EXPIRED, lock0_0.getLockState());
}
if (timeout == 0) {
children = getLockWaiters(zkc, lockPath);
assertEquals(1, children.size());
assertEquals(State.CLAIMED, lock1.getLockState());
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(0))));
} else {
assertNotNull(lock0Thread);
if (!isUnlock) {
// both lock0_0 and lock0_1 would be expired
lock0DoneLatch.await();
lock0Thread.join();
assertEquals(clientId0, ownerFromLock0.get());
assertEquals(State.CLOSED, lock0_1.getLockState());
children = getLockWaiters(zkc, lockPath);
assertEquals(1, children.size());
assertEquals(State.CLAIMED, lock1.getLockState());
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(0))));
} else {
children = getLockWaiters(zkc, lockPath);
assertEquals(2, children.size());
assertEquals(State.CLAIMED, lock1.getLockState());
assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(0))));
assertEquals(State.WAITING, lock0_1.getLockState());
assertEquals(lock0_1.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(1))));
}
}
lock1.unlock();
if (timeout != 0 && isUnlock) {
lock0DoneLatch.await();
lock0Thread.join();
children = getLockWaiters(zkc, lockPath);
assertEquals(1, children.size());
assertEquals(State.CLAIMED, lock0_1.getLockState());
assertEquals(lock0_1.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
}
}
use of com.twitter.distributedlog.exceptions.LockingException in project distributedlog by twitter.
the class ZKDistributedLock method asyncTryLock.
void asyncTryLock(SessionLock lock, final Promise<ZKDistributedLock> acquirePromise, final long lockTimeout) {
if (null != tryLockFuture) {
tryLockFuture.cancel();
}
tryLockFuture = lock.asyncTryLock(lockTimeout, TimeUnit.MILLISECONDS);
tryLockFuture.addEventListener(OrderedFutureEventListener.of(new FutureEventListener<LockWaiter>() {
@Override
public void onSuccess(LockWaiter waiter) {
synchronized (ZKDistributedLock.this) {
if (closed) {
LOG.info("Skipping acquiring lock {} since it is already closed", lockPath);
waiter.getAcquireFuture().raise(new LockingException(lockPath, "lock is already closed."));
FutureUtils.setException(acquirePromise, newLockClosedException());
return;
}
}
tryLockFuture = null;
lockWaiter = waiter;
waitForAcquire(waiter, acquirePromise);
}
@Override
public void onFailure(Throwable cause) {
FutureUtils.setException(acquirePromise, cause);
}
}, lockStateExecutor, lockPath));
}
use of com.twitter.distributedlog.exceptions.LockingException in project distributedlog by twitter.
the class ZKSessionLock method waitForTry.
synchronized LockWaiter waitForTry(Stopwatch stopwatch, Future<LockWaiter> tryFuture) throws LockingException {
boolean success = false;
boolean stateChanged = false;
LockWaiter waiter;
try {
waiter = Await.result(tryFuture, Duration.fromMilliseconds(lockOpTimeout));
success = true;
} catch (LockStateChangedException ex) {
stateChanged = true;
throw ex;
} catch (LockingException ex) {
throw ex;
} catch (TimeoutException toe) {
tryTimeouts.inc();
throw new LockingException(lockPath, "Timeout during try phase of lock acquire", toe);
} catch (Exception ex) {
String message = getLockId() + " failed to lock " + lockPath;
throw new LockingException(lockPath, message, ex);
} finally {
if (success) {
tryStats.registerSuccessfulEvent(stopwatch.elapsed(TimeUnit.MICROSECONDS));
} else {
tryStats.registerFailedEvent(stopwatch.elapsed(TimeUnit.MICROSECONDS));
}
// Exception, i.e. an Error
if (!success && !stateChanged) {
unlock();
}
}
return waiter;
}
use of com.twitter.distributedlog.exceptions.LockingException in project distributedlog by twitter.
the class TestDistributedLock method testCheckWriteLockFailureWhenLockIsAcquiredByOthers.
@Test(timeout = 60000)
public void testCheckWriteLockFailureWhenLockIsAcquiredByOthers() throws Exception {
String lockPath = "/test-check-write-lock-failure-when-lock-is-acquired-by-others-" + System.currentTimeMillis();
String clientId = "test-check-write-lock-failure";
createLockPath(zkc.get(), lockPath);
SessionLockFactory lockFactory0 = createLockFactory(clientId, zkc0);
ZKDistributedLock lock0 = new ZKDistributedLock(lockStateExecutor, lockFactory0, lockPath, Long.MAX_VALUE, NullStatsLogger.INSTANCE);
FutureUtils.result(lock0.asyncAcquire());
Pair<String, Long> lockId0_1 = ((ZKSessionLock) lock0.getInternalLock()).getLockId();
List<String> children = getLockWaiters(zkc, lockPath);
assertEquals(1, children.size());
assertTrue(lock0.haveLock());
assertEquals(lockId0_1, Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
// expire the session
ZooKeeperClientUtils.expireSession(zkc0, zkServers, sessionTimeoutMs);
// reacquire the lock and wait reacquire completed
checkLockAndReacquire(lock0, true);
Pair<String, Long> lockId0_2 = ((ZKSessionLock) lock0.getInternalLock()).getLockId();
assertFalse("New lock should be created under different session", lockId0_1.equals(lockId0_2));
children = getLockWaiters(zkc, lockPath);
assertEquals(1, children.size());
assertTrue(lock0.haveLock());
assertEquals(lockId0_2, Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
SessionLockFactory lockFactory = createLockFactory(clientId, zkc);
final ZKDistributedLock lock1 = new ZKDistributedLock(lockStateExecutor, lockFactory, lockPath, Long.MAX_VALUE, NullStatsLogger.INSTANCE);
final CountDownLatch lockLatch = new CountDownLatch(1);
Thread lockThread = new Thread(new Runnable() {
@Override
public void run() {
try {
FutureUtils.result(lock1.asyncAcquire());
lockLatch.countDown();
} catch (IOException e) {
logger.error("Failed on locking lock1 : ", e);
}
}
}, "lock-thread");
lockThread.start();
// ensure lock1 is waiting for lock0
do {
Thread.sleep(1);
children = getLockWaiters(zkc, lockPath);
} while (children.size() < 2);
// expire the session
ZooKeeperClientUtils.expireSession(zkc0, zkServers, sessionTimeoutMs);
lockLatch.await();
lockThread.join();
try {
checkLockAndReacquire(lock0, true);
fail("Should fail on checking write lock since lock is acquired by lock1");
} catch (LockingException le) {
// expected
}
try {
checkLockAndReacquire(lock0, false);
fail("Should fail on checking write lock since lock is acquired by lock1");
} catch (LockingException le) {
// expected
}
}
Aggregations