curator-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dragonsi...@apache.org
Subject [01/41] curator git commit: Assuming that ZOOKEEPER-2163 is accepted, container node support has been added to Curator. Also, all recipes that create parent nodes now create container nodes
Date Mon, 17 Aug 2015 17:02:09 GMT
Repository: curator
Updated Branches:
  refs/heads/CURATOR-3.0 8c8d7ec2b -> 44ee8547e


Assuming that ZOOKEEPER-2163 is accepted, container node support has been added to Curator. Also, all recipes that create parent nodes now create container nodes


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

Branch: refs/heads/CURATOR-3.0
Commit: 04ae8115512f03210cf930118788c67e433bd904
Parents: 7f20986
Author: randgalt <randgalt@apache.org>
Authored: Tue May 19 14:33:24 2015 -0700
Committer: randgalt <randgalt@apache.org>
Committed: Tue May 19 14:33:24 2015 -0700

----------------------------------------------------------------------
 .../org/apache/curator/utils/EnsurePath.java    | 22 +++++-
 .../curator/utils/EnsurePathContainers.java     | 49 +++++++++++++
 .../java/org/apache/curator/utils/ZKPaths.java  | 23 +++++-
 .../src/main/java/cache/PathCacheExample.java   |  2 +-
 .../curator/framework/CuratorFramework.java     |  9 +++
 .../api/CreateBackgroundModeACLable.java        |  7 ++
 .../curator/framework/api/CreateBuilder.java    |  7 ++
 .../framework/imps/CreateBuilderImpl.java       | 20 ++++-
 .../framework/imps/CuratorFrameworkImpl.java    |  7 ++
 .../curator/framework/imps/NamespaceFacade.java |  7 ++
 .../curator/framework/imps/NamespaceImpl.java   |  6 ++
 .../curator/framework/imps/TestFramework.java   | 43 +++++++++++
 .../recipes/atomic/DistributedAtomicValue.java  |  9 +--
 .../recipes/barriers/DistributedBarrier.java    |  2 +-
 .../barriers/DistributedDoubleBarrier.java      |  2 +-
 .../framework/recipes/cache/NodeCache.java      |  8 +-
 .../recipes/cache/PathChildrenCache.java        |  9 +--
 .../framework/recipes/leader/LeaderLatch.java   |  2 +-
 .../framework/recipes/locks/ChildReaper.java    |  4 +
 .../recipes/locks/InterProcessSemaphoreV2.java  |  2 +-
 .../curator/framework/recipes/locks/Reaper.java |  4 +
 .../locks/StandardLockInternalsDriver.java      |  4 +-
 .../recipes/nodes/PersistentEphemeralNode.java  |  2 +-
 .../recipes/queue/DistributedQueue.java         |  4 +-
 .../recipes/queue/SimpleDistributedQueue.java   |  8 +-
 .../framework/recipes/shared/SharedValue.java   |  2 +-
 .../src/site/confluence/index.confluence        |  2 +
 .../locks/TestInterProcessMultiMutex.java       |  4 +-
 .../recipes/locks/TestInterProcessMutex.java    |  2 +-
 .../locks/TestInterProcessMutexBase.java        | 77 +++++++++++++++++++-
 .../locks/TestInterProcessSemaphoreMutex.java   |  2 +-
 .../discovery/details/ServiceDiscoveryImpl.java |  4 +-
 .../idl/services/CuratorProjectionService.java  |  4 +
 .../curator/x/rpc/idl/structs/CreateSpec.java   |  6 +-
 .../x/rpc/idl/structs/RpcCreateMode.java        |  3 +-
 curator-x-rpc/src/main/thrift/curator.thrift    |  3 +-
 .../src/site/confluence/reference.confluence    |  1 +
 pom.xml                                         |  2 +-
 src/site/confluence/utilities.confluence        | 14 ----
 39 files changed, 324 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-client/src/main/java/org/apache/curator/utils/EnsurePath.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/utils/EnsurePath.java b/curator-client/src/main/java/org/apache/curator/utils/EnsurePath.java
index f072775..3181aca 100644
--- a/curator-client/src/main/java/org/apache/curator/utils/EnsurePath.java
+++ b/curator-client/src/main/java/org/apache/curator/utils/EnsurePath.java
@@ -64,7 +64,7 @@ public class EnsurePath
         }
     };
 
-    private interface Helper
+    interface Helper
     {
         public void ensure(CuratorZookeeperClient client, String path, final boolean makeLastNode) throws Exception;
     }
@@ -110,7 +110,18 @@ public class EnsurePath
         return new EnsurePath(path, helper, false, aclProvider);
     }
 
-    private EnsurePath(String path, AtomicReference<Helper> helper, boolean makeLastNode, InternalACLProvider aclProvider)
+    /**
+     * Returns a view of this EnsurePath instance that does not make the last node and also makes containers.
+     * i.e. if the path is "/a/b/c" only "/a/b" will be ensured
+     *
+     * @return view
+     */
+    public EnsurePathContainers excludingLastContainers()
+    {
+        return new EnsurePathContainers(path, helper, false, aclProvider);
+    }
+
+    protected EnsurePath(String path, AtomicReference<Helper> helper, boolean makeLastNode, InternalACLProvider aclProvider)
     {
         this.path = path;
         this.makeLastNode = makeLastNode;
@@ -128,6 +139,11 @@ public class EnsurePath
         return this.path;
     }
 
+    protected boolean asContainers()
+    {
+        return false;
+    }
+
     private class InitialHelper implements Helper
     {
         private boolean isSet = false;  // guarded by synchronization
@@ -145,7 +161,7 @@ public class EnsurePath
                             @Override
                             public Object call() throws Exception
                             {
-                                ZKPaths.mkdirs(client.getZooKeeper(), path, makeLastNode, aclProvider);
+                                ZKPaths.mkdirs(client.getZooKeeper(), path, makeLastNode, aclProvider, asContainers());
                                 helper.set(doNothingHelper);
                                 isSet = true;
                                 return null;

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-client/src/main/java/org/apache/curator/utils/EnsurePathContainers.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/utils/EnsurePathContainers.java b/curator-client/src/main/java/org/apache/curator/utils/EnsurePathContainers.java
new file mode 100644
index 0000000..455d58d
--- /dev/null
+++ b/curator-client/src/main/java/org/apache/curator/utils/EnsurePathContainers.java
@@ -0,0 +1,49 @@
+/**
+ * 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.utils;
+
+import org.apache.zookeeper.CreateMode;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Same as {@link EnsurePath} but creates parents as {@link CreateMode#CONTAINER}
+ */
+public class EnsurePathContainers extends EnsurePath
+{
+    public EnsurePathContainers(String path)
+    {
+        super(path);
+    }
+
+    public EnsurePathContainers(String path, InternalACLProvider aclProvider)
+    {
+        super(path, aclProvider);
+    }
+
+    EnsurePathContainers(String path, AtomicReference<EnsurePath.Helper> helper, boolean makeLastNode, InternalACLProvider aclProvider)
+    {
+        super(path, helper, makeLastNode, aclProvider);
+    }
+
+    @Override
+    protected boolean asContainers()
+    {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java b/curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java
index f4623a3..3a68b5b 100644
--- a/curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java
+++ b/curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java
@@ -161,7 +161,7 @@ public class ZKPaths
      */
     public static void mkdirs(ZooKeeper zookeeper, String path) throws InterruptedException, KeeperException
     {
-        mkdirs(zookeeper, path, true, null);
+        mkdirs(zookeeper, path, true, null, false);
     }
 
     /**
@@ -176,7 +176,7 @@ public class ZKPaths
      */
     public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode) throws InterruptedException, KeeperException
     {
-        mkdirs(zookeeper, path, makeLastNode, null);
+        mkdirs(zookeeper, path, makeLastNode, null, false);
     }
 
     /**
@@ -192,6 +192,23 @@ public class ZKPaths
      */
     public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode, InternalACLProvider aclProvider) throws InterruptedException, KeeperException
     {
+        mkdirs(zookeeper, path, makeLastNode, aclProvider, false);
+    }
+
+    /**
+     * Make sure all the nodes in the path are created. NOTE: Unlike File.mkdirs(), Zookeeper doesn't distinguish
+     * between directories and files. So, every node in the path is created. The data for each node is an empty blob
+     *
+     * @param zookeeper    the client
+     * @param path         path to ensure
+     * @param makeLastNode if true, all nodes are created. If false, only the parent nodes are created
+     * @param aclProvider  if not null, the ACL provider to use when creating parent nodes
+     * @param asContainers if true, nodes are created as {@link CreateMode#CONTAINER}
+     * @throws InterruptedException                 thread interruption
+     * @throws org.apache.zookeeper.KeeperException Zookeeper errors
+     */
+    public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode, InternalACLProvider aclProvider, boolean asContainers) throws InterruptedException, KeeperException
+    {
         PathUtils.validatePath(path);
 
         int pos = 1; // skip first slash, root is guaranteed to exist
@@ -229,7 +246,7 @@ public class ZKPaths
                     {
                         acl = ZooDefs.Ids.OPEN_ACL_UNSAFE;
                     }
-                    zookeeper.create(subPath, new byte[0], acl, CreateMode.PERSISTENT);
+                    zookeeper.create(subPath, new byte[0], acl, asContainers ? CreateMode.CONTAINER : CreateMode.PERSISTENT);
                 }
                 catch ( KeeperException.NodeExistsException e )
                 {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-examples/src/main/java/cache/PathCacheExample.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/cache/PathCacheExample.java b/curator-examples/src/main/java/cache/PathCacheExample.java
index 7c25ec1..e121337 100644
--- a/curator-examples/src/main/java/cache/PathCacheExample.java
+++ b/curator-examples/src/main/java/cache/PathCacheExample.java
@@ -231,7 +231,7 @@ public class PathCacheExample
         }
         catch ( KeeperException.NoNodeException e )
         {
-            client.create().creatingParentsIfNeeded().forPath(path, bytes);
+            client.create().creatingParentContainersIfNeeded().forPath(path, bytes);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..0e09872 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
@@ -27,6 +27,7 @@ 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.curator.utils.EnsurePathContainers;
 import org.apache.zookeeper.Watcher;
 
 import java.io.Closeable;
@@ -207,6 +208,14 @@ public interface CuratorFramework extends Closeable
     public EnsurePath newNamespaceAwareEnsurePath(String path);
 
     /**
+     * Allocates an ensure path containers instance that is namespace aware
+     *
+     * @param path path to ensure
+     * @return new EnsurePath instance
+     */
+    public EnsurePathContainers newNamespaceAwareEnsurePathContainers(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.
      *

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBackgroundModeACLable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBackgroundModeACLable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBackgroundModeACLable.java
index d2a4e27..3dc9c21 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBackgroundModeACLable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBackgroundModeACLable.java
@@ -31,6 +31,13 @@ public interface CreateBackgroundModeACLable extends
     public ACLCreateModePathAndBytesable<String>    creatingParentsIfNeeded();
 
     /**
+     * Causes any parent nodes to get created as containers if they haven't already been
+     *
+     * @return this
+     */
+    public ACLCreateModePathAndBytesable<String> creatingParentContainersIfNeeded();
+
+    /**
      * <p>
      *     Hat-tip to https://github.com/sbridges for pointing this out
      * </p>

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBuilder.java
index d29b475..9e6ad15 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CreateBuilder.java
@@ -32,6 +32,13 @@ public interface CreateBuilder extends
     public ProtectACLCreateModePathAndBytesable<String> creatingParentsIfNeeded();
 
     /**
+     * Causes any parent nodes to get created as containers if they haven't already been
+     *
+     * @return this
+     */
+    public ProtectACLCreateModePathAndBytesable<String> creatingParentContainersIfNeeded();
+
+    /**
      * @deprecated this has been generalized to support all create modes. Instead, use:
      * <pre>
      *     client.create().withProtection().withMode(CreateMode.PERSISTENT_SEQUENTIAL)...

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
index 6eef4d4..7b1e855 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
@@ -47,6 +47,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
     private CreateMode createMode;
     private Backgrounding backgrounding;
     private boolean createParentsIfNeeded;
+    private boolean createParentsAsContainers;
     private boolean doProtected;
     private boolean compress;
     private String protectedId;
@@ -65,6 +66,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
         backgrounding = new Backgrounding();
         acling = new ACLing(client.getAclProvider());
         createParentsIfNeeded = false;
+        createParentsAsContainers = false;
         compress = false;
         doProtected = false;
         protectedId = null;
@@ -130,6 +132,13 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
             }
 
             @Override
+            public ACLCreateModePathAndBytesable<String> creatingParentContainersIfNeeded()
+            {
+                createParentsAsContainers = true;
+                return creatingParentsIfNeeded();
+            }
+
+            @Override
             public ACLPathAndBytesable<String> withProtectedEphemeralSequential()
             {
                 return CreateBuilderImpl.this.withProtectedEphemeralSequential();
@@ -260,6 +269,13 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
     }
 
     @Override
+    public ProtectACLCreateModePathAndBytesable<String> creatingParentContainersIfNeeded()
+    {
+        createParentsAsContainers = true;
+        return creatingParentsIfNeeded();
+    }
+
+    @Override
     public ProtectACLCreateModePathAndBytesable<String> creatingParentsIfNeeded()
     {
         createParentsIfNeeded = true;
@@ -519,7 +535,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
             {
                 try
                 {
-                    ZKPaths.mkdirs(client.getZooKeeper(), mainOperationAndData.getData().getPath(), false, client.getAclProvider());
+                    ZKPaths.mkdirs(client.getZooKeeper(), mainOperationAndData.getData().getPath(), false, client.getAclProvider(), createParentsAsContainers);
                 }
                 catch ( KeeperException e )
                 {
@@ -699,7 +715,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
                             {
                                 if ( createParentsIfNeeded )
                                 {
-                                    ZKPaths.mkdirs(client.getZooKeeper(), path, false, client.getAclProvider());
+                                    ZKPaths.mkdirs(client.getZooKeeper(), path, false, client.getAclProvider(), createParentsAsContainers);
                                     createdPath = client.getZooKeeper().create(path, data, acling.getAclList(path), createMode);
                                 }
                                 else

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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 5034ed9..800b67f 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
@@ -39,6 +39,7 @@ import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.framework.state.ConnectionStateManager;
 import org.apache.curator.utils.DebugUtils;
 import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.EnsurePathContainers;
 import org.apache.curator.utils.ThreadUtils;
 import org.apache.curator.utils.ZookeeperFactory;
 import org.apache.zookeeper.KeeperException;
@@ -457,6 +458,12 @@ public class CuratorFrameworkImpl implements CuratorFramework
         return namespace.newNamespaceAwareEnsurePath(path);
     }
 
+    @Override
+    public EnsurePathContainers newNamespaceAwareEnsurePathContainers(String path)
+    {
+        return namespace.newNamespaceAwareEnsurePathContainers(path);
+    }
+
     ACLProvider getAclProvider()
     {
         return aclProvider;

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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 3f24c79..7807f69 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
@@ -25,6 +25,7 @@ import org.apache.curator.framework.api.*;
 import org.apache.curator.framework.listen.Listenable;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.EnsurePathContainers;
 import org.apache.zookeeper.ZooKeeper;
 
 class NamespaceFacade extends CuratorFrameworkImpl
@@ -149,6 +150,12 @@ class NamespaceFacade extends CuratorFrameworkImpl
     }
 
     @Override
+    public EnsurePathContainers newNamespaceAwareEnsurePathContainers(String path)
+    {
+        return namespace.newNamespaceAwareEnsurePathContainers(path);
+    }
+
+    @Override
     FailedDeleteManager getFailedDeleteManager()
     {
         return failedDeleteManager;

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceImpl.java
index 717b2f4..99f2b3b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/NamespaceImpl.java
@@ -19,6 +19,7 @@
 package org.apache.curator.framework.imps;
 
 import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.EnsurePathContainers;
 import org.apache.curator.utils.ZKPaths;
 import org.apache.curator.utils.PathUtils;
 
@@ -86,4 +87,9 @@ class NamespaceImpl
     {
         return new EnsurePath(fixForNamespace(path, false), client.getAclProvider());
     }
+
+    EnsurePathContainers newNamespaceAwareEnsurePathContainers(String path)
+    {
+        return new EnsurePathContainers(fixForNamespace(path, false), client.getAclProvider());
+    }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFramework.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFramework.java
index a1d9a8f..ac21172 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFramework.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestFramework.java
@@ -41,6 +41,8 @@ import org.apache.zookeeper.ZooDefs;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Stat;
 import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 import java.util.ArrayList;
 import java.util.List;
@@ -52,6 +54,22 @@ import java.util.concurrent.TimeUnit;
 @SuppressWarnings("deprecation")
 public class TestFramework extends BaseClassForTests
 {
+    @BeforeMethod
+    @Override
+    public void setup() throws Exception
+    {
+        System.setProperty("container.checkIntervalMs", "1000");
+        super.setup();
+    }
+
+    @AfterMethod
+    @Override
+    public void teardown() throws Exception
+    {
+        System.clearProperty("container.checkIntervalMs");
+        super.teardown();
+    }
+
     @Test
     public void testConnectionState() throws Exception
     {
@@ -401,6 +419,31 @@ public class TestFramework extends BaseClassForTests
     }
 
     @Test
+    public void testCreateParentContainers() throws Exception
+    {
+        CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
+        CuratorFramework client = builder.connectString(server.getConnectString()).retryPolicy(new RetryOneTime(1)).build();
+        client.start();
+        try
+        {
+            client.create().creatingParentContainersIfNeeded().forPath("/one/two/three", "foo".getBytes());
+            byte[] data = client.getData().forPath("/one/two/three");
+            Assert.assertEquals(data, "foo".getBytes());
+
+            client.delete().forPath("/one/two/three");
+            new Timing().sleepABit();
+
+            Assert.assertNull(client.checkExists().forPath("/one/two"));
+            new Timing().sleepABit();
+            Assert.assertNull(client.checkExists().forPath("/one"));
+        }
+        finally
+        {
+            client.close();
+        }
+    }
+
+    @Test
     public void testEnsurePathWithNamespace() throws Exception
     {
         final String namespace = "jz";

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/atomic/DistributedAtomicValue.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/atomic/DistributedAtomicValue.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/atomic/DistributedAtomicValue.java
index c90fb2b..8553364 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/atomic/DistributedAtomicValue.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/atomic/DistributedAtomicValue.java
@@ -22,12 +22,11 @@ import org.apache.curator.RetryLoop;
 import org.apache.curator.RetryPolicy;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.recipes.locks.InterProcessMutex;
-import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.EnsurePathContainers;
+import org.apache.curator.utils.PathUtils;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.data.Stat;
 import java.util.Arrays;
-import org.apache.curator.utils.PathUtils;
-import org.apache.zookeeper.ZKUtil;
 
 /**
  * <p>A distributed value that attempts atomic sets. It first tries uses optimistic locking. If that fails,
@@ -44,7 +43,7 @@ public class DistributedAtomicValue
     private final RetryPolicy       retryPolicy;
     private final PromotedToLock    promotedToLock;
     private final InterProcessMutex mutex;
-    private final EnsurePath        ensurePath;
+    private final EnsurePathContainers ensurePath;
 
     /**
      * Creates in optimistic mode only - i.e. the promotion to a mutex is not done
@@ -75,7 +74,7 @@ public class DistributedAtomicValue
         this.retryPolicy = retryPolicy;
         this.promotedToLock = promotedToLock;
         mutex = (promotedToLock != null) ? new InterProcessMutex(client, promotedToLock.getPath()) : null;
-        ensurePath = client.newNamespaceAwareEnsurePath(path).excludingLast();
+        ensurePath = client.newNamespaceAwareEnsurePathContainers(path).excludingLastContainers();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedBarrier.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedBarrier.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedBarrier.java
index b891b2b..8a376f1 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedBarrier.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedBarrier.java
@@ -67,7 +67,7 @@ public class DistributedBarrier
     {
         try
         {
-            client.create().creatingParentsIfNeeded().forPath(barrierPath);
+            client.create().creatingParentContainersIfNeeded().forPath(barrierPath);
         }
         catch ( KeeperException.NodeExistsException ignore )
         {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedDoubleBarrier.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedDoubleBarrier.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedDoubleBarrier.java
index 5034b0a..b3bdf2c 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedDoubleBarrier.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/barriers/DistributedDoubleBarrier.java
@@ -118,7 +118,7 @@ public class DistributedDoubleBarrier
         long            maxWaitMs = hasMaxWait ? TimeUnit.MILLISECONDS.convert(maxWait, unit) : Long.MAX_VALUE;
 
         boolean         readyPathExists = (client.checkExists().usingWatcher(watcher).forPath(readyPath) != null);
-        client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(ourPath);
+        client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(ourPath);
 
         boolean         result = (readyPathExists || internalEnter(startMs, hasMaxWait, maxWaitMs));
         if ( connectionLost.get() )

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..0292cde 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
@@ -29,7 +29,8 @@ import org.apache.curator.framework.api.CuratorWatcher;
 import org.apache.curator.framework.listen.ListenerContainer;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
-import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.EnsurePathContainers;
+import org.apache.curator.utils.PathUtils;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.data.Stat;
@@ -40,7 +41,6 @@ import java.io.IOException;
 import java.util.concurrent.Exchanger;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
-import org.apache.curator.utils.PathUtils;
 
 /**
  * <p>A utility that attempts to keep the data from a node locally cached. This class
@@ -57,7 +57,7 @@ public class NodeCache implements Closeable
     private final CuratorFramework client;
     private final String path;
     private final boolean dataIsCompressed;
-    private final EnsurePath ensurePath;
+    private final EnsurePathContainers 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>();
@@ -132,7 +132,7 @@ public class NodeCache implements Closeable
         this.client = client;
         this.path = PathUtils.validatePath(path);
         this.dataIsCompressed = dataIsCompressed;
-        ensurePath = client.newNamespaceAwareEnsurePath(path).excludingLast();
+        ensurePath = client.newNamespaceAwareEnsurePathContainers(path).excludingLastContainers();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..f8fd8db 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,7 +24,6 @@ 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;
@@ -34,7 +33,8 @@ import org.apache.curator.framework.listen.ListenerContainer;
 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.EnsurePathContainers;
+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 +54,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
@@ -74,7 +73,7 @@ public class PathChildrenCache implements Closeable
     private final CloseableExecutorService executorService;
     private final boolean cacheData;
     private final boolean dataIsCompressed;
-    private final EnsurePath ensurePath;
+    private final EnsurePathContainers ensurePath;
     private final ListenerContainer<PathChildrenCacheListener> listeners = new ListenerContainer<PathChildrenCacheListener>();
     private final ConcurrentMap<String, ChildData> currentData = Maps.newConcurrentMap();
     private final AtomicReference<Map<String, ChildData>> initialSet = new AtomicReference<Map<String, ChildData>>();
@@ -221,7 +220,7 @@ public class PathChildrenCache implements Closeable
         this.cacheData = cacheData;
         this.dataIsCompressed = dataIsCompressed;
         this.executorService = executorService;
-        ensurePath = client.newNamespaceAwareEnsurePath(path);
+        ensurePath = client.newNamespaceAwareEnsurePathContainers(path);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..a6d8145 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
@@ -500,7 +500,7 @@ public class LeaderLatch implements Closeable
                 }
             }
         };
-        client.create().creatingParentsIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).inBackground(callback).forPath(ZKPaths.makePath(latchPath, LOCK_NAME), LeaderSelector.getIdBytes(id));
+        client.create().creatingParentContainersIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).inBackground(callback).forPath(ZKPaths.makePath(latchPath, LOCK_NAME), LeaderSelector.getIdBytes(id));
     }
 
     private synchronized void internalStart()

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/ChildReaper.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/ChildReaper.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/ChildReaper.java
index 2a1d73e..5949b95 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/ChildReaper.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/ChildReaper.java
@@ -29,6 +29,7 @@ import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.utils.PathUtils;
 import org.apache.curator.utils.ThreadUtils;
 import org.apache.curator.utils.ZKPaths;
+import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,6 +49,9 @@ import java.util.concurrent.atomic.AtomicReference;
 /**
  * Utility to reap empty child nodes of a parent node. Periodically calls getChildren on
  * the node and adds empty nodes to an internally managed {@link Reaper}
+ *
+ * @deprecated Reaper/ChildReaper are no longer needed. Use {@link CreateMode#CONTAINER}.
+ * Also, all Curator recipes create container parents.
  */
 public class ChildReaper implements Closeable
 {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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 b6d5ca2..f4af39b 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
@@ -347,7 +347,7 @@ public class InterProcessSemaphoreV2
         }
         try
         {
-            PathAndBytesable<String> createBuilder = client.create().creatingParentsIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL);
+            PathAndBytesable<String> createBuilder = client.create().creatingParentContainersIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL);
             String path = (nodeData != null) ? createBuilder.forPath(ZKPaths.makePath(leasesPath, LEASE_BASE_NAME), nodeData) : createBuilder.forPath(ZKPaths.makePath(leasesPath, LEASE_BASE_NAME));
             String nodeName = ZKPaths.getNodeFromPath(path);
             builder.add(makeLease(path));

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Reaper.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Reaper.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Reaper.java
index efd363f..578fa0c 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Reaper.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/Reaper.java
@@ -26,6 +26,7 @@ import org.apache.curator.framework.recipes.leader.LeaderLatch;
 import org.apache.curator.framework.recipes.leader.LeaderLatchListener;
 import org.apache.curator.utils.CloseableScheduledExecutorService;
 import org.apache.curator.utils.ThreadUtils;
+import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
@@ -41,6 +42,9 @@ import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Utility to clean up parent lock nodes so that they don't stay around as garbage
+ *
+ * @deprecated Reaper/ChildReaper are no longer needed. Use {@link CreateMode#CONTAINER}.
+ * Also, all Curator recipes create container parents.
  */
 public class Reaper implements Closeable
 {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/StandardLockInternalsDriver.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/StandardLockInternalsDriver.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/StandardLockInternalsDriver.java
index 0c9b6de..43184f5 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/StandardLockInternalsDriver.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/StandardLockInternalsDriver.java
@@ -47,11 +47,11 @@ public class StandardLockInternalsDriver implements LockInternalsDriver
         String ourPath;
         if ( lockNodeBytes != null )
         {
-            ourPath = client.create().creatingParentsIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, lockNodeBytes);
+            ourPath = client.create().creatingParentContainersIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, lockNodeBytes);
         }
         else
         {
-            ourPath = client.create().creatingParentsIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path);
+            ourPath = client.create().creatingParentContainersIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path);
         }
         return ourPath;
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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 ddf91ba..f50dca4 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
@@ -254,7 +254,7 @@ public class PersistentEphemeralNode implements Closeable
             }
         };
 
-        createMethod = mode.isProtected() ? client.create().creatingParentsIfNeeded().withProtection() : client.create().creatingParentsIfNeeded();
+        createMethod = mode.isProtected() ? client.create().creatingParentContainersIfNeeded().withProtection() : client.create().creatingParentContainersIfNeeded();
         this.data.set(Arrays.copyOf(data, data.length));
     }
     

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/DistributedQueue.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/DistributedQueue.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/DistributedQueue.java
index 9dd2217..5d5b53e 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/DistributedQueue.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/DistributedQueue.java
@@ -163,7 +163,7 @@ public class DistributedQueue<T> implements QueueBase<T>
 
         try
         {
-            client.create().creatingParentsIfNeeded().forPath(queuePath);
+            client.create().creatingParentContainersIfNeeded().forPath(queuePath);
         }
         catch ( KeeperException.NodeExistsException ignore )
         {
@@ -173,7 +173,7 @@ public class DistributedQueue<T> implements QueueBase<T>
         {
             try
             {
-                client.create().creatingParentsIfNeeded().forPath(lockPath);
+                client.create().creatingParentContainersIfNeeded().forPath(lockPath);
             }
             catch ( KeeperException.NodeExistsException ignore )
             {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/SimpleDistributedQueue.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/SimpleDistributedQueue.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/SimpleDistributedQueue.java
index 0c386cd..e577046 100644
--- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/SimpleDistributedQueue.java
+++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/queue/SimpleDistributedQueue.java
@@ -19,7 +19,8 @@
 package org.apache.curator.framework.recipes.queue;
 
 import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.utils.EnsurePath;
+import org.apache.curator.utils.EnsurePathContainers;
+import org.apache.curator.utils.PathUtils;
 import org.apache.curator.utils.ZKPaths;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
@@ -32,7 +33,6 @@ import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import org.apache.curator.utils.PathUtils;
 
 /**
  * <p>
@@ -50,7 +50,7 @@ public class SimpleDistributedQueue
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final CuratorFramework client;
     private final String path;
-    private final EnsurePath ensurePath;
+    private final EnsurePathContainers ensurePath;
 
     private final String PREFIX = "qn-";
 
@@ -62,7 +62,7 @@ public class SimpleDistributedQueue
     {
         this.client = client;
         this.path = PathUtils.validatePath(path);
-        ensurePath = client.newNamespaceAwareEnsurePath(path);
+        ensurePath = client.newNamespaceAwareEnsurePathContainers(path);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..6ce6bf4 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
@@ -220,7 +220,7 @@ public class SharedValue implements Closeable, SharedValueReader
         client.getConnectionStateListenable().addListener(connectionStateListener);
         try
         {
-            client.create().creatingParentsIfNeeded().forPath(path, seedValue);
+            client.create().creatingParentContainersIfNeeded().forPath(path, seedValue);
         }
         catch ( KeeperException.NodeExistsException ignore )
         {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-recipes/src/site/confluence/index.confluence b/curator-recipes/src/site/confluence/index.confluence
index a43963c..4f3a032 100644
--- a/curator-recipes/src/site/confluence/index.confluence
+++ b/curator-recipes/src/site/confluence/index.confluence
@@ -1,6 +1,8 @@
 h1. Recipes
 
 Curator implements all of the recipes listed on the ZooKeeper recipes doc (except two phase commit). Click on the recipe name below for detailed documentation.
+NOTE: Most Curator recipes will auto-create parent nodes of paths given to the recipe as CreateMode.CONTAINER. Also, see [[Tech Note 7|https://cwiki.apache.org/confluence/display/CURATOR/TN7]]
+regarding "Curator Recipes Own Their ZNode/Paths".
 
 ||Elections||
 |[[Leader Latch|leader-latch.html]] \- In distributed computing, leader election is the process of designating a single process as the organizer of some task distributed among several computers (nodes). Before the task is begun, all network nodes are unaware which node will serve as the "leader," or coordinator, of the task. After a leader election algorithm has been run, however, each node throughout the network recognizes a particular, unique node as the task leader.|

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..09b5fe6 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
@@ -30,8 +30,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 public class TestInterProcessMultiMutex extends TestInterProcessMutexBase
 {
-    private static final String     LOCK_PATH_1 = "/locks/our-lock-1";
-    private static final String     LOCK_PATH_2 = "/locks/our-lock-2";
+    private static final String     LOCK_PATH_1 = LOCK_BASE_PATH + "/our-lock-1";
+    private static final String     LOCK_PATH_2 = LOCK_BASE_PATH + "/our-lock-2";
 
     @Override
     protected InterProcessLock makeLock(CuratorFramework client)

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..a2c079e 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
@@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit;
 
 public class TestInterProcessMutex extends TestInterProcessMutexBase
 {
-    private static final String LOCK_PATH = "/locks/our-lock";
+    private static final String LOCK_PATH = LOCK_BASE_PATH + "/our-lock";
 
     @Override
     protected InterProcessLock makeLock(CuratorFramework client)

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/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..9c1037f 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,17 +20,16 @@
 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.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.apache.curator.utils.CloseableUtils;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import java.util.List;
@@ -47,6 +46,8 @@ import java.util.concurrent.atomic.AtomicReference;
 
 public abstract class TestInterProcessMutexBase extends BaseClassForTests
 {
+    protected static final String LOCK_BASE_PATH = "/locks";
+
     private volatile CountDownLatch waitLatchForBar = null;
     private volatile CountDownLatch countLatchForBar = null;
 
@@ -182,6 +183,76 @@ public abstract class TestInterProcessMutexBase extends BaseClassForTests
     }
 
     @Test
+    public void testContainerCleanup() throws Exception
+    {
+        server.close();
+
+        System.setProperty("container.checkIntervalMs", "10");
+        try
+        {
+            server = new TestingServer();
+
+            final int THREAD_QTY = 10;
+
+            ExecutorService service = null;
+            final CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(100, 3));
+            try
+            {
+                client.start();
+
+                List<Future<Object>> threads = Lists.newArrayList();
+                service = Executors.newCachedThreadPool();
+                for ( int i = 0; i < THREAD_QTY; ++i )
+                {
+                    Future<Object> t = service.submit
+                    (
+                        new Callable<Object>()
+                        {
+                            @Override
+                            public Object call() throws Exception
+                            {
+                                InterProcessLock lock = makeLock(client);
+                                lock.acquire();
+                                try
+                                {
+                                    Thread.sleep(10);
+                                }
+                                finally
+                                {
+                                    lock.release();
+                                }
+                                return null;
+                            }
+                        }
+                    );
+                    threads.add(t);
+                }
+
+                for ( Future<Object> t : threads )
+                {
+                    t.get();
+                }
+
+                new Timing().sleepABit();
+
+                Assert.assertNull(client.checkExists().forPath(LOCK_BASE_PATH));
+            }
+            finally
+            {
+                if ( service != null )
+                {
+                    service.shutdownNow();
+                }
+                CloseableUtils.closeQuietly(client);
+            }
+        }
+        finally
+        {
+            System.clearProperty("container.checkIntervalMs");
+        }
+    }
+
+    @Test
     public void testWithNamespace() throws Exception
     {
         CuratorFramework client = CuratorFrameworkFactory.builder().

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreMutex.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreMutex.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreMutex.java
index 0af2bf4..cd8b83e 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreMutex.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphoreMutex.java
@@ -23,7 +23,7 @@ import org.testng.annotations.Test;
 
 public class TestInterProcessSemaphoreMutex extends TestInterProcessMutexBase
 {
-    private static final String LOCK_PATH = "/locks/our-lock";
+    private static final String LOCK_PATH = LOCK_BASE_PATH + "/our-lock";
 
     @Override
     @Test(enabled = false)

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/ServiceDiscoveryImpl.java
----------------------------------------------------------------------
diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/ServiceDiscoveryImpl.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/ServiceDiscoveryImpl.java
index 7b0bffe..21c9e07 100644
--- a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/ServiceDiscoveryImpl.java
+++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/ServiceDiscoveryImpl.java
@@ -219,7 +219,7 @@ public class ServiceDiscoveryImpl<T> implements ServiceDiscovery<T>
             try
             {
                 CreateMode mode = (service.getServiceType() == ServiceType.DYNAMIC) ? CreateMode.EPHEMERAL : CreateMode.PERSISTENT;
-                client.create().creatingParentsIfNeeded().withMode(mode).forPath(path, bytes);
+                client.create().creatingParentContainersIfNeeded().withMode(mode).forPath(path, bytes);
                 isDone = true;
             }
             catch ( KeeperException.NodeExistsException e )
@@ -404,7 +404,7 @@ public class ServiceDiscoveryImpl<T> implements ServiceDiscovery<T>
             {
                 try
                 {
-                    client.create().creatingParentsIfNeeded().forPath(path);
+                    client.create().creatingParentContainersIfNeeded().forPath(path);
                 }
                 catch ( KeeperException.NodeExistsException ignore )
                 {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
index 777472c..eb67341 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
@@ -125,6 +125,10 @@ public class CuratorProjectionService
             {
                 builder = castBuilder(builder, CreateBuilder.class).creatingParentsIfNeeded();
             }
+            if ( spec.creatingParentContainersIfNeeded )
+            {
+                builder = castBuilder(builder, CreateBuilder.class).creatingParentContainersIfNeeded();
+            }
             if ( spec.compressed )
             {
                 builder = castBuilder(builder, Compressible.class).compressed();

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/CreateSpec.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/CreateSpec.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/CreateSpec.java
index d0232a9..a15fe92 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/CreateSpec.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/CreateSpec.java
@@ -45,11 +45,14 @@ public class CreateSpec
     @ThriftField(7)
     public boolean withProtection;
 
+    @ThriftField(8)
+    public boolean creatingParentContainersIfNeeded;
+
     public CreateSpec()
     {
     }
 
-    public CreateSpec(String path, byte[] data, RpcCreateMode mode, String asyncContext, boolean compressed, boolean creatingParentsIfNeeded, boolean withProtection)
+    public CreateSpec(String path, byte[] data, RpcCreateMode mode, String asyncContext, boolean compressed, boolean creatingParentsIfNeeded, boolean withProtection, boolean creatingParentContainersIfNeeded)
     {
         this.path = path;
         this.data = data;
@@ -58,5 +61,6 @@ public class CreateSpec
         this.compressed = compressed;
         this.creatingParentsIfNeeded = creatingParentsIfNeeded;
         this.withProtection = withProtection;
+        this.creatingParentContainersIfNeeded = creatingParentContainersIfNeeded;
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/RpcCreateMode.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/RpcCreateMode.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/RpcCreateMode.java
index d50bb74..020f283 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/RpcCreateMode.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/structs/RpcCreateMode.java
@@ -26,5 +26,6 @@ public enum RpcCreateMode
     PERSISTENT,
     PERSISTENT_SEQUENTIAL,
     EPHEMERAL,
-    EPHEMERAL_SEQUENTIAL
+    EPHEMERAL_SEQUENTIAL,
+    CONTAINER
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-x-rpc/src/main/thrift/curator.thrift
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/thrift/curator.thrift b/curator-x-rpc/src/main/thrift/curator.thrift
index d6bcd94..41f2362 100644
--- a/curator-x-rpc/src/main/thrift/curator.thrift
+++ b/curator-x-rpc/src/main/thrift/curator.thrift
@@ -8,7 +8,7 @@ enum PathChildrenCacheStartMode {
 }
 
 enum CreateMode {
-  PERSISTENT, PERSISTENT_SEQUENTIAL, EPHEMERAL, EPHEMERAL_SEQUENTIAL
+  PERSISTENT, PERSISTENT_SEQUENTIAL, EPHEMERAL, EPHEMERAL_SEQUENTIAL, CONTAINER
 }
 
 enum CuratorEventType {
@@ -175,6 +175,7 @@ struct CreateSpec {
   5: bool compressed;
   6: bool creatingParentsIfNeeded;
   7: bool withProtection;
+  8: bool creatingParentContainersIfNeeded;
 }
 
 struct DeleteSpec {

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/curator-x-rpc/src/site/confluence/reference.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/site/confluence/reference.confluence b/curator-x-rpc/src/site/confluence/reference.confluence
index 68c3692..bb7ea46 100644
--- a/curator-x-rpc/src/site/confluence/reference.confluence
+++ b/curator-x-rpc/src/site/confluence/reference.confluence
@@ -57,6 +57,7 @@ h2. CreateSpec
 |compressed|bool|\-|if true, compress the data|
 |creatingParentsIfNeeded|bool|\-|if true, create any needed parent nodes|
 |withProtection|bool|\-|if true, use Curator protection|
+|creatingParentContainersIfNeeded|bool|\-|if true, create any needed parent nodes as CONTAINERs|
 
 h2. DeleteSpec
 

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f3db843..30ace6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,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.4.7-SNAPSHOT</zookeeper-version>
         <guava-version>16.0.1</guava-version>
         <testng-version>6.8.8</testng-version>
         <swift-version>0.12.0</swift-version>

http://git-wip-us.apache.org/repos/asf/curator/blob/04ae8115/src/site/confluence/utilities.confluence
----------------------------------------------------------------------
diff --git a/src/site/confluence/utilities.confluence b/src/site/confluence/utilities.confluence
index 7a8e95f..d1484e3 100644
--- a/src/site/confluence/utilities.confluence
+++ b/src/site/confluence/utilities.confluence
@@ -43,17 +43,3 @@ h2. QueueSharder
 Due to limitations in ZooKeeper's transport layer, a single queue will break if it has more than 10K\-ish items in it. This class
 provides a facade over multiple distributed queues. It monitors the queues and if any one of them goes over a threshold, a new
 queue is added. Puts are distributed amongst the queues.
-
-h2. Reaper and ChildReaper
-
-_Reaper_
-
-A Utility to delete parent paths of locks, etc. Periodically checks paths added to the reaper. If at check time, there are no
-children, the path is deleted. Clients should create one Reaper instance per application. Add lock paths to the reaper as
-needed and the reaper will periodically delete them. Curator's lock recipes will correctly handle parents getting deleted.
-
-_ChildReaper_
-
-Utility to reap the empty child nodes in a parent node. Periodically calls getChildren() on the node and adds empty nodes to an internally managed Reaper.
-
-*NOTE:* You should consider using LeaderSelector to run the Reapers as they don't need to run in every client.


Mime
View raw message