Repository: curator Updated Branches: refs/heads/CURATOR-222 [created] 04ae81155
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-222 Commit: 04ae8115512f03210cf930118788c67e433bd904 Parents: 7f20986 Author: randgalt <[email protected]> Authored: Tue May 19 14:33:24 2015 -0700 Committer: randgalt <[email protected]> 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.
