Search in sources :

Example 1 with ZKSessionLock

use of com.twitter.distributedlog.lock.ZKSessionLock 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());
    }
}
Also used : SafeRunnable(org.apache.bookkeeper.util.SafeRunnable) ZKSessionLock(com.twitter.distributedlog.lock.ZKSessionLock) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 2 with ZKSessionLock

use of com.twitter.distributedlog.lock.ZKSessionLock 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))));
    }
}
Also used : LockingException(com.twitter.distributedlog.exceptions.LockingException) OwnershipAcquireFailedException(com.twitter.distributedlog.exceptions.OwnershipAcquireFailedException) SafeRunnable(org.apache.bookkeeper.util.SafeRunnable) ZKSessionLock(com.twitter.distributedlog.lock.ZKSessionLock) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 3 with ZKSessionLock

use of com.twitter.distributedlog.lock.ZKSessionLock in project distributedlog by twitter.

the class TestZKSessionLock method testWaitForLockReleased.

/**
     * Test lock wait for the lock owner to release the lock. The lock waiter should acquire lock successfully
     * if the lock owner unlock or it is expired.
     *
     * @param lockPath
     *          lock path
     * @param isUnlock
     *          whether to unlock or expire the lock
     * @throws Exception
     */
private void testWaitForLockReleased(String lockPath, boolean isUnlock) throws Exception {
    String clientId0 = "test-wait-for-lock-released-0-" + System.currentTimeMillis();
    String clientId1 = "test-wait-for-lock-released-1-" + System.currentTimeMillis();
    createLockPath(zkc.get(), lockPath);
    final ZKSessionLock lock0 = new ZKSessionLock(zkc0, lockPath, clientId0, lockStateExecutor);
    final ZKSessionLock lock1 = new ZKSessionLock(zkc, lockPath, clientId1, lockStateExecutor);
    lock0.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
    // verification after lock0 lock
    assertEquals(State.CLAIMED, lock0.getLockState());
    List<String> children = getLockWaiters(zkc0, lockPath);
    assertEquals(1, children.size());
    assertEquals(lock0.getLockId(), Await.result(asyncParseClientID(zkc0.get(), lockPath, children.get(0))));
    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();
    // ensure lock1 is waiting for lock0
    children = awaitWaiters(2, zkc, lockPath);
    if (isUnlock) {
        lock0.unlock();
    } else {
        ZooKeeperClientUtils.expireSession(zkc0, zkServers, sessionTimeoutMs);
    }
    lock1DoneLatch.await();
    lock1Thread.join();
    // verification after lock2 lock
    if (isUnlock) {
        assertEquals(State.CLOSED, lock0.getLockState());
    } else {
        assertEquals(State.EXPIRED, lock0.getLockState());
    }
    assertEquals(State.CLAIMED, lock1.getLockState());
    children = getLockWaiters(zkc, lockPath);
    assertEquals(1, children.size());
    assertEquals(lock1.getLockId(), Await.result(asyncParseClientID(zkc.get(), lockPath, children.get(0))));
    lock1.unlock();
}
Also used : LockingException(com.twitter.distributedlog.exceptions.LockingException) SafeRunnable(org.apache.bookkeeper.util.SafeRunnable) ZKSessionLock(com.twitter.distributedlog.lock.ZKSessionLock) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 4 with ZKSessionLock

use of com.twitter.distributedlog.lock.ZKSessionLock in project distributedlog by twitter.

the class TestZKSessionLock method testLockWhenPreviousLockZnodeStillExists.

@Test(timeout = 60000)
public void testLockWhenPreviousLockZnodeStillExists() throws Exception {
    String lockPath = "/test-lock-when-previous-lock-znode-still-exists-" + System.currentTimeMillis();
    String clientId = "client-id";
    ZooKeeper zk = zkc.get();
    createLockPath(zk, lockPath);
    final ZKSessionLock lock0 = new ZKSessionLock(zkc0, lockPath, clientId, lockStateExecutor);
    // lock0 lock
    lock0.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
    // simulate lock0 expires but znode still exists
    final DistributedLockContext context1 = new DistributedLockContext();
    context1.addLockId(lock0.getLockId());
    final ZKSessionLock lock1 = new ZKSessionLock(zkc, lockPath, clientId, lockStateExecutor, 60000, NullStatsLogger.INSTANCE, context1);
    lock1.tryLock(0L, TimeUnit.MILLISECONDS);
    assertEquals(State.CLAIMED, lock1.getLockState());
    lock1.unlock();
    final DistributedLockContext context2 = new DistributedLockContext();
    context2.addLockId(lock0.getLockId());
    final ZKSessionLock lock2 = new ZKSessionLock(zkc, lockPath, clientId, lockStateExecutor, 60000, NullStatsLogger.INSTANCE, context2);
    lock2.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
    assertEquals(State.CLAIMED, lock2.getLockState());
    lock2.unlock();
    lock0.unlock();
}
Also used : ZooKeeper(org.apache.zookeeper.ZooKeeper) ZKSessionLock(com.twitter.distributedlog.lock.ZKSessionLock) Test(org.junit.Test)

Example 5 with ZKSessionLock

use of com.twitter.distributedlog.lock.ZKSessionLock in project distributedlog by twitter.

the class TestZKSessionLock method testLockAfterUnlock.

/**
     * Test lock after unlock is called.
     *
     * @throws Exception
     */
@Test(timeout = 60000)
public void testLockAfterUnlock() throws Exception {
    String lockPath = "/test-lock-after-unlock";
    String clientId = "test-lock-after-unlock";
    ZKSessionLock lock = new ZKSessionLock(zkc, lockPath, clientId, lockStateExecutor);
    lock.unlock();
    assertEquals(State.CLOSED, lock.getLockState());
    try {
        lock.tryLock(0, TimeUnit.MILLISECONDS);
        fail("Should fail on tryLock since lock state has changed.");
    } catch (LockStateChangedException lsce) {
    // expected
    }
    assertEquals(State.CLOSED, lock.getLockState());
    try {
        lock.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
        fail("Should fail on tryLock immediately if lock state has changed.");
    } catch (LockStateChangedException lsce) {
    // expected
    }
    assertEquals(State.CLOSED, lock.getLockState());
}
Also used : ZKSessionLock(com.twitter.distributedlog.lock.ZKSessionLock) Test(org.junit.Test)

Aggregations

ZKSessionLock (com.twitter.distributedlog.lock.ZKSessionLock)16 Test (org.junit.Test)9 CountDownLatch (java.util.concurrent.CountDownLatch)8 LockingException (com.twitter.distributedlog.exceptions.LockingException)7 SafeRunnable (org.apache.bookkeeper.util.SafeRunnable)6 OwnershipAcquireFailedException (com.twitter.distributedlog.exceptions.OwnershipAcquireFailedException)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 KeeperException (org.apache.zookeeper.KeeperException)2 Promise (com.twitter.util.Promise)1 IOException (java.io.IOException)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 ZooKeeper (org.apache.zookeeper.ZooKeeper)1 BoxedUnit (scala.runtime.BoxedUnit)1