Repository: curator Updated Branches: refs/heads/CURATOR-3.0 9fc755a9e -> f8814f619
Added Locker which uses Java 7's try-with-resource feature to make locking more reliable Project: http://git-wip-us.apache.org/repos/asf/curator/repo Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/58a8818b Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/58a8818b Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/58a8818b Branch: refs/heads/CURATOR-3.0 Commit: 58a8818b749475cf2089d116c06359ad0390a2cc Parents: d57aaeb Author: randgalt <randg...@apache.org> Authored: Sun Sep 6 12:26:56 2015 -0700 Committer: randgalt <randg...@apache.org> Committed: Sun Sep 6 12:26:56 2015 -0700 ---------------------------------------------------------------------- .../curator/framework/recipes/locks/Locker.java | 67 ++++++++++++++++++++ .../locks/TestInterProcessMutexBase.java | 22 +++++++ 2 files changed, 89 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/58a8818b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Locker.java ---------------------------------------------------------------------- diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Locker.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Locker.java new file mode 100644 index 0000000..97788af --- /dev/null +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Locker.java @@ -0,0 +1,67 @@ +package org.apache.curator.framework.recipes.locks; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * <p> + * Utility for safely acquiring a lock and releasing it using Java 7's + * try-with-resource feature. + * </p> + * + * <p> + * Canonical usage: + * <code><pre> + * InterProcessMutex mutex = new InterProcessMutex(...) // or any InterProcessLock + * try ( Locker locker = new Locker(mutex, maxTimeout, unit) ) + * { + * // do work + * } + * </pre></code> + * </p> + */ +public class Locker implements AutoCloseable +{ + private final InterProcessLock lock; + private final AtomicBoolean acquired; + + /** + * @param lock a lock implementation (e.g. {@link InterProcessMutex}, {@link InterProcessSemaphoreV2}, etc.) + * @param timeout max timeout to acquire lock + * @param unit time unit of timeout + * @throws Exception Curator errors or {@link TimeoutException} if the lock cannot be acquired within the timeout + */ + public Locker(InterProcessLock lock, long timeout, TimeUnit unit) throws Exception + { + this.lock = lock; + acquired = new AtomicBoolean(acquireLock(lock, timeout, unit)); + if ( !acquired.get() ) + { + throw new TimeoutException("Could not acquire lock within timeout of " + unit.toMillis(timeout) + "ms"); + } + } + + @Override + /** + * Relase the lock if it has been acquired. Can be safely called multiple times. + * Only the first call will unlock. + */ + public void close() throws Exception + { + if ( acquired.compareAndSet(true, false) ) + { + releaseLock(); + } + } + + protected void releaseLock() throws Exception + { + lock.release(); + } + + protected boolean acquireLock(InterProcessLock lock, long timeout, TimeUnit unit) throws Exception + { + return lock.acquire(timeout, unit); + } +} http://git-wip-us.apache.org/repos/asf/curator/blob/58a8818b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java ---------------------------------------------------------------------- diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java index a784e46..5a8168e 100644 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java @@ -56,6 +56,28 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests protected abstract InterProcessLock makeLock(CuratorFramework client); @Test + public void testLocker() throws Exception + { + final Timing timing = new Timing(); + final CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new ExponentialBackoffRetry(100, 3)); + try + { + client.start(); + + InterProcessLock lock = makeLock(client); + try ( Locker locker = new Locker(lock, timing.milliseconds(), TimeUnit.MILLISECONDS) ) + { + Assert.assertTrue(lock.isAcquiredInThisProcess()); + } + Assert.assertFalse(lock.isAcquiredInThisProcess()); + } + finally + { + CloseableUtils.closeQuietly(client); + } + } + + @Test public void testWaitingProcessKilledServer() throws Exception { final Timing timing = new Timing();