You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by dr...@apache.org on 2015/08/19 01:18:17 UTC

[01/31] curator git commit: Upgrade to ZooKeeper 3.5.0-alpha.

Repository: curator
Updated Branches:
  refs/heads/CURATOR-3.0 44ee8547e -> 7d972593a


Upgrade to ZooKeeper 3.5.0-alpha.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/034e910a
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/034e910a
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/034e910a

Branch: refs/heads/CURATOR-3.0
Commit: 034e910a907fa89e1c0cd3373fa3bf8ee7759ae6
Parents: ef2ca57
Author: Ioannis Canellos <io...@gmail.com>
Authored: Thu Nov 6 16:53:09 2014 +0200
Committer: Ioannis Canellos <io...@gmail.com>
Committed: Thu Nov 6 16:56:00 2014 +0200

----------------------------------------------------------------------
 .../framework/recipes/leader/ChaosMonkeyCnxnFactory.java      | 7 -------
 pom.xml                                                       | 2 +-
 2 files changed, 1 insertion(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/034e910a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
index 5f10c5e..ce5b23d 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
@@ -59,13 +59,6 @@ public class ChaosMonkeyCnxnFactory extends NIOServerCnxnFactory
         super.startup(new ChaosMonkeyZookeeperServer(zks));
     }
 
-    /**
-     * Build a connection with a Chaos Monkey ZookeeperServer
-     */
-    protected NIOServerCnxn createConnection(SocketChannel sock, SelectionKey sk) throws IOException
-    {
-        return new NIOServerCnxn(zkServer, sock, sk, this);
-    }
 
     public static class ChaosMonkeyZookeeperServer extends ZooKeeperServer
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/034e910a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 6dd5d14..7b94d03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -82,7 +82,7 @@
         <jetty-version>6.1.26</jetty-version>
         <scannotation-version>1.0.2</scannotation-version>
         <resteasy-jaxrs-version>2.3.0.GA</resteasy-jaxrs-version>
-        <zookeeper-version>3.4.6</zookeeper-version>
+        <zookeeper-version>3.5.0-alpha</zookeeper-version>
         <guava-version>16.0.1</guava-version>
         <testng-version>6.8.8</testng-version>
         <swift-version>0.12.0</swift-version>


[31/31] curator git commit: MED-217 - Fixing up merge issues.

Posted by dr...@apache.org.
MED-217 - Fixing up merge issues.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/7d972593
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/7d972593
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/7d972593

Branch: refs/heads/CURATOR-3.0
Commit: 7d972593a53f260c78d18bff9d8929b5dea94fe4
Parents: d5d12c8
Author: Cam McKenzie <ca...@apache.org>
Authored: Wed Aug 19 09:12:47 2015 +1000
Committer: Cam McKenzie <ca...@apache.org>
Committed: Wed Aug 19 09:12:47 2015 +1000

----------------------------------------------------------------------
 .../curator/framework/imps/RemoveWatchesBuilderImpl.java       | 2 +-
 .../apache/curator/framework/imps/WatcherRemovalFacade.java    | 6 ++++++
 .../framework/recipes/locks/TestInterProcessMutexBase.java     | 1 +
 3 files changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/7d972593/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index d872ced..f2666e6 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -296,7 +296,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
             public void processResult(int rc, String path, Object ctx)
             {
                 trace.commit();
-                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.REMOVE_WATCHES, rc, path, null, ctx, null, null, null, null, null);
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.REMOVE_WATCHES, rc, path, null, ctx, null, null, null, null, null, null);
                 client.processBackgroundOperation(operationAndData, event);                
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7d972593/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
index 156341e..47c2104 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
@@ -161,6 +161,12 @@ class WatcherRemovalFacade extends CuratorFrameworkImpl implements WatcherRemove
     {
         return client.fixForNamespace(path);
     }
+    
+    @Override
+    String fixForNamespace(String path, boolean isSequential)
+    {
+    	return client.fixForNamespace(path, isSequential);
+    }
 
     @Override
     public EnsurePath newNamespaceAwareEnsurePath(String path)

http://git-wip-us.apache.org/repos/asf/curator/blob/7d972593/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 f44d238..9eb4144 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
@@ -28,6 +28,7 @@ import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.retry.ExponentialBackoffRetry;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.KillSession;
+import org.apache.curator.test.TestingServer;
 import org.apache.curator.test.Timing;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.utils.ZKPaths;


[21/31] curator git commit: Do watcher removal guaranteed in background

Posted by dr...@apache.org.
Do watcher removal guaranteed in background


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/115611ec
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/115611ec
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/115611ec

Branch: refs/heads/CURATOR-3.0
Commit: 115611eca927b6e8f91a0f27af46a888eac6b008
Parents: fb274b1
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 17:56:35 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 17:56:35 2015 -0700

----------------------------------------------------------------------
 .../curator/framework/imps/RemoveWatchesBuilderImpl.java      | 7 ++++---
 .../apache/curator/framework/imps/WatcherRemovalManager.java  | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/115611ec/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 4b1b029..862a44b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -66,7 +66,8 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         this.watcher = watcher;
         watcherType = WatcherType.Any;
         quietly = true;
-        this.backgrounding = new Backgrounding();
+        this.backgrounding = new Backgrounding(true);
+        guaranteed = true;
     }
 
     @Override
@@ -190,7 +191,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         return null;
     }    
     
-    private void pathInBackground(final String path)
+    void pathInBackground(final String path)
     {
         OperationAndData.ErrorCallback<String>  errorCallback = null;
         
@@ -211,7 +212,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
                                                                        errorCallback, backgrounding.getContext(), !local), null);
     }
     
-    void pathInForeground(final String path) throws Exception
+    private void pathInForeground(final String path) throws Exception
     {
         //For the local case we don't want to use the normal retry loop and we don't want to block until a connection is available.
         //We just execute the removeWatch, and if it fails, ZK will just remove local watches.

http://git-wip-us.apache.org/repos/asf/curator/blob/115611ec/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
index fe5d4d6..72430ee 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
@@ -69,7 +69,7 @@ public class WatcherRemovalManager
                 log.debug("Removing watcher for path: " + entry.path);
                 RemoveWatchesBuilderImpl builder = new RemoveWatchesBuilderImpl(client);
                 builder.prepInternalRemoval(entry);
-                builder.pathInForeground(entry.path);
+                builder.pathInBackground(entry.path);
             }
             catch ( Exception e )
             {


[14/31] curator git commit: wip

Posted by dr...@apache.org.
wip


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/5030c198
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/5030c198
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/5030c198

Branch: refs/heads/CURATOR-3.0
Commit: 5030c198456150a82bf2a2a2e5aea75b65b2efc8
Parents: ff8eb4b
Author: randgalt <ra...@apache.org>
Authored: Tue May 12 08:53:24 2015 -0500
Committer: randgalt <ra...@apache.org>
Committed: Tue May 12 08:53:24 2015 -0500

----------------------------------------------------------------------
 .../curator/framework/imps/WatcherRemovalManager.java       | 5 ++---
 .../apache/curator/framework/recipes/cache/NodeCache.java   | 6 ++++--
 .../apache/curator/framework/recipes/cache/TreeCache.java   | 6 ++++--
 .../curator/framework/recipes/cache/BaseTestTreeCache.java  | 3 ++-
 .../curator/framework/recipes/cache/TestNodeCache.java      | 9 +++++----
 5 files changed, 17 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/5030c198/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
index 5a705a4..fe5d4d6 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
@@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
 import java.util.HashSet;
 import java.util.Set;
 
-class WatcherRemovalManager
+public class WatcherRemovalManager
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final CuratorFrameworkImpl client;
@@ -73,8 +73,7 @@ class WatcherRemovalManager
             }
             catch ( Exception e )
             {
-                String message = "Could not remove watcher for path: " + entry.path;
-                log.error(message);
+                log.error("Could not remove watcher for path: " + entry.path);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/5030c198/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
index fa0df51..4d87732 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
@@ -23,6 +23,7 @@ import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorWatcher;
@@ -54,7 +55,7 @@ import org.apache.curator.utils.PathUtils;
 public class NodeCache implements Closeable
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final String path;
     private final boolean dataIsCompressed;
     private final EnsurePath ensurePath;
@@ -129,7 +130,7 @@ public class NodeCache implements Closeable
      */
     public NodeCache(CuratorFramework client, String path, boolean dataIsCompressed)
     {
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         this.path = PathUtils.validatePath(path);
         this.dataIsCompressed = dataIsCompressed;
         ensurePath = client.newNamespaceAwareEnsurePath(path).excludingLast();
@@ -172,6 +173,7 @@ public class NodeCache implements Closeable
     {
         if ( state.compareAndSet(State.STARTED, State.CLOSED) )
         {
+            client.removeWatchers();
             listeners.clear();
         }
         client.getConnectionStateListenable().removeListener(connectionStateListener);

http://git-wip-us.apache.org/repos/asf/curator/blob/5030c198/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
index fbe51df..c3958aa 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
@@ -25,6 +25,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.UnhandledErrorListener;
@@ -465,7 +466,7 @@ public class TreeCache implements Closeable
     private final AtomicBoolean isInitialized = new AtomicBoolean(false);
 
     private final TreeNode root;
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final CloseableExecutorService executorService;
     private final boolean cacheData;
     private final boolean dataIsCompressed;
@@ -513,7 +514,7 @@ public class TreeCache implements Closeable
     TreeCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, int maxDepth, final CloseableExecutorService executorService)
     {
         this.root = new TreeNode(validatePath(path), null);
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         this.cacheData = cacheData;
         this.dataIsCompressed = dataIsCompressed;
         this.maxDepth = maxDepth;
@@ -545,6 +546,7 @@ public class TreeCache implements Closeable
     {
         if ( treeState.compareAndSet(TreeState.STARTED, TreeState.CLOSED) )
         {
+            client.removeWatchers();
             client.getConnectionStateListenable().removeListener(connectionStateListener);
             listeners.clear();
             executorService.close();

http://git-wip-us.apache.org/repos/asf/curator/blob/5030c198/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java
index ab37785..f32c9b2 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java
@@ -22,6 +22,7 @@ package org.apache.curator.framework.recipes.cache;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.framework.api.UnhandledErrorListener;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.Timing;
@@ -123,7 +124,7 @@ public class BaseTestTreeCache extends BaseClassForTests
             finally
             {
                 CloseableUtils.closeQuietly(cache);
-                CloseableUtils.closeQuietly(client);
+                TestCleanState.closeAndTestClean(client);
             }
         }
         finally

http://git-wip-us.apache.org/repos/asf/curator/blob/5030c198/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestNodeCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestNodeCache.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestNodeCache.java
index 27af6ac..d6d495a 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestNodeCache.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestNodeCache.java
@@ -18,6 +18,7 @@
  */
 package org.apache.curator.framework.recipes.cache;
 
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.framework.CuratorFramework;
@@ -98,7 +99,7 @@ public class TestNodeCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -161,7 +162,7 @@ public class TestNodeCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -204,7 +205,7 @@ public class TestNodeCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -252,7 +253,7 @@ public class TestNodeCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 }


[12/31] curator git commit: more tests, refinements

Posted by dr...@apache.org.
more tests, refinements


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/49b2fd3a
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/49b2fd3a
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/49b2fd3a

Branch: refs/heads/CURATOR-3.0
Commit: 49b2fd3a8313cd05292e2ca8edb4b14b08f0de55
Parents: d3672a5
Author: randgalt <ra...@apache.org>
Authored: Mon May 11 18:04:01 2015 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon May 11 18:04:01 2015 -0500

----------------------------------------------------------------------
 .../framework/imps/WatcherRemovalFacade.java    |  5 ++
 .../framework/imps/WatcherRemovalManager.java   | 90 ++++++++++++++++----
 .../apache/curator/framework/imps/Watching.java |  2 +-
 .../imps/TestWatcherRemovalManager.java         | 68 +++++++++++++++
 .../curator/framework/imps/TestCleanState.java  |  5 ++
 5 files changed, 151 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/49b2fd3a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
index 664c9b0..eee423f 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
@@ -48,6 +48,11 @@ class WatcherRemovalFacade extends CuratorFrameworkImpl implements WatcherRemove
         throw new UnsupportedOperationException();
     }
 
+    WatcherRemovalManager getRemovalManager()
+    {
+        return removalManager;
+    }
+
     @Override
     public void removeWatchers()
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/49b2fd3a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
index 689ade2..5a705a4 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
@@ -18,68 +18,122 @@
  */
 package org.apache.curator.framework.imps;
 
-import com.google.common.collect.Maps;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.util.Map;
+import java.util.HashSet;
+import java.util.Set;
 
 class WatcherRemovalManager
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final CuratorFrameworkImpl client;
-    private final Map<Watcher, String> entries = Maps.newConcurrentMap();
+    private final Set<WrappedWatcher> entries = Sets.newHashSet();  // guarded by sync
 
     WatcherRemovalManager(CuratorFrameworkImpl client)
     {
         this.client = client;
     }
 
-    Watcher add(String path, Watcher watcher)
+    synchronized Watcher add(String path, Watcher watcher)
     {
-        Watcher wrappedWatcher = new WrappedWatcher(entries, watcher);
-        entries.put(wrappedWatcher, path);
+        path = Preconditions.checkNotNull(path, "path cannot be null");
+        watcher = Preconditions.checkNotNull(watcher, "watcher cannot be null");
+
+        WrappedWatcher wrappedWatcher = new WrappedWatcher(watcher, path);
+        entries.add(wrappedWatcher);
         return wrappedWatcher;
     }
 
+    @VisibleForTesting
+    synchronized Set<? extends Watcher> getEntries()
+    {
+        return Sets.newHashSet(entries);
+    }
+
     void removeWatchers()
     {
-        for ( Map.Entry<Watcher, String> entry : entries.entrySet() )
+        HashSet<WrappedWatcher> localEntries;
+        synchronized(this)
+        {
+            localEntries = Sets.newHashSet(entries);
+        }
+        for ( WrappedWatcher entry : localEntries )
         {
-            Watcher watcher = entry.getKey();
-            String path = entry.getValue();
             try
             {
-                log.debug("Removing watcher for path: " + path);
+                log.debug("Removing watcher for path: " + entry.path);
                 RemoveWatchesBuilderImpl builder = new RemoveWatchesBuilderImpl(client);
-                builder.prepInternalRemoval(watcher);
-                builder.pathInForeground(path);
+                builder.prepInternalRemoval(entry);
+                builder.pathInForeground(entry.path);
             }
             catch ( Exception e )
             {
-                String message = "Could not remove watcher for path: " + path;
+                String message = "Could not remove watcher for path: " + entry.path;
                 log.error(message);
             }
         }
     }
 
-    private static class WrappedWatcher implements Watcher
+    private synchronized void internalRemove(WrappedWatcher entry)
+    {
+        entries.remove(entry);
+    }
+
+    private class WrappedWatcher implements Watcher
     {
-        private final Map<Watcher, String> entries;
         private final Watcher watcher;
+        private final String path;
 
-        WrappedWatcher(Map<Watcher, String> entries, Watcher watcher)
+        WrappedWatcher(Watcher watcher, String path)
         {
-            this.entries = entries;
             this.watcher = watcher;
+            this.path = path;
         }
 
         @Override
         public void process(WatchedEvent event)
         {
-            entries.remove(this);
+            if ( event.getType() != Event.EventType.None )
+            {
+                internalRemove(this);
+            }
             watcher.process(event);
         }
+
+        @Override
+        public boolean equals(Object o)
+        {
+            if ( this == o )
+            {
+                return true;
+            }
+            if ( o == null || getClass() != o.getClass() )
+            {
+                return false;
+            }
+
+            WrappedWatcher entry = (WrappedWatcher)o;
+
+            //noinspection SimplifiableIfStatement
+            if ( !watcher.equals(entry.watcher) )
+            {
+                return false;
+            }
+            return path.equals(entry.path);
+
+        }
+
+        @Override
+        public int hashCode()
+        {
+            int result = watcher.hashCode();
+            result = 31 * result + path.hashCode();
+            return result;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/49b2fd3a/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
index ae16dfc..4bebbd5 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
@@ -52,7 +52,7 @@ class Watching
 
     Watcher getWatcher(CuratorFrameworkImpl client, String unfixedPath)
     {
-        if ( client.getWatcherRemovalManager() != null )
+        if ( (watcher != null) && (client.getWatcherRemovalManager() != null) )
         {
             return client.getWatcherRemovalManager().add(unfixedPath, watcher);
         }

http://git-wip-us.apache.org/repos/asf/curator/blob/49b2fd3a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
index 6e28bea..d951c57 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
@@ -31,6 +31,7 @@ import org.apache.zookeeper.Watcher;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 public class TestWatcherRemovalManager extends BaseClassForTests
 {
@@ -102,6 +103,73 @@ public class TestWatcherRemovalManager extends BaseClassForTests
         }
     }
 
+    @Test
+    public void testSameWatcher() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            WatcherRemovalFacade removerClient = (WatcherRemovalFacade)client.newWatcherRemoveCuratorFramework();
+
+            Watcher watcher = new Watcher()
+            {
+                @Override
+                public void process(WatchedEvent event)
+                {
+                    // NOP
+                }
+            };
+
+            removerClient.getData().usingWatcher(watcher).forPath("/");
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
+            removerClient.getData().usingWatcher(watcher).forPath("/");
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void testTriggered() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            WatcherRemovalFacade removerClient = (WatcherRemovalFacade)client.newWatcherRemoveCuratorFramework();
+
+            final CountDownLatch latch = new CountDownLatch(1);
+            Watcher watcher = new Watcher()
+            {
+                @Override
+                public void process(WatchedEvent event)
+                {
+                    if ( event.getType() == Event.EventType.NodeCreated )
+                    {
+                        latch.countDown();
+                    }
+                }
+            };
+
+            removerClient.checkExists().usingWatcher(watcher).forPath("/yo");
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
+            removerClient.create().forPath("/yo");
+
+            Assert.assertTrue(new Timing().awaitLatch(latch));
+
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 0);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
     private void internalTryBasic(CuratorFramework client) throws Exception
     {
         WatcherRemoveCuratorFramework removerClient = client.newWatcherRemoveCuratorFramework();

http://git-wip-us.apache.org/repos/asf/curator/blob/49b2fd3a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java b/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
index 95a1088..8ca8409 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
@@ -35,6 +35,11 @@ public class TestCleanState
         try
         {
             CuratorFrameworkImpl internalClient = (CuratorFrameworkImpl)client;
+            if ( !internalClient.getNamespaceWatcherMap().isEmpty() )
+            {
+                throw new AssertionError("NamespaceWatcherMap is not empty");
+            }
+
             ZooKeeper zooKeeper = internalClient.getZooKeeper();
             if ( zooKeeper != null )
             {


[25/31] curator git commit: make test more rational by using a latch

Posted by dr...@apache.org.
make test more rational by using a latch


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/ff2ed849
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/ff2ed849
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/ff2ed849

Branch: refs/heads/CURATOR-3.0
Commit: ff2ed8490660a3ea8caa046ecc5f80664cb0d8bd
Parents: 4ad09e7
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 19:40:46 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 19:40:46 2015 -0700

----------------------------------------------------------------------
 .../curator/framework/imps/TestWatcherRemovalManager.java | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/ff2ed849/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
index bf690fd..e20c450 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
@@ -181,7 +181,8 @@ public class TestWatcherRemovalManager extends BaseClassForTests
 
             final WatcherRemovalFacade removerClient = (WatcherRemovalFacade)client.newWatcherRemoveCuratorFramework();
 
-            final CountDownLatch latch = new CountDownLatch(1);
+            final CountDownLatch createdLatch = new CountDownLatch(1);
+            final CountDownLatch deletedLatch = new CountDownLatch(1);
             Watcher watcher = new Watcher()
             {
                 @Override
@@ -197,10 +198,11 @@ public class TestWatcherRemovalManager extends BaseClassForTests
                         {
                             e.printStackTrace();
                         }
+                        createdLatch.countDown();
                     }
                     else if ( event.getType() == Event.EventType.NodeDeleted )
                     {
-                        latch.countDown();
+                        deletedLatch.countDown();
                     }
                 }
             };
@@ -209,12 +211,12 @@ public class TestWatcherRemovalManager extends BaseClassForTests
             Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
             removerClient.create().forPath("/yo");
 
-            timing.sleepABit();
+            Assert.assertTrue(timing.awaitLatch(createdLatch));
             Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
 
             removerClient.delete().forPath("/yo");
 
-            Assert.assertTrue(timing.awaitLatch(latch));
+            Assert.assertTrue(timing.awaitLatch(deletedLatch));
 
             Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 0);
         }


[08/31] curator git commit: CURATOR-161 - Modified to make the watcher type optional, defaulting to 'All'.

Posted by dr...@apache.org.
CURATOR-161 - Modified to make the watcher type optional, defaulting to
'All'.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/389e0b0d
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/389e0b0d
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/389e0b0d

Branch: refs/heads/CURATOR-3.0
Commit: 389e0b0d29899bd35ebd4d7c81302d3d8ee53889
Parents: 198ba68
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Mon May 11 13:14:40 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Mon May 11 13:14:40 2015 +1000

----------------------------------------------------------------------
 .../framework/api/RemoveWatchesType.java        |   2 +-
 .../imps/RemoveWatchesBuilderImpl.java          |   2 +-
 .../framework/imps/TestRemoveWatches.java       | 218 ++++++++++++-------
 3 files changed, 140 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/389e0b0d/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
index 3c58b7b..1123afd 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
@@ -6,7 +6,7 @@ import org.apache.zookeeper.Watcher.WatcherType;
  * Builder to allow the specification of whether it is acceptable to remove client side watch information
  * in the case where ZK cannot be contacted. 
  */
-public interface RemoveWatchesType
+public interface RemoveWatchesType extends RemoveWatchesLocal
 {
    
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/389e0b0d/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 4354653..5a34f7d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -35,7 +35,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     {
         this.client = client;
         this.watcher = null;
-        this.watcherType = null;
+        this.watcherType = WatcherType.Any;
         this.local = false;
         this.quietly = false;
         this.backgrounding = new Backgrounding();

http://git-wip-us.apache.org/repos/asf/curator/blob/389e0b0d/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 39967c9..414c819 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -1,6 +1,7 @@
 package org.apache.curator.framework.imps;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.curator.framework.CuratorFramework;
@@ -53,7 +54,7 @@ public class TestRemoveWatches extends BaseClassForTests
                         
             client.checkExists().watched().forPath(path);
             
-            client.watches().removeAll().ofType(WatcherType.Data).forPath(path);
+            client.watches().removeAll().forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -92,7 +93,7 @@ public class TestRemoveWatches extends BaseClassForTests
                         
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.watches().remove(watcher).ofType(WatcherType.Data).forPath(path);
+            client.watches().remove(watcher).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -117,20 +118,11 @@ public class TestRemoveWatches extends BaseClassForTests
             final CountDownLatch removedLatch = new CountDownLatch(1);
             
             final String path = "/";    
-            Watcher watcher = new Watcher()
-            {                
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
-                        removedLatch.countDown();
-                    }                    
-                }
-            };
+            Watcher watcher = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);
             
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.watches().remove(watcher).ofType(WatcherType.Data).forPath(path);
+            client.watches().remove(watcher).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -155,16 +147,7 @@ public class TestRemoveWatches extends BaseClassForTests
             //Make sure that the event fires on both the watcher and the callback.
             final CountDownLatch removedLatch = new CountDownLatch(2);
             final String path = "/";
-            Watcher watcher = new Watcher()
-            {                
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
-                        removedLatch.countDown();
-                    }                        
-                }
-            };
+            Watcher watcher = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);
             
             BackgroundCallback callback = new BackgroundCallback()
             {
@@ -207,20 +190,11 @@ public class TestRemoveWatches extends BaseClassForTests
             
             final String path = "/";
             final CountDownLatch removedLatch = new CountDownLatch(1);
-            Watcher watcher = new Watcher()
-            {                
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
-                        removedLatch.countDown();
-                    }                    
-                }
-            };
+            Watcher watcher = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);
             
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.watches().remove(watcher).ofType(WatcherType.Any).inBackground().forPath(path);
+            client.watches().remove(watcher).inBackground().forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
             
@@ -246,41 +220,87 @@ public class TestRemoveWatches extends BaseClassForTests
             final String path = "/";
             final CountDownLatch removedLatch = new CountDownLatch(2);
             
-            Watcher watcher1 = new Watcher()
-            {                
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
-                        removedLatch.countDown();
-                    }
-                }
-            };
+            Watcher watcher1 = new CountDownWatcher(path, removedLatch, EventType.ChildWatchRemoved);            
+            Watcher watcher2 = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);                        
             
-            Watcher watcher2 = new Watcher()
-            {                
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
-                        removedLatch.countDown();
-                    }                    
-                }
-            };            
+            client.getChildren().usingWatcher(watcher1).forPath(path);
+            client.checkExists().usingWatcher(watcher2).forPath(path);
             
+            client.watches().removeAll().forPath(path);
             
-            client.checkExists().usingWatcher(watcher1).forPath(path);
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }  
+    
+    @Test
+    public void testRemoveAllDataWatches() throws Exception
+    {       
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final String path = "/";
+            final AtomicBoolean removedFlag = new AtomicBoolean(false);
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            Watcher watcher1 = new BooleanWatcher(path, removedFlag, EventType.ChildWatchRemoved);            
+            Watcher watcher2 = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);                        
+            
+            client.getChildren().usingWatcher(watcher1).forPath(path);
             client.checkExists().usingWatcher(watcher2).forPath(path);
             
-            client.watches().removeAll().ofType(WatcherType.Any).forPath(path);
+            client.watches().removeAll().ofType(WatcherType.Data).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+            Assert.assertEquals(removedFlag.get(), false);
         }
         finally
         {
             CloseableUtils.closeQuietly(client);
         }
-    }  
+    }
+    
+    @Test
+    public void testRemoveAllChildWatches() throws Exception
+    {       
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final String path = "/";
+            final AtomicBoolean removedFlag = new AtomicBoolean(false);
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            Watcher watcher1 = new BooleanWatcher(path, removedFlag, EventType.DataWatchRemoved);            
+            Watcher watcher2 = new CountDownWatcher(path, removedLatch, EventType.ChildWatchRemoved);                        
+                        
+            client.checkExists().usingWatcher(watcher1).forPath(path);
+            client.getChildren().usingWatcher(watcher2).forPath(path);
+            
+            client.watches().removeAll().ofType(WatcherType.Children).forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+            Assert.assertEquals(removedFlag.get(), false);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }     
     
     /**
      * TODO: THIS IS STILL A WORK IN PROGRESS. local() is currently broken if no connection to ZK is available.
@@ -301,20 +321,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             final CountDownLatch removedLatch = new CountDownLatch(1);
             
-            Watcher watcher = new Watcher()
-            {                
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    if(event.getPath() == null || event.getType() == null) {
-                        return;
-                    }
-                    
-                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
-                        removedLatch.countDown();
-                    }
-                }
-            };            
+            Watcher watcher = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);        
             
             client.checkExists().usingWatcher(watcher).forPath(path);
             
@@ -323,7 +330,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             timing.sleepABit();
             
-            client.watches().removeAll().ofType(WatcherType.Any).locally().forPath(path);
+            client.watches().removeAll().locally().forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -357,7 +364,7 @@ public class TestRemoveWatches extends BaseClassForTests
                 }                
             };
             
-            client.watches().remove(watcher).ofType(WatcherType.Data).forPath(path);
+            client.watches().remove(watcher).forPath(path);
         }
         finally
         {
@@ -372,6 +379,7 @@ public class TestRemoveWatches extends BaseClassForTests
     @Test
     public void testRemoveUnregisteredWatcherQuietly() throws Exception
     {
+        Timing timing = new Timing();
         CuratorFramework client = CuratorFrameworkFactory.builder().
                 connectString(server.getConnectString()).
                 retryPolicy(new RetryOneTime(1)).
@@ -380,19 +388,69 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            final AtomicBoolean watcherRemoved = new AtomicBoolean(false);
+            
             final String path = "/";            
-            Watcher watcher = new Watcher() {
-                @Override
-                public void process(WatchedEvent event)
-                {
-                }                
-            };
+            Watcher watcher = new BooleanWatcher(path, watcherRemoved, EventType.DataWatchRemoved);
             
-            client.watches().remove(watcher).ofType(WatcherType.Data).quietly().forPath(path);
+            client.watches().remove(watcher).quietly().forPath(path);
+            
+            timing.sleepABit();
+            
+            //There should be no watcher removed as none were registered.
+            Assert.assertEquals(watcherRemoved.get(), false);
         }
         finally
         {
             CloseableUtils.closeQuietly(client);
         }
+    }
+    
+    private static class CountDownWatcher implements Watcher {
+        private String path;
+        private EventType eventType;
+        private CountDownLatch removeLatch;
+        
+        public CountDownWatcher(String path, CountDownLatch removeLatch, EventType eventType) {
+            this.path = path;
+            this.eventType = eventType;
+            this.removeLatch = removeLatch;            
+        }
+        
+        @Override
+        public void process(WatchedEvent event)
+        {
+            if(event.getPath() == null || event.getType() == null) {
+                return;
+            }
+            
+            if(event.getPath().equals(path) && event.getType() == eventType) {
+                removeLatch.countDown();
+            }
+        }  
+    }
+    
+    private static class BooleanWatcher implements Watcher {
+        private String path;
+        private EventType eventType;
+        private AtomicBoolean removedFlag;
+        
+        public BooleanWatcher(String path, AtomicBoolean removedFlag, EventType eventType) {
+            this.path = path;
+            this.eventType = eventType;
+            this.removedFlag = removedFlag;            
+        }
+        
+        @Override
+        public void process(WatchedEvent event)
+        {
+            if(event.getPath() == null || event.getType() == null) {
+                return;
+            }
+            
+            if(event.getPath().equals(path) && event.getType() == eventType) {
+                removedFlag.set(true);
+            }
+        }  
     }    
 }


[09/31] curator git commit: first pass at implementation and a simple test

Posted by dr...@apache.org.
first pass at implementation and a simple test


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/58fcc548
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/58fcc548
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/58fcc548

Branch: refs/heads/CURATOR-3.0
Commit: 58fcc548f87e3c787f82d48931e2e9992f6c3366
Parents: 4c2ba37
Author: randgalt <ra...@apache.org>
Authored: Mon May 11 15:29:09 2015 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon May 11 15:29:09 2015 -0500

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |   2 +
 .../WatcherRemoveCuratorFramework.java          |   6 +
 .../framework/imps/CuratorFrameworkImpl.java    |  26 ++-
 .../framework/imps/ExistsBuilderImpl.java       |   4 +-
 .../framework/imps/GetChildrenBuilderImpl.java  |   4 +-
 .../framework/imps/GetDataBuilderImpl.java      |   4 +-
 .../curator/framework/imps/NamespaceFacade.java |   7 +
 .../imps/RemoveWatchesBuilderImpl.java          |  10 +-
 .../framework/imps/WatcherRemovalFacade.java    | 170 +++++++++++++++++++
 .../framework/imps/WatcherRemovalManager.java   |  67 ++++++++
 .../apache/curator/framework/imps/Watching.java |   6 +-
 .../imps/TestWatcherRemovalManager.java         |  54 ++++++
 .../org/apache/curator/test/WatchersDebug.java  |  74 ++++++++
 13 files changed, 419 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 4b30fd4..75b434a 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -235,4 +235,6 @@ public interface CuratorFramework extends Closeable
      * @throws InterruptedException If interrupted while waiting
      */
     public void blockUntilConnected() throws InterruptedException;
+
+    WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework();
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
new file mode 100644
index 0000000..58b4bf8
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
@@ -0,0 +1,6 @@
+package org.apache.curator.framework;
+
+public interface WatcherRemoveCuratorFramework extends CuratorFramework
+{
+    void removeWatchers();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index 5caff7d..35816a4 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -29,6 +29,7 @@ import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.*;
 import org.apache.curator.framework.api.transaction.CuratorTransaction;
 import org.apache.curator.framework.listen.Listenable;
@@ -150,6 +151,12 @@ public class CuratorFrameworkImpl implements CuratorFramework
         namespaceFacadeCache = new NamespaceFacadeCache(this);
     }
 
+    @Override
+    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework()
+    {
+        return new WatcherRemovalFacade(this);
+    }
+
     private ZookeeperFactory makeZookeeperFactory(final ZookeeperFactory actualZookeeperFactory)
     {
         return new ZookeeperFactory()
@@ -570,14 +577,14 @@ public class CuratorFrameworkImpl implements CuratorFramework
 
         final String localReason = reason;
         unhandledErrorListeners.forEach(new Function<UnhandledErrorListener, Void>()
+        {
+            @Override
+            public Void apply(UnhandledErrorListener listener)
             {
-                @Override
-                public Void apply(UnhandledErrorListener listener)
-                {
-                    listener.unhandledError(localReason, e);
-                    return null;
-                }
-            });
+                listener.unhandledError(localReason, e);
+                return null;
+            }
+        });
 
         if ( debugUnhandledErrorListener != null )
         {
@@ -660,6 +667,11 @@ public class CuratorFrameworkImpl implements CuratorFramework
         return Watcher.Event.KeeperState.fromInt(-1);
     }
 
+    WatcherRemovalManager getWatcherRemovalManager()
+    {
+        return null;
+    }
+
     private void suspendConnection()
     {
         if ( !connectionStateManager.setToSuspended() )

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
index a1e2ee5..d5f7b5b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
@@ -129,7 +129,7 @@ class ExistsBuilderImpl implements ExistsBuilder, BackgroundOperation<String>
         }
         else
         {
-            client.getZooKeeper().exists(operationAndData.getData(), watching.getWatcher(), callback, backgrounding.getContext());
+            client.getZooKeeper().exists(operationAndData.getData(), watching.getWatcher(client, operationAndData.getData()), callback, backgrounding.getContext());
         }
     }
 
@@ -169,7 +169,7 @@ class ExistsBuilderImpl implements ExistsBuilder, BackgroundOperation<String>
                     }
                     else
                     {
-                        returnStat = client.getZooKeeper().exists(path, watching.getWatcher());
+                        returnStat = client.getZooKeeper().exists(path, watching.getWatcher(client, path));
                     }
                     return returnStat;
                 }

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
index 16f6d4b..f9f784f 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
@@ -172,7 +172,7 @@ class GetChildrenBuilderImpl implements GetChildrenBuilder, BackgroundOperation<
         }
         else
         {
-            client.getZooKeeper().getChildren(operationAndData.getData(), watching.getWatcher(), callback, backgrounding.getContext());
+            client.getZooKeeper().getChildren(operationAndData.getData(), watching.getWatcher(client, operationAndData.getData()), callback, backgrounding.getContext());
         }
     }
 
@@ -211,7 +211,7 @@ class GetChildrenBuilderImpl implements GetChildrenBuilder, BackgroundOperation<
                     }
                     else
                     {
-                        children = client.getZooKeeper().getChildren(path, watching.getWatcher(), responseStat);
+                        children = client.getZooKeeper().getChildren(path, watching.getWatcher(client, path), responseStat);
                     }
                     return children;
                 }

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
index e994b03..7077839 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
@@ -260,7 +260,7 @@ class GetDataBuilderImpl implements GetDataBuilder, BackgroundOperation<String>
         }
         else
         {
-            client.getZooKeeper().getData(operationAndData.getData(), watching.getWatcher(), callback, backgrounding.getContext());
+            client.getZooKeeper().getData(operationAndData.getData(), watching.getWatcher(client, operationAndData.getData()), callback, backgrounding.getContext());
         }
     }
 
@@ -299,7 +299,7 @@ class GetDataBuilderImpl implements GetDataBuilder, BackgroundOperation<String>
                     }
                     else
                     {
-                        responseData = client.getZooKeeper().getData(path, watching.getWatcher(), responseStat);
+                        responseData = client.getZooKeeper().getData(path, watching.getWatcher(client, path), responseStat);
                     }
                     return responseData;
                 }

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
index 818fe5f..8dc7ae1 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
@@ -21,6 +21,7 @@ package org.apache.curator.framework.imps;
 import org.apache.curator.CuratorZookeeperClient;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.*;
 import org.apache.curator.framework.listen.Listenable;
 import org.apache.curator.framework.state.ConnectionStateListener;
@@ -41,6 +42,12 @@ class NamespaceFacade extends CuratorFrameworkImpl
     }
 
     @Override
+    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public CuratorFramework nonNamespaceView()
     {
         return usingNamespace(null);

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 1e4fb88..ab977a9 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -40,7 +40,15 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         this.quietly = false;
         this.backgrounding = new Backgrounding();
     }
-    
+
+    void prepInternalRemoval(Watcher watcher)
+    {
+        this.watcher = watcher;
+        watcherType = WatcherType.Any;
+        quietly = true;
+        this.backgrounding = new Backgrounding();
+    }
+
     @Override
     public RemoveWatchesType remove(Watcher watcher)
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
new file mode 100644
index 0000000..a11ca5d
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
@@ -0,0 +1,170 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.imps;
+
+import org.apache.curator.CuratorZookeeperClient;
+import org.apache.curator.RetryLoop;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorListener;
+import org.apache.curator.framework.api.UnhandledErrorListener;
+import org.apache.curator.framework.listen.Listenable;
+import org.apache.curator.framework.state.ConnectionStateListener;
+import org.apache.curator.utils.EnsurePath;
+import org.apache.zookeeper.ZooKeeper;
+
+class WatcherRemovalFacade extends CuratorFrameworkImpl implements WatcherRemoveCuratorFramework
+{
+    private final CuratorFrameworkImpl client;
+    private final WatcherRemovalManager removalManager;
+
+    WatcherRemovalFacade(CuratorFrameworkImpl client)
+    {
+        super(client);
+        this.client = client;
+        removalManager = new WatcherRemovalManager(client);
+    }
+
+    @Override
+    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeWatchers()
+    {
+        removalManager.removeWatchers();
+    }
+
+    @Override
+    WatcherRemovalManager getWatcherRemovalManager()
+    {
+        return removalManager;
+    }
+
+    @Override
+    public CuratorFramework nonNamespaceView()
+    {
+        return client.usingNamespace(null);
+    }
+
+    @Override
+    public CuratorFramework usingNamespace(String newNamespace)
+    {
+        return client.getNamespaceFacadeCache().get(newNamespace);
+    }
+
+    @Override
+    public String getNamespace()
+    {
+        return client.getNamespace();
+    }
+
+    @Override
+    public void start()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void close()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Listenable<ConnectionStateListener> getConnectionStateListenable()
+    {
+        return client.getConnectionStateListenable();
+    }
+
+    @Override
+    public Listenable<CuratorListener> getCuratorListenable()
+    {
+        return client.getCuratorListenable();
+    }
+
+    @Override
+    public Listenable<UnhandledErrorListener> getUnhandledErrorListenable()
+    {
+        return client.getUnhandledErrorListenable();
+    }
+
+    @Override
+    public void sync(String path, Object context)
+    {
+        client.sync(path, context);
+    }
+
+    @Override
+    public CuratorZookeeperClient getZookeeperClient()
+    {
+        return client.getZookeeperClient();
+    }
+
+    @Override
+    RetryLoop newRetryLoop()
+    {
+        return client.newRetryLoop();
+    }
+
+    @Override
+    ZooKeeper getZooKeeper() throws Exception
+    {
+        return client.getZooKeeper();
+    }
+
+    @Override
+    <DATA_TYPE> void processBackgroundOperation(OperationAndData<DATA_TYPE> operationAndData, CuratorEvent event)
+    {
+        client.processBackgroundOperation(operationAndData, event);
+    }
+
+    @Override
+    void logError(String reason, Throwable e)
+    {
+        client.logError(reason, e);
+    }
+
+    @Override
+    String unfixForNamespace(String path)
+    {
+        return client.unfixForNamespace(path);
+    }
+
+    @Override
+    String fixForNamespace(String path)
+    {
+        return client.fixForNamespace(path);
+    }
+
+    @Override
+    public EnsurePath newNamespaceAwareEnsurePath(String path)
+    {
+        return client.newNamespaceAwareEnsurePath(path);
+    }
+
+    @Override
+    FailedDeleteManager getFailedDeleteManager()
+    {
+        return client.getFailedDeleteManager();
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
new file mode 100644
index 0000000..9461de5
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
@@ -0,0 +1,67 @@
+package org.apache.curator.framework.imps;
+
+import com.google.common.collect.Maps;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Map;
+
+class WatcherRemovalManager
+{
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final CuratorFrameworkImpl client;
+    private final Map<Watcher, String> entries = Maps.newConcurrentMap();
+
+    WatcherRemovalManager(CuratorFrameworkImpl client)
+    {
+        this.client = client;
+    }
+
+    Watcher add(String path, Watcher watcher)
+    {
+        Watcher wrappedWatcher = new WrappedWatcher(entries, watcher);
+        entries.put(wrappedWatcher, path);
+        return wrappedWatcher;
+    }
+
+    void removeWatchers()
+    {
+        for ( Map.Entry<Watcher, String> entry : entries.entrySet() )
+        {
+            Watcher watcher = entry.getKey();
+            String path = entry.getValue();
+            try
+            {
+                log.debug("Removing watcher for path: " + path);
+                RemoveWatchesBuilderImpl builder = new RemoveWatchesBuilderImpl(client);
+                builder.prepInternalRemoval(watcher);
+                builder.forPath(path);
+            }
+            catch ( Exception e )
+            {
+                String message = "Could not remove watcher for path: " + path;
+                log.error(message);
+            }
+        }
+    }
+
+    private static class WrappedWatcher implements Watcher
+    {
+        private final Map<Watcher, String> entries;
+        private final Watcher watcher;
+
+        WrappedWatcher(Map<Watcher, String> entries, Watcher watcher)
+        {
+            this.entries = entries;
+            this.watcher = watcher;
+        }
+
+        @Override
+        public void process(WatchedEvent event)
+        {
+            entries.remove(this);
+            watcher.process(event);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
index a9d0ab1..ae16dfc 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/Watching.java
@@ -50,8 +50,12 @@ class Watching
         watched = false;
     }
 
-    Watcher getWatcher()
+    Watcher getWatcher(CuratorFrameworkImpl client, String unfixedPath)
     {
+        if ( client.getWatcherRemovalManager() != null )
+        {
+            return client.getWatcherRemovalManager().add(unfixedPath, watcher);
+        }
         return watcher;
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
new file mode 100644
index 0000000..9a5dbdc
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
@@ -0,0 +1,54 @@
+package org.apache.curator.framework.imps;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.test.Timing;
+import org.apache.curator.test.WatchersDebug;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import java.util.List;
+
+public class TestWatcherRemovalManager extends BaseClassForTests
+{
+    @Test
+    public void testBasic() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            WatcherRemoveCuratorFramework removerClient = client.newWatcherRemoveCuratorFramework();
+
+            Watcher watcher = new Watcher()
+            {
+                @Override
+                public void process(WatchedEvent event)
+                {
+                    // NOP
+                }
+            };
+            removerClient.checkExists().usingWatcher(watcher).forPath("/hey");
+
+            List<String> existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
+            Assert.assertEquals(existWatches.size(), 1);
+
+            removerClient.removeWatchers();
+
+            new Timing().sleepABit();
+
+            existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
+            Assert.assertEquals(existWatches.size(), 0);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/58fcc548/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
----------------------------------------------------------------------
diff --git a/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java b/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
new file mode 100644
index 0000000..a97e5c1
--- /dev/null
+++ b/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
@@ -0,0 +1,74 @@
+package org.apache.curator.test;
+
+import org.apache.zookeeper.ZooKeeper;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class WatchersDebug
+{
+    private static final Method getDataWatches;
+    private static final Method getExistWatches;
+    private static final Method getChildWatches;
+    static
+    {
+        Method localGetDataWatches = null;
+        Method localGetExistWatches = null;
+        Method localGetChildWatches = null;
+        try
+        {
+            localGetDataWatches = getMethod("getDataWatches");
+            localGetExistWatches = getMethod("getExistWatches");
+            localGetChildWatches = getMethod("getChildWatches");
+        }
+        catch ( NoSuchMethodException e )
+        {
+            e.printStackTrace();
+        }
+        getDataWatches = localGetDataWatches;
+        getExistWatches = localGetExistWatches;
+        getChildWatches = localGetChildWatches;
+    }
+
+    public static List<String> getDataWatches(ZooKeeper zooKeeper)
+    {
+        return callMethod(zooKeeper, WatchersDebug.getDataWatches);
+    }
+
+    public static List<String> getExistWatches(ZooKeeper zooKeeper)
+    {
+        return callMethod(zooKeeper, getExistWatches);
+    }
+
+    public static List<String> getChildWatches(ZooKeeper zooKeeper)
+    {
+        return callMethod(zooKeeper, getChildWatches);
+    }
+
+    private WatchersDebug()
+    {
+    }
+
+    private static Method getMethod(String name) throws NoSuchMethodException
+    {
+        Method m = ZooKeeper.class.getDeclaredMethod(name);
+        m.setAccessible(true);
+        return m;
+    }
+
+    private static List<String> callMethod(ZooKeeper zooKeeper, Method method)
+    {
+        if ( zooKeeper == null )
+        {
+            return null;
+        }
+        try
+        {
+            //noinspection unchecked
+            return (List<String>)method.invoke(zooKeeper);
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException(e);
+        }
+    }
+}


[06/31] curator git commit: CURATOR-161 - Added support for quietly() call that will suppress NoWatcherException exceptions.

Posted by dr...@apache.org.
CURATOR-161 - Added support for quietly() call that will suppress
NoWatcherException exceptions.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/4c2ba374
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/4c2ba374
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/4c2ba374

Branch: refs/heads/CURATOR-3.0
Commit: 4c2ba3744d90f2af12d815e8aa0747fd0d1a1c67
Parents: a83090b
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Mon May 11 09:19:45 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Mon May 11 09:19:45 2015 +1000

----------------------------------------------------------------------
 .../api/BackgroundPathableQuietly.java          |  5 ++
 .../apache/curator/framework/api/Quietly.java   |  6 ++
 .../framework/api/RemoveWatchesLocal.java       |  4 +-
 .../imps/RemoveWatchesBuilderImpl.java          | 38 +++++++++---
 .../framework/imps/TestRemoveWatches.java       | 64 ++++++++++++++++++++
 5 files changed, 107 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4c2ba374/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
new file mode 100644
index 0000000..1174067
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
@@ -0,0 +1,5 @@
+package org.apache.curator.framework.api;
+
+public interface BackgroundPathableQuietly<T> extends BackgroundPathable<T>, Quietly<BackgroundPathable<T>>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4c2ba374/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
new file mode 100644
index 0000000..cf4edc8
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
@@ -0,0 +1,6 @@
+package org.apache.curator.framework.api;
+
+public interface Quietly<T>
+{
+    public T quietly();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4c2ba374/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
index 2e9816b..d183a6a 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -4,7 +4,7 @@ package org.apache.curator.framework.api;
  * Builder to allow the specification of whether it is acceptable to remove client side watch information
  * in the case where ZK cannot be contacted. 
  */
-public interface RemoveWatchesLocal extends BackgroundPathable<Void>
+public interface RemoveWatchesLocal extends BackgroundPathableQuietly<Void>
 {
    
     /**
@@ -12,6 +12,6 @@ public interface RemoveWatchesLocal extends BackgroundPathable<Void>
      * is not available.
      * @return
      */
-    public BackgroundPathable<Void> local();
+    public BackgroundPathableQuietly<Void> local();
     
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/4c2ba374/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 5d1f945..1e4fb88 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -7,6 +7,7 @@ import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.BackgroundPathable;
+import org.apache.curator.framework.api.BackgroundPathableQuietly;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.CuratorWatcher;
@@ -15,6 +16,7 @@ import org.apache.curator.framework.api.RemoveWatchesLocal;
 import org.apache.curator.framework.api.RemoveWatchesBuilder;
 import org.apache.curator.framework.api.RemoveWatchesType;
 import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.Watcher.WatcherType;
 import org.apache.zookeeper.ZooKeeper;
@@ -25,7 +27,8 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     private CuratorFrameworkImpl client;
     private Watcher watcher;
     private WatcherType watcherType;
-    private boolean local;    
+    private boolean local;
+    private boolean quietly;
     private Backgrounding backgrounding;
     
     public RemoveWatchesBuilderImpl(CuratorFrameworkImpl client)
@@ -34,6 +37,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         this.watcher = null;
         this.watcherType = null;
         this.local = false;
+        this.quietly = false;
         this.backgrounding = new Backgrounding();
     }
     
@@ -109,13 +113,20 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     }
 
     @Override
-    public BackgroundPathable<Void> local()
+    public BackgroundPathableQuietly<Void> local()
     {
         local = true;
         return this;
     }
     
     @Override
+    public BackgroundPathable<Void> quietly()
+    {
+        quietly = true;
+        return this;
+    }
+    
+    @Override
     public Void forPath(String path) throws Exception
     {
         final String adjustedPath = client.fixForNamespace(path);
@@ -146,16 +157,27 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
                     @Override
                     public Void call() throws Exception
                     {
-                        ZooKeeper zkClient = client.getZooKeeper();
-                        if(watcher == null)
+                        try
                         {
-                            zkClient.removeAllWatches(path, watcherType, local);    
+                            ZooKeeper zkClient = client.getZooKeeper();
+                            if(watcher == null)
+                            {
+                                zkClient.removeAllWatches(path, watcherType, local);    
+                            }
+                            else
+                            {
+                                zkClient.removeWatches(path, watcher, watcherType, local);
+                            }
                         }
-                        else
+                        catch(KeeperException.NoWatcherException e)
                         {
-                            zkClient.removeWatches(path, watcher, watcherType, local);
+                            //Swallow this exception if the quietly flag is set, otherwise rethrow.
+                            if(!quietly)
+                            {
+                                throw e;
+                            }
                         }
-                        
+                     
                         return null;
                     }
                 });

http://git-wip-us.apache.org/repos/asf/curator/blob/4c2ba374/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index b740286..28799f7 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -14,6 +14,7 @@ import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.Timing;
 import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.Watcher.Event.EventType;
@@ -331,4 +332,67 @@ public class TestRemoveWatches extends BaseClassForTests
             CloseableUtils.closeQuietly(client);
         }
     }
+    
+    /**
+     * Test the case where we try and remove an unregistered watcher. In this case we expect a NoWatcherException to
+     * be thrown. 
+     * @throws Exception
+     */
+    @Test(expectedExceptions=KeeperException.NoWatcherException.class)
+    public void testRemoveUnregisteredWatcher() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final String path = "/";            
+            Watcher watcher = new Watcher() {
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }                
+            };
+            
+            client.watches().remove(watcher).ofType(WatcherType.Data).forPath(path);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    /**
+     * Test the case where we try and remove an unregistered watcher but have the quietly flag set. In this case we expect success. 
+     * @throws Exception
+     */
+    @Test
+    public void testRemoveUnregisteredWatcherQuietly() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final String path = "/";            
+            Watcher watcher = new Watcher() {
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }                
+            };
+            
+            client.watches().remove(watcher).ofType(WatcherType.Data).quietly().forPath(path);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
 }


[19/31] curator git commit: doc

Posted by dr...@apache.org.
doc


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/43afca7b
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/43afca7b
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/43afca7b

Branch: refs/heads/CURATOR-3.0
Commit: 43afca7b902bf3d52c33c23924be4ca37c4df23f
Parents: 79d152c
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 16:38:37 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 16:38:37 2015 -0700

----------------------------------------------------------------------
 .../curator/framework/WatcherRemoveCuratorFramework.java       | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/43afca7b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
index e41b186..871b53c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
@@ -18,7 +18,13 @@
  */
 package org.apache.curator.framework;
 
+/**
+ * A CuratorFramework facade that tracks watchers created and allows a one-shot removal of all watchers
+ */
 public interface WatcherRemoveCuratorFramework extends CuratorFramework
 {
+    /**
+     * Remove all outstanding watchers that have been set
+     */
     void removeWatchers();
 }


[17/31] curator git commit: CURATOR-161 - Fixed up some potential race conditions with unit tests.

Posted by dr...@apache.org.
CURATOR-161 - Fixed up some potential race conditions with unit tests.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/a47c0367
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/a47c0367
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/a47c0367

Branch: refs/heads/CURATOR-3.0
Commit: a47c03671452a20e70deb2b8668d70bd92d78ce7
Parents: ba4da2c
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Thu May 14 09:33:22 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Thu May 14 09:33:22 2015 +1000

----------------------------------------------------------------------
 .../framework/imps/TestRemoveWatches.java       | 55 ++++++++++++++++----
 1 file changed, 46 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/a47c0367/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index fc15f0c..49f34ea 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -4,6 +4,7 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -30,23 +31,51 @@ import org.testng.annotations.Test;
 
 public class TestRemoveWatches extends BaseClassForTests
 {
-    private boolean blockUntilDesiredConnectionState(CuratorFramework client, Timing timing, final ConnectionState desiredState)
+    private AtomicReference<ConnectionState> registerConnectionStateListener(CuratorFramework client)
     {
-        final CountDownLatch latch = new CountDownLatch(1);
+        final AtomicReference<ConnectionState> state = new AtomicReference<ConnectionState>();
         client.getConnectionStateListenable().addListener(new ConnectionStateListener()
         {
             
             @Override
             public void stateChanged(CuratorFramework client, ConnectionState newState)
             {
-                if(newState == desiredState)
+                state.set(newState);
+                synchronized(state)
                 {
-                    latch.countDown();
+                    state.notify();
                 }
             }
         });
         
-        return timing.awaitLatch(latch);
+        return state;
+    }
+    
+    private boolean blockUntilDesiredConnectionState(AtomicReference<ConnectionState> stateRef, Timing timing, final ConnectionState desiredState)
+    {
+        if(stateRef.get() == desiredState)
+        {
+            return true;
+        }
+        
+        synchronized(stateRef)
+        {
+            if(stateRef.get() == desiredState)
+            {
+                return true;
+            }
+            
+            try
+            {
+                stateRef.wait(timing.milliseconds());
+                return stateRef.get() == desiredState;
+            }
+            catch(InterruptedException e)
+            {
+                Thread.currentThread().interrupt();
+                return false;
+            }
+        }
     }
     
     @Test
@@ -337,6 +366,8 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            AtomicReference<ConnectionState> stateRef = registerConnectionStateListener(client);
+            
             final String path = "/";
             
             final CountDownLatch removedLatch = new CountDownLatch(1);
@@ -348,7 +379,7 @@ public class TestRemoveWatches extends BaseClassForTests
             //Stop the server so we can check if we can remove watches locally when offline
             server.stop();
             
-            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
+            Assert.assertTrue(blockUntilDesiredConnectionState(stateRef, timing, ConnectionState.SUSPENDED));
                        
             client.watches().removeAll().locally().forPath(path);
             
@@ -371,6 +402,8 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            AtomicReference<ConnectionState> stateRef = registerConnectionStateListener(client);
+            
             final String path = "/";
             
             final CountDownLatch removedLatch = new CountDownLatch(1);
@@ -382,7 +415,7 @@ public class TestRemoveWatches extends BaseClassForTests
             //Stop the server so we can check if we can remove watches locally when offline
             server.stop();
             
-            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
+            Assert.assertTrue(blockUntilDesiredConnectionState(stateRef, timing, ConnectionState.SUSPENDED));
                        
             client.watches().removeAll().locally().inBackground().forPath(path);
             
@@ -470,6 +503,8 @@ public class TestRemoveWatches extends BaseClassForTests
         try
         {
             client.start();
+            
+            AtomicReference<ConnectionState> stateRef = registerConnectionStateListener(client);
                        
             String path = "/";
             
@@ -480,7 +515,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             server.stop();           
             
-            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
+            Assert.assertTrue(blockUntilDesiredConnectionState(stateRef, timing, ConnectionState.SUSPENDED));
             
             //Remove the watch while we're not connected
             try 
@@ -511,6 +546,8 @@ public class TestRemoveWatches extends BaseClassForTests
         try
         {
             client.start();
+            
+            AtomicReference<ConnectionState> stateRef = registerConnectionStateListener(client);
                         
             final CountDownLatch guaranteeAddedLatch = new CountDownLatch(1);
             
@@ -533,7 +570,7 @@ public class TestRemoveWatches extends BaseClassForTests
             client.checkExists().usingWatcher(watcher).forPath(path);
             
             server.stop();           
-            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
+            Assert.assertTrue(blockUntilDesiredConnectionState(stateRef, timing, ConnectionState.SUSPENDED));
             
             //Remove the watch while we're not connected
             client.watches().remove(watcher).guaranteed().inBackground().forPath(path);


[22/31] curator git commit: CURATOR-161 - Updates after review.

Posted by dr...@apache.org.
CURATOR-161 - Updates after review.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/4f21e318
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/4f21e318
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/4f21e318

Branch: refs/heads/CURATOR-3.0
Commit: 4f21e318f796cec4b32cafe14e0e2bf240817114
Parents: a47c036
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Wed May 20 11:57:10 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Wed May 20 11:57:10 2015 +1000

----------------------------------------------------------------------
 .../api/BackgroundPathableQuietly.java          |  5 ---
 .../api/BackgroundPathableQuietlyable.java      |  5 +++
 .../curator/framework/api/DeleteBuilder.java    |  2 +-
 .../curator/framework/api/Guaranteeable.java    |  2 +-
 .../framework/api/GuaranteeableDeletable.java   | 39 ++++++++++++++++++++
 .../framework/api/GuaranteeableDelete.java      | 39 --------------------
 .../framework/api/RemoveWatchesLocal.java       |  4 +-
 .../framework/api/RemoveWatchesType.java        |  2 +-
 .../imps/FailedRemoveWatchManager.java          |  2 +-
 .../framework/imps/NamespaceWatcherMap.java     |  8 ----
 .../imps/RemoveWatchesBuilderImpl.java          |  4 +-
 11 files changed, 52 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
deleted file mode 100644
index 1174067..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.apache.curator.framework.api;
-
-public interface BackgroundPathableQuietly<T> extends BackgroundPathable<T>, Quietly<BackgroundPathable<T>>
-{
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietlyable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietlyable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietlyable.java
new file mode 100644
index 0000000..8ed73fa
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietlyable.java
@@ -0,0 +1,5 @@
+package org.apache.curator.framework.api;
+
+public interface BackgroundPathableQuietlyable<T> extends BackgroundPathable<T>, Quietly<BackgroundPathable<T>>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
index 893e825..2da1843 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
@@ -18,6 +18,6 @@
  */
 package org.apache.curator.framework.api;
 
-public interface DeleteBuilder extends GuaranteeableDelete, ChildrenDeletable
+public interface DeleteBuilder extends GuaranteeableDeletable, ChildrenDeletable
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
index b43d6b0..bc033ac 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
@@ -24,7 +24,7 @@ public interface Guaranteeable<T>
      * Solves edge cases where an operation may succeed on the server but connection failure occurs before a
      * response can be successfully returned to the client.
      * 
-     * @see org.apache.curator.framework.api.GuaranteeableDelete 
+     * @see org.apache.curator.framework.api.GuaranteeableDeletable 
      *  
      * @return this
      */

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDeletable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDeletable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDeletable.java
new file mode 100644
index 0000000..7f8139c
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDeletable.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.api;
+
+/**
+ * <p>
+ *     Solves this edge case: deleting a node can fail due to connection issues. Further,
+ *     if the node was ephemeral, the node will not get auto-deleted as the session is still valid.
+ *     This can wreak havoc with lock implementations.
+ * </p>
+ *
+ * <p>
+ *     When <code>guaranteed</code> is set, Curator will record failed node deletions and
+ *     attempt to delete them in the background until successful. NOTE: you will still get an
+ *     exception when the deletion fails. But, you can be assured that as long as the
+ *     {@link org.apache.curator.framework.CuratorFramework} instance is open attempts will be made to delete the node.
+ * </p>
+ *  
+ * @return this
+ */
+public interface GuaranteeableDeletable extends Guaranteeable<ChildrenDeletable>, BackgroundVersionable
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java b/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java
deleted file mode 100644
index d04e7ea..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.curator.framework.api;
-
-/**
- * <p>
- *     Solves this edge case: deleting a node can fail due to connection issues. Further,
- *     if the node was ephemeral, the node will not get auto-deleted as the session is still valid.
- *     This can wreak havoc with lock implementations.
- * </p>
- *
- * <p>
- *     When <code>guaranteed</code> is set, Curator will record failed node deletions and
- *     attempt to delete them in the background until successful. NOTE: you will still get an
- *     exception when the deletion fails. But, you can be assured that as long as the
- *     {@link org.apache.curator.framework.CuratorFramework} instance is open attempts will be made to delete the node.
- * </p>
- *  
- * @return this
- */
-public interface GuaranteeableDelete extends Guaranteeable<ChildrenDeletable>, BackgroundVersionable
-{
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
index e002857..1c94fb3 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -4,7 +4,7 @@ package org.apache.curator.framework.api;
  * Builder to allow the specification of whether it is acceptable to remove client side watch information
  * in the case where ZK cannot be contacted. 
  */
-public interface RemoveWatchesLocal extends BackgroundPathableQuietly<Void>
+public interface RemoveWatchesLocal extends BackgroundPathableQuietlyable<Void>
 {
    
     /**
@@ -12,6 +12,6 @@ public interface RemoveWatchesLocal extends BackgroundPathableQuietly<Void>
      * is not available. Note that the standard Curator retry loop will not be used in t
      * @return
      */
-    public BackgroundPathableQuietly<Void> locally();
+    public BackgroundPathableQuietlyable<Void> locally();
     
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
index 3112eac..21b5b50 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
@@ -6,7 +6,7 @@ import org.apache.zookeeper.Watcher.WatcherType;
  * Builder to allow the specification of whether it is acceptable to remove client side watch information
  * in the case where ZK cannot be contacted. 
  */
-public interface RemoveWatchesType extends RemoveWatchesLocal, Guaranteeable<BackgroundPathableQuietly<Void>>
+public interface RemoveWatchesType extends RemoveWatchesLocal, Guaranteeable<BackgroundPathableQuietlyable<Void>>
 {
    
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
index f954e2a..f635660 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
@@ -32,7 +32,7 @@ class FailedRemoveWatchManager extends FailedOperationManager<FailedRemoveWatchM
     protected void executeGuaranteedOperationInBackground(FailedRemoveWatchDetails details)
             throws Exception
     {
-        if(details.watcher ==  null)
+        if(details.watcher == null)
         {
             client.watches().removeAll().guaranteed().inBackground().forPath(details.path);
         }

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
index f656ba1..e5aecb2 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
@@ -70,14 +70,6 @@ class NamespaceWatcherMap implements Closeable
     {
         return map.remove(key);
     }
-    
-    /**
-     * Remove all watchers for a given path
-     * @param path
-     */
-    void removeAllForPath(String path) {
-        
-    }
 
     @VisibleForTesting
     boolean isEmpty()

http://git-wip-us.apache.org/repos/asf/curator/blob/4f21e318/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 932706b..d734f79 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -7,7 +7,7 @@ import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.BackgroundPathable;
-import org.apache.curator.framework.api.BackgroundPathableQuietly;
+import org.apache.curator.framework.api.BackgroundPathableQuietlyable;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.CuratorWatcher;
@@ -134,7 +134,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     }    
 
     @Override
-    public BackgroundPathableQuietly<Void> locally()
+    public BackgroundPathableQuietlyable<Void> locally()
     {
         local = true;
         return this;


[24/31] curator git commit: make test more rational by using a latch

Posted by dr...@apache.org.
make test more rational by using a latch


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/4ad09e7d
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/4ad09e7d
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/4ad09e7d

Branch: refs/heads/CURATOR-3.0
Commit: 4ad09e7d1d71acebba97bb5594205d96f76eba3c
Parents: 115611e
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 19:38:24 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 19:38:24 2015 -0700

----------------------------------------------------------------------
 .../curator/framework/imps/TestWatcherRemovalManager.java    | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4ad09e7d/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
index 9508f43..bf690fd 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
@@ -228,12 +228,16 @@ public class TestWatcherRemovalManager extends BaseClassForTests
     {
         WatcherRemoveCuratorFramework removerClient = client.newWatcherRemoveCuratorFramework();
 
+        final CountDownLatch latch = new CountDownLatch(1);
         Watcher watcher = new Watcher()
         {
             @Override
             public void process(WatchedEvent event)
             {
-                // NOP
+                if ( event.getType() == Event.EventType.DataWatchRemoved )
+                {
+                    latch.countDown();
+                }
             }
         };
         removerClient.checkExists().usingWatcher(watcher).forPath("/hey");
@@ -243,7 +247,7 @@ public class TestWatcherRemovalManager extends BaseClassForTests
 
         removerClient.removeWatchers();
 
-        new Timing().sleepABit();
+        Assert.assertTrue(new Timing().awaitLatch(latch));
 
         existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
         Assert.assertEquals(existWatches.size(), 0);


[02/31] curator git commit: Update project version to 3.0.0-SNAPSHOT.

Posted by dr...@apache.org.
Update project version to 3.0.0-SNAPSHOT.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/d4883a84
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/d4883a84
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/d4883a84

Branch: refs/heads/CURATOR-3.0
Commit: d4883a845a3778bcad4a776bb18b146f733d8885
Parents: 034e910
Author: Ioannis Canellos <io...@gmail.com>
Authored: Thu Nov 6 17:30:29 2014 +0200
Committer: Ioannis Canellos <io...@gmail.com>
Committed: Thu Nov 6 17:30:29 2014 +0200

----------------------------------------------------------------------
 curator-client/pom.xml             | 4 ++--
 curator-examples/pom.xml           | 2 +-
 curator-framework/pom.xml          | 4 ++--
 curator-recipes/pom.xml            | 4 ++--
 curator-test/pom.xml               | 4 ++--
 curator-x-discovery-server/pom.xml | 4 ++--
 curator-x-discovery/pom.xml        | 4 ++--
 curator-x-rpc/pom.xml              | 4 ++--
 pom.xml                            | 2 +-
 9 files changed, 16 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-client/pom.xml
----------------------------------------------------------------------
diff --git a/curator-client/pom.xml b/curator-client/pom.xml
index cd0af80..0f3955b 100644
--- a/curator-client/pom.xml
+++ b/curator-client/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-client</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Client</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-examples/pom.xml
----------------------------------------------------------------------
diff --git a/curator-examples/pom.xml b/curator-examples/pom.xml
index 1728ec9..825ca16 100644
--- a/curator-examples/pom.xml
+++ b/curator-examples/pom.xml
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-examples</artifactId>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-framework/pom.xml
----------------------------------------------------------------------
diff --git a/curator-framework/pom.xml b/curator-framework/pom.xml
index 446c2fd..a45ce77 100644
--- a/curator-framework/pom.xml
+++ b/curator-framework/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-framework</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Framework</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-recipes/pom.xml
----------------------------------------------------------------------
diff --git a/curator-recipes/pom.xml b/curator-recipes/pom.xml
index 4955dde..9d1d081 100644
--- a/curator-recipes/pom.xml
+++ b/curator-recipes/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-recipes</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Recipes</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-test/pom.xml
----------------------------------------------------------------------
diff --git a/curator-test/pom.xml b/curator-test/pom.xml
index 5b6352a..1cbd93c 100644
--- a/curator-test/pom.xml
+++ b/curator-test/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-test</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
 
     <name>Curator Testing</name>
     <description>Unit testing utilities.</description>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-x-discovery-server/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-discovery-server/pom.xml b/curator-x-discovery-server/pom.xml
index f6851be..352310f 100644
--- a/curator-x-discovery-server/pom.xml
+++ b/curator-x-discovery-server/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-x-discovery-server</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Service Discovery Server</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-x-discovery/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-discovery/pom.xml b/curator-x-discovery/pom.xml
index 69d8410..e211d89 100644
--- a/curator-x-discovery/pom.xml
+++ b/curator-x-discovery/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-x-discovery</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Service Discovery</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/curator-x-rpc/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-rpc/pom.xml b/curator-x-rpc/pom.xml
index 0e0b528..fe167e0 100644
--- a/curator-x-rpc/pom.xml
+++ b/curator-x-rpc/pom.xml
@@ -3,12 +3,12 @@
     <parent>
         <artifactId>apache-curator</artifactId>
         <groupId>org.apache.curator</groupId>
-        <version>2.7.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>curator-x-rpc</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
 
     <name>Curator RPC Proxy</name>
     <description>A proxy that bridges non-java environments with the Curator framework and recipes</description>

http://git-wip-us.apache.org/repos/asf/curator/blob/d4883a84/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 7b94d03..3e122c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
     <groupId>org.apache.curator</groupId>
     <artifactId>apache-curator</artifactId>
-    <version>2.7.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>Apache Curator</name>


[23/31] curator git commit: CURATOR-161 - Added @VisibleForTesting annotation to debugListener

Posted by dr...@apache.org.
CURATOR-161 - Added @VisibleForTesting annotation to debugListener


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/6612c91e
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/6612c91e
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/6612c91e

Branch: refs/heads/CURATOR-3.0
Commit: 6612c91e7f6aa50ce961e0bfcc9fb4c3134e0a39
Parents: 4f21e31
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Wed May 20 12:03:17 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Wed May 20 12:03:17 2015 +1000

----------------------------------------------------------------------
 .../org/apache/curator/framework/imps/FailedOperationManager.java | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/6612c91e/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
index a1efde2..405561b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
@@ -22,11 +22,14 @@ import org.apache.curator.framework.CuratorFramework;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
+
 abstract class FailedOperationManager<T>
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
     protected final CuratorFramework client;
     
+    @VisibleForTesting
     volatile FailedOperationManagerListener<T> debugListener = null;
     
     interface FailedOperationManagerListener<T>


[07/31] curator git commit: CURATOR-161 - Changed local() call to be called locally()

Posted by dr...@apache.org.
CURATOR-161 - Changed local() call to be called locally()


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/198ba684
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/198ba684
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/198ba684

Branch: refs/heads/CURATOR-3.0
Commit: 198ba684ff8bb47e10e40dd46c6e97023b7a365f
Parents: 4c2ba37
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Mon May 11 12:38:18 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Mon May 11 12:38:18 2015 +1000

----------------------------------------------------------------------
 .../java/org/apache/curator/framework/api/RemoveWatchesLocal.java  | 2 +-
 .../apache/curator/framework/imps/RemoveWatchesBuilderImpl.java    | 2 +-
 .../java/org/apache/curator/framework/imps/TestRemoveWatches.java  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/198ba684/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
index d183a6a..3769d1f 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -12,6 +12,6 @@ public interface RemoveWatchesLocal extends BackgroundPathableQuietly<Void>
      * is not available.
      * @return
      */
-    public BackgroundPathableQuietly<Void> local();
+    public BackgroundPathableQuietly<Void> locally();
     
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/198ba684/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 1e4fb88..4354653 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -113,7 +113,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     }
 
     @Override
-    public BackgroundPathableQuietly<Void> local()
+    public BackgroundPathableQuietly<Void> locally()
     {
         local = true;
         return this;

http://git-wip-us.apache.org/repos/asf/curator/blob/198ba684/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 28799f7..39967c9 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -323,7 +323,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             timing.sleepABit();
             
-            client.watches().removeAll().ofType(WatcherType.Any).local().forPath(path);
+            client.watches().removeAll().ofType(WatcherType.Any).locally().forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }


[11/31] curator git commit: CURATOR-161 - Some progress in getting locally() to work. Working now for the foreground case, but still not working for the background case because it tries to guarantee a connection before the command is executed.

Posted by dr...@apache.org.
CURATOR-161 - Some progress in getting locally() to work. Working now for
the foreground case, but still not working for the background case because
it tries to guarantee a connection before the command is executed.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/04caf36c
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/04caf36c
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/04caf36c

Branch: refs/heads/CURATOR-3.0
Commit: 04caf36cd4ee76b358c7866da18c858b5608ebca
Parents: 389e0b0
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Tue May 12 07:46:43 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Tue May 12 07:46:43 2015 +1000

----------------------------------------------------------------------
 .../framework/api/RemoveWatchesLocal.java       |  2 +-
 .../imps/RemoveWatchesBuilderImpl.java          | 62 ++++++++++++--------
 .../framework/imps/TestRemoveWatches.java       | 42 +++++++++++--
 3 files changed, 77 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/04caf36c/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
index 3769d1f..e002857 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -9,7 +9,7 @@ public interface RemoveWatchesLocal extends BackgroundPathableQuietly<Void>
    
     /**
      * Specify if the client should just remove client side watches if a connection to ZK
-     * is not available.
+     * is not available. Note that the standard Curator retry loop will not be used in t
      * @return
      */
     public BackgroundPathableQuietly<Void> locally();

http://git-wip-us.apache.org/repos/asf/curator/blob/04caf36c/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 5a34f7d..c9868f4 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -151,36 +151,52 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     
     private void pathInForeground(final String path) throws Exception
     {
-        RetryLoop.callWithRetry(client.getZookeeperClient(), 
-                new Callable<Void>()
-                {
-                    @Override
-                    public Void call() throws Exception
+        if(local)
+        {
+            ZooKeeper zkClient = client.getZooKeeper();
+            if(watcher == null)
+            {
+                zkClient.removeAllWatches(path, watcherType, local);    
+            }
+            else
+            {
+                zkClient.removeWatches(path, watcher, watcherType, local);
+            }
+        }
+        else
+        {
+            RetryLoop.callWithRetry(client.getZookeeperClient(), 
+                    new Callable<Void>()
                     {
-                        try
+                        @Override
+                        public Void call() throws Exception
                         {
-                            ZooKeeper zkClient = client.getZooKeeper();
-                            if(watcher == null)
+                            try
                             {
-                                zkClient.removeAllWatches(path, watcherType, local);    
+                                ZooKeeper zkClient = client.getZookeeperClient().getZooKeeper();    
+                                
+                                if(watcher == null)
+                                {
+                                    zkClient.removeAllWatches(path, watcherType, local);    
+                                }
+                                else
+                                {
+                                    zkClient.removeWatches(path, watcher, watcherType, local);
+                                }
                             }
-                            else
+                            catch(KeeperException.NoWatcherException e)
                             {
-                                zkClient.removeWatches(path, watcher, watcherType, local);
+                                //Swallow this exception if the quietly flag is set, otherwise rethrow.
+                                if(!quietly)
+                                {
+                                    throw e;
+                                }
                             }
-                        }
-                        catch(KeeperException.NoWatcherException e)
-                        {
-                            //Swallow this exception if the quietly flag is set, otherwise rethrow.
-                            if(!quietly)
-                            {
-                                throw e;
-                            }
-                        }
                      
-                        return null;
-                    }
-                });
+                            return null;
+                        }
+            });
+        }
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/curator/blob/04caf36c/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 414c819..0912c70 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -20,6 +20,8 @@ import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.Watcher.Event.EventType;
 import org.apache.zookeeper.Watcher.WatcherType;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -302,10 +304,6 @@ public class TestRemoveWatches extends BaseClassForTests
         }
     }     
     
-    /**
-     * TODO: THIS IS STILL A WORK IN PROGRESS. local() is currently broken if no connection to ZK is available.
-     * @throws Exception
-     */
     @Test
     public void testRemoveLocalWatch() throws Exception {
         Timing timing = new Timing();
@@ -329,7 +327,7 @@ public class TestRemoveWatches extends BaseClassForTests
             server.stop();
             
             timing.sleepABit();
-            
+                       
             client.watches().removeAll().locally().forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
@@ -340,6 +338,40 @@ public class TestRemoveWatches extends BaseClassForTests
         }
     }
     
+    @Test
+    public void testRemoveLocalWatchInBackground() throws Exception {
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final String path = "/";
+            
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            Watcher watcher = new CountDownWatcher(path, removedLatch, EventType.DataWatchRemoved);        
+            
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            //Stop the server so we can check if we can remove watches locally when offline
+            server.stop();
+            
+            timing.sleepABit();
+                       
+            client.watches().removeAll().locally().inBackground().forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
     /**
      * Test the case where we try and remove an unregistered watcher. In this case we expect a NoWatcherException to
      * be thrown. 


[26/31] curator git commit: Merge branch 'CURATOR-161' into CURATOR-217

Posted by dr...@apache.org.
Merge branch 'CURATOR-161' into CURATOR-217

Conflicts:
	curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/eba6ce8f
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/eba6ce8f
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/eba6ce8f

Branch: refs/heads/CURATOR-3.0
Commit: eba6ce8f9ae772d0a30ced495b1b9130dec0ad40
Parents: ff2ed84 6612c91
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 19:42:23 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 19:42:23 2015 -0700

----------------------------------------------------------------------
 .../api/BackgroundPathableQuietlyable.java      |  5 +++
 .../curator/framework/api/DeleteBuilder.java    |  2 +-
 .../curator/framework/api/Guaranteeable.java    |  2 +-
 .../framework/api/GuaranteeableDeletable.java   | 39 ++++++++++++++++++++
 .../framework/api/GuaranteeableDelete.java      | 39 --------------------
 .../framework/api/RemoveWatchesLocal.java       |  4 +-
 .../framework/api/RemoveWatchesType.java        |  2 +-
 .../framework/imps/FailedOperationManager.java  |  3 ++
 .../imps/FailedRemoveWatchManager.java          |  2 +-
 .../framework/imps/NamespaceWatcherMap.java     |  8 ----
 .../imps/RemoveWatchesBuilderImpl.java          |  4 +-
 11 files changed, 55 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/eba6ce8f/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/eba6ce8f/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/eba6ce8f/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------


[20/31] curator git commit: Merge branch 'CURATOR-161' into CURATOR-217

Posted by dr...@apache.org.
Merge branch 'CURATOR-161' into CURATOR-217


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/fb274b1c
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/fb274b1c
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/fb274b1c

Branch: refs/heads/CURATOR-3.0
Commit: fb274b1c8d56eeae97c50966ba69e6b98fd71274
Parents: 43afca7 a47c036
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 17:52:58 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 17:52:58 2015 -0700

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |   4 +
 .../curator/framework/api/DeleteBuilder.java    |   2 +-
 .../curator/framework/api/Guaranteeable.java    |  20 +-
 .../framework/api/GuaranteeableDelete.java      |  39 ++
 .../framework/api/RemoveWatchesLocal.java       |   4 +-
 .../framework/api/RemoveWatchesType.java        |   2 +-
 .../framework/imps/CuratorFrameworkImpl.java    |  10 +-
 .../framework/imps/DeleteBuilderImpl.java       |   4 +-
 .../framework/imps/FailedDeleteManager.java     |  39 +-
 .../framework/imps/FailedOperationManager.java  |  65 +++
 .../imps/FailedRemoveWatchManager.java          |  56 +++
 .../framework/imps/NamespaceWatcherMap.java     |   8 +
 .../framework/imps/OperationAndData.java        |  16 +-
 .../imps/RemoveWatchesBuilderImpl.java          | 126 ++++--
 .../framework/imps/TestFailedDeleteManager.java |   9 +-
 .../framework/imps/TestRemoveWatches.java       | 407 +++++++++++++++----
 16 files changed, 635 insertions(+), 176 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/fb274b1c/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/fb274b1c/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/fb274b1c/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/fb274b1c/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/fb274b1c/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 10d58d0,932706b..4b1b029
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@@ -169,44 -164,87 +190,87 @@@ public class RemoveWatchesBuilderImpl i
          return null;
      }    
      
-     private void pathInBackground(String path)
+     private void pathInBackground(final String path)
      {
-         OperationAndData.ErrorCallback<String>  errorCallback = null;        
-         client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(), errorCallback, backgrounding.getContext()), null);
+         OperationAndData.ErrorCallback<String>  errorCallback = null;
+         
+         //Only need an error callback if we're in guaranteed mode
+         if(guaranteed)
+         {
+             errorCallback = new OperationAndData.ErrorCallback<String>()
+             {
+                 @Override
+                 public void retriesExhausted(OperationAndData<String> operationAndData)
+                 {
+                     client.getFailedRemoveWatcherManager().addFailedOperation(new FailedRemoveWatchManager.FailedRemoveWatchDetails(path, watcher));
+                 }            
+             };
+         }
+         
+         client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(),
+                                                                        errorCallback, backgrounding.getContext(), !local), null);
      }
      
 -    private void pathInForeground(final String path) throws Exception
 +    void pathInForeground(final String path) throws Exception
      {
-         RetryLoop.callWithRetry(client.getZookeeperClient(), 
-                 new Callable<Void>()
-                 {
-                     @Override
-                     public Void call() throws Exception
+         //For the local case we don't want to use the normal retry loop and we don't want to block until a connection is available.
+         //We just execute the removeWatch, and if it fails, ZK will just remove local watches.
+         if(local)
+         {
+             ZooKeeper zkClient = client.getZooKeeper();
+             if(watcher == null)
+             {
+                 zkClient.removeAllWatches(path, watcherType, local);    
+             }
+             else
+             {
+                 zkClient.removeWatches(path, watcher, watcherType, local);
+             }
+         }
+         else
+         {
+             RetryLoop.callWithRetry(client.getZookeeperClient(), 
+                     new Callable<Void>()
                      {
-                         try
+                         @Override
+                         public Void call() throws Exception
                          {
-                             ZooKeeper zkClient = client.getZooKeeper();
-                             if(watcher == null)
-                             {
-                                 zkClient.removeAllWatches(path, watcherType, local);    
-                             }
-                             else
+                             try
                              {
-                                 zkClient.removeWatches(path, watcher, watcherType, local);
+                                 ZooKeeper zkClient = client.getZookeeperClient().getZooKeeper();    
+                                 
+                                 if(watcher == null)
+                                 {
+                                     zkClient.removeAllWatches(path, watcherType, local);    
+                                 }
+                                 else
+                                 {
+                                     zkClient.removeWatches(path, watcher, watcherType, local);
+                                 }
                              }
-                         }
-                         catch(KeeperException.NoWatcherException e)
-                         {
-                             //Swallow this exception if the quietly flag is set, otherwise rethrow.
-                             if(!quietly)
+                             catch(Exception e)
                              {
-                                 throw e;
+                                 if( RetryLoop.isRetryException(e) && guaranteed )
+                                 {
+                                     //Setup the guaranteed handler
+                                     client.getFailedRemoveWatcherManager().addFailedOperation(new FailedRemoveWatchManager.FailedRemoveWatchDetails(path, watcher));
+                                     throw e;
+                                 }
+                                 else if(e instanceof KeeperException.NoWatcherException && quietly)
+                                 {
+                                     //Ignore
+                                 }
+                                 else
+                                 {
+                                     //Rethrow
+                                     throw e;
+                                 }
                              }
-                         }
                       
-                         return null;
-                     }
-                 });
+                             return null;
+                         }
+             });
+         }
      }
      
      @Override

http://git-wip-us.apache.org/repos/asf/curator/blob/fb274b1c/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------


[15/31] curator git commit: CURATOR-161 - Added support for guaranteed removal of watches. This includes refactoring the FailedDeleteManager code into a FailedOperationManager to allow subclassing.

Posted by dr...@apache.org.
CURATOR-161 - Added support for guaranteed removal of watches. This
includes refactoring the FailedDeleteManager code into a
FailedOperationManager to allow subclassing.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/22d034af
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/22d034af
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/22d034af

Branch: refs/heads/CURATOR-3.0
Commit: 22d034af90987940420649c5f320e8dc09910c8a
Parents: 04caf36
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Wed May 13 09:28:45 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Wed May 13 09:28:45 2015 +1000

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |   4 +
 .../curator/framework/api/DeleteBuilder.java    |   2 +-
 .../curator/framework/api/Guaranteeable.java    |  20 +--
 .../framework/api/GuaranteeableDelete.java      |  39 ++++++
 .../framework/api/RemoveWatchesType.java        |   2 +-
 .../framework/imps/CuratorFrameworkImpl.java    |   8 ++
 .../framework/imps/DeleteBuilderImpl.java       |   4 +-
 .../framework/imps/FailedDeleteManager.java     |  39 +-----
 .../framework/imps/FailedOperationManager.java  |  65 ++++++++++
 .../imps/FailedRemoveWatchManager.java          |  56 ++++++++
 .../framework/imps/NamespaceWatcherMap.java     |   8 ++
 .../imps/RemoveWatchesBuilderImpl.java          |  56 ++++++--
 .../framework/imps/TestFailedDeleteManager.java |   9 +-
 .../framework/imps/TestRemoveWatches.java       | 129 +++++++++++++++++++
 14 files changed, 377 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 4b30fd4..2bce552 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -216,7 +216,11 @@ public interface CuratorFramework extends Closeable
      * Call this method on watchers you are no longer interested in.
      *
      * @param watcher the watcher
+     * 
+     * @deprecated As of ZooKeeper 3.5 Curators recipes will handle removing watcher references
+     * when they are no longer used.
      */
+    @Deprecated
     public void clearWatcherReferences(Watcher watcher);
         
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
index 3a3faf7..893e825 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/DeleteBuilder.java
@@ -18,6 +18,6 @@
  */
 package org.apache.curator.framework.api;
 
-public interface DeleteBuilder extends Guaranteeable, ChildrenDeletable
+public interface DeleteBuilder extends GuaranteeableDelete, ChildrenDeletable
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
index 481911b..b43d6b0 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Guaranteeable.java
@@ -18,23 +18,15 @@
  */
 package org.apache.curator.framework.api;
 
-public interface Guaranteeable extends BackgroundVersionable
+public interface Guaranteeable<T>
 {
     /**
-     * <p>
-     *     Solves this edge case: deleting a node can fail due to connection issues. Further,
-     *     if the node was ephemeral, the node will not get auto-deleted as the session is still valid.
-     *     This can wreak havoc with lock implementations.
-     * </p>
-     *
-     * <p>
-     *     When <code>guaranteed</code> is set, Curator will record failed node deletions and
-     *     attempt to delete them in the background until successful. NOTE: you will still get an
-     *     exception when the deletion fails. But, you can be assured that as long as the
-     *     {@link org.apache.curator.framework.CuratorFramework} instance is open attempts will be made to delete the node.
-     * </p>
+     * Solves edge cases where an operation may succeed on the server but connection failure occurs before a
+     * response can be successfully returned to the client.
+     * 
+     * @see org.apache.curator.framework.api.GuaranteeableDelete 
      *  
      * @return this
      */
-    public ChildrenDeletable guaranteed();
+    public T guaranteed();
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java b/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java
new file mode 100644
index 0000000..d04e7ea
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/GuaranteeableDelete.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.api;
+
+/**
+ * <p>
+ *     Solves this edge case: deleting a node can fail due to connection issues. Further,
+ *     if the node was ephemeral, the node will not get auto-deleted as the session is still valid.
+ *     This can wreak havoc with lock implementations.
+ * </p>
+ *
+ * <p>
+ *     When <code>guaranteed</code> is set, Curator will record failed node deletions and
+ *     attempt to delete them in the background until successful. NOTE: you will still get an
+ *     exception when the deletion fails. But, you can be assured that as long as the
+ *     {@link org.apache.curator.framework.CuratorFramework} instance is open attempts will be made to delete the node.
+ * </p>
+ *  
+ * @return this
+ */
+public interface GuaranteeableDelete extends Guaranteeable<ChildrenDeletable>, BackgroundVersionable
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
index 1123afd..3112eac 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
@@ -6,7 +6,7 @@ import org.apache.zookeeper.Watcher.WatcherType;
  * Builder to allow the specification of whether it is acceptable to remove client side watch information
  * in the case where ZK cannot be contacted. 
  */
-public interface RemoveWatchesType extends RemoveWatchesLocal
+public interface RemoveWatchesType extends RemoveWatchesLocal, Guaranteeable<BackgroundPathableQuietly<Void>>
 {
    
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index 5caff7d..b4a1d93 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -72,6 +72,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
     private final AtomicReference<AuthInfo> authInfo = new AtomicReference<AuthInfo>();
     private final byte[] defaultData;
     private final FailedDeleteManager failedDeleteManager;
+    private final FailedRemoveWatchManager failedRemoveWatcherManager;
     private final CompressionProvider compressionProvider;
     private final ACLProvider aclProvider;
     private final NamespaceFacadeCache namespaceFacadeCache;
@@ -147,6 +148,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
         }
 
         failedDeleteManager = new FailedDeleteManager(this);
+        failedRemoveWatcherManager = new FailedRemoveWatchManager(this);
         namespaceFacadeCache = new NamespaceFacadeCache(this);
     }
 
@@ -190,6 +192,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
         connectionStateManager = parent.connectionStateManager;
         defaultData = parent.defaultData;
         failedDeleteManager = parent.failedDeleteManager;
+        failedRemoveWatcherManager = parent.failedRemoveWatcherManager;
         compressionProvider = parent.compressionProvider;
         aclProvider = parent.aclProvider;
         namespaceFacadeCache = parent.namespaceFacadeCache;
@@ -487,6 +490,11 @@ public class CuratorFrameworkImpl implements CuratorFramework
     {
         return failedDeleteManager;
     }
+    
+    FailedRemoveWatchManager getFailedRemoveWatcherManager()
+    {
+        return failedRemoveWatcherManager;
+    }    
 
     RetryLoop newRetryLoop()
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
index 5d8b846..51691dd 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
@@ -203,7 +203,7 @@ class DeleteBuilderImpl implements DeleteBuilder, BackgroundOperation<String>
                     @Override
                     public void retriesExhausted(OperationAndData<String> operationAndData)
                     {
-                        client.getFailedDeleteManager().addFailedDelete(unfixedPath);
+                        client.getFailedDeleteManager().addFailedOperation(unfixedPath);
                     }
                 };
             }
@@ -253,7 +253,7 @@ class DeleteBuilderImpl implements DeleteBuilder, BackgroundOperation<String>
             //Only retry a guaranteed delete if it's a retryable error
             if( RetryLoop.isRetryException(e) && guaranteed )
             {
-                client.getFailedDeleteManager().addFailedDelete(unfixedPath);
+                client.getFailedDeleteManager().addFailedOperation(unfixedPath);
             }
             throw e;
         }

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedDeleteManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedDeleteManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedDeleteManager.java
index deb7f40..934ae40 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedDeleteManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedDeleteManager.java
@@ -19,45 +19,18 @@
 package org.apache.curator.framework.imps;
 
 import org.apache.curator.framework.CuratorFramework;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-class FailedDeleteManager
+class FailedDeleteManager extends FailedOperationManager<String>
 {
-    private final Logger log = LoggerFactory.getLogger(getClass());
-    private final CuratorFramework client;
-    
-    volatile FailedDeleteManagerListener debugListener = null;
-    
-    interface FailedDeleteManagerListener
-    {
-       public void pathAddedForDelete(String path);
-    }
-
     FailedDeleteManager(CuratorFramework client)
     {
-        this.client = client;
+        super(client);
     }
 
-    void addFailedDelete(String path)
+    @Override
+    protected void executeGuaranteedOperationInBackground(String path)
+            throws Exception
     {
-        if ( debugListener != null )
-        {
-            debugListener.pathAddedForDelete(path);
-        }
-        
-        
-        if ( client.getState() == CuratorFrameworkState.STARTED )
-        {
-            log.debug("Path being added to guaranteed delete set: " + path);
-            try
-            {
-                client.delete().guaranteed().inBackground().forPath(path);
-            }
-            catch ( Exception e )
-            {
-                addFailedDelete(path);
-            }
-        }
+        client.delete().guaranteed().inBackground().forPath(path);
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
new file mode 100644
index 0000000..a1efde2
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedOperationManager.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.imps;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class FailedOperationManager<T>
+{
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    protected final CuratorFramework client;
+    
+    volatile FailedOperationManagerListener<T> debugListener = null;
+    
+    interface FailedOperationManagerListener<T>
+    {
+       public void pathAddedForGuaranteedOperation(T detail);
+    }
+
+    FailedOperationManager(CuratorFramework client)
+    {
+        this.client = client;
+    }
+
+    void addFailedOperation(T details)
+    {
+        if ( debugListener != null )
+        {
+            debugListener.pathAddedForGuaranteedOperation(details);
+        }
+        
+        
+        if ( client.getState() == CuratorFrameworkState.STARTED )
+        {
+            log.debug("Details being added to guaranteed operation set: " + details);
+            try
+            {
+                executeGuaranteedOperationInBackground(details);
+            }
+            catch ( Exception e )
+            {
+                addFailedOperation(details);
+            }
+        }
+    }
+    
+    protected abstract void executeGuaranteedOperationInBackground(T details) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
new file mode 100644
index 0000000..f954e2a
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/FailedRemoveWatchManager.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.imps;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.zookeeper.Watcher;
+
+class FailedRemoveWatchManager extends FailedOperationManager<FailedRemoveWatchManager.FailedRemoveWatchDetails>
+{
+    FailedRemoveWatchManager(CuratorFramework client)
+    {
+        super(client);
+    }
+
+    @Override
+    protected void executeGuaranteedOperationInBackground(FailedRemoveWatchDetails details)
+            throws Exception
+    {
+        if(details.watcher ==  null)
+        {
+            client.watches().removeAll().guaranteed().inBackground().forPath(details.path);
+        }
+        else
+        {
+            client.watches().remove(details.watcher).guaranteed().inBackground().forPath(details.path);
+        }
+    }
+    
+    static class FailedRemoveWatchDetails
+    {
+        public final String path;
+        public final Watcher watcher;
+        
+        public FailedRemoveWatchDetails(String path, Watcher watcher)
+        {
+            this.path = path;
+            this.watcher = watcher;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
index e5aecb2..f656ba1 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceWatcherMap.java
@@ -70,6 +70,14 @@ class NamespaceWatcherMap implements Closeable
     {
         return map.remove(key);
     }
+    
+    /**
+     * Remove all watchers for a given path
+     * @param path
+     */
+    void removeAllForPath(String path) {
+        
+    }
 
     @VisibleForTesting
     boolean isEmpty()

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index c9868f4..27d05da 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -27,8 +27,9 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     private CuratorFrameworkImpl client;
     private Watcher watcher;
     private WatcherType watcherType;
+    private boolean guaranteed;
     private boolean local;
-    private boolean quietly;
+    private boolean quietly;    
     private Backgrounding backgrounding;
     
     public RemoveWatchesBuilderImpl(CuratorFrameworkImpl client)
@@ -36,6 +37,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         this.client = client;
         this.watcher = null;
         this.watcherType = WatcherType.Any;
+        this.guaranteed = false;
         this.local = false;
         this.quietly = false;
         this.backgrounding = new Backgrounding();
@@ -44,14 +46,26 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     @Override
     public RemoveWatchesType remove(Watcher watcher)
     {
-        this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().getNamespaceWatcher(watcher);
+        if(watcher == null) {
+            this.watcher = null;
+        } else {
+            //Try and get the namespaced version of the watcher.
+            this.watcher = client.getNamespaceWatcherMap().get(watcher);
+            
+            //If this is not present then default to the original watcher. This shouldn't happen in practice unless the user
+            //has added a watch directly to the ZK client rather than via the CuratorFramework.
+            if(this.watcher == null) {
+                this.watcher = watcher;
+            }
+        }
+
         return this;
     }
     
     @Override
     public RemoveWatchesType remove(CuratorWatcher watcher)
     {
-        this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().getNamespaceWatcher(watcher);
+        this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().get(watcher);
         return this;
     }    
 
@@ -111,6 +125,13 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         backgrounding = new Backgrounding(context);
         return this;
     }
+    
+    @Override
+    public RemoveWatchesLocal guaranteed()
+    {
+        guaranteed = true;
+        return this;
+    }    
 
     @Override
     public BackgroundPathableQuietly<Void> locally()
@@ -143,14 +164,23 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         return null;
     }    
     
-    private void pathInBackground(String path)
+    private void pathInBackground(final String path)
     {
-        OperationAndData.ErrorCallback<String>  errorCallback = null;        
+        OperationAndData.ErrorCallback<String>  errorCallback = new OperationAndData.ErrorCallback<String>()
+        {
+            @Override
+            public void retriesExhausted(OperationAndData<String> operationAndData)
+            {
+                client.getFailedRemoveWatcherManager().addFailedOperation(new FailedRemoveWatchManager.FailedRemoveWatchDetails(path, watcher));
+            }            
+        };        
         client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(), errorCallback, backgrounding.getContext()), null);
     }
     
     private void pathInForeground(final String path) throws Exception
     {
+        //For the local case we don't want to use the normal retry loop and we don't want to block until a connection is available.
+        //We just execute the removeWatch, and if it fails, ZK will just remove local watches.
         if(local)
         {
             ZooKeeper zkClient = client.getZooKeeper();
@@ -184,11 +214,21 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
                                     zkClient.removeWatches(path, watcher, watcherType, local);
                                 }
                             }
-                            catch(KeeperException.NoWatcherException e)
+                            catch(Exception e)
                             {
-                                //Swallow this exception if the quietly flag is set, otherwise rethrow.
-                                if(!quietly)
+                                if( RetryLoop.isRetryException(e) && guaranteed )
+                                {
+                                    //Setup the guaranteed handler
+                                    client.getFailedRemoveWatcherManager().addFailedOperation(new FailedRemoveWatchManager.FailedRemoveWatchDetails(path, watcher));
+                                    throw e;
+                                }
+                                else if(e instanceof KeeperException.NoWatcherException && quietly)
+                                {
+                                    //Ignore
+                                }
+                                else
                                 {
+                                    //Rethrow
                                     throw e;
                                 }
                             }

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFailedDeleteManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFailedDeleteManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFailedDeleteManager.java
index 6599745..943529f 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFailedDeleteManager.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFailedDeleteManager.java
@@ -22,7 +22,6 @@ import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
-import org.apache.curator.framework.imps.FailedDeleteManager.FailedDeleteManagerListener;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.retry.ExponentialBackoffRetry;
@@ -291,11 +290,11 @@ public class TestFailedDeleteManager extends BaseClassForTests
         
         final AtomicBoolean pathAdded = new AtomicBoolean(false);
         
-        ((CuratorFrameworkImpl)client).getFailedDeleteManager().debugListener = new FailedDeleteManagerListener()
+        ((CuratorFrameworkImpl)client).getFailedDeleteManager().debugListener = new FailedOperationManager.FailedOperationManagerListener<String>()
         {
             
             @Override
-            public void pathAddedForDelete(String path)
+            public void pathAddedForGuaranteedOperation(String path)
             {
                 pathAdded.set(true);
             }
@@ -325,11 +324,11 @@ public class TestFailedDeleteManager extends BaseClassForTests
         
         final AtomicBoolean pathAdded = new AtomicBoolean(false);
         
-        ((CuratorFrameworkImpl)client).getFailedDeleteManager().debugListener = new FailedDeleteManagerListener()
+        ((CuratorFrameworkImpl)client).getFailedDeleteManager().debugListener = new FailedOperationManager.FailedOperationManagerListener<String>()
         {
             
             @Override
-            public void pathAddedForDelete(String path)
+            public void pathAddedForGuaranteedOperation(String path)
             {
                 pathAdded.set(true);
             }

http://git-wip-us.apache.org/repos/asf/curator/blob/22d034af/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 0912c70..518f13b 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -11,6 +11,10 @@ import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.CuratorListener;
 import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.framework.imps.FailedRemoveWatchManager.FailedRemoveWatchDetails;
+import org.apache.curator.framework.state.ConnectionState;
+import org.apache.curator.framework.state.ConnectionStateListener;
+import org.apache.curator.retry.ExponentialBackoffRetry;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.Timing;
@@ -438,6 +442,131 @@ public class TestRemoveWatches extends BaseClassForTests
         }
     }
     
+    @Test
+    public void testGuaranteedRemoveWatch() throws Exception {
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+            final CountDownLatch suspendedLatch = new CountDownLatch(1);
+            client.getConnectionStateListenable().addListener(new ConnectionStateListener()
+            {
+                @Override
+                public void stateChanged(CuratorFramework client, ConnectionState newState)
+                {
+                    if(newState == ConnectionState.SUSPENDED)
+                    {
+                        suspendedLatch.countDown();
+                    }
+                    else if(newState == ConnectionState.RECONNECTED)
+                    {
+                        reconnectedLatch.countDown();
+                    }
+                }
+            });
+            
+            String path = "/";
+            
+            CountDownLatch removeLatch = new CountDownLatch(1);
+            
+            Watcher watcher = new CountDownWatcher(path, removeLatch, EventType.DataWatchRemoved);            
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            server.stop();           
+            timing.awaitLatch(suspendedLatch);
+            
+            //Remove the watch while we're not connected
+            try 
+            {
+                client.watches().remove(watcher).guaranteed().forPath(path);
+                Assert.fail();
+            }
+            catch(KeeperException.ConnectionLossException e)
+            {
+                //Expected
+            }
+            
+            server.restart();
+            
+            timing.awaitLatch(removeLatch);            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    @Test
+    public void testGuaranteedRemoveWatchInBackground() throws Exception {
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(),
+                                                                    new ExponentialBackoffRetry(100, 3));
+        try
+        {
+            client.start();
+            
+            final CountDownLatch reconnectedLatch = new CountDownLatch(1);
+            final CountDownLatch suspendedLatch = new CountDownLatch(1);
+            client.getConnectionStateListenable().addListener(new ConnectionStateListener()
+            {
+                @Override
+                public void stateChanged(CuratorFramework client, ConnectionState newState)
+                {
+                    if(newState == ConnectionState.SUSPENDED)
+                    {
+                        suspendedLatch.countDown();
+                    }
+                    else if(newState == ConnectionState.RECONNECTED)
+                    {
+                        reconnectedLatch.countDown();
+                    }
+                }
+            });
+            
+            final CountDownLatch guaranteeAddedLatch = new CountDownLatch(1);
+            
+            ((CuratorFrameworkImpl)client).getFailedRemoveWatcherManager().debugListener = new FailedOperationManager.FailedOperationManagerListener<FailedRemoveWatchManager.FailedRemoveWatchDetails>()
+            {
+
+                @Override
+                public void pathAddedForGuaranteedOperation(
+                        FailedRemoveWatchDetails detail)
+                {
+                    guaranteeAddedLatch.countDown();
+                }
+            };
+            
+            String path = "/";
+            
+            CountDownLatch removeLatch = new CountDownLatch(1);
+            
+            Watcher watcher = new CountDownWatcher(path, removeLatch, EventType.DataWatchRemoved);            
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            server.stop();           
+            timing.awaitLatch(suspendedLatch);
+            
+            //Remove the watch while we're not connected
+            client.watches().remove(watcher).guaranteed().inBackground().forPath(path);
+            
+            timing.awaitLatch(guaranteeAddedLatch);
+            
+            server.restart();
+            
+            timing.awaitLatch(removeLatch);            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
     private static class CountDownWatcher implements Watcher {
         private String path;
         private EventType eventType;


[28/31] curator git commit: More uses of WatcherRemoveCuratorFramework, more tests, etc.

Posted by dr...@apache.org.
More uses of WatcherRemoveCuratorFramework, more tests, etc.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/2c921d62
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/2c921d62
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/2c921d62

Branch: refs/heads/CURATOR-3.0
Commit: 2c921d62fc2894f136d088d93870ac8c9b026dcb
Parents: a95d52e
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 20:33:40 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 20:33:40 2015 -0700

----------------------------------------------------------------------
 .../org/apache/curator/utils/DebugUtils.java    |  1 +
 .../imps/RemoveWatchesBuilderImpl.java          | 16 +++++++++---
 .../framework/imps/WatcherRemovalManager.java   |  3 +--
 .../recipes/nodes/PersistentEphemeralNode.java  |  3 ++-
 .../framework/recipes/shared/SharedValue.java   |  2 +-
 .../curator/framework/imps/TestCleanState.java  | 11 +++------
 .../recipes/leader/TestLeaderLatch.java         | 26 ++++++++++----------
 .../nodes/TestPersistentEphemeralNode.java      | 17 +++++++------
 .../recipes/shared/TestSharedCount.java         | 11 +++++----
 .../apache/curator/test/BaseClassForTests.java  | 14 +++++++++++
 10 files changed, 64 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java b/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
index ce751ec..e84e06b 100644
--- a/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
+++ b/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
@@ -23,6 +23,7 @@ public class DebugUtils
     public static final String          PROPERTY_LOG_EVENTS = "curator-log-events";
     public static final String          PROPERTY_DONT_LOG_CONNECTION_ISSUES = "curator-dont-log-connection-problems";
     public static final String          PROPERTY_LOG_ONLY_FIRST_CONNECTION_ISSUE_AS_ERROR_LEVEL = "curator-log-only-first-connection-issue-as-error-level";
+    public static final String          PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND = "curator-remove-watchers-in-foreground";
 
     private DebugUtils()
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 8f61878..d872ced 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -33,6 +33,7 @@ import org.apache.curator.framework.api.Pathable;
 import org.apache.curator.framework.api.RemoveWatchesLocal;
 import org.apache.curator.framework.api.RemoveWatchesBuilder;
 import org.apache.curator.framework.api.RemoveWatchesType;
+import org.apache.curator.utils.DebugUtils;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Watcher;
@@ -61,13 +62,22 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         this.backgrounding = new Backgrounding();
     }
 
-    void prepInternalRemoval(Watcher watcher)
+    void internalRemoval(Watcher watcher, String path) throws Exception
     {
         this.watcher = watcher;
         watcherType = WatcherType.Any;
         quietly = true;
-        this.backgrounding = new Backgrounding(true);
         guaranteed = true;
+        if ( Boolean.getBoolean(DebugUtils.PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND) )
+        {
+            this.backgrounding = new Backgrounding();
+            pathInForeground(path);
+        }
+        else
+        {
+            this.backgrounding = new Backgrounding(true);
+            pathInBackground(path);
+        }
     }
 
     @Override
@@ -191,7 +201,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         return null;
     }    
     
-    void pathInBackground(final String path)
+    private void pathInBackground(final String path)
     {
         OperationAndData.ErrorCallback<String>  errorCallback = null;
         

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
index 72430ee..a691a94 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
@@ -68,8 +68,7 @@ public class WatcherRemovalManager
             {
                 log.debug("Removing watcher for path: " + entry.path);
                 RemoveWatchesBuilderImpl builder = new RemoveWatchesBuilderImpl(client);
-                builder.prepInternalRemoval(entry);
-                builder.pathInBackground(entry.path);
+                builder.internalRemoval(entry, entry.path);
             }
             catch ( Exception e )
             {

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
index 3bad8e3..98b09c9 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
@@ -269,7 +269,6 @@ public class PersistentEphemeralNode implements Closeable
             return;
         }
 
-        client.removeWatchers();
         client.getConnectionStateListenable().removeListener(connectionStateListener);
 
         try
@@ -280,6 +279,8 @@ public class PersistentEphemeralNode implements Closeable
         {
             throw new IOException(e);
         }
+
+        client.removeWatchers();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
index 7e7ad56..e6d8157 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
@@ -234,9 +234,9 @@ public class SharedValue implements Closeable, SharedValueReader
     @Override
     public void close() throws IOException
     {
+        state.set(State.CLOSED);
         client.removeWatchers();
         client.getConnectionStateListenable().removeListener(connectionStateListener);
-        state.set(State.CLOSED);
         listeners.clear();
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java b/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
index 8ca8409..82de1fc 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
@@ -35,25 +35,20 @@ public class TestCleanState
         try
         {
             CuratorFrameworkImpl internalClient = (CuratorFrameworkImpl)client;
-            if ( !internalClient.getNamespaceWatcherMap().isEmpty() )
-            {
-                throw new AssertionError("NamespaceWatcherMap is not empty");
-            }
-
             ZooKeeper zooKeeper = internalClient.getZooKeeper();
             if ( zooKeeper != null )
             {
                 if ( WatchersDebug.getChildWatches(zooKeeper).size() != 0 )
                 {
-                    throw new AssertionError("One or more child watchers are still registered");
+                    throw new AssertionError("One or more child watchers are still registered: " + WatchersDebug.getChildWatches(zooKeeper));
                 }
                 if ( WatchersDebug.getExistWatches(zooKeeper).size() != 0 )
                 {
-                    throw new AssertionError("One or more exists watchers are still registered");
+                    throw new AssertionError("One or more exists watchers are still registered: " + WatchersDebug.getExistWatches(zooKeeper));
                 }
                 if ( WatchersDebug.getDataWatches(zooKeeper).size() != 0 )
                 {
-                    throw new AssertionError("One or more data watchers are still registered");
+                    throw new AssertionError("One or more data watchers are still registered: " + WatchersDebug.getDataWatches(zooKeeper));
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/TestLeaderLatch.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/TestLeaderLatch.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/TestLeaderLatch.java
index 96e6d45..3742fb7 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/TestLeaderLatch.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/TestLeaderLatch.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.retry.RetryNTimes;
@@ -96,7 +97,7 @@ public class TestLeaderLatch extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(latch);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -126,7 +127,7 @@ public class TestLeaderLatch extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(latch);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -158,7 +159,7 @@ public class TestLeaderLatch extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -213,7 +214,7 @@ public class TestLeaderLatch extends BaseClassForTests
             {
                 CloseableUtils.closeQuietly(latch);
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -256,9 +257,8 @@ public class TestLeaderLatch extends BaseClassForTests
             {
                 CloseableUtils.closeQuietly(latch);
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
-
     }
 
     @Test
@@ -320,7 +320,7 @@ public class TestLeaderLatch extends BaseClassForTests
         finally
         {
             executorService.shutdownNow();
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -416,7 +416,7 @@ public class TestLeaderLatch extends BaseClassForTests
                     CloseableUtils.closeQuietly(latch);
                 }
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -504,7 +504,7 @@ public class TestLeaderLatch extends BaseClassForTests
                     CloseableUtils.closeQuietly(latch);
                 }
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -583,7 +583,7 @@ public class TestLeaderLatch extends BaseClassForTests
             {
                 CloseableUtils.closeQuietly(notifiedLeader);
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -639,7 +639,7 @@ public class TestLeaderLatch extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(leader);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
             CloseableUtils.closeQuietly(server);
         }
     }
@@ -709,7 +709,7 @@ public class TestLeaderLatch extends BaseClassForTests
             {
                 CloseableUtils.closeQuietly(latch);
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -745,6 +745,6 @@ public class TestLeaderLatch extends BaseClassForTests
     {
         Timing timing = new Timing();
         CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
-        LeaderLatch latch = new LeaderLatch(client, "parent");
+        new LeaderLatch(client, "parent");
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
index 47ae757..5a58b2a 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
@@ -22,6 +22,7 @@ import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.retry.RetryOneTime;
@@ -36,6 +37,7 @@ import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.data.Stat;
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
 import org.testng.annotations.Test;
 import java.io.IOException;
 import java.util.Arrays;
@@ -57,6 +59,7 @@ public class TestPersistentEphemeralNode extends BaseClassForTests
     private final Timing timing = new Timing();
 
     @AfterMethod
+    @Override
     public void teardown() throws Exception
     {
         for ( PersistentEphemeralNode node : createdNodes )
@@ -66,10 +69,8 @@ public class TestPersistentEphemeralNode extends BaseClassForTests
 
         for ( CuratorFramework curator : curatorInstances )
         {
-            curator.close();
+            TestCleanState.closeAndTestClean(curator);
         }
-
-        super.teardown();
     }
 
     @Test
@@ -115,7 +116,7 @@ public class TestPersistentEphemeralNode extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -125,10 +126,11 @@ public class TestPersistentEphemeralNode extends BaseClassForTests
         server.close();
 
         CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
+        PersistentEphemeralNode node = null;
         try
         {
             client.start();
-            PersistentEphemeralNode node = new PersistentEphemeralNode(client, PersistentEphemeralNode.Mode.EPHEMERAL, "/abc/node", "hello".getBytes());
+            node = new PersistentEphemeralNode(client, PersistentEphemeralNode.Mode.EPHEMERAL, "/abc/node", "hello".getBytes());
             node.start();
 
             final CountDownLatch connectedLatch = new CountDownLatch(1);
@@ -157,7 +159,8 @@ public class TestPersistentEphemeralNode extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            CloseableUtils.closeQuietly(node);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -240,7 +243,7 @@ public class TestPersistentEphemeralNode extends BaseClassForTests
             {
                 node.close();
             }
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-recipes/src/test/java/org/apache/curator/framework/recipes/shared/TestSharedCount.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/shared/TestSharedCount.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/shared/TestSharedCount.java
index 659154a..2bdd278 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/shared/TestSharedCount.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/shared/TestSharedCount.java
@@ -23,6 +23,7 @@ import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.BaseClassForTests;
@@ -147,7 +148,7 @@ public class TestSharedCount extends BaseClassForTests
             }
             for ( CuratorFramework client : clients )
             {
-                CloseableUtils.closeQuietly(client);
+                TestCleanState.closeAndTestClean(client);
             }
         }
     }
@@ -170,7 +171,7 @@ public class TestSharedCount extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(count);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -215,7 +216,7 @@ public class TestSharedCount extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(count);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -252,8 +253,8 @@ public class TestSharedCount extends BaseClassForTests
         {
             CloseableUtils.closeQuietly(count2);
             CloseableUtils.closeQuietly(count1);
-            CloseableUtils.closeQuietly(client2);
-            CloseableUtils.closeQuietly(client1);
+            TestCleanState.closeAndTestClean(client2);
+            TestCleanState.closeAndTestClean(client1);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/2c921d62/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
----------------------------------------------------------------------
diff --git a/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java b/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
index d676a9b..d5c434f 100644
--- a/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
+++ b/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
@@ -34,6 +34,7 @@ public class BaseClassForTests
 
     private static final int    RETRY_WAIT_MS = 5000;
     private static final String INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES;
+    private static final String INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND;
     static
     {
         String s = null;
@@ -47,6 +48,17 @@ public class BaseClassForTests
             e.printStackTrace();
         }
         INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES = s;
+
+        try
+        {
+            // use reflection to avoid adding a circular dependency in the pom
+            s = (String)Class.forName("org.apache.curator.utils.DebugUtils").getField("PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND").get(null);
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+        }
+        INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND = s;
     }
 
     @BeforeSuite(alwaysRun = true)
@@ -65,6 +77,7 @@ public class BaseClassForTests
         {
             System.setProperty(INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES, "true");
         }
+        System.setProperty(INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND, "true");
 
         while ( server == null )
         {
@@ -83,6 +96,7 @@ public class BaseClassForTests
     @AfterMethod
     public void teardown() throws Exception
     {
+        System.clearProperty(INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND);
         server.close();
         server = null;
     }


[03/31] curator git commit: CURATOR-161 - Initial cut of remove watches functionality. This provides the ability to remove watches, but does not yet provide a framework for observers being notified when a watch has been removed.

Posted by dr...@apache.org.
CURATOR-161 - Initial cut of remove watches functionality. This provides
the ability to remove watches, but does not yet provide a framework for
observers being notified when a watch has been removed.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/9ff9ccd2
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/9ff9ccd2
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/9ff9ccd2

Branch: refs/heads/CURATOR-3.0
Commit: 9ff9ccd23c8d033b2e7d72b83a0183d05f5dd685
Parents: d4883a8
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Tue Dec 2 09:16:40 2014 +1100
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Tue Dec 2 09:18:40 2014 +1100

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     | 471 ++++++++++---------
 .../curator/framework/api/CuratorEventType.java | 165 +++----
 .../framework/api/RemoveWatchesBuilder.java     |  29 ++
 .../framework/api/RemoveWatchesLocal.java       |  18 +
 .../framework/api/RemoveWatchesType.java        |  19 +
 .../framework/imps/CuratorFrameworkImpl.java    |   8 +-
 .../imps/RemoveWatchesBuilderImpl.java          | 192 ++++++++
 .../framework/imps/TestRemoveWatches.java       | 218 +++++++++
 8 files changed, 806 insertions(+), 314 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 9c23ddb..9d1039a 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -1,233 +1,238 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.curator.framework;
-
-import org.apache.curator.CuratorZookeeperClient;
-import org.apache.curator.framework.api.*;
-import org.apache.curator.framework.api.transaction.CuratorTransaction;
-import org.apache.curator.framework.imps.CuratorFrameworkState;
-import org.apache.curator.framework.listen.Listenable;
-import org.apache.curator.framework.state.ConnectionState;
-import org.apache.curator.framework.state.ConnectionStateListener;
-import org.apache.curator.utils.EnsurePath;
-import org.apache.zookeeper.Watcher;
-
-import java.io.Closeable;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Zookeeper framework-style client
- */
-public interface CuratorFramework extends Closeable
-{
-    /**
-     * Start the client. Most mutator methods will not work until the client is started
-     */
-    public void start();
-
-    /**
-     * Stop the client
-     */
-    public void close();
-
-    /**
-     * Returns the state of this instance
-     *
-     * @return state
-     */
-    public CuratorFrameworkState getState();
-
-    /**
-     * Return true if the client is started, not closed, etc.
-     *
-     * @return true/false
-     * @deprecated use {@link #getState()} instead
-     */
-    public boolean isStarted();
-
-    /**
-     * Start a create builder
-     *
-     * @return builder object
-     */
-    public CreateBuilder create();
-
-    /**
-     * Start a delete builder
-     *
-     * @return builder object
-     */
-    public DeleteBuilder delete();
-
-    /**
-     * Start an exists builder
-     * <p>
-     * The builder will return a Stat object as if org.apache.zookeeper.ZooKeeper.exists() were called.  Thus, a null
-     * means that it does not exist and an actual Stat object means it does exist.
-     *
-     * @return builder object
-     */
-    public ExistsBuilder checkExists();
-
-    /**
-     * Start a get data builder
-     *
-     * @return builder object
-     */
-    public GetDataBuilder getData();
-
-    /**
-     * Start a set data builder
-     *
-     * @return builder object
-     */
-    public SetDataBuilder setData();
-
-    /**
-     * Start a get children builder
-     *
-     * @return builder object
-     */
-    public GetChildrenBuilder getChildren();
-
-    /**
-     * Start a get ACL builder
-     *
-     * @return builder object
-     */
-    public GetACLBuilder getACL();
-
-    /**
-     * Start a set ACL builder
-     *
-     * @return builder object
-     */
-    public SetACLBuilder setACL();
-
-    /**
-     * Start a transaction builder
-     *
-     * @return builder object
-     */
-    public CuratorTransaction inTransaction();
-
-    /**
-     * Perform a sync on the given path - syncs are always in the background
-     *
-     * @param path                    the path
-     * @param backgroundContextObject optional context
-     * @deprecated use {@link #sync()} instead
-     */
-    public void sync(String path, Object backgroundContextObject);
-
-    /**
-     * Start a sync builder. Note: sync is ALWAYS in the background even
-     * if you don't use one of the background() methods
-     *
-     * @return builder object
-     */
-    public SyncBuilder sync();
-
-    /**
-     * Returns the listenable interface for the Connect State
-     *
-     * @return listenable
-     */
-    public Listenable<ConnectionStateListener> getConnectionStateListenable();
-
-    /**
-     * Returns the listenable interface for events
-     *
-     * @return listenable
-     */
-    public Listenable<CuratorListener> getCuratorListenable();
-
-    /**
-     * Returns the listenable interface for unhandled errors
-     *
-     * @return listenable
-     */
-    public Listenable<UnhandledErrorListener> getUnhandledErrorListenable();
-
-    /**
-     * Returns a facade of the current instance that does _not_ automatically
-     * pre-pend the namespace to all paths
-     *
-     * @return facade
-     * @deprecated use {@link #usingNamespace} passing <code>null</code>
-     */
-    public CuratorFramework nonNamespaceView();
-
-    /**
-     * Returns a facade of the current instance that uses the specified namespace
-     * or no namespace if <code>newNamespace</code> is <code>null</code>.
-     *
-     * @param newNamespace the new namespace or null for none
-     * @return facade
-     */
-    public CuratorFramework usingNamespace(String newNamespace);
-
-    /**
-     * Return the current namespace or "" if none
-     *
-     * @return namespace
-     */
-    public String getNamespace();
-
-    /**
-     * Return the managed zookeeper client
-     *
-     * @return client
-     */
-    public CuratorZookeeperClient getZookeeperClient();
-
-    /**
-     * Allocates an ensure path instance that is namespace aware
-     *
-     * @param path path to ensure
-     * @return new EnsurePath instance
-     */
-    public EnsurePath newNamespaceAwareEnsurePath(String path);
-
-    /**
-     * Curator can hold internal references to watchers that may inhibit garbage collection.
-     * Call this method on watchers you are no longer interested in.
-     *
-     * @param watcher the watcher
-     */
-    public void clearWatcherReferences(Watcher watcher);
-        
-    /**
-     * Block until a connection to ZooKeeper is available or the maxWaitTime has been exceeded
-     * @param maxWaitTime The maximum wait time. Specify a value &lt;= 0 to wait indefinitely
-     * @param units The time units for the maximum wait time.
-     * @return True if connection has been established, false otherwise.
-     * @throws InterruptedException If interrupted while waiting
-     */
-    public boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException;
-    
-    /**
-     * Block until a connection to ZooKeeper is available. This method will not return until a
-     * connection is available or it is interrupted, in which case an InterruptedException will
-     * be thrown
-     * @throws InterruptedException If interrupted while waiting
-     */
-    public void blockUntilConnected() throws InterruptedException;
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.curator.framework;
+
+import org.apache.curator.CuratorZookeeperClient;
+import org.apache.curator.framework.api.*;
+import org.apache.curator.framework.api.transaction.CuratorTransaction;
+import org.apache.curator.framework.imps.CuratorFrameworkState;
+import org.apache.curator.framework.listen.Listenable;
+import org.apache.curator.framework.state.ConnectionStateListener;
+import org.apache.curator.utils.EnsurePath;
+import org.apache.zookeeper.Watcher;
+
+import java.io.Closeable;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Zookeeper framework-style client
+ */
+public interface CuratorFramework extends Closeable
+{
+    /**
+     * Start the client. Most mutator methods will not work until the client is started
+     */
+    public void start();
+
+    /**
+     * Stop the client
+     */
+    public void close();
+
+    /**
+     * Returns the state of this instance
+     *
+     * @return state
+     */
+    public CuratorFrameworkState getState();
+
+    /**
+     * Return true if the client is started, not closed, etc.
+     *
+     * @return true/false
+     * @deprecated use {@link #getState()} instead
+     */
+    public boolean isStarted();
+
+    /**
+     * Start a create builder
+     *
+     * @return builder object
+     */
+    public CreateBuilder create();
+
+    /**
+     * Start a delete builder
+     *
+     * @return builder object
+     */
+    public DeleteBuilder delete();
+
+    /**
+     * Start an exists builder
+     * <p>
+     * The builder will return a Stat object as if org.apache.zookeeper.ZooKeeper.exists() were called.  Thus, a null
+     * means that it does not exist and an actual Stat object means it does exist.
+     *
+     * @return builder object
+     */
+    public ExistsBuilder checkExists();
+
+    /**
+     * Start a get data builder
+     *
+     * @return builder object
+     */
+    public GetDataBuilder getData();
+
+    /**
+     * Start a set data builder
+     *
+     * @return builder object
+     */
+    public SetDataBuilder setData();
+
+    /**
+     * Start a get children builder
+     *
+     * @return builder object
+     */
+    public GetChildrenBuilder getChildren();
+
+    /**
+     * Start a get ACL builder
+     *
+     * @return builder object
+     */
+    public GetACLBuilder getACL();
+
+    /**
+     * Start a set ACL builder
+     *
+     * @return builder object
+     */
+    public SetACLBuilder setACL();
+
+    /**
+     * Start a transaction builder
+     *
+     * @return builder object
+     */
+    public CuratorTransaction inTransaction();
+
+    /**
+     * Perform a sync on the given path - syncs are always in the background
+     *
+     * @param path                    the path
+     * @param backgroundContextObject optional context
+     * @deprecated use {@link #sync()} instead
+     */
+    public void sync(String path, Object backgroundContextObject);
+
+    /**
+     * Start a sync builder. Note: sync is ALWAYS in the background even
+     * if you don't use one of the background() methods
+     *
+     * @return builder object
+     */
+    public SyncBuilder sync();
+
+    /**
+     * Start a remove watches builder.
+     * @return builder object
+     */
+    public RemoveWatchesBuilder removeWatches();    
+
+    /**
+     * Returns the listenable interface for the Connect State
+     *
+     * @return listenable
+     */
+    public Listenable<ConnectionStateListener> getConnectionStateListenable();
+
+    /**
+     * Returns the listenable interface for events
+     *
+     * @return listenable
+     */
+    public Listenable<CuratorListener> getCuratorListenable();
+
+    /**
+     * Returns the listenable interface for unhandled errors
+     *
+     * @return listenable
+     */
+    public Listenable<UnhandledErrorListener> getUnhandledErrorListenable();
+
+    /**
+     * Returns a facade of the current instance that does _not_ automatically
+     * pre-pend the namespace to all paths
+     *
+     * @return facade
+     * @deprecated use {@link #usingNamespace} passing <code>null</code>
+     */
+    public CuratorFramework nonNamespaceView();
+
+    /**
+     * Returns a facade of the current instance that uses the specified namespace
+     * or no namespace if <code>newNamespace</code> is <code>null</code>.
+     *
+     * @param newNamespace the new namespace or null for none
+     * @return facade
+     */
+    public CuratorFramework usingNamespace(String newNamespace);
+
+    /**
+     * Return the current namespace or "" if none
+     *
+     * @return namespace
+     */
+    public String getNamespace();
+
+    /**
+     * Return the managed zookeeper client
+     *
+     * @return client
+     */
+    public CuratorZookeeperClient getZookeeperClient();
+
+    /**
+     * Allocates an ensure path instance that is namespace aware
+     *
+     * @param path path to ensure
+     * @return new EnsurePath instance
+     */
+    public EnsurePath newNamespaceAwareEnsurePath(String path);
+
+    /**
+     * Curator can hold internal references to watchers that may inhibit garbage collection.
+     * Call this method on watchers you are no longer interested in.
+     *
+     * @param watcher the watcher
+     */
+    public void clearWatcherReferences(Watcher watcher);
+        
+    /**
+     * Block until a connection to ZooKeeper is available or the maxWaitTime has been exceeded
+     * @param maxWaitTime The maximum wait time. Specify a value &lt;= 0 to wait indefinitely
+     * @param units The time units for the maximum wait time.
+     * @return True if connection has been established, false otherwise.
+     * @throws InterruptedException If interrupted while waiting
+     */
+    public boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException;
+    
+    /**
+     * Block until a connection to ZooKeeper is available. This method will not return until a
+     * connection is available or it is interrupted, in which case an InterruptedException will
+     * be thrown
+     * @throws InterruptedException If interrupted while waiting
+     */
+    public void blockUntilConnected() throws InterruptedException;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
index 684d11b..480d5ec 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
@@ -1,80 +1,85 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.curator.framework.api;
-
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.zookeeper.Watcher;
-
-public enum CuratorEventType
-{
-    /**
-     * Corresponds to {@link CuratorFramework#create()}
-     */
-    CREATE,
-
-    /**
-     * Corresponds to {@link CuratorFramework#delete()}
-     */
-    DELETE,
-
-    /**
-     * Corresponds to {@link CuratorFramework#checkExists()}
-     */
-    EXISTS,
-
-    /**
-     * Corresponds to {@link CuratorFramework#getData()}
-     */
-    GET_DATA,
-
-    /**
-     * Corresponds to {@link CuratorFramework#setData()}
-     */
-    SET_DATA,
-
-    /**
-     * Corresponds to {@link CuratorFramework#getChildren()}
-     */
-    CHILDREN,
-
-    /**
-     * Corresponds to {@link CuratorFramework#sync(String, Object)}
-     */
-    SYNC,
-
-    /**
-     * Corresponds to {@link CuratorFramework#getACL()}
-     */
-    GET_ACL,
-
-    /**
-     * Corresponds to {@link CuratorFramework#setACL()}
-     */
-    SET_ACL,
-
-    /**
-     * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()}
-     */
-    WATCHED,
-
-    /**
-     * Event sent when client is being closed
-     */
-    CLOSING
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.api;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.zookeeper.Watcher;
+
+public enum CuratorEventType
+{
+    /**
+     * Corresponds to {@link CuratorFramework#create()}
+     */
+    CREATE,
+
+    /**
+     * Corresponds to {@link CuratorFramework#delete()}
+     */
+    DELETE,
+
+    /**
+     * Corresponds to {@link CuratorFramework#checkExists()}
+     */
+    EXISTS,
+
+    /**
+     * Corresponds to {@link CuratorFramework#getData()}
+     */
+    GET_DATA,
+
+    /**
+     * Corresponds to {@link CuratorFramework#setData()}
+     */
+    SET_DATA,
+
+    /**
+     * Corresponds to {@link CuratorFramework#getChildren()}
+     */
+    CHILDREN,
+
+    /**
+     * Corresponds to {@link CuratorFramework#sync(String, Object)}
+     */
+    SYNC,
+
+    /**
+     * Corresponds to {@link CuratorFramework#getACL()}
+     */
+    GET_ACL,
+
+    /**
+     * Corresponds to {@link CuratorFramework#setACL()}
+     */
+    SET_ACL,
+
+    /**
+     * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()}
+     */
+    WATCHED,
+    
+    /**
+     * Corresponds to {@link CuratorFramework#removeWatches()}
+     */
+    REMOVE_WATCHES,
+
+    /**
+     * Event sent when client is being closed
+     */
+    CLOSING
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
new file mode 100644
index 0000000..2ed3c05
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
@@ -0,0 +1,29 @@
+package org.apache.curator.framework.api;
+
+import org.apache.zookeeper.Watcher;
+
+/**
+ * Builder to allow watches to be removed 
+ */
+public interface RemoveWatchesBuilder
+{
+    /**
+     * Specify the watcher to be removed
+     * @param watcher
+     * @return
+     */
+    public RemoveWatchesType watcher(Watcher watcher);
+    
+    /**
+     * Specify the watcher to be removed
+     * @param watcher
+     * @return
+     */
+    public RemoveWatchesType watcher(CuratorWatcher watcher);
+    
+    /**
+     * Specify that all watches should be removed
+     * @return
+     */
+    public RemoveWatchesType allWatches();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
new file mode 100644
index 0000000..d54638c
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -0,0 +1,18 @@
+package org.apache.curator.framework.api;
+
+/**
+ * Builder to allow the specification of whether it is acceptable to remove client side watch information
+ * in the case where ZK cannot be contacted. 
+ */
+public interface RemoveWatchesLocal extends BackgroundPathable<Void>
+{
+   
+    /**
+     * Specify if the client should just remove client side watches if a connection to ZK
+     * is not available.
+     * @param local
+     * @return
+     */
+    public BackgroundPathable<Void> local(boolean local);
+    
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
new file mode 100644
index 0000000..3c58b7b
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
@@ -0,0 +1,19 @@
+package org.apache.curator.framework.api;
+
+import org.apache.zookeeper.Watcher.WatcherType;
+
+/**
+ * Builder to allow the specification of whether it is acceptable to remove client side watch information
+ * in the case where ZK cannot be contacted. 
+ */
+public interface RemoveWatchesType
+{
+   
+    /**
+     * Specify the type of watcher to be removed.
+     * @param watcherType
+     * @return
+     */
+    public RemoveWatchesLocal ofType(WatcherType watcherType);
+    
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index cf38e21..b9614ee 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -453,6 +453,12 @@ public class CuratorFrameworkImpl implements CuratorFramework
     {
         return new SyncBuilderImpl(this);
     }
+    
+    @Override
+    public RemoveWatchesBuilder removeWatches()
+    {
+        return new RemoveWatchesBuilderImpl(this);
+    }
 
     protected void internalSync(CuratorFrameworkImpl impl, String path, Object context)
     {
@@ -471,7 +477,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
     {
         return namespace.newNamespaceAwareEnsurePath(path);
     }
-
+    
     ACLProvider getAclProvider()
     {
         return aclProvider;

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
new file mode 100644
index 0000000..08f0791
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -0,0 +1,192 @@
+package org.apache.curator.framework.imps;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+import org.apache.curator.RetryLoop;
+import org.apache.curator.TimeTrace;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.BackgroundPathable;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorEventType;
+import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.framework.api.Pathable;
+import org.apache.curator.framework.api.RemoveWatchesLocal;
+import org.apache.curator.framework.api.RemoveWatchesBuilder;
+import org.apache.curator.framework.api.RemoveWatchesType;
+import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.Watcher.WatcherType;
+import org.apache.zookeeper.ZooKeeper;
+
+
+public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWatchesType, RemoveWatchesLocal, BackgroundOperation<String>
+{
+    private CuratorFrameworkImpl client;
+    private Watcher watcher;
+    private WatcherType watcherType;
+    private boolean local;    
+    private Backgrounding backgrounding;
+    
+    public RemoveWatchesBuilderImpl(CuratorFrameworkImpl client)
+    {
+        this.client = client;
+        this.watcher = null;
+        this.watcherType = null;
+        this.local = false;
+        this.backgrounding = new Backgrounding();
+    }
+    
+    @Override
+    public RemoveWatchesType watcher(Watcher watcher)
+    {
+        this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().getNamespaceWatcher(watcher);
+        return this;
+    }
+    
+    @Override
+    public RemoveWatchesType watcher(CuratorWatcher watcher)
+    {
+        this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().getNamespaceWatcher(watcher);
+        return this;
+    }    
+
+    @Override
+    public RemoveWatchesType allWatches()
+    {
+        this.watcher = null;
+        return this;
+    }
+
+    @Override
+    public RemoveWatchesLocal ofType(WatcherType watcherType)
+    {
+        this.watcherType = watcherType;
+        
+        return this;
+    }
+
+    @Override
+    public Pathable<Void> inBackground(BackgroundCallback callback, Object context)
+    {
+        backgrounding = new Backgrounding(callback, context);
+        return this;
+    }
+
+    @Override
+    public Pathable<Void> inBackground(BackgroundCallback callback, Object context, Executor executor)
+    {
+        backgrounding = new Backgrounding(client, callback, context, executor);
+        return this;
+    }
+
+    @Override
+    public Pathable<Void> inBackground(BackgroundCallback callback)
+    {
+        backgrounding = new Backgrounding(callback);
+        return this;
+    }
+
+    @Override
+    public Pathable<Void> inBackground(BackgroundCallback callback, Executor executor)
+    {
+        backgrounding = new Backgrounding(client, callback, executor);
+        return this;
+    }
+
+    @Override
+    public Pathable<Void> inBackground()
+    {
+        backgrounding = new Backgrounding(true);
+        return this;
+    }
+
+    @Override
+    public Pathable<Void> inBackground(Object context)
+    {
+        backgrounding = new Backgrounding(context);
+        return this;
+    }
+
+    @Override
+    public BackgroundPathable<Void> local(boolean local)
+    {
+        this.local = local;
+        return this;
+    }
+    
+    @Override
+    public Void forPath(String path) throws Exception
+    {
+        final String adjustedPath = client.fixForNamespace(path);
+        
+        if(backgrounding.inBackground())
+        {
+            pathInBackground(adjustedPath);
+        }
+        else
+        {
+            pathInForeground(adjustedPath);
+        }        
+        
+        return null;
+    }    
+    
+    private void pathInBackground(String path)
+    {
+        OperationAndData.ErrorCallback<String>  errorCallback = null;        
+        client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(), errorCallback, backgrounding.getContext()), null);
+    }
+    
+    private void pathInForeground(final String path) throws Exception
+    {
+        RetryLoop.callWithRetry(client.getZookeeperClient(), 
+                new Callable<Void>()
+                {
+                    @Override
+                    public Void call() throws Exception
+                    {
+                        ZooKeeper zkClient = client.getZooKeeper();
+                        if(watcher == null)
+                        {
+                            zkClient.removeAllWatches(path, watcherType, local);    
+                        }
+                        else
+                        {
+                            zkClient.removeWatches(path, watcher, watcherType, local);
+                        }
+                        
+                        return null;
+                    }
+                });
+    }
+    
+    @Override
+    public void performBackgroundOperation(final OperationAndData<String> operationAndData)
+            throws Exception
+    {
+        final TimeTrace   trace = client.getZookeeperClient().startTracer("RemoteWatches-Background");
+        
+        AsyncCallback.VoidCallback callback = new AsyncCallback.VoidCallback()
+        {
+            @Override
+            public void processResult(int rc, String path, Object ctx)
+            {
+                trace.commit();
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.REMOVE_WATCHES, rc, path, null, ctx, null, null, null, null, null);
+                client.processBackgroundOperation(operationAndData, event);                
+            }
+        };
+        
+        ZooKeeper zkClient = client.getZooKeeper();
+        if(watcher == null)
+        {
+            zkClient.removeAllWatches(operationAndData.getData(), watcherType, local, callback, operationAndData.getContext());    
+        }
+        else
+        {
+            zkClient.removeWatches(operationAndData.getData(), watcher, watcherType, local, callback, operationAndData.getContext());
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/curator/blob/9ff9ccd2/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
new file mode 100644
index 0000000..d7e8886
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -0,0 +1,218 @@
+package org.apache.curator.framework.imps;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorListener;
+import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.test.Timing;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.Watcher.WatcherType;
+import org.apache.zookeeper.ZooKeeper;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TestRemoveWatches extends BaseClassForTests
+{
+    @Test
+    public void testRemoveCuratorWatch() throws Exception
+    {       
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            CuratorWatcher watcher = new CuratorWatcher()
+            {
+                
+                @Override
+                public void process(WatchedEvent event) throws Exception
+                {
+                    // TODO Auto-generated method stub
+                    
+                }
+            };
+            
+            String path = "/";
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).forPath(path);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
+    @Test
+    public void testRemoveWatch() throws Exception
+    {       
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            Watcher watcher = new Watcher()
+            {                
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }
+            };
+            
+            String path = "/";
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).forPath(path);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    @Test
+    public void testRemoveWatchInBackgroundWithCallback() throws Exception
+    {       
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            Watcher watcher = new Watcher()
+            {                
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }
+            };
+
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            BackgroundCallback callback = new BackgroundCallback()
+            {
+                
+                @Override
+                public void processResult(CuratorFramework client, CuratorEvent event)
+                        throws Exception
+                {
+                    removedLatch.countDown();
+                }
+            };
+            
+            String path = "/";
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).inBackground(callback).forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    @Test
+    public void testRemoveWatchInBackgroundWithNoCallback() throws Exception
+    {       
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            Watcher watcher = new Watcher()
+            {                
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }
+            };
+
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            client.getCuratorListenable().addListener(new CuratorListener()
+            {
+                
+                @Override
+                public void eventReceived(CuratorFramework client, CuratorEvent event)
+                        throws Exception
+                {
+                    removedLatch.countDown();
+                }
+            });
+            
+            String path = "/";
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).inBackground().forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }        
+    
+    @Test
+    public void testRemoveAllWatches() throws Exception
+    {       
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            Watcher watcher1 = new Watcher()
+            {                
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }
+            };
+            
+            Watcher watcher2 = new Watcher()
+            {                
+                @Override
+                public void process(WatchedEvent event)
+                {
+                }
+            };            
+            
+            String path = "/";
+            client.checkExists().usingWatcher(watcher1).forPath(path);
+            client.checkExists().usingWatcher(watcher2).forPath(path);
+            
+            client.removeWatches().allWatches().ofType(WatcherType.Any).forPath(path);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+}


[30/31] curator git commit: Merge 'CURATOR-217' into CURATOR-3.0

Posted by dr...@apache.org.
Merge 'CURATOR-217' into CURATOR-3.0


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/d5d12c88
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/d5d12c88
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/d5d12c88

Branch: refs/heads/CURATOR-3.0
Commit: d5d12c88b075fd1fc51a29412b3c08918cceb983
Parents: 44ee854 f0a09db
Author: Scott Blum <dr...@apache.org>
Authored: Mon Aug 17 22:13:37 2015 -0400
Committer: Scott Blum <dr...@apache.org>
Committed: Mon Aug 17 22:13:37 2015 -0400

----------------------------------------------------------------------
 .../org/apache/curator/utils/DebugUtils.java    |   1 +
 .../curator/framework/CuratorFramework.java     |  19 +
 .../WatcherRemoveCuratorFramework.java          |  30 +
 .../api/BackgroundPathableQuietly.java          |  23 +
 .../api/BackgroundPathableQuietlyable.java      |   5 +
 .../curator/framework/api/CuratorEventType.java |   5 +
 .../curator/framework/api/DeleteBuilder.java    |   2 +-
 .../curator/framework/api/Guaranteeable.java    |  20 +-
 .../framework/api/GuaranteeableDeletable.java   |  39 ++
 .../apache/curator/framework/api/Quietly.java   |  24 +
 .../framework/api/RemoveWatchesBuilder.java     |  47 ++
 .../framework/api/RemoveWatchesLocal.java       |  35 +
 .../framework/api/RemoveWatchesType.java        |  37 ++
 .../framework/imps/CuratorFrameworkImpl.java    |  28 +-
 .../framework/imps/DeleteBuilderImpl.java       |   4 +-
 .../framework/imps/ExistsBuilderImpl.java       |   4 +-
 .../framework/imps/FailedDeleteManager.java     |  39 +-
 .../framework/imps/FailedOperationManager.java  |  68 ++
 .../imps/FailedRemoveWatchManager.java          |  56 ++
 .../framework/imps/GetChildrenBuilderImpl.java  |   4 +-
 .../framework/imps/GetConfigBuilderImpl.java    |   5 +-
 .../framework/imps/GetDataBuilderImpl.java      |   4 +-
 .../framework/imps/OperationAndData.java        |  16 +-
 .../imps/RemoveWatchesBuilderImpl.java          | 315 +++++++++
 .../framework/imps/WatcherRemovalFacade.java    | 176 +++++
 .../framework/imps/WatcherRemovalManager.java   | 137 ++++
 .../apache/curator/framework/imps/Watching.java |   6 +-
 .../framework/imps/TestFailedDeleteManager.java |   9 +-
 .../framework/imps/TestRemoveWatches.java       | 655 +++++++++++++++++++
 .../imps/TestWatcherRemovalManager.java         | 257 ++++++++
 .../framework/recipes/cache/NodeCache.java      |   6 +-
 .../recipes/cache/PathChildrenCache.java        |  13 +-
 .../framework/recipes/cache/TreeCache.java      |   6 +-
 .../framework/recipes/leader/LeaderLatch.java   |   6 +-
 .../locks/InterProcessSemaphoreMutex.java       |   6 +-
 .../recipes/locks/InterProcessSemaphoreV2.java  |  60 +-
 .../framework/recipes/locks/LockInternals.java  |   9 +-
 .../recipes/nodes/PersistentEphemeralNode.java  |   7 +-
 .../framework/recipes/queue/ChildrenCache.java  |   6 +-
 .../framework/recipes/shared/SharedValue.java   |   8 +-
 .../curator/framework/imps/TestCleanState.java  |  68 ++
 .../recipes/cache/BaseTestTreeCache.java        |   3 +-
 .../framework/recipes/cache/TestNodeCache.java  |   9 +-
 .../recipes/cache/TestPathChildrenCache.java    |  58 +-
 .../recipes/leader/TestLeaderLatch.java         |  26 +-
 .../locks/TestInterProcessMultiMutex.java       |   7 +-
 .../recipes/locks/TestInterProcessMutex.java    |   5 +-
 .../locks/TestInterProcessMutexBase.java        |  19 +-
 .../locks/TestInterProcessReadWriteLock.java    | 223 ++++---
 .../locks/TestInterProcessSemaphore.java        |  27 +-
 .../locks/TestInterProcessSemaphoreCluster.java |   3 +-
 .../framework/recipes/locks/TestLockACLs.java   |   3 +-
 .../locks/TestLockCleanlinessWithFaults.java    |   3 +-
 .../nodes/TestPersistentEphemeralNode.java      |  18 +-
 .../recipes/shared/TestSharedCount.java         |  11 +-
 .../apache/curator/test/BaseClassForTests.java  |  14 +
 .../org/apache/curator/test/WatchersDebug.java  |  92 +++
 57 files changed, 2491 insertions(+), 295 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
----------------------------------------------------------------------
diff --cc curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
index b098989,e84e06b..383bc13
--- a/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
+++ b/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java
@@@ -23,7 -23,7 +23,8 @@@ public class DebugUtil
      public static final String          PROPERTY_LOG_EVENTS = "curator-log-events";
      public static final String          PROPERTY_DONT_LOG_CONNECTION_ISSUES = "curator-dont-log-connection-problems";
      public static final String          PROPERTY_LOG_ONLY_FIRST_CONNECTION_ISSUE_AS_ERROR_LEVEL = "curator-log-only-first-connection-issue-as-error-level";
+     public static final String          PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND = "curator-remove-watchers-in-foreground";
 +    public static final String          PROPERTY_RETRY_FAILED_TESTS = "curator-retry-failed-tests";
  
      private DebugUtils()
      {

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --cc curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 9239ac4,7de6308..58c5bf5
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@@ -1,281 -1,251 +1,300 @@@
 -/**
 - * Licensed to the Apache Software Foundation (ASF) under one
 - * or more contributor license agreements.  See the NOTICE file
 - * distributed with this work for additional information
 - * regarding copyright ownership.  The ASF licenses this file
 - * to you under the Apache License, Version 2.0 (the
 - * "License"); you may not use this file except in compliance
 - * with the License.  You may obtain a copy of the License at
 - *
 - *   http://www.apache.org/licenses/LICENSE-2.0
 - *
 - * Unless required by applicable law or agreed to in writing,
 - * software distributed under the License is distributed on an
 - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 - * KIND, either express or implied.  See the License for the
 - * specific language governing permissions and limitations
 - * under the License.
 - */
 -
 -package org.apache.curator.framework;
 -
 -import org.apache.curator.CuratorZookeeperClient;
 -import org.apache.curator.framework.api.*;
 -import org.apache.curator.framework.api.transaction.CuratorTransaction;
 -import org.apache.curator.framework.imps.CuratorFrameworkState;
 -import org.apache.curator.framework.listen.Listenable;
 -import org.apache.curator.framework.state.ConnectionStateListener;
 -import org.apache.curator.utils.EnsurePath;
 -import org.apache.zookeeper.Watcher;
 -
 -import java.io.Closeable;
 -import java.util.concurrent.TimeUnit;
 -
 -/**
 - * Zookeeper framework-style client
 - */
 -public interface CuratorFramework extends Closeable
 -{
 -    /**
 -     * Start the client. Most mutator methods will not work until the client is started
 -     */
 -    public void start();
 -
 -    /**
 -     * Stop the client
 -     */
 -    public void close();
 -
 -    /**
 -     * Returns the state of this instance
 -     *
 -     * @return state
 -     */
 -    public CuratorFrameworkState getState();
 -
 -    /**
 -     * Return true if the client is started, not closed, etc.
 -     *
 -     * @return true/false
 -     * @deprecated use {@link #getState()} instead
 -     */
 -    public boolean isStarted();
 -
 -    /**
 -     * Start a create builder
 -     *
 -     * @return builder object
 -     */
 -    public CreateBuilder create();
 -
 -    /**
 -     * Start a delete builder
 -     *
 -     * @return builder object
 -     */
 -    public DeleteBuilder delete();
 -
 -    /**
 -     * Start an exists builder
 -     * <p>
 -     * The builder will return a Stat object as if org.apache.zookeeper.ZooKeeper.exists() were called.  Thus, a null
 -     * means that it does not exist and an actual Stat object means it does exist.
 -     *
 -     * @return builder object
 -     */
 -    public ExistsBuilder checkExists();
 -
 -    /**
 -     * Start a get data builder
 -     *
 -     * @return builder object
 -     */
 -    public GetDataBuilder getData();
 -
 -    /**
 -     * Start a set data builder
 -     *
 -     * @return builder object
 -     */
 -    public SetDataBuilder setData();
 -
 -    /**
 -     * Start a get children builder
 -     *
 -     * @return builder object
 -     */
 -    public GetChildrenBuilder getChildren();
 -
 -    /**
 -     * Start a get ACL builder
 -     *
 -     * @return builder object
 -     */
 -    public GetACLBuilder getACL();
 -
 -    /**
 -     * Start a set ACL builder
 -     *
 -     * @return builder object
 -     */
 -    public SetACLBuilder setACL();
 -
 -    /**
 -     * Start a transaction builder
 -     *
 -     * @return builder object
 -     */
 -    public CuratorTransaction inTransaction();
 -
 -    /**
 -     * Perform a sync on the given path - syncs are always in the background
 -     *
 -     * @param path                    the path
 -     * @param backgroundContextObject optional context
 -     * @deprecated use {@link #sync()} instead
 -     */
 -    public void sync(String path, Object backgroundContextObject);
 -
 -    /**
 -     * Start a sync builder. Note: sync is ALWAYS in the background even
 -     * if you don't use one of the background() methods
 -     *
 -     * @return builder object
 -     */
 -    public SyncBuilder sync();
 -
 -    /**
 -     * Start a remove watches builder.
 -     * @return builder object
 -     */
 -    public RemoveWatchesBuilder watches();    
 -
 -    /**
 -     * Returns the listenable interface for the Connect State
 -     *
 -     * @return listenable
 -     */
 -    public Listenable<ConnectionStateListener> getConnectionStateListenable();
 -
 -    /**
 -     * Returns the listenable interface for events
 -     *
 -     * @return listenable
 -     */
 -    public Listenable<CuratorListener> getCuratorListenable();
 -
 -    /**
 -     * Returns the listenable interface for unhandled errors
 -     *
 -     * @return listenable
 -     */
 -    public Listenable<UnhandledErrorListener> getUnhandledErrorListenable();
 -
 -    /**
 -     * Returns a facade of the current instance that does _not_ automatically
 -     * pre-pend the namespace to all paths
 -     *
 -     * @return facade
 -     * @deprecated use {@link #usingNamespace} passing <code>null</code>
 -     */
 -    public CuratorFramework nonNamespaceView();
 -
 -    /**
 -     * Returns a facade of the current instance that uses the specified namespace
 -     * or no namespace if <code>newNamespace</code> is <code>null</code>.
 -     *
 -     * @param newNamespace the new namespace or null for none
 -     * @return facade
 -     */
 -    public CuratorFramework usingNamespace(String newNamespace);
 -
 -    /**
 -     * Return the current namespace or "" if none
 -     *
 -     * @return namespace
 -     */
 -    public String getNamespace();
 -
 -    /**
 -     * Return the managed zookeeper client
 -     *
 -     * @return client
 -     */
 -    public CuratorZookeeperClient getZookeeperClient();
 -
 -    /**
 -     * Allocates an ensure path instance that is namespace aware
 -     *
 -     * @param path path to ensure
 -     * @return new EnsurePath instance
 -     */
 -    public EnsurePath newNamespaceAwareEnsurePath(String path);
 -
 -    /**
 -     * Curator can hold internal references to watchers that may inhibit garbage collection.
 -     * Call this method on watchers you are no longer interested in.
 -     *
 -     * @param watcher the watcher
 -     * 
 -     * @deprecated As of ZooKeeper 3.5 Curators recipes will handle removing watcher references
 -     * when they are no longer used.
 -     */
 -    @Deprecated
 -    public void clearWatcherReferences(Watcher watcher);
 -        
 -    /**
 -     * Block until a connection to ZooKeeper is available or the maxWaitTime has been exceeded
 -     * @param maxWaitTime The maximum wait time. Specify a value &lt;= 0 to wait indefinitely
 -     * @param units The time units for the maximum wait time.
 -     * @return True if connection has been established, false otherwise.
 -     * @throws InterruptedException If interrupted while waiting
 -     */
 -    public boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException;
 -    
 -    /**
 -     * Block until a connection to ZooKeeper is available. This method will not return until a
 -     * connection is available or it is interrupted, in which case an InterruptedException will
 -     * be thrown
 -     * @throws InterruptedException If interrupted while waiting
 -     */
 -    public void blockUntilConnected() throws InterruptedException;
 -
 -    /**
 -     * Returns a facade of the current instance that tracks
 -     * watchers created and allows a one-shot removal of all watchers
 -     * via {@link WatcherRemoveCuratorFramework#removeWatchers()}
 -     *
 -     * @return facade
 -     */
 -    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework();
 -}
 +/**
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +
 +package org.apache.curator.framework;
 +
 +import org.apache.curator.CuratorZookeeperClient;
 +import org.apache.curator.framework.api.*;
 +import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
 +import org.apache.curator.framework.api.transaction.CuratorOp;
 +import org.apache.curator.framework.api.transaction.CuratorTransaction;
 +import org.apache.curator.framework.api.transaction.TransactionOp;
 +import org.apache.curator.framework.imps.CuratorFrameworkState;
 +import org.apache.curator.framework.listen.Listenable;
 +import org.apache.curator.framework.state.ConnectionStateListener;
 +import org.apache.curator.utils.EnsurePath;
 +import org.apache.zookeeper.Watcher;
 +
 +import java.io.Closeable;
 +import java.util.concurrent.TimeUnit;
 +
 +/**
 + * Zookeeper framework-style client
 + */
 +public interface CuratorFramework extends Closeable
 +{
 +    /**
 +     * Start the client. Most mutator methods will not work until the client is started
 +     */
 +    public void start();
 +
 +    /**
 +     * Stop the client
 +     */
 +    public void close();
 +
 +    /**
 +     * Returns the state of this instance
 +     *
 +     * @return state
 +     */
 +    public CuratorFrameworkState getState();
 +
 +    /**
 +     * Return true if the client is started, not closed, etc.
 +     *
 +     * @return true/false
 +     * @deprecated use {@link #getState()} instead
 +     */
 +    @Deprecated
 +    public boolean isStarted();
 +
 +    /**
 +     * Start a create builder
 +     *
 +     * @return builder object
 +     */
 +    public CreateBuilder create();
 +
 +    /**
 +     * Start a delete builder
 +     *
 +     * @return builder object
 +     */
 +    public DeleteBuilder delete();
 +
 +    /**
 +     * Start an exists builder
 +     * <p>
 +     * The builder will return a Stat object as if org.apache.zookeeper.ZooKeeper.exists() were called.  Thus, a null
 +     * means that it does not exist and an actual Stat object means it does exist.
 +     *
 +     * @return builder object
 +     */
 +    public ExistsBuilder checkExists();
 +
 +    /**
 +     * Start a get data builder
 +     *
 +     * @return builder object
 +     */
 +    public GetDataBuilder getData();
 +
 +    /**
 +     * Start a set data builder
 +     *
 +     * @return builder object
 +     */
 +    public SetDataBuilder setData();
 +
 +    /**
 +     * Start a get children builder
 +     *
 +     * @return builder object
 +     */
 +    public GetChildrenBuilder getChildren();
 +
 +    /**
 +     * Start a get ACL builder
 +     *
 +     * @return builder object
 +     */
 +    public GetACLBuilder getACL();
 +
 +    /**
 +     * Start a set ACL builder
 +     *
 +     * @return builder object
 +     */
 +    public SetACLBuilder setACL();
 +
 +    /**
 +     * Start a reconfig builder
 +     *
 +     * @return builder object
 +     */
 +    public ReconfigBuilder reconfig();
 +
 +    /**
 +     * Start a getConfig builder
 +     *
 +     * @return builder object
 +     */
 +    public GetConfigBuilder getConfig();
 +
 +    /**
 +     * Start a transaction builder
 +     *
 +     * @return builder object
 +     * @deprecated use {@link #transaction()} instead
 +     */
 +    public CuratorTransaction inTransaction();
 +
 +    /**
 +     * Start a transaction builder
 +     *
 +     * @return builder object
 +     */
 +    public CuratorMultiTransaction transaction();
 +
 +    /**
 +     * Allocate an operation that can be used with {@link #transaction()}.
 +     * NOTE: {@link CuratorOp} instances created by this builder are
 +     * reusable.
 +     *
 +     * @return operation builder
 +     */
 +    public TransactionOp transactionOp();
 +
 +    /**
 +     * Perform a sync on the given path - syncs are always in the background
 +     *
 +     * @param path                    the path
 +     * @param backgroundContextObject optional context
 +     * @deprecated use {@link #sync()} instead
 +     */
 +    @Deprecated
 +    public void sync(String path, Object backgroundContextObject);
 +
 +    /**
 +     * Create all nodes in the specified path as containers if they don't
 +     * already exist
 +     *
 +     * @param path path to create
 +     * @throws Exception errors
 +     */
 +    public void createContainers(String path) throws Exception;
 +
 +    /**
 +     * Start a sync builder. Note: sync is ALWAYS in the background even
 +     * if you don't use one of the background() methods
 +     *
 +     * @return builder object
 +     */
 +    public SyncBuilder sync();
 +
 +    /**
++     * Start a remove watches builder.
++     * @return builder object
++     */
++    public RemoveWatchesBuilder watches();
++
++    /**
 +     * Returns the listenable interface for the Connect State
 +     *
 +     * @return listenable
 +     */
 +    public Listenable<ConnectionStateListener> getConnectionStateListenable();
 +
 +    /**
 +     * Returns the listenable interface for events
 +     *
 +     * @return listenable
 +     */
 +    public Listenable<CuratorListener> getCuratorListenable();
 +
 +    /**
 +     * Returns the listenable interface for unhandled errors
 +     *
 +     * @return listenable
 +     */
 +    public Listenable<UnhandledErrorListener> getUnhandledErrorListenable();
 +
 +    /**
 +     * Returns a facade of the current instance that does _not_ automatically
 +     * pre-pend the namespace to all paths
 +     *
 +     * @return facade
 +     * @deprecated Since 2.9.0 - use {@link #usingNamespace} passing <code>null</code>
 +     */
 +    @Deprecated
 +    public CuratorFramework nonNamespaceView();
 +
 +    /**
 +     * Returns a facade of the current instance that uses the specified namespace
 +     * or no namespace if <code>newNamespace</code> is <code>null</code>.
 +     *
 +     * @param newNamespace the new namespace or null for none
 +     * @return facade
 +     */
 +    public CuratorFramework usingNamespace(String newNamespace);
 +
 +    /**
 +     * Return the current namespace or "" if none
 +     *
 +     * @return namespace
 +     */
 +    public String getNamespace();
 +
 +    /**
 +     * Return the managed zookeeper client
 +     *
 +     * @return client
 +     */
 +    public CuratorZookeeperClient getZookeeperClient();
 +
 +    /**
 +     * Allocates an ensure path instance that is namespace aware
 +     *
 +     * @param path path to ensure
 +     * @return new EnsurePath instance
 +     * @deprecated Since 2.9.0 - prefer {@link CreateBuilder#creatingParentContainersIfNeeded()}, {@link ExistsBuilder#creatingParentContainersIfNeeded()}
 +     * or {@link CuratorFramework#createContainers(String)}
 +     */
 +    @Deprecated
 +    public EnsurePath newNamespaceAwareEnsurePath(String path);
 +
 +    /**
 +     * Curator can hold internal references to watchers that may inhibit garbage collection.
 +     * Call this method on watchers you are no longer interested in.
 +     *
 +     * @param watcher the watcher
++     * 
++     * @deprecated As of ZooKeeper 3.5 Curators recipes will handle removing watcher references
++     * when they are no longer used.
 +     */
++    @Deprecated
 +    public void clearWatcherReferences(Watcher watcher);
 +        
 +    /**
 +     * Block until a connection to ZooKeeper is available or the maxWaitTime has been exceeded
 +     * @param maxWaitTime The maximum wait time. Specify a value &lt;= 0 to wait indefinitely
 +     * @param units The time units for the maximum wait time.
 +     * @return True if connection has been established, false otherwise.
 +     * @throws InterruptedException If interrupted while waiting
 +     */
 +    public boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException;
 +    
 +    /**
 +     * Block until a connection to ZooKeeper is available. This method will not return until a
 +     * connection is available or it is interrupted, in which case an InterruptedException will
 +     * be thrown
 +     * @throws InterruptedException If interrupted while waiting
 +     */
 +    public void blockUntilConnected() throws InterruptedException;
++
++    /**
++     * Returns a facade of the current instance that tracks
++     * watchers created and allows a one-shot removal of all watchers
++     * via {@link WatcherRemoveCuratorFramework#removeWatchers()}
++     *
++     * @return facade
++     */
++    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework();
 +}

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
----------------------------------------------------------------------
diff --cc curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
index 5a2dc56,480d5ec..5dea211
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
@@@ -1,95 -1,85 +1,100 @@@
 -/**
 - * Licensed to the Apache Software Foundation (ASF) under one
 - * or more contributor license agreements.  See the NOTICE file
 - * distributed with this work for additional information
 - * regarding copyright ownership.  The ASF licenses this file
 - * to you under the Apache License, Version 2.0 (the
 - * "License"); you may not use this file except in compliance
 - * with the License.  You may obtain a copy of the License at
 - *
 - *   http://www.apache.org/licenses/LICENSE-2.0
 - *
 - * Unless required by applicable law or agreed to in writing,
 - * software distributed under the License is distributed on an
 - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 - * KIND, either express or implied.  See the License for the
 - * specific language governing permissions and limitations
 - * under the License.
 - */
 -package org.apache.curator.framework.api;
 -
 -import org.apache.curator.framework.CuratorFramework;
 -import org.apache.zookeeper.Watcher;
 -
 -public enum CuratorEventType
 -{
 -    /**
 -     * Corresponds to {@link CuratorFramework#create()}
 -     */
 -    CREATE,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#delete()}
 -     */
 -    DELETE,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#checkExists()}
 -     */
 -    EXISTS,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#getData()}
 -     */
 -    GET_DATA,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#setData()}
 -     */
 -    SET_DATA,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#getChildren()}
 -     */
 -    CHILDREN,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#sync(String, Object)}
 -     */
 -    SYNC,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#getACL()}
 -     */
 -    GET_ACL,
 -
 -    /**
 -     * Corresponds to {@link CuratorFramework#setACL()}
 -     */
 -    SET_ACL,
 -
 -    /**
 -     * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()}
 -     */
 -    WATCHED,
 -    
 -    /**
 -     * Corresponds to {@link CuratorFramework#removeWatches()}
 -     */
 -    REMOVE_WATCHES,
 -
 -    /**
 -     * Event sent when client is being closed
 -     */
 -    CLOSING
 -}
 +/**
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.curator.framework.api;
 +
 +import org.apache.curator.framework.CuratorFramework;
 +import org.apache.zookeeper.Watcher;
 +
 +public enum CuratorEventType
 +{
 +    /**
 +     * Corresponds to {@link CuratorFramework#create()}
 +     */
 +    CREATE,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#delete()}
 +     */
 +    DELETE,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#checkExists()}
 +     */
 +    EXISTS,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#getData()}
 +     */
 +    GET_DATA,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#setData()}
 +     */
 +    SET_DATA,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#getChildren()}
 +     */
 +    CHILDREN,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#sync(String, Object)}
 +     */
 +    SYNC,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#getACL()}
 +     */
 +    GET_ACL,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#setACL()}
 +     */
 +    SET_ACL,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#transaction()}
 +     */
 +    TRANSACTION,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#getConfig()}
 +     */
 +    GET_CONFIG,
 +
 +    /**
 +     * Corresponds to {@link CuratorFramework#reconfig()}
 +     */
 +    RECONFIG,
 +
 +    /**
 +     * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()}
 +     */
 +    WATCHED,
 +
 +    /**
++     * Corresponds to {@link CuratorFramework#watches()} ()}
++     */
++    REMOVE_WATCHES,
++
++    /**
 +     * Event sent when client is being closed
 +     */
 +    CLOSING
 +}

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index 900374b,b078768..41bb7cd
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@@ -27,13 -27,11 +27,14 @@@ import org.apache.curator.CuratorConnec
  import org.apache.curator.CuratorZookeeperClient;
  import org.apache.curator.RetryLoop;
  import org.apache.curator.TimeTrace;
 +import org.apache.curator.framework.AuthInfo;
  import org.apache.curator.framework.CuratorFramework;
  import org.apache.curator.framework.CuratorFrameworkFactory;
+ import org.apache.curator.framework.WatcherRemoveCuratorFramework;
  import org.apache.curator.framework.api.*;
 +import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
  import org.apache.curator.framework.api.transaction.CuratorTransaction;
 +import org.apache.curator.framework.api.transaction.TransactionOp;
  import org.apache.curator.framework.listen.Listenable;
  import org.apache.curator.framework.listen.ListenerContainer;
  import org.apache.curator.framework.state.ConnectionState;
@@@ -73,9 -70,10 +74,10 @@@ public class CuratorFrameworkImpl imple
      private final BlockingQueue<OperationAndData<?>> backgroundOperations;
      private final NamespaceImpl namespace;
      private final ConnectionStateManager connectionStateManager;
 -    private final AtomicReference<AuthInfo> authInfo = new AtomicReference<AuthInfo>();
 +    private final List<AuthInfo> authInfos;
      private final byte[] defaultData;
      private final FailedDeleteManager failedDeleteManager;
+     private final FailedRemoveWatchManager failedRemoveWatcherManager;
      private final CompressionProvider compressionProvider;
      private final ACLProvider aclProvider;
      private final NamespaceFacadeCache namespaceFacadeCache;
@@@ -125,22 -142,23 +127,29 @@@
  
          byte[] builderDefaultData = builder.getDefaultData();
          defaultData = (builderDefaultData != null) ? Arrays.copyOf(builderDefaultData, builderDefaultData.length) : new byte[0];
 -
 -        if ( builder.getAuthScheme() != null )
 -        {
 -            authInfo.set(new AuthInfo(builder.getAuthScheme(), builder.getAuthValue()));
 -        }
 +        authInfos = buildAuths(builder);
  
          failedDeleteManager = new FailedDeleteManager(this);
+         failedRemoveWatcherManager = new FailedRemoveWatchManager(this);
          namespaceFacadeCache = new NamespaceFacadeCache(this);
      }
  
 +    private List<AuthInfo> buildAuths(CuratorFrameworkFactory.Builder builder)
 +    {
 +        ImmutableList.Builder<AuthInfo> builder1 = ImmutableList.builder();
 +        if ( builder.getAuthInfos() != null )
 +        {
 +            builder1.addAll(builder.getAuthInfos());
 +        }
 +        return builder1.build();
 +    }
 +
+     @Override
+     public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework()
+     {
+         return new WatcherRemovalFacade(this);
+     }
+ 
      private ZookeeperFactory makeZookeeperFactory(final ZookeeperFactory actualZookeeperFactory)
      {
          return new ZookeeperFactory()
@@@ -478,7 -463,13 +488,13 @@@
      {
          return new SyncBuilderImpl(this);
      }
 -    
 +
+     @Override
+     public RemoveWatchesBuilder watches()
+     {
+         return new RemoveWatchesBuilderImpl(this);
+     }
+ 
      protected void internalSync(CuratorFrameworkImpl impl, String path, Object context)
      {
          BackgroundOperation<String> operation = new BackgroundSyncImpl(impl, context);
@@@ -506,7 -497,12 +522,12 @@@
      {
          return failedDeleteManager;
      }
 -    
 +
+     FailedRemoveWatchManager getFailedRemoveWatcherManager()
+     {
+         return failedRemoveWatcherManager;
 -    }    
++    }
+ 
      RetryLoop newRetryLoop()
      {
          return client.newRetryLoop();

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
----------------------------------------------------------------------
diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
index 51641b8,51691dd..2a98f56
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
@@@ -259,9 -251,9 +259,9 @@@ class DeleteBuilderImpl implements Dele
          catch ( Exception e )
          {
              //Only retry a guaranteed delete if it's a retryable error
 -            if( RetryLoop.isRetryException(e) && guaranteed )
 +            if( (RetryLoop.isRetryException(e) || (e instanceof InterruptedException)) && guaranteed )
              {
-                 client.getFailedDeleteManager().addFailedDelete(unfixedPath);
+                 client.getFailedDeleteManager().addFailedOperation(unfixedPath);
              }
              throw e;
          }

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index a837809,0000000..5468bd4
mode 100644,000000..100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@@ -1,187 -1,0 +1,188 @@@
 +/**
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +
 +package org.apache.curator.framework.imps;
 +
 +import org.apache.curator.RetryLoop;
 +import org.apache.curator.TimeTrace;
 +import org.apache.curator.framework.api.BackgroundCallback;
 +import org.apache.curator.framework.api.BackgroundStatable;
 +import org.apache.curator.framework.api.CuratorEvent;
 +import org.apache.curator.framework.api.CuratorEventType;
 +import org.apache.curator.framework.api.CuratorWatcher;
 +import org.apache.curator.framework.api.Ensembleable;
 +import org.apache.curator.framework.api.GetConfigBuilder;
 +import org.apache.zookeeper.AsyncCallback;
 +import org.apache.zookeeper.Watcher;
++import org.apache.zookeeper.ZooDefs;
 +import org.apache.zookeeper.data.Stat;
 +import java.util.concurrent.Callable;
 +import java.util.concurrent.Executor;
 +
 +public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperation<Void>
 +{
 +    private final CuratorFrameworkImpl client;
 +
 +    private Backgrounding backgrounding;
 +    private Watching watching;
 +    private Stat stat;
 +
 +    public GetConfigBuilderImpl(CuratorFrameworkImpl client)
 +    {
 +        this.client = client;
 +        backgrounding = new Backgrounding();
 +        watching = new Watching();
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> storingStatIn(Stat stat)
 +    {
 +        this.stat = stat;
 +        return this;
 +    }
 +
 +    @Override
 +    public BackgroundStatable<Ensembleable<byte[]>> watched()
 +    {
 +        watching = new Watching(true);
 +        return this;
 +    }
 +
 +    @Override
 +    public GetConfigBuilder usingWatcher(Watcher watcher)
 +    {
 +        watching = new Watching(client, watcher);
 +        return this;
 +    }
 +
 +    @Override
 +    public GetConfigBuilder usingWatcher(final CuratorWatcher watcher)
 +    {
 +        watching = new Watching(client, watcher);
 +        return this;
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> inBackground()
 +    {
 +        backgrounding = new Backgrounding(true);
 +        return this;
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> inBackground(Object context)
 +    {
 +        backgrounding = new Backgrounding(context);
 +        return this;
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> inBackground(BackgroundCallback callback)
 +    {
 +        backgrounding = new Backgrounding(callback);
 +        return this;
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context)
 +    {
 +        backgrounding = new Backgrounding(callback, context);
 +        return this;
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Executor executor)
 +    {
 +        backgrounding = new Backgrounding(callback, executor);
 +        return this;
 +    }
 +
 +    @Override
 +    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor)
 +    {
 +        backgrounding = new Backgrounding(client, callback, context, executor);
 +        return this;
 +    }
 +
 +    @Override
 +    public byte[] forEnsemble() throws Exception
 +    {
 +        if ( backgrounding.inBackground() )
 +        {
 +            client.processBackgroundOperation(new OperationAndData<Void>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
 +            return null;
 +        }
 +        else
 +        {
 +            return configInForeground();
 +        }
 +    }
 +
 +    @Override
 +    public void performBackgroundOperation(final OperationAndData<Void> operationAndData) throws Exception
 +    {
 +        final TimeTrace trace = client.getZookeeperClient().startTracer("GetDataBuilderImpl-Background");
 +        AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback()
 +        {
 +            @Override
 +            public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat)
 +            {
 +                trace.commit();
 +                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_CONFIG, rc, path, null, ctx, stat, data, null, null, null, null);
 +                client.processBackgroundOperation(operationAndData, event);
 +            }
 +        };
 +        if ( watching.isWatched() )
 +        {
 +            client.getZooKeeper().getConfig(true, callback, backgrounding.getContext());
 +        }
 +        else
 +        {
-             client.getZooKeeper().getConfig(watching.getWatcher(), callback, backgrounding.getContext());
++            client.getZooKeeper().getConfig(watching.getWatcher(client, ZooDefs.CONFIG_NODE), callback, backgrounding.getContext());
 +        }
 +    }
 +
 +    private byte[] configInForeground() throws Exception
 +    {
 +        TimeTrace trace = client.getZookeeperClient().startTracer("GetConfigBuilderImpl-Foreground");
 +        try
 +        {
 +            return RetryLoop.callWithRetry
 +            (
 +                client.getZookeeperClient(),
 +                new Callable<byte[]>()
 +                {
 +                    @Override
 +                    public byte[] call() throws Exception
 +                    {
 +                        if ( watching.isWatched() )
 +                        {
 +                            return client.getZooKeeper().getConfig(true, stat);
 +                        }
-                         return client.getZooKeeper().getConfig(watching.getWatcher(), stat);
++                        return client.getZooKeeper().getConfig(watching.getWatcher(client, ZooDefs.CONFIG_NODE), stat);
 +                    }
 +                }
 +            );
 +        }
 +        finally
 +        {
 +            trace.commit();
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
index 72ee5ff,4d87732..49b9a3f
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java
@@@ -53,9 -55,10 +54,9 @@@ import java.util.concurrent.atomic.Atom
  public class NodeCache implements Closeable
  {
      private final Logger log = LoggerFactory.getLogger(getClass());
-     private final CuratorFramework client;
+     private final WatcherRemoveCuratorFramework client;
      private final String path;
      private final boolean dataIsCompressed;
 -    private final EnsurePath ensurePath;
      private final AtomicReference<ChildData> data = new AtomicReference<ChildData>(null);
      private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
      private final ListenerContainer<NodeCacheListener> listeners = new ListenerContainer<NodeCacheListener>();
@@@ -127,9 -130,10 +128,9 @@@
       */
      public NodeCache(CuratorFramework client, String path, boolean dataIsCompressed)
      {
-         this.client = client;
+         this.client = client.newWatcherRemoveCuratorFramework();
          this.path = PathUtils.validatePath(path);
          this.dataIsCompressed = dataIsCompressed;
 -        ensurePath = client.newNamespaceAwareEnsurePath(path).excludingLast();
      }
  
      /**

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
index b5d912c,5c413b6..99a652d
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
@@@ -42,16 -44,16 +43,13 @@@ import org.apache.zookeeper.Watcher
  import org.apache.zookeeper.data.Stat;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
++
  import java.io.Closeable;
  import java.io.IOException;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
--import java.util.concurrent.ConcurrentMap;
--import java.util.concurrent.Exchanger;
--import java.util.concurrent.ExecutorService;
--import java.util.concurrent.Executors;
--import java.util.concurrent.ThreadFactory;
++import java.util.concurrent.*;
  import java.util.concurrent.atomic.AtomicReference;
  
  /**

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
index 4f3ffb6,c3958aa..bda00bf
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java
@@@ -524,13 -510,11 +525,13 @@@ public class TreeCache implements Close
       * @param cacheData        if true, node contents are cached in addition to the stat
       * @param dataIsCompressed if true, data in the path is compressed
       * @param executorService  Closeable ExecutorService to use for the TreeCache's background thread
 +     * @param createParentNodes true to create parent nodes as containers
       */
 -    TreeCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, int maxDepth, final CloseableExecutorService executorService)
 +    TreeCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, int maxDepth, final CloseableExecutorService executorService, boolean createParentNodes)
      {
 +        this.createParentNodes = createParentNodes;
          this.root = new TreeNode(validatePath(path), null);
-         this.client = client;
+         this.client = client.newWatcherRemoveCuratorFramework();
          this.cacheData = cacheData;
          this.dataIsCompressed = dataIsCompressed;
          this.maxDepth = maxDepth;

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
index f4af39b,2a55107..3bf2ec3
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
@@@ -21,16 -21,15 +21,17 @@@ package org.apache.curator.framework.re
  
  import com.google.common.base.Preconditions;
  import com.google.common.collect.ImmutableList;
 -import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 -import org.apache.curator.utils.CloseableUtils;
 +import com.google.common.collect.Sets;
- 
- import org.apache.curator.utils.CloseableUtils;
  import org.apache.curator.RetryLoop;
  import org.apache.curator.framework.CuratorFramework;
++import org.apache.curator.framework.WatcherRemoveCuratorFramework;
  import org.apache.curator.framework.api.PathAndBytesable;
  import org.apache.curator.framework.imps.CuratorFrameworkState;
  import org.apache.curator.framework.recipes.shared.SharedCountListener;
  import org.apache.curator.framework.recipes.shared.SharedCountReader;
  import org.apache.curator.framework.state.ConnectionState;
++import org.apache.curator.utils.CloseableUtils;
++import org.apache.curator.utils.PathUtils;
  import org.apache.curator.utils.ZKPaths;
  import org.apache.zookeeper.CreateMode;
  import org.apache.zookeeper.KeeperException;
@@@ -38,13 -37,12 +39,13 @@@ import org.apache.zookeeper.WatchedEven
  import org.apache.zookeeper.Watcher;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
++
  import java.io.IOException;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.List;
 +import java.util.Set;
  import java.util.concurrent.TimeUnit;
--import org.apache.curator.utils.PathUtils;
  
  /**
   * <p>

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
index 0d963e0,98b09c9..0b482ef
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
@@@ -20,8 -20,8 +20,9 @@@
  package org.apache.curator.framework.recipes.nodes;
  
  import com.google.common.base.Preconditions;
 +
  import org.apache.curator.framework.CuratorFramework;
+ import org.apache.curator.framework.WatcherRemoveCuratorFramework;
  import org.apache.curator.framework.api.ACLBackgroundPathAndBytesable;
  import org.apache.curator.framework.api.BackgroundCallback;
  import org.apache.curator.framework.api.CreateModable;
@@@ -210,12 -189,12 +211,12 @@@ public class PersistentEphemeralNode im
       * @param basePath the base path for the node
       * @param data     data for the node
       */
 -    public PersistentEphemeralNode(CuratorFramework client, Mode mode, String basePath, byte[] data)
 +    public PersistentEphemeralNode(CuratorFramework client, Mode mode, String basePath, byte[] initData)
      {
-         this.client = Preconditions.checkNotNull(client, "client cannot be null");
+         this.client = Preconditions.checkNotNull(client, "client cannot be null").newWatcherRemoveCuratorFramework();
          this.basePath = PathUtils.validatePath(basePath);
          this.mode = Preconditions.checkNotNull(mode, "mode cannot be null");
 -        data = Preconditions.checkNotNull(data, "data cannot be null");
 +        final byte[] data = Preconditions.checkNotNull(initData, "data cannot be null");
  
          backgroundCallback = new BackgroundCallback()
          {

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
index 14d061f,ffcf251..3571ca7
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
@@@ -28,10 -28,9 +28,10 @@@ import org.apache.curator.framework.api
  import org.apache.curator.framework.api.CuratorEvent;
  import org.apache.curator.framework.api.Pathable;
  import org.apache.curator.framework.api.UnhandledErrorListener;
- import org.apache.curator.framework.imps.CuratorFrameworkImpl;
+ import org.apache.curator.framework.imps.TestCleanState;
  import org.apache.curator.retry.RetryOneTime;
  import org.apache.curator.test.BaseClassForTests;
 +import org.apache.curator.test.ExecuteCalledWatchingExecutorService;
  import org.apache.curator.test.KillSession;
  import org.apache.curator.test.Timing;
  import org.apache.curator.utils.CloseableUtils;
@@@ -957,9 -1041,133 +966,10 @@@ public class TestPathChildrenCache exte
              latch.await(5, TimeUnit.SECONDS);
  
              Assert.assertTrue(latch.getCount() == 1, "Unexpected exception occurred");
-         } finally
+         }
+         finally
          {
-             CloseableUtils.closeQuietly(client);
+             TestCleanState.closeAndTestClean(client);
          }
      }
 -
 -    public static class ExecuteCalledWatchingExecutorService extends DelegatingExecutorService
 -    {
 -        boolean executeCalled = false;
 -
 -        public ExecuteCalledWatchingExecutorService(ExecutorService delegate)
 -        {
 -            super(delegate);
 -        }
 -
 -        @Override
 -        public synchronized void execute(Runnable command)
 -        {
 -            executeCalled = true;
 -            super.execute(command);
 -        }
 -
 -        public synchronized boolean isExecuteCalled()
 -        {
 -            return executeCalled;
 -        }
 -
 -        public synchronized void setExecuteCalled(boolean executeCalled)
 -        {
 -            this.executeCalled = executeCalled;
 -        }
 -    }
 -
 -    public static class DelegatingExecutorService implements ExecutorService
 -    {
 -        private final ExecutorService delegate;
 -
 -        public DelegatingExecutorService(
 -                ExecutorService delegate
 -        )
 -        {
 -            this.delegate = delegate;
 -        }
 -
 -
 -        @Override
 -        public void shutdown()
 -        {
 -            delegate.shutdown();
 -        }
 -
 -        @Override
 -        public List<Runnable> shutdownNow()
 -        {
 -            return delegate.shutdownNow();
 -        }
 -
 -        @Override
 -        public boolean isShutdown()
 -        {
 -            return delegate.isShutdown();
 -        }
 -
 -        @Override
 -        public boolean isTerminated()
 -        {
 -            return delegate.isTerminated();
 -        }
 -
 -        @Override
 -        public boolean awaitTermination(long timeout, TimeUnit unit)
 -                throws InterruptedException
 -        {
 -            return delegate.awaitTermination(timeout, unit);
 -        }
 -
 -        @Override
 -        public <T> Future<T> submit(Callable<T> task)
 -        {
 -            return delegate.submit(task);
 -        }
 -
 -        @Override
 -        public <T> Future<T> submit(Runnable task, T result)
 -        {
 -            return delegate.submit(task, result);
 -        }
 -
 -        @Override
 -        public Future<?> submit(Runnable task)
 -        {
 -            return delegate.submit(task);
 -        }
 -
 -        @Override
 -        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
 -                throws InterruptedException
 -        {
 -            return delegate.invokeAll(tasks);
 -        }
 -
 -        @Override
 -        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
 -                throws InterruptedException
 -        {
 -            return delegate.invokeAll(tasks, timeout, unit);
 -        }
 -
 -        @Override
 -        public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
 -                throws InterruptedException, ExecutionException
 -        {
 -            return delegate.invokeAny(tasks);
 -        }
 -
 -        @Override
 -        public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
 -                throws InterruptedException, ExecutionException, TimeoutException
 -        {
 -            return delegate.invokeAny(tasks, timeout, unit);
 -        }
 -
 -        @Override
 -        public void execute(Runnable command)
 -        {
 -            delegate.execute(command);
 -        }
 -    }
  }

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java
index 99ea11f,49e5d19..f44d238
--- 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
@@@ -27,11 -28,7 +28,10 @@@ import org.apache.curator.framework.sta
  import org.apache.curator.retry.ExponentialBackoffRetry;
  import org.apache.curator.test.BaseClassForTests;
  import org.apache.curator.test.KillSession;
- import org.apache.curator.test.TestingServer;
  import org.apache.curator.test.Timing;
 +import org.apache.curator.utils.CloseableUtils;
 +import org.apache.curator.utils.ZKPaths;
 +import org.apache.zookeeper.CreateMode;
  import org.testng.Assert;
  import org.testng.annotations.Test;
  import java.util.List;

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
index 631b7c7,2797b5f..3ba75d8
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
@@@ -528,47 -531,7 +531,47 @@@ public class TestInterProcessSemaphore 
              {
                  CloseableUtils.closeQuietly(l);
              }
-             CloseableUtils.closeQuietly(client);
+             TestCleanState.closeAndTestClean(client);
          }
      }
 +
 +    @Test
 +    public void testChildReaperCleansUpLockNodes() throws Exception
 +    {
 +        Timing timing = new Timing();
 +        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
 +        client.start();
 +
 +        ChildReaper childReaper = null;
 +        try
 +        {
 +            InterProcessSemaphoreV2 semaphore = new InterProcessSemaphoreV2(client, "/test/lock", 1);
 +            semaphore.returnLease(semaphore.acquire(timing.forWaiting().seconds(), TimeUnit.SECONDS));
 +
 +            Assert.assertTrue(client.getChildren().forPath("/test").size() > 0);
 +
 +            childReaper = new ChildReaper(
 +                    client,
 +                    "/test",
 +                    Reaper.Mode.REAP_UNTIL_GONE,
 +                    ChildReaper.newExecutorService(),
 +                    1,
 +                    "/test-leader",
 +                    InterProcessSemaphoreV2.LOCK_SCHEMA
 +            );
 +            childReaper.start();
 +
 +            timing.forWaiting().sleepABit();
 +
 +            List<String> children = client.getChildren().forPath("/test");
 +
 +            Assert.assertEquals(children.size(), 0, "All children of /test should have been reaped");
 +        }
 +        finally
 +        {
 +            CloseableUtils.closeQuietly(childReaper);
 +            CloseableUtils.closeQuietly(client);
 +        }
 +
 +    }
  }

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
----------------------------------------------------------------------
diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
index 9f5907a,5a58b2a..c81cc65
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java
@@@ -20,17 -20,15 +20,16 @@@ package org.apache.curator.framework.re
  
  import com.google.common.base.Throwables;
  import com.google.common.collect.Lists;
- 
  import org.apache.curator.framework.CuratorFramework;
  import org.apache.curator.framework.CuratorFrameworkFactory;
 +import org.apache.curator.framework.api.BackgroundCallback;
 +import org.apache.curator.framework.api.CuratorEvent;
+ import org.apache.curator.framework.imps.TestCleanState;
  import org.apache.curator.framework.state.ConnectionState;
  import org.apache.curator.framework.state.ConnectionStateListener;
  import org.apache.curator.retry.RetryOneTime;
  import org.apache.curator.test.BaseClassForTests;
  import org.apache.curator.test.KillSession;
--import org.apache.curator.test.TestingServer;
  import org.apache.curator.test.Timing;
  import org.apache.curator.utils.CloseableUtils;
  import org.apache.curator.utils.ZKPaths;
@@@ -129,9 -123,10 +127,10 @@@ public class TestPersistentEphemeralNod
      @Test
      public void testNoServerAtStart() throws Exception
      {
 -        server.close();
 +        server.stop();
  
          CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
+         PersistentEphemeralNode node = null;
          try
          {
              client.start();

http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
----------------------------------------------------------------------
diff --cc curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
index 13c3138,d5c434f..6ef3bb0
--- a/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
+++ b/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java
@@@ -35,11 -34,10 +35,12 @@@ public class BaseClassForTest
  
      private static final int    RETRY_WAIT_MS = 5000;
      private static final String INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES;
+     private static final String INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND;
 +    private static final String INTERNAL_RETRY_FAILED_TESTS;
      static
      {
 -        String s = null;
 +        String logConnectionIssues = null;
 +        String retryFailedTests = null;
          try
          {
              // use reflection to avoid adding a circular dependency in the pom
@@@ -51,8 -47,18 +52,19 @@@
          {
              e.printStackTrace();
          }
 -        INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES = s;
 -
 +        INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES = logConnectionIssues;
 +        INTERNAL_RETRY_FAILED_TESTS = retryFailedTests;
++        String s = null;
+         try
+         {
+             // use reflection to avoid adding a circular dependency in the pom
+             s = (String)Class.forName("org.apache.curator.utils.DebugUtils").getField("PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND").get(null);
+         }
+         catch ( Exception e )
+         {
+             e.printStackTrace();
+         }
+         INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND = s;
      }
  
      @BeforeSuite(alwaysRun = true)
@@@ -89,18 -96,9 +102,19 @@@
      @AfterMethod
      public void teardown() throws Exception
      {
+         System.clearProperty(INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND);
 -        server.close();
 -        server = null;
 +        if ( server != null )
 +        {
 +            try
 +            {
 +                server.close();
 +            }
 +            catch ( IOException e )
 +            {
 +                e.printStackTrace();
 +            }
 +            server = null;
 +        }
      }
  
      private static class RetryTest implements IRetryAnalyzer


[05/31] curator git commit: CURATOR-161 - Updates to naming based on review. Added unit test for local() case, which has still not been resolved. Need to make changes to the framework to allow some ZK calls (local watch removal in this case) to occur eve

Posted by dr...@apache.org.
CURATOR-161 - Updates to naming based on review. Added unit test for
local() case, which has still not been resolved. Need to make changes to
the framework to allow some ZK calls (local watch removal in this case) to
occur even if no ZK connection is available.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/a83090be
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/a83090be
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/a83090be

Branch: refs/heads/CURATOR-3.0
Commit: a83090bea7cdd69aa094ddaa9d4a70f401c28861
Parents: b2b9af3
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Fri May 8 14:05:18 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Fri May 8 14:07:48 2015 +1000

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |  2 +-
 .../framework/api/RemoveWatchesBuilder.java     |  6 +-
 .../framework/api/RemoveWatchesLocal.java       |  3 +-
 .../framework/imps/CuratorFrameworkImpl.java    |  2 +-
 .../imps/RemoveWatchesBuilderImpl.java          | 10 +--
 .../framework/imps/TestRemoveWatches.java       | 67 +++++++++++++++++---
 6 files changed, 70 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/a83090be/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 9d1039a..4b30fd4 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -148,7 +148,7 @@ public interface CuratorFramework extends Closeable
      * Start a remove watches builder.
      * @return builder object
      */
-    public RemoveWatchesBuilder removeWatches();    
+    public RemoveWatchesBuilder watches();    
 
     /**
      * Returns the listenable interface for the Connect State

http://git-wip-us.apache.org/repos/asf/curator/blob/a83090be/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
index 2ed3c05..5d48a9e 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
@@ -12,18 +12,18 @@ public interface RemoveWatchesBuilder
      * @param watcher
      * @return
      */
-    public RemoveWatchesType watcher(Watcher watcher);
+    public RemoveWatchesType remove(Watcher watcher);
     
     /**
      * Specify the watcher to be removed
      * @param watcher
      * @return
      */
-    public RemoveWatchesType watcher(CuratorWatcher watcher);
+    public RemoveWatchesType remove(CuratorWatcher watcher);
     
     /**
      * Specify that all watches should be removed
      * @return
      */
-    public RemoveWatchesType allWatches();
+    public RemoveWatchesType removeAll();
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/a83090be/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
index d54638c..2e9816b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -10,9 +10,8 @@ public interface RemoveWatchesLocal extends BackgroundPathable<Void>
     /**
      * Specify if the client should just remove client side watches if a connection to ZK
      * is not available.
-     * @param local
      * @return
      */
-    public BackgroundPathable<Void> local(boolean local);
+    public BackgroundPathable<Void> local();
     
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/a83090be/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index b9614ee..5caff7d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -455,7 +455,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
     }
     
     @Override
-    public RemoveWatchesBuilder removeWatches()
+    public RemoveWatchesBuilder watches()
     {
         return new RemoveWatchesBuilderImpl(this);
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/a83090be/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 08f0791..5d1f945 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -38,21 +38,21 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     }
     
     @Override
-    public RemoveWatchesType watcher(Watcher watcher)
+    public RemoveWatchesType remove(Watcher watcher)
     {
         this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().getNamespaceWatcher(watcher);
         return this;
     }
     
     @Override
-    public RemoveWatchesType watcher(CuratorWatcher watcher)
+    public RemoveWatchesType remove(CuratorWatcher watcher)
     {
         this.watcher = watcher == null ? null : client.getNamespaceWatcherMap().getNamespaceWatcher(watcher);
         return this;
     }    
 
     @Override
-    public RemoveWatchesType allWatches()
+    public RemoveWatchesType removeAll()
     {
         this.watcher = null;
         return this;
@@ -109,9 +109,9 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     }
 
     @Override
-    public BackgroundPathable<Void> local(boolean local)
+    public BackgroundPathable<Void> local()
     {
-        this.local = local;
+        local = true;
         return this;
     }
     

http://git-wip-us.apache.org/repos/asf/curator/blob/a83090be/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 15fb24c..b740286 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -1,7 +1,7 @@
 package org.apache.curator.framework.imps;
 
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -52,7 +52,7 @@ public class TestRemoveWatches extends BaseClassForTests
                         
             client.checkExists().watched().forPath(path);
             
-            client.removeWatches().allWatches().ofType(WatcherType.Data).forPath(path);
+            client.watches().removeAll().ofType(WatcherType.Data).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -91,7 +91,7 @@ public class TestRemoveWatches extends BaseClassForTests
                         
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.removeWatches().watcher(watcher).ofType(WatcherType.Data).forPath(path);
+            client.watches().remove(watcher).ofType(WatcherType.Data).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -129,7 +129,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.removeWatches().watcher(watcher).ofType(WatcherType.Data).forPath(path);
+            client.watches().remove(watcher).ofType(WatcherType.Data).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -181,7 +181,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).inBackground(callback).forPath(path);
+            client.watches().remove(watcher).ofType(WatcherType.Any).inBackground(callback).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
             
@@ -219,7 +219,7 @@ public class TestRemoveWatches extends BaseClassForTests
             
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).inBackground().forPath(path);
+            client.watches().remove(watcher).ofType(WatcherType.Any).inBackground().forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
             
@@ -271,7 +271,7 @@ public class TestRemoveWatches extends BaseClassForTests
             client.checkExists().usingWatcher(watcher1).forPath(path);
             client.checkExists().usingWatcher(watcher2).forPath(path);
             
-            client.removeWatches().allWatches().ofType(WatcherType.Any).forPath(path);
+            client.watches().removeAll().ofType(WatcherType.Any).forPath(path);
             
             Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
@@ -279,5 +279,56 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             CloseableUtils.closeQuietly(client);
         }
-    }    
+    }  
+    
+    /**
+     * TODO: THIS IS STILL A WORK IN PROGRESS. local() is currently broken if no connection to ZK is available.
+     * @throws Exception
+     */
+    @Test
+    public void testRemoveLocalWatch() throws Exception {
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final String path = "/";
+            
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            Watcher watcher = new Watcher()
+            {                
+                @Override
+                public void process(WatchedEvent event)
+                {
+                    if(event.getPath() == null || event.getType() == null) {
+                        return;
+                    }
+                    
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }
+                }
+            };            
+            
+            client.checkExists().usingWatcher(watcher).forPath(path);
+            
+            //Stop the server so we can check if we can remove watches locally when offline
+            server.stop();
+            
+            timing.sleepABit();
+            
+            client.watches().removeAll().ofType(WatcherType.Any).local().forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
 }


[13/31] curator git commit: more tests

Posted by dr...@apache.org.
more tests


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/ff8eb4b2
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/ff8eb4b2
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/ff8eb4b2

Branch: refs/heads/CURATOR-3.0
Commit: ff8eb4b2ec7c99258e62416453bef649fdc6220e
Parents: 49b2fd3
Author: randgalt <ra...@apache.org>
Authored: Mon May 11 20:48:16 2015 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon May 11 20:48:16 2015 -0500

----------------------------------------------------------------------
 .../imps/TestWatcherRemovalManager.java         | 54 ++++++++++++++++++++
 1 file changed, 54 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/ff8eb4b2/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
index d951c57..9508f43 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
@@ -170,6 +170,60 @@ public class TestWatcherRemovalManager extends BaseClassForTests
         }
     }
 
+    @Test
+    public void testResetFromWatcher() throws Exception
+    {
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            final WatcherRemovalFacade removerClient = (WatcherRemovalFacade)client.newWatcherRemoveCuratorFramework();
+
+            final CountDownLatch latch = new CountDownLatch(1);
+            Watcher watcher = new Watcher()
+            {
+                @Override
+                public void process(WatchedEvent event)
+                {
+                    if ( event.getType() == Event.EventType.NodeCreated )
+                    {
+                        try
+                        {
+                            removerClient.checkExists().usingWatcher(this).forPath("/yo");
+                        }
+                        catch ( Exception e )
+                        {
+                            e.printStackTrace();
+                        }
+                    }
+                    else if ( event.getType() == Event.EventType.NodeDeleted )
+                    {
+                        latch.countDown();
+                    }
+                }
+            };
+
+            removerClient.checkExists().usingWatcher(watcher).forPath("/yo");
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
+            removerClient.create().forPath("/yo");
+
+            timing.sleepABit();
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 1);
+
+            removerClient.delete().forPath("/yo");
+
+            Assert.assertTrue(timing.awaitLatch(latch));
+
+            Assert.assertEquals(removerClient.getRemovalManager().getEntries().size(), 0);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
     private void internalTryBasic(CuratorFramework client) throws Exception
     {
         WatcherRemoveCuratorFramework removerClient = client.newWatcherRemoveCuratorFramework();


[29/31] curator git commit: Added WatcherRemoveCuratorFramework to locks and updated tests to check for cleanliness

Posted by dr...@apache.org.
Added WatcherRemoveCuratorFramework to locks and updated tests to check for cleanliness


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/f0a09db4
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/f0a09db4
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/f0a09db4

Branch: refs/heads/CURATOR-3.0
Commit: f0a09db4423f06455ed93c20778c65aaf7e8b06e
Parents: 2c921d6
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 22:42:14 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 22:42:14 2015 -0700

----------------------------------------------------------------------
 .../framework/imps/WatcherRemovalFacade.java    |   3 +-
 .../locks/InterProcessSemaphoreMutex.java       |   6 +-
 .../recipes/locks/InterProcessSemaphoreV2.java  |  54 +++--
 .../framework/recipes/locks/LockInternals.java  |   9 +-
 .../locks/TestInterProcessMultiMutex.java       |   7 +-
 .../recipes/locks/TestInterProcessMutex.java    |   5 +-
 .../locks/TestInterProcessMutexBase.java        |  23 +-
 .../locks/TestInterProcessReadWriteLock.java    | 223 +++++++++++--------
 .../locks/TestInterProcessSemaphore.java        |  27 ++-
 .../locks/TestInterProcessSemaphoreCluster.java |   3 +-
 .../framework/recipes/locks/TestLockACLs.java   |   3 +-
 .../locks/TestLockCleanlinessWithFaults.java    |   3 +-
 12 files changed, 213 insertions(+), 153 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
index eee423f..156341e 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import org.apache.curator.CuratorZookeeperClient;
@@ -45,7 +46,7 @@ class WatcherRemovalFacade extends CuratorFrameworkImpl implements WatcherRemove
     @Override
     public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework()
     {
-        throw new UnsupportedOperationException();
+        return client.newWatcherRemoveCuratorFramework();
     }
 
     WatcherRemovalManager getRemovalManager()

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreMutex.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreMutex.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreMutex.java
index 88b5f5d..444b10d 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreMutex.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreMutex.java
@@ -20,6 +20,7 @@ package org.apache.curator.framework.recipes.locks;
 
 import com.google.common.base.Preconditions;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -29,6 +30,7 @@ import java.util.concurrent.TimeUnit;
 public class InterProcessSemaphoreMutex implements InterProcessLock
 {
     private final InterProcessSemaphoreV2 semaphore;
+    private final WatcherRemoveCuratorFramework watcherRemoveClient;
     private volatile Lease lease;
 
     /**
@@ -37,7 +39,8 @@ public class InterProcessSemaphoreMutex implements InterProcessLock
      */
     public InterProcessSemaphoreMutex(CuratorFramework client, String path)
     {
-        this.semaphore = new InterProcessSemaphoreV2(client, path, 1);
+        watcherRemoveClient = client.newWatcherRemoveCuratorFramework();
+        this.semaphore = new InterProcessSemaphoreV2(watcherRemoveClient, path, 1);
     }
 
     @Override
@@ -66,6 +69,7 @@ public class InterProcessSemaphoreMutex implements InterProcessLock
         try
         {
             lease.close();
+            watcherRemoveClient.removeWatchers();
         }
         finally
         {

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
index 2e14ee1..2a55107 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java
@@ -21,6 +21,7 @@ package org.apache.curator.framework.recipes.locks;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.framework.CuratorFramework;
@@ -75,7 +76,7 @@ public class InterProcessSemaphoreV2
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final InterProcessMutex lock;
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final String leasesPath;
     private final Watcher watcher = new Watcher()
     {
@@ -115,7 +116,7 @@ public class InterProcessSemaphoreV2
 
     private InterProcessSemaphoreV2(CuratorFramework client, String path, int maxLeases, SharedCountReader count)
     {
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         path = PathUtils.validatePath(path);
         lock = new InterProcessMutex(client, ZKPaths.makePath(path, LOCK_PARENT));
         this.maxLeases = (count != null) ? count.getCount() : maxLeases;
@@ -345,36 +346,43 @@ public class InterProcessSemaphoreV2
             String nodeName = ZKPaths.getNodeFromPath(path);
             builder.add(makeLease(path));
 
-            synchronized(this)
+            try
             {
-                for(;;)
+                synchronized(this)
                 {
-                    List<String> children = client.getChildren().usingWatcher(watcher).forPath(leasesPath);
-                    if ( !children.contains(nodeName) )
+                    for(;;)
                     {
-                        log.error("Sequential path not found: " + path);
-                        return InternalAcquireResult.RETRY_DUE_TO_MISSING_NODE;
-                    }
+                        List<String> children = client.getChildren().usingWatcher(watcher).forPath(leasesPath);
+                        if ( !children.contains(nodeName) )
+                        {
+                            log.error("Sequential path not found: " + path);
+                            return InternalAcquireResult.RETRY_DUE_TO_MISSING_NODE;
+                        }
 
-                    if ( children.size() <= maxLeases )
-                    {
-                        break;
-                    }
-                    if ( hasWait )
-                    {
-                        long thisWaitMs = getThisWaitMs(startMs, waitMs);
-                        if ( thisWaitMs <= 0 )
+                        if ( children.size() <= maxLeases )
                         {
-                            return InternalAcquireResult.RETURN_NULL;
+                            break;
+                        }
+                        if ( hasWait )
+                        {
+                            long thisWaitMs = getThisWaitMs(startMs, waitMs);
+                            if ( thisWaitMs <= 0 )
+                            {
+                                return InternalAcquireResult.RETURN_NULL;
+                            }
+                            wait(thisWaitMs);
+                        }
+                        else
+                        {
+                            wait();
                         }
-                        wait(thisWaitMs);
-                    }
-                    else
-                    {
-                        wait();
                     }
                 }
             }
+            finally
+            {
+                client.removeWatchers();
+            }
         }
         finally
         {

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/LockInternals.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/LockInternals.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/LockInternals.java
index 2b4d3d9..4b0da11 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/LockInternals.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/LockInternals.java
@@ -24,11 +24,11 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.CuratorWatcher;
 import org.apache.curator.framework.imps.CuratorFrameworkState;
 import org.apache.curator.utils.PathUtils;
 import org.apache.curator.utils.ZKPaths;
-import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
@@ -42,7 +42,7 @@ import java.util.concurrent.atomic.AtomicReference;
 
 public class LockInternals
 {
-    private final CuratorFramework                  client;
+    private final WatcherRemoveCuratorFramework     client;
     private final String                            path;
     private final String                            basePath;
     private final LockInternalsDriver               driver;
@@ -100,7 +100,7 @@ public class LockInternals
         this.lockName = lockName;
         this.maxLeases = maxLeases;
 
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         this.basePath = PathUtils.validatePath(path);
         this.path = ZKPaths.makePath(path, lockName);
     }
@@ -116,8 +116,9 @@ public class LockInternals
         revocable.set(entry);
     }
 
-    void releaseLock(String lockPath) throws Exception
+    final void releaseLock(String lockPath) throws Exception
     {
+        client.removeWatchers();
         revocable.set(null);
         deleteOurPath(lockPath);
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java
index b1631a0..df6a2f5 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java
@@ -20,6 +20,7 @@ package org.apache.curator.framework.recipes.locks;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.retry.RetryOneTime;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -84,13 +85,14 @@ public class TestInterProcessMultiMutex extends TestInterProcessMutexBase
             }
             catch ( Exception e )
             {
+                // ignore
             }
             Assert.assertFalse(goodLock.isAcquiredInThisProcess());
             Assert.assertTrue(otherGoodLock.isAcquiredInThisProcess());
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -142,13 +144,14 @@ public class TestInterProcessMultiMutex extends TestInterProcessMutexBase
             }
             catch ( Exception e )
             {
+                // ignore
             }
             Assert.assertFalse(goodLock.isAcquiredInThisProcess());
             Assert.assertTrue(goodLockWasLocked.get());
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java
index 453de33..d6f8a1d 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java
@@ -20,6 +20,7 @@ package org.apache.curator.framework.recipes.locks;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.KillSession;
 import org.apache.zookeeper.CreateMode;
@@ -106,7 +107,7 @@ public class TestInterProcessMutex extends TestInterProcessMutexBase
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -151,7 +152,7 @@ public class TestInterProcessMutex extends TestInterProcessMutexBase
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/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 3fe8110..49e5d19 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
@@ -20,16 +20,14 @@
 package org.apache.curator.framework.recipes.locks;
 
 import com.google.common.collect.Lists;
-import org.apache.curator.test.BaseClassForTests;
-import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.KillSession;
-import org.apache.curator.test.TestingServer;
 import org.apache.curator.test.Timing;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -123,7 +121,7 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -199,7 +197,7 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -265,7 +263,7 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -311,7 +309,7 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -328,7 +326,7 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -460,11 +458,14 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
                 Assert.assertTrue(acquiredLatchForClient1.await(10, TimeUnit.SECONDS));
                 Assert.assertTrue(mutexForClient1.isAcquiredInThisProcess());
             }
+
+            future1.get();
+            future2.get();
         }
         finally
         {
-            CloseableUtils.closeQuietly(client1);
-            CloseableUtils.closeQuietly(client2);
+            TestCleanState.closeAndTestClean(client1);
+            TestCleanState.closeAndTestClean(client2);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessReadWriteLock.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessReadWriteLock.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessReadWriteLock.java
index f7636ed..48e4805 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessReadWriteLock.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessReadWriteLock.java
@@ -16,14 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.recipes.locks;
 
 import com.google.common.collect.Lists;
-import org.apache.curator.test.BaseClassForTests;
-import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import java.util.Collection;
@@ -31,6 +32,7 @@ import java.util.List;
 import java.util.Random;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorCompletionService;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -40,21 +42,22 @@ import java.util.concurrent.atomic.AtomicInteger;
 public class TestInterProcessReadWriteLock extends BaseClassForTests
 {
     @Test
-    public void     testGetParticipantNodes() throws Exception
+    public void testGetParticipantNodes() throws Exception
     {
-        final int               READERS = 20;
-        final int               WRITERS = 8;
+        final int READERS = 20;
+        final int WRITERS = 8;
 
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
         try
         {
             client.start();
 
-            final CountDownLatch              latch = new CountDownLatch(READERS + WRITERS);
-            final CountDownLatch              readLatch = new CountDownLatch(READERS);
-            final InterProcessReadWriteLock   lock = new InterProcessReadWriteLock(client, "/lock");
+            final CountDownLatch latch = new CountDownLatch(READERS + WRITERS);
+            final CountDownLatch readLatch = new CountDownLatch(READERS);
+            final InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/lock");
 
-            ExecutorService                   service = Executors.newCachedThreadPool();
+            final CountDownLatch exitLatch = new CountDownLatch(1);
+            ExecutorCompletionService<Void> service = new ExecutorCompletionService<Void>(Executors.newCachedThreadPool());
             for ( int i = 0; i < READERS; ++i )
             {
                 service.submit
@@ -65,8 +68,16 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
                         public Void call() throws Exception
                         {
                             lock.readLock().acquire();
-                            latch.countDown();
-                            readLatch.countDown();
+                            try
+                            {
+                                latch.countDown();
+                                readLatch.countDown();
+                                exitLatch.await();
+                            }
+                            finally
+                            {
+                                lock.readLock().release();
+                            }
                             return null;
                         }
                     }
@@ -84,6 +95,14 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
                             Assert.assertTrue(readLatch.await(10, TimeUnit.SECONDS));
                             latch.countDown();  // must be before as there can only be one writer
                             lock.writeLock().acquire();
+                            try
+                            {
+                                exitLatch.await();
+                            }
+                            finally
+                            {
+                                lock.writeLock().release();
+                            }
                             return null;
                         }
                     }
@@ -97,22 +116,28 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
 
             Assert.assertEquals(readers.size(), READERS);
             Assert.assertEquals(writers.size(), WRITERS);
+
+            exitLatch.countDown();
+            for ( int i = 0; i < (READERS + WRITERS); ++i )
+            {
+                service.take().get();
+            }
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
     @Test
-    public void     testThatUpgradingIsDisallowed() throws Exception
+    public void testThatUpgradingIsDisallowed() throws Exception
     {
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
         try
         {
             client.start();
 
-            InterProcessReadWriteLock   lock = new InterProcessReadWriteLock(client, "/lock");
+            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/lock");
             lock.readLock().acquire();
             Assert.assertFalse(lock.writeLock().acquire(5, TimeUnit.SECONDS));
 
@@ -120,70 +145,80 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
     @Test
-    public void     testThatDowngradingRespectsThreads() throws Exception
+    public void testThatDowngradingRespectsThreads() throws Exception
     {
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
         try
         {
             client.start();
 
-            final InterProcessReadWriteLock   lock = new InterProcessReadWriteLock(client, "/lock");
-            ExecutorService                   t1 = Executors.newSingleThreadExecutor();
-            ExecutorService                   t2 = Executors.newSingleThreadExecutor();
+            final InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/lock");
+            ExecutorService t1 = Executors.newSingleThreadExecutor();
+            ExecutorService t2 = Executors.newSingleThreadExecutor();
 
-            final CountDownLatch              latch = new CountDownLatch(1);
+            final CountDownLatch latch = new CountDownLatch(1);
 
-            Future<Object>                    f1 = t1.submit
-            (
-                new Callable<Object>()
-                {
-                    @Override
-                    public Object call() throws Exception
+            final CountDownLatch releaseLatch = new CountDownLatch(1);
+            Future<Object> f1 = t1.submit
+                (
+                    new Callable<Object>()
                     {
-                        lock.writeLock().acquire();
-                        latch.countDown();
-                        return null;
+                        @Override
+                        public Object call() throws Exception
+                        {
+                            lock.writeLock().acquire();
+                            latch.countDown();
+                            try
+                            {
+                                releaseLatch.await();
+                            }
+                            finally
+                            {
+                                lock.writeLock().release();
+                            }
+                            return null;
+                        }
                     }
-                }
-            );
+                );
 
-            Future<Object>                    f2 = t2.submit
-            (
-                new Callable<Object>()
-                {
-                    @Override
-                    public Object call() throws Exception
+            Future<Object> f2 = t2.submit
+                (
+                    new Callable<Object>()
                     {
-                        Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));
-                        Assert.assertFalse(lock.readLock().acquire(5, TimeUnit.SECONDS));
-                        return null;
+                        @Override
+                        public Object call() throws Exception
+                        {
+                            Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));
+                            Assert.assertFalse(lock.readLock().acquire(5, TimeUnit.SECONDS));
+                            return null;
+                        }
                     }
-                }
-            );
+                );
 
-            f1.get();
             f2.get();
+            releaseLatch.countDown();
+            f1.get();
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
     @Test
-    public void     testDowngrading() throws Exception
+    public void testDowngrading() throws Exception
     {
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
         try
         {
             client.start();
 
-            InterProcessReadWriteLock   lock = new InterProcessReadWriteLock(client, "/lock");
+            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/lock");
             lock.writeLock().acquire();
             Assert.assertTrue(lock.readLock().acquire(5, TimeUnit.SECONDS));
             lock.writeLock().release();
@@ -192,60 +227,60 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
     @Test
-    public void     testBasic() throws Exception
+    public void testBasic() throws Exception
     {
-        final int               CONCURRENCY = 8;
-        final int               ITERATIONS = 100;
+        final int CONCURRENCY = 8;
+        final int ITERATIONS = 100;
 
-        final Random            random = new Random();
-        final AtomicInteger     concurrentCount = new AtomicInteger(0);
-        final AtomicInteger     maxConcurrentCount = new AtomicInteger(0);
-        final AtomicInteger     writeCount = new AtomicInteger(0);
-        final AtomicInteger     readCount = new AtomicInteger(0);
+        final Random random = new Random();
+        final AtomicInteger concurrentCount = new AtomicInteger(0);
+        final AtomicInteger maxConcurrentCount = new AtomicInteger(0);
+        final AtomicInteger writeCount = new AtomicInteger(0);
+        final AtomicInteger readCount = new AtomicInteger(0);
 
-        List<Future<Void>>  futures = Lists.newArrayList();
-        ExecutorService     service = Executors.newCachedThreadPool();
+        List<Future<Void>> futures = Lists.newArrayList();
+        ExecutorService service = Executors.newCachedThreadPool();
         for ( int i = 0; i < CONCURRENCY; ++i )
         {
-            Future<Void>    future = service.submit
-            (
-                new Callable<Void>()
-                {
-                    @Override
-                    public Void call() throws Exception
+            Future<Void> future = service.submit
+                (
+                    new Callable<Void>()
                     {
-                        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-                        client.start();
-                        try
+                        @Override
+                        public Void call() throws Exception
                         {
-                            InterProcessReadWriteLock   lock = new InterProcessReadWriteLock(client, "/lock");
-                            for ( int i = 0; i < ITERATIONS; ++i )
+                            CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+                            client.start();
+                            try
                             {
-                                if ( random.nextInt(100) < 10 )
+                                InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/lock");
+                                for ( int i = 0; i < ITERATIONS; ++i )
                                 {
-                                    doLocking(lock.writeLock(), concurrentCount, maxConcurrentCount, random, 1);
-                                    writeCount.incrementAndGet();
-                                }
-                                else
-                                {
-                                    doLocking(lock.readLock(), concurrentCount, maxConcurrentCount, random, Integer.MAX_VALUE);
-                                    readCount.incrementAndGet();
+                                    if ( random.nextInt(100) < 10 )
+                                    {
+                                        doLocking(lock.writeLock(), concurrentCount, maxConcurrentCount, random, 1);
+                                        writeCount.incrementAndGet();
+                                    }
+                                    else
+                                    {
+                                        doLocking(lock.readLock(), concurrentCount, maxConcurrentCount, random, Integer.MAX_VALUE);
+                                        readCount.incrementAndGet();
+                                    }
                                 }
                             }
+                            finally
+                            {
+                                TestCleanState.closeAndTestClean(client);
+                            }
+                            return null;
                         }
-                        finally
-                        {
-                            CloseableUtils.closeQuietly(client);
-                        }
-                        return null;
                     }
-                }
-            );
+                );
             futures.add(future);
         }
 
@@ -262,17 +297,17 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
     }
 
     @Test
-    public void     testSetNodeData() throws Exception
+    public void testSetNodeData() throws Exception
     {
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
 
         try
         {
             client.start();
 
-            final byte[] nodeData = new byte[] { 1, 2, 3, 4 };
+            final byte[] nodeData = new byte[]{1, 2, 3, 4};
 
-            InterProcessReadWriteLock   lock = new InterProcessReadWriteLock(client, "/lock", nodeData);
+            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/lock", nodeData);
 
             // mutate passed-in node data, lock has made copy
             nodeData[0] = 5;
@@ -284,13 +319,13 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
 
             byte dataInZk[] = client.getData().forPath("/lock/" + children.get(0));
             Assert.assertNotNull(dataInZk);
-            Assert.assertEquals(new byte[] { 1, 2, 3, 4 }, dataInZk);
+            Assert.assertEquals(new byte[]{1, 2, 3, 4}, dataInZk);
 
             lock.writeLock().release();
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -299,7 +334,7 @@ public class TestInterProcessReadWriteLock extends BaseClassForTests
         try
         {
             Assert.assertTrue(lock.acquire(10, TimeUnit.SECONDS));
-            int     localConcurrentCount;
+            int localConcurrentCount;
             synchronized(this)
             {
                 localConcurrentCount = concurrentCount.incrementAndGet();

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
index dd3f98f..2797b5f 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java
@@ -20,13 +20,14 @@
 package org.apache.curator.framework.recipes.locks;
 
 import com.google.common.collect.Lists;
-import org.apache.curator.test.BaseClassForTests;
-import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.framework.recipes.shared.SharedCount;
 import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.Timing;
+import org.apache.curator.utils.CloseableUtils;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import java.util.Collection;
@@ -100,10 +101,12 @@ public class TestInterProcessSemaphore extends BaseClassForTests
 
             future1.get();
             future2.get();
+
+            count.close();
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -140,8 +143,8 @@ public class TestInterProcessSemaphore extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client1);
-            CloseableUtils.closeQuietly(client2);
+            TestCleanState.closeAndTestClean(client1);
+            TestCleanState.closeAndTestClean(client2);
         }
     }
 
@@ -226,7 +229,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
                                     }
                                     finally
                                     {
-                                        client.close();
+                                        TestCleanState.closeAndTestClean(client);
                                     }
                                     return null;
                                 }
@@ -299,7 +302,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
                             }
                             finally
                             {
-                                client.close();
+                                TestCleanState.closeAndTestClean(client);
                             }
                             return null;
                         }
@@ -401,7 +404,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -445,7 +448,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -463,7 +466,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -499,7 +502,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
             {
                 CloseableUtils.closeQuietly(l);
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -528,7 +531,7 @@ public class TestInterProcessSemaphore extends BaseClassForTests
             {
                 CloseableUtils.closeQuietly(l);
             }
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreCluster.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreCluster.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreCluster.java
index 2aa8a72..f4cb7bb 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreCluster.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreCluster.java
@@ -22,6 +22,7 @@ import com.google.common.collect.Lists;
 import org.apache.curator.ensemble.EnsembleProvider;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.retry.ExponentialBackoffRetry;
@@ -147,7 +148,7 @@ public class TestInterProcessSemaphoreCluster
                             }
                             finally
                             {
-                                CloseableUtils.closeQuietly(client);
+                                TestCleanState.closeAndTestClean(client);
                             }
                             return null;
                         }

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockACLs.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockACLs.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockACLs.java
index 2d9a9aa..d1e6db5 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockACLs.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockACLs.java
@@ -19,6 +19,7 @@
 
 package org.apache.curator.framework.recipes.locks;
 
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.RetryPolicy;
@@ -74,7 +75,7 @@ public class TestLockACLs extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/f0a09db4/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockCleanlinessWithFaults.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockCleanlinessWithFaults.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockCleanlinessWithFaults.java
index 457be75..dc14c11 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockCleanlinessWithFaults.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestLockCleanlinessWithFaults.java
@@ -20,6 +20,7 @@ package org.apache.curator.framework.recipes.locks;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.retry.RetryNTimes;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.utils.CloseableUtils;
@@ -67,7 +68,7 @@ public class TestLockCleanlinessWithFaults extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 }


[04/31] curator git commit: CURATOR-161 - Updates to unit tests.

Posted by dr...@apache.org.
CURATOR-161 - Updates to unit tests.

Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/b2b9af31
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/b2b9af31
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/b2b9af31

Branch: refs/heads/CURATOR-3.0
Commit: b2b9af31c181d7e4f790dbfd9f8850a7b948822d
Parents: 9ff9ccd
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Tue Dec 2 09:56:02 2014 +1100
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Tue Dec 2 09:56:02 2014 +1100

----------------------------------------------------------------------
 .../framework/imps/TestRemoveWatches.java       | 121 ++++++++++++++-----
 1 file changed, 93 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/b2b9af31/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index d7e8886..15fb24c 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -7,6 +7,7 @@ import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.CuratorListener;
 import org.apache.curator.framework.api.CuratorWatcher;
 import org.apache.curator.retry.RetryOneTime;
@@ -15,16 +16,56 @@ import org.apache.curator.test.Timing;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.Watcher.Event.EventType;
 import org.apache.zookeeper.Watcher.WatcherType;
-import org.apache.zookeeper.ZooKeeper;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class TestRemoveWatches extends BaseClassForTests
 {
     @Test
+    public void testRemoveCuratorDefaultWatcher() throws Exception
+    {
+        Timing timing = new Timing();
+        CuratorFramework client = CuratorFrameworkFactory.builder().
+                connectString(server.getConnectString()).
+                retryPolicy(new RetryOneTime(1)).
+                build();
+        try
+        {
+            client.start();
+            
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            final String path = "/";            
+            client.getCuratorListenable().addListener(new CuratorListener()
+            {                
+                @Override
+                public void eventReceived(CuratorFramework client, CuratorEvent event)
+                        throws Exception
+                {
+                    if(event.getType() == CuratorEventType.WATCHED && event.getWatchedEvent().getType() == EventType.DataWatchRemoved) {                        
+                        removedLatch.countDown();
+                    }        
+                }
+            });
+                        
+            client.checkExists().watched().forPath(path);
+            
+            client.removeWatches().allWatches().ofType(WatcherType.Data).forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    @Test
     public void testRemoveCuratorWatch() throws Exception
     {       
+        Timing timing = new Timing();
         CuratorFramework client = CuratorFrameworkFactory.builder().
                 connectString(server.getConnectString()).
                 retryPolicy(new RetryOneTime(1)).
@@ -33,21 +74,26 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            final String path = "/";            
             CuratorWatcher watcher = new CuratorWatcher()
             {
                 
                 @Override
                 public void process(WatchedEvent event) throws Exception
                 {
-                    // TODO Auto-generated method stub
-                    
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }
                 }
             };
-            
-            String path = "/";
+                        
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).forPath(path);
+            client.removeWatches().watcher(watcher).ofType(WatcherType.Data).forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
         finally
         {
@@ -58,6 +104,7 @@ public class TestRemoveWatches extends BaseClassForTests
     @Test
     public void testRemoveWatch() throws Exception
     {       
+        Timing timing = new Timing();
         CuratorFramework client = CuratorFrameworkFactory.builder().
                 connectString(server.getConnectString()).
                 retryPolicy(new RetryOneTime(1)).
@@ -66,18 +113,25 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
+            final String path = "/";    
             Watcher watcher = new Watcher()
             {                
                 @Override
                 public void process(WatchedEvent event)
                 {
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }                    
                 }
             };
             
-            String path = "/";
             client.checkExists().usingWatcher(watcher).forPath(path);
             
-            client.removeWatches().watcher(watcher).ofType(WatcherType.Any).forPath(path);
+            client.removeWatches().watcher(watcher).ofType(WatcherType.Data).forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
         finally
         {
@@ -94,18 +148,23 @@ public class TestRemoveWatches extends BaseClassForTests
                 retryPolicy(new RetryOneTime(1)).
                 build();
         try
-        {
+        {            
             client.start();
-            
+         
+            //Make sure that the event fires on both the watcher and the callback.
+            final CountDownLatch removedLatch = new CountDownLatch(2);
+            final String path = "/";
             Watcher watcher = new Watcher()
             {                
                 @Override
                 public void process(WatchedEvent event)
                 {
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }                        
                 }
             };
-
-            final CountDownLatch removedLatch = new CountDownLatch(1);
+            
             BackgroundCallback callback = new BackgroundCallback()
             {
                 
@@ -113,11 +172,13 @@ public class TestRemoveWatches extends BaseClassForTests
                 public void processResult(CuratorFramework client, CuratorEvent event)
                         throws Exception
                 {
-                    removedLatch.countDown();
+                    if(event.getType() == CuratorEventType.REMOVE_WATCHES && event.getPath().equals(path)) {
+                        removedLatch.countDown();
+                    }
                 }
             };
             
-            String path = "/";
+            
             client.checkExists().usingWatcher(watcher).forPath(path);
             
             client.removeWatches().watcher(watcher).ofType(WatcherType.Any).inBackground(callback).forPath(path);
@@ -143,27 +204,19 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            final String path = "/";
+            final CountDownLatch removedLatch = new CountDownLatch(1);
             Watcher watcher = new Watcher()
             {                
                 @Override
                 public void process(WatchedEvent event)
                 {
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }                    
                 }
             };
-
-            final CountDownLatch removedLatch = new CountDownLatch(1);
-            client.getCuratorListenable().addListener(new CuratorListener()
-            {
-                
-                @Override
-                public void eventReceived(CuratorFramework client, CuratorEvent event)
-                        throws Exception
-                {
-                    removedLatch.countDown();
-                }
-            });
             
-            String path = "/";
             client.checkExists().usingWatcher(watcher).forPath(path);
             
             client.removeWatches().watcher(watcher).ofType(WatcherType.Any).inBackground().forPath(path);
@@ -180,6 +233,7 @@ public class TestRemoveWatches extends BaseClassForTests
     @Test
     public void testRemoveAllWatches() throws Exception
     {       
+        Timing timing = new Timing();
         CuratorFramework client = CuratorFrameworkFactory.builder().
                 connectString(server.getConnectString()).
                 retryPolicy(new RetryOneTime(1)).
@@ -188,11 +242,17 @@ public class TestRemoveWatches extends BaseClassForTests
         {
             client.start();
             
+            final String path = "/";
+            final CountDownLatch removedLatch = new CountDownLatch(2);
+            
             Watcher watcher1 = new Watcher()
             {                
                 @Override
                 public void process(WatchedEvent event)
                 {
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }
                 }
             };
             
@@ -201,14 +261,19 @@ public class TestRemoveWatches extends BaseClassForTests
                 @Override
                 public void process(WatchedEvent event)
                 {
+                    if(event.getPath().equals(path) && event.getType() == EventType.DataWatchRemoved) {
+                        removedLatch.countDown();
+                    }                    
                 }
             };            
             
-            String path = "/";
+            
             client.checkExists().usingWatcher(watcher1).forPath(path);
             client.checkExists().usingWatcher(watcher2).forPath(path);
             
             client.removeWatches().allWatches().ofType(WatcherType.Any).forPath(path);
+            
+            Assert.assertTrue(timing.awaitLatch(removedLatch), "Timed out waiting for watch removal");
         }
         finally
         {


[18/31] curator git commit: doc

Posted by dr...@apache.org.
doc


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/79d152ca
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/79d152ca
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/79d152ca

Branch: refs/heads/CURATOR-3.0
Commit: 79d152ca42b0a34826369c5620ce7807c668ad63
Parents: 5030c19
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 16:37:08 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 16:37:08 2015 -0700

----------------------------------------------------------------------
 .../java/org/apache/curator/framework/CuratorFramework.java | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/79d152ca/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 75b434a..f75a5a8 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -236,5 +236,12 @@ public interface CuratorFramework extends Closeable
      */
     public void blockUntilConnected() throws InterruptedException;
 
-    WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework();
+    /**
+     * Returns a facade of the current instance that tracks
+     * watchers created and allows a one-shot removal of all watchers
+     * via {@link WatcherRemoveCuratorFramework#removeWatchers()}
+     *
+     * @return facade
+     */
+    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework();
 }


[27/31] curator git commit: Use WatcherRemoveCuratorFramework in a few more places

Posted by dr...@apache.org.
Use WatcherRemoveCuratorFramework in a few more places


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/a95d52e5
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/a95d52e5
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/a95d52e5

Branch: refs/heads/CURATOR-3.0
Commit: a95d52e53ef0fc63468eb1fc257869c82bd3dc4e
Parents: eba6ce8
Author: randgalt <ra...@apache.org>
Authored: Tue May 19 20:01:26 2015 -0700
Committer: randgalt <ra...@apache.org>
Committed: Tue May 19 20:01:26 2015 -0700

----------------------------------------------------------------------
 .../apache/curator/framework/recipes/leader/LeaderLatch.java   | 6 ++++--
 .../framework/recipes/nodes/PersistentEphemeralNode.java       | 6 ++++--
 .../apache/curator/framework/recipes/queue/ChildrenCache.java  | 6 ++++--
 .../apache/curator/framework/recipes/shared/SharedValue.java   | 6 ++++--
 4 files changed, 16 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/a95d52e5/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java
index 40d92e4..8d2d0f0 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.listen.ListenerContainer;
@@ -63,7 +64,7 @@ import org.apache.curator.utils.PathUtils;
 public class LeaderLatch implements Closeable
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final String latchPath;
     private final String id;
     private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
@@ -143,7 +144,7 @@ public class LeaderLatch implements Closeable
      */
     public LeaderLatch(CuratorFramework client, String latchPath, String id, CloseMode closeMode)
     {
-        this.client = Preconditions.checkNotNull(client, "client cannot be null");
+        this.client = Preconditions.checkNotNull(client, "client cannot be null").newWatcherRemoveCuratorFramework();
         this.latchPath = PathUtils.validatePath(latchPath);
         this.id = Preconditions.checkNotNull(id, "id cannot be null");
         this.closeMode = Preconditions.checkNotNull(closeMode, "closeMode cannot be null");
@@ -206,6 +207,7 @@ public class LeaderLatch implements Closeable
         try
         {
             setNode(null);
+            client.removeWatchers();
         }
         catch ( Exception e )
         {

http://git-wip-us.apache.org/repos/asf/curator/blob/a95d52e5/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
index d78573c..3bad8e3 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java
@@ -21,6 +21,7 @@ package org.apache.curator.framework.recipes.nodes;
 
 import com.google.common.base.Preconditions;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.ACLBackgroundPathAndBytesable;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CreateModable;
@@ -54,7 +55,7 @@ public class PersistentEphemeralNode implements Closeable
 {
     private final AtomicReference<CountDownLatch> initialCreateLatch = new AtomicReference<CountDownLatch>(new CountDownLatch(1));
     private final Logger log = LoggerFactory.getLogger(getClass());
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final CreateModable<ACLBackgroundPathAndBytesable<String>> createMethod;
     private final AtomicReference<String> nodePath = new AtomicReference<String>(null);
     private final String basePath;
@@ -190,7 +191,7 @@ public class PersistentEphemeralNode implements Closeable
      */
     public PersistentEphemeralNode(CuratorFramework client, Mode mode, String basePath, byte[] data)
     {
-        this.client = Preconditions.checkNotNull(client, "client cannot be null");
+        this.client = Preconditions.checkNotNull(client, "client cannot be null").newWatcherRemoveCuratorFramework();
         this.basePath = PathUtils.validatePath(basePath);
         this.mode = Preconditions.checkNotNull(mode, "mode cannot be null");
         data = Preconditions.checkNotNull(data, "data cannot be null");
@@ -268,6 +269,7 @@ public class PersistentEphemeralNode implements Closeable
             return;
         }
 
+        client.removeWatchers();
         client.getConnectionStateListenable().removeListener(connectionStateListener);
 
         try

http://git-wip-us.apache.org/repos/asf/curator/blob/a95d52e5/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/ChildrenCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/ChildrenCache.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/ChildrenCache.java
index 032dc7a..e5c7e8c 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/ChildrenCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/ChildrenCache.java
@@ -21,6 +21,7 @@ package org.apache.curator.framework.recipes.queue;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorWatcher;
@@ -36,7 +37,7 @@ import org.apache.curator.utils.PathUtils;
 
 class ChildrenCache implements Closeable
 {
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final String path;
     private final AtomicReference<Data> children = new AtomicReference<Data>(new Data(Lists.<String>newArrayList(), 0));
     private final AtomicBoolean isClosed = new AtomicBoolean(false);
@@ -79,7 +80,7 @@ class ChildrenCache implements Closeable
 
     ChildrenCache(CuratorFramework client, String path)
     {
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         this.path = PathUtils.validatePath(path);
     }
 
@@ -91,6 +92,7 @@ class ChildrenCache implements Closeable
     @Override
     public void close() throws IOException
     {
+        client.removeWatchers();
         isClosed.set(true);
         notifyFromCallback();
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/a95d52e5/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
index 6ca53ec..7e7ad56 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java
@@ -22,6 +22,7 @@ package org.apache.curator.framework.recipes.shared;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.CuratorWatcher;
 import org.apache.curator.framework.listen.ListenerContainer;
 import org.apache.curator.framework.state.ConnectionState;
@@ -45,7 +46,7 @@ public class SharedValue implements Closeable, SharedValueReader
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final ListenerContainer<SharedValueListener> listeners = new ListenerContainer<SharedValueListener>();
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final String path;
     private final byte[] seedValue;
     private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
@@ -87,7 +88,7 @@ public class SharedValue implements Closeable, SharedValueReader
      */
     public SharedValue(CuratorFramework client, String path, byte[] seedValue)
     {
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         this.path = PathUtils.validatePath(path);
         this.seedValue = Arrays.copyOf(seedValue, seedValue.length);
         currentValue = new AtomicReference<VersionedValue<byte[]>>(new VersionedValue<byte[]>(0, Arrays.copyOf(seedValue, seedValue.length)));
@@ -233,6 +234,7 @@ public class SharedValue implements Closeable, SharedValueReader
     @Override
     public void close() throws IOException
     {
+        client.removeWatchers();
         client.getConnectionStateListenable().removeListener(connectionStateListener);
         state.set(State.CLOSED);
         listeners.clear();


[16/31] curator git commit: CURATOR-161 - Modified the background processing framework to allow operations to request that a live connection is not necessary to execute (this is needed to run the remove watches with 'local' set to true. Cleaned up some u

Posted by dr...@apache.org.
CURATOR-161 - Modified the background processing framework to allow
operations to request that a live connection is not necessary to execute
(this is needed to run the remove watches with 'local' set to true.
Cleaned up some unit tests.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/ba4da2c3
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/ba4da2c3
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/ba4da2c3

Branch: refs/heads/CURATOR-3.0
Commit: ba4da2c3c7048ea249f18e7b4c815db76f0b1ad0
Parents: 22d034a
Author: Cameron McKenzie <ca...@unico.com.au>
Authored: Thu May 14 09:19:09 2015 +1000
Committer: Cameron McKenzie <ca...@unico.com.au>
Committed: Thu May 14 09:19:09 2015 +1000

----------------------------------------------------------------------
 .../framework/imps/CuratorFrameworkImpl.java    |  2 +-
 .../framework/imps/OperationAndData.java        | 16 ++++-
 .../imps/RemoveWatchesBuilderImpl.java          | 22 ++++--
 .../framework/imps/TestRemoveWatches.java       | 73 ++++++++------------
 4 files changed, 58 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/ba4da2c3/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index b4a1d93..c82f984 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -821,7 +821,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
     {
         try
         {
-            if ( client.isConnected() )
+            if ( !operationAndData.isConnectionRequired() || client.isConnected() )
             {
                 operationAndData.callPerformBackgroundOperation();
             }

http://git-wip-us.apache.org/repos/asf/curator/blob/ba4da2c3/curator-framework/src/main/java/org/apache/curator/framework/imps/OperationAndData.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/OperationAndData.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/OperationAndData.java
index 38f59a0..b46cddb 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/OperationAndData.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/OperationAndData.java
@@ -40,25 +40,37 @@ class OperationAndData<T> implements Delayed, RetrySleeper
     private final AtomicLong sleepUntilTimeMs = new AtomicLong(0);
     private final long ordinal = nextOrdinal.getAndIncrement();
     private final Object context;
+    private final boolean connectionRequired;
 
     interface ErrorCallback<T>
     {
         void retriesExhausted(OperationAndData<T> operationAndData);
     }
-
-    OperationAndData(BackgroundOperation<T> operation, T data, BackgroundCallback callback, ErrorCallback<T> errorCallback, Object context)
+    
+    OperationAndData(BackgroundOperation<T> operation, T data, BackgroundCallback callback, ErrorCallback<T> errorCallback, Object context, boolean connectionRequired)
     {
         this.operation = operation;
         this.data = data;
         this.callback = callback;
         this.errorCallback = errorCallback;
         this.context = context;
+        this.connectionRequired = connectionRequired;
+    }      
+
+    OperationAndData(BackgroundOperation<T> operation, T data, BackgroundCallback callback, ErrorCallback<T> errorCallback, Object context)
+    {
+        this(operation, data, callback, errorCallback, context, true);
     }
 
     Object getContext()
     {
         return context;
     }
+    
+    boolean isConnectionRequired()
+    {
+        return connectionRequired;
+    }
 
     void callPerformBackgroundOperation() throws Exception
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/ba4da2c3/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index 27d05da..932706b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -166,15 +166,23 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
     
     private void pathInBackground(final String path)
     {
-        OperationAndData.ErrorCallback<String>  errorCallback = new OperationAndData.ErrorCallback<String>()
+        OperationAndData.ErrorCallback<String>  errorCallback = null;
+        
+        //Only need an error callback if we're in guaranteed mode
+        if(guaranteed)
         {
-            @Override
-            public void retriesExhausted(OperationAndData<String> operationAndData)
+            errorCallback = new OperationAndData.ErrorCallback<String>()
             {
-                client.getFailedRemoveWatcherManager().addFailedOperation(new FailedRemoveWatchManager.FailedRemoveWatchDetails(path, watcher));
-            }            
-        };        
-        client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(), errorCallback, backgrounding.getContext()), null);
+                @Override
+                public void retriesExhausted(OperationAndData<String> operationAndData)
+                {
+                    client.getFailedRemoveWatcherManager().addFailedOperation(new FailedRemoveWatchManager.FailedRemoveWatchDetails(path, watcher));
+                }            
+            };
+        }
+        
+        client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(),
+                                                                       errorCallback, backgrounding.getContext(), !local), null);
     }
     
     private void pathInForeground(final String path) throws Exception

http://git-wip-us.apache.org/repos/asf/curator/blob/ba4da2c3/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 518f13b..fc15f0c 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -1,8 +1,9 @@
 package org.apache.curator.framework.imps;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -24,13 +25,30 @@ import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.Watcher.Event.EventType;
 import org.apache.zookeeper.Watcher.WatcherType;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.data.Stat;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class TestRemoveWatches extends BaseClassForTests
 {
+    private boolean blockUntilDesiredConnectionState(CuratorFramework client, Timing timing, final ConnectionState desiredState)
+    {
+        final CountDownLatch latch = new CountDownLatch(1);
+        client.getConnectionStateListenable().addListener(new ConnectionStateListener()
+        {
+            
+            @Override
+            public void stateChanged(CuratorFramework client, ConnectionState newState)
+            {
+                if(newState == desiredState)
+                {
+                    latch.countDown();
+                }
+            }
+        });
+        
+        return timing.awaitLatch(latch);
+    }
+    
     @Test
     public void testRemoveCuratorDefaultWatcher() throws Exception
     {
@@ -330,7 +348,7 @@ public class TestRemoveWatches extends BaseClassForTests
             //Stop the server so we can check if we can remove watches locally when offline
             server.stop();
             
-            timing.sleepABit();
+            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
                        
             client.watches().removeAll().locally().forPath(path);
             
@@ -364,7 +382,7 @@ public class TestRemoveWatches extends BaseClassForTests
             //Stop the server so we can check if we can remove watches locally when offline
             server.stop();
             
-            timing.sleepABit();
+            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
                        
             client.watches().removeAll().locally().inBackground().forPath(path);
             
@@ -452,25 +470,7 @@ public class TestRemoveWatches extends BaseClassForTests
         try
         {
             client.start();
-            
-            final CountDownLatch reconnectedLatch = new CountDownLatch(1);
-            final CountDownLatch suspendedLatch = new CountDownLatch(1);
-            client.getConnectionStateListenable().addListener(new ConnectionStateListener()
-            {
-                @Override
-                public void stateChanged(CuratorFramework client, ConnectionState newState)
-                {
-                    if(newState == ConnectionState.SUSPENDED)
-                    {
-                        suspendedLatch.countDown();
-                    }
-                    else if(newState == ConnectionState.RECONNECTED)
-                    {
-                        reconnectedLatch.countDown();
-                    }
-                }
-            });
-            
+                       
             String path = "/";
             
             CountDownLatch removeLatch = new CountDownLatch(1);
@@ -479,7 +479,8 @@ public class TestRemoveWatches extends BaseClassForTests
             client.checkExists().usingWatcher(watcher).forPath(path);
             
             server.stop();           
-            timing.awaitLatch(suspendedLatch);
+            
+            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
             
             //Remove the watch while we're not connected
             try 
@@ -510,25 +511,7 @@ public class TestRemoveWatches extends BaseClassForTests
         try
         {
             client.start();
-            
-            final CountDownLatch reconnectedLatch = new CountDownLatch(1);
-            final CountDownLatch suspendedLatch = new CountDownLatch(1);
-            client.getConnectionStateListenable().addListener(new ConnectionStateListener()
-            {
-                @Override
-                public void stateChanged(CuratorFramework client, ConnectionState newState)
-                {
-                    if(newState == ConnectionState.SUSPENDED)
-                    {
-                        suspendedLatch.countDown();
-                    }
-                    else if(newState == ConnectionState.RECONNECTED)
-                    {
-                        reconnectedLatch.countDown();
-                    }
-                }
-            });
-            
+                        
             final CountDownLatch guaranteeAddedLatch = new CountDownLatch(1);
             
             ((CuratorFrameworkImpl)client).getFailedRemoveWatcherManager().debugListener = new FailedOperationManager.FailedOperationManagerListener<FailedRemoveWatchManager.FailedRemoveWatchDetails>()
@@ -550,7 +533,7 @@ public class TestRemoveWatches extends BaseClassForTests
             client.checkExists().usingWatcher(watcher).forPath(path);
             
             server.stop();           
-            timing.awaitLatch(suspendedLatch);
+            blockUntilDesiredConnectionState(client, timing, ConnectionState.SUSPENDED);
             
             //Remove the watch while we're not connected
             client.watches().remove(watcher).guaranteed().inBackground().forPath(path);


[10/31] curator git commit: wip

Posted by dr...@apache.org.
wip


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/d3672a5a
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/d3672a5a
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/d3672a5a

Branch: refs/heads/CURATOR-3.0
Commit: d3672a5acbd2bdf0f8caa9b7c8ea07e9d4e4dd2a
Parents: 58fcc54
Author: randgalt <ra...@apache.org>
Authored: Mon May 11 16:19:45 2015 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon May 11 16:19:45 2015 -0500

----------------------------------------------------------------------
 .../WatcherRemoveCuratorFramework.java          |  18 +++
 .../api/BackgroundPathableQuietly.java          |  18 +++
 .../apache/curator/framework/api/Quietly.java   |  18 +++
 .../framework/api/RemoveWatchesBuilder.java     |  18 +++
 .../framework/api/RemoveWatchesLocal.java       |  18 +++
 .../framework/api/RemoveWatchesType.java        |  18 +++
 .../curator/framework/imps/NamespaceFacade.java |   6 -
 .../imps/RemoveWatchesBuilderImpl.java          |  20 +++-
 .../framework/imps/WatcherRemovalFacade.java    |   4 +-
 .../framework/imps/WatcherRemovalManager.java   |  20 +++-
 .../framework/imps/TestRemoveWatches.java       |  18 +++
 .../imps/TestWatcherRemovalManager.java         | 113 +++++++++++++++----
 .../recipes/cache/PathChildrenCache.java        |   9 +-
 .../curator/framework/imps/TestCleanState.java  |  68 +++++++++++
 .../recipes/cache/TestPathChildrenCache.java    |  60 +++++-----
 .../org/apache/curator/test/WatchersDebug.java  |  18 +++
 16 files changed, 385 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
index 58b4bf8..e41b186 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/WatcherRemoveCuratorFramework.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework;
 
 public interface WatcherRemoveCuratorFramework extends CuratorFramework

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
index 1174067..13202aa 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundPathableQuietly.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.api;
 
 public interface BackgroundPathableQuietly<T> extends BackgroundPathable<T>, Quietly<BackgroundPathable<T>>

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
index cf4edc8..ad3762f 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Quietly.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.api;
 
 public interface Quietly<T>

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
index 5d48a9e..6cc0b05 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesBuilder.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.api;
 
 import org.apache.zookeeper.Watcher;

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
index d183a6a..de6ad9b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesLocal.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.api;
 
 /**

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
index 3c58b7b..4885423 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/RemoveWatchesType.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.api;
 
 import org.apache.zookeeper.Watcher.WatcherType;

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
index 8dc7ae1..c8b952a 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceFacade.java
@@ -42,12 +42,6 @@ class NamespaceFacade extends CuratorFrameworkImpl
     }
 
     @Override
-    public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework()
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public CuratorFramework nonNamespaceView()
     {
         return usingNamespace(null);

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
index ab977a9..10d58d0 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/RemoveWatchesBuilderImpl.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.imps;
 
 import java.util.concurrent.Callable;
@@ -157,7 +175,7 @@ public class RemoveWatchesBuilderImpl implements RemoveWatchesBuilder, RemoveWat
         client.processBackgroundOperation(new OperationAndData<String>(this, path, backgrounding.getCallback(), errorCallback, backgrounding.getContext()), null);
     }
     
-    private void pathInForeground(final String path) throws Exception
+    void pathInForeground(final String path) throws Exception
     {
         RetryLoop.callWithRetry(client.getZookeeperClient(), 
                 new Callable<Void>()

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
index a11ca5d..664c9b0 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalFacade.java
@@ -63,13 +63,13 @@ class WatcherRemovalFacade extends CuratorFrameworkImpl implements WatcherRemove
     @Override
     public CuratorFramework nonNamespaceView()
     {
-        return client.usingNamespace(null);
+        return client.nonNamespaceView();
     }
 
     @Override
     public CuratorFramework usingNamespace(String newNamespace)
     {
-        return client.getNamespaceFacadeCache().get(newNamespace);
+        return client.usingNamespace(newNamespace);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
index 9461de5..689ade2 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/WatcherRemovalManager.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.imps;
 
 import com.google.common.collect.Maps;
@@ -36,7 +54,7 @@ class WatcherRemovalManager
                 log.debug("Removing watcher for path: " + path);
                 RemoveWatchesBuilderImpl builder = new RemoveWatchesBuilderImpl(client);
                 builder.prepInternalRemoval(watcher);
-                builder.forPath(path);
+                builder.pathInForeground(path);
             }
             catch ( Exception e )
             {

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
index 28799f7..0533b25 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestRemoveWatches.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.imps;
 
 import java.util.concurrent.CountDownLatch;

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
index 9a5dbdc..6e28bea 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestWatcherRemovalManager.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.framework.imps;
 
 import org.apache.curator.framework.CuratorFramework;
@@ -23,32 +41,89 @@ public class TestWatcherRemovalManager extends BaseClassForTests
         try
         {
             client.start();
+            internalTryBasic(client);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
 
-            WatcherRemoveCuratorFramework removerClient = client.newWatcherRemoveCuratorFramework();
-
-            Watcher watcher = new Watcher()
-            {
-                @Override
-                public void process(WatchedEvent event)
-                {
-                    // NOP
-                }
-            };
-            removerClient.checkExists().usingWatcher(watcher).forPath("/hey");
-
-            List<String> existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
-            Assert.assertEquals(existWatches.size(), 1);
-
-            removerClient.removeWatchers();
+    @Test
+    public void testBasicNamespace1() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+            internalTryBasic(client.usingNamespace("foo"));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
 
-            new Timing().sleepABit();
+    @Test
+    public void testBasicNamespace2() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.builder()
+            .connectString(server.getConnectString())
+            .retryPolicy(new RetryOneTime(1))
+            .namespace("hey")
+            .build();
+        try
+        {
+            client.start();
+            internalTryBasic(client);
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
 
-            existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
-            Assert.assertEquals(existWatches.size(), 0);
+    @Test
+    public void testBasicNamespace3() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.builder()
+            .connectString(server.getConnectString())
+            .retryPolicy(new RetryOneTime(1))
+            .namespace("hey")
+            .build();
+        try
+        {
+            client.start();
+            internalTryBasic(client.usingNamespace("lakjsf"));
         }
         finally
         {
             CloseableUtils.closeQuietly(client);
         }
     }
+
+    private void internalTryBasic(CuratorFramework client) throws Exception
+    {
+        WatcherRemoveCuratorFramework removerClient = client.newWatcherRemoveCuratorFramework();
+
+        Watcher watcher = new Watcher()
+        {
+            @Override
+            public void process(WatchedEvent event)
+            {
+                // NOP
+            }
+        };
+        removerClient.checkExists().usingWatcher(watcher).forPath("/hey");
+
+        List<String> existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
+        Assert.assertEquals(existWatches.size(), 1);
+
+        removerClient.removeWatchers();
+
+        new Timing().sleepABit();
+
+        existWatches = WatchersDebug.getExistWatches(client.getZookeeperClient().getZooKeeper());
+        Assert.assertEquals(existWatches.size(), 0);
+    }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
index 71d83fe..5c413b6 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
@@ -24,10 +24,10 @@ import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.WatcherRemoveCuratorFramework;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.listen.ListenerContainer;
@@ -35,6 +35,7 @@ import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.utils.CloseableExecutorService;
 import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.PathUtils;
 import org.apache.curator.utils.ThreadUtils;
 import org.apache.curator.utils.ZKPaths;
 import org.apache.zookeeper.KeeperException;
@@ -54,7 +55,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicReference;
-import org.apache.curator.utils.PathUtils;
 
 /**
  * <p>A utility that attempts to keep all data from all children of a ZK path locally cached. This class
@@ -69,7 +69,7 @@ import org.apache.curator.utils.PathUtils;
 public class PathChildrenCache implements Closeable
 {
     private final Logger log = LoggerFactory.getLogger(getClass());
-    private final CuratorFramework client;
+    private final WatcherRemoveCuratorFramework client;
     private final String path;
     private final CloseableExecutorService executorService;
     private final boolean cacheData;
@@ -216,7 +216,7 @@ public class PathChildrenCache implements Closeable
      */
     public PathChildrenCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, final CloseableExecutorService executorService)
     {
-        this.client = client;
+        this.client = client.newWatcherRemoveCuratorFramework();
         this.path = PathUtils.validatePath(path);
         this.cacheData = cacheData;
         this.dataIsCompressed = dataIsCompressed;
@@ -375,6 +375,7 @@ public class PathChildrenCache implements Closeable
             executorService.close();
             client.clearWatcherReferences(childrenWatcher);
             client.clearWatcherReferences(dataWatcher);
+            client.removeWatchers();
 
             // TODO
             // This seems to enable even more GC - I'm not sure why yet - it

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java b/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
new file mode 100644
index 0000000..95a1088
--- /dev/null
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/imps/TestCleanState.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.framework.imps;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.test.WatchersDebug;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.ZooKeeper;
+
+public class TestCleanState
+{
+    public static void closeAndTestClean(CuratorFramework client)
+    {
+        if ( client == null )
+        {
+            return;
+        }
+
+        try
+        {
+            CuratorFrameworkImpl internalClient = (CuratorFrameworkImpl)client;
+            ZooKeeper zooKeeper = internalClient.getZooKeeper();
+            if ( zooKeeper != null )
+            {
+                if ( WatchersDebug.getChildWatches(zooKeeper).size() != 0 )
+                {
+                    throw new AssertionError("One or more child watchers are still registered");
+                }
+                if ( WatchersDebug.getExistWatches(zooKeeper).size() != 0 )
+                {
+                    throw new AssertionError("One or more exists watchers are still registered");
+                }
+                if ( WatchersDebug.getDataWatches(zooKeeper).size() != 0 )
+                {
+                    throw new AssertionError("One or more data watchers are still registered");
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();    // not sure what to do here
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    private TestCleanState()
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
index b904bdc..ffcf251 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java
@@ -28,7 +28,7 @@ import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.Pathable;
 import org.apache.curator.framework.api.UnhandledErrorListener;
-import org.apache.curator.framework.imps.CuratorFrameworkImpl;
+import org.apache.curator.framework.imps.TestCleanState;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.BaseClassForTests;
 import org.apache.curator.test.KillSession;
@@ -96,15 +96,13 @@ public class TestPathChildrenCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
     @Test
     public void testClientClosedDuringRefreshErrorMessage() throws Exception
     {
-        Timing timing = new Timing();
-
         // Fiddle with logging so we can intercept the error events for org.apache.curator
         final List<LoggingEvent> events = Lists.newArrayList();
         Collection<String> messages = Collections2.transform(events, new Function<LoggingEvent, String>() {
@@ -216,7 +214,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -270,7 +268,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -319,7 +317,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -328,6 +326,7 @@ public class TestPathChildrenCache extends BaseClassForTests
     {
         Timing timing = new Timing();
 
+        PathChildrenCache cache = null;
         CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
         client.start();
         try
@@ -335,7 +334,7 @@ public class TestPathChildrenCache extends BaseClassForTests
             final CountDownLatch updatedLatch = new CountDownLatch(1);
             final CountDownLatch addedLatch = new CountDownLatch(1);
             client.create().creatingParentsIfNeeded().forPath("/test");
-            PathChildrenCache cache = new PathChildrenCache(client, "/test", false);
+            cache = new PathChildrenCache(client, "/test", false);
             cache.getListenable().addListener
                 (
                     new PathChildrenCacheListener()
@@ -364,7 +363,8 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            CloseableUtils.closeQuietly(cache);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -392,7 +392,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -468,7 +468,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -562,7 +562,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -571,6 +571,7 @@ public class TestPathChildrenCache extends BaseClassForTests
     public void testIssue27() throws Exception
     {
         Timing timing = new Timing();
+        PathChildrenCache cache = null;
         CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
         client.start();
         try
@@ -584,7 +585,7 @@ public class TestPathChildrenCache extends BaseClassForTests
 
             final List<PathChildrenCacheEvent.Type> events = Lists.newArrayList();
             final Semaphore semaphore = new Semaphore(0);
-            PathChildrenCache cache = new PathChildrenCache(client, "/base", true);
+            cache = new PathChildrenCache(client, "/base", true);
             cache.getListenable().addListener
                 (
                     new PathChildrenCacheListener()
@@ -619,7 +620,8 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            CloseableUtils.closeQuietly(cache);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -628,6 +630,7 @@ public class TestPathChildrenCache extends BaseClassForTests
     public void testIssue27Alt() throws Exception
     {
         Timing timing = new Timing();
+        PathChildrenCache cache = null;
         CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
         client.start();
         try
@@ -641,7 +644,7 @@ public class TestPathChildrenCache extends BaseClassForTests
 
             final List<PathChildrenCacheEvent.Type> events = Lists.newArrayList();
             final Semaphore semaphore = new Semaphore(0);
-            PathChildrenCache cache = new PathChildrenCache(client, "/base", true);
+            cache = new PathChildrenCache(client, "/base", true);
             cache.getListenable().addListener
                 (
                     new PathChildrenCacheListener()
@@ -671,7 +674,8 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            CloseableUtils.closeQuietly(cache);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -679,6 +683,7 @@ public class TestPathChildrenCache extends BaseClassForTests
     public void testKilledSession() throws Exception
     {
         Timing timing = new Timing();
+        PathChildrenCache cache = null;
         CuratorFramework client = null;
         try
         {
@@ -686,7 +691,7 @@ public class TestPathChildrenCache extends BaseClassForTests
             client.start();
             client.create().forPath("/test");
 
-            PathChildrenCache cache = new PathChildrenCache(client, "/test", true);
+            cache = new PathChildrenCache(client, "/test", true);
             cache.start();
 
             final CountDownLatch childAddedLatch = new CountDownLatch(1);
@@ -730,7 +735,8 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            CloseableUtils.closeQuietly(client);
+            CloseableUtils.closeQuietly(cache);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -754,7 +760,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -798,7 +804,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         finally
         {
             CloseableUtils.closeQuietly(cache);
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -886,7 +892,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -955,7 +961,7 @@ public class TestPathChildrenCache extends BaseClassForTests
         }
         finally
         {
-            client.close();
+            TestCleanState.closeAndTestClean(client);
         }
     }
 
@@ -988,8 +994,9 @@ public class TestPathChildrenCache extends BaseClassForTests
             timing.sleepABit();
             Assert.assertFalse(exec.isExecuteCalled());
         }
-        finally {
-            client.close();
+        finally
+        {
+            TestCleanState.closeAndTestClean(client);
         }
 
     }
@@ -1034,9 +1041,10 @@ public class TestPathChildrenCache extends BaseClassForTests
             latch.await(5, TimeUnit.SECONDS);
 
             Assert.assertTrue(latch.getCount() == 1, "Unexpected exception occurred");
-        } finally
+        }
+        finally
         {
-            CloseableUtils.closeQuietly(client);
+            TestCleanState.closeAndTestClean(client);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/d3672a5a/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
----------------------------------------------------------------------
diff --git a/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java b/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
index a97e5c1..e4c3b7e 100644
--- a/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
+++ b/curator-test/src/main/java/org/apache/curator/test/WatchersDebug.java
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.curator.test;
 
 import org.apache.zookeeper.ZooKeeper;