Return-Path: X-Original-To: apmail-curator-commits-archive@minotaur.apache.org Delivered-To: apmail-curator-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C1D7A105B9 for ; Mon, 7 Sep 2015 06:51:42 +0000 (UTC) Received: (qmail 95186 invoked by uid 500); 7 Sep 2015 06:51:36 -0000 Delivered-To: apmail-curator-commits-archive@curator.apache.org Received: (qmail 95118 invoked by uid 500); 7 Sep 2015 06:51:36 -0000 Mailing-List: contact commits-help@curator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@curator.apache.org Delivered-To: mailing list commits@curator.apache.org Received: (qmail 95085 invoked by uid 99); 7 Sep 2015 06:51:36 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 07 Sep 2015 06:51:36 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 21617DF9A3; Mon, 7 Sep 2015 06:51:36 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: randgalt@apache.org To: commits@curator.apache.org Date: Mon, 07 Sep 2015 06:51:38 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/8] curator git commit: Added Locker which uses Java 7's try-with-resource feature to make locking more reliable 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-248 Commit: 58a8818b749475cf2089d116c06359ad0390a2cc Parents: d57aaeb Author: randgalt Authored: Sun Sep 6 12:26:56 2015 -0700 Committer: randgalt 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; + +/** + *

+ * Utility for safely acquiring a lock and releasing it using Java 7's + * try-with-resource feature. + *

+ * + *

+ * Canonical usage: + *

+ *     InterProcessMutex mutex = new InterProcessMutex(...) // or any InterProcessLock
+ *     try ( Locker locker = new Locker(mutex, maxTimeout, unit) )
+ *     {
+ *         // do work
+ *     }
+ * 
+ *

+ */ +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();