more doc and tests
Project: http://git-wip-us.apache.org/repos/asf/curator/repo Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/7aa5617e Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/7aa5617e Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/7aa5617e Branch: refs/heads/CURATOR-3.0 Commit: 7aa5617e299a6259de3360bef307a231b426bcfb Parents: 994778c Author: randgalt <randg...@apache.org> Authored: Fri Dec 9 15:35:50 2016 +0100 Committer: randgalt <randg...@apache.org> Committed: Fri Dec 9 15:35:50 2016 +0100 ---------------------------------------------------------------------- .../src/site/confluence/index.confluence | 2 +- .../persistent-ephemeral-node.confluence | 39 -------------- .../site/confluence/persistent-node.confluence | 39 ++++++++++++++ .../confluence/persistent-ttl-node.confluence | 2 + .../recipes/nodes/TestPersistentTtlNode.java | 55 ++++++++++++++++++++ 5 files changed, 97 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/7aa5617e/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 4cf2cde..08ef762 100644 --- a/curator-recipes/src/site/confluence/index.confluence +++ b/curator-recipes/src/site/confluence/index.confluence @@ -29,7 +29,7 @@ regarding "Curator Recipes Own Their ZNode/Paths". |[[Tree Cache|tree-cache.html]] \- A utility that attempts to keep all data from all children of a ZK path locally cached. This class will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can register a listener that will get notified when changes occur.| ||Nodes|| -|[[Persistent Node|persistent-ephemeral-node.html]] \- A node that attempts to stay present in ZooKeeper, even through connection and session interruptions.| +|[[Persistent Node|persistent-node.html]] \- A node that attempts to stay present in ZooKeeper, even through connection and session interruptions.| |[[Persistent TTL Node|persistent-ttl-node.html]] \- Useful when you need to create a TTL node but don't want to keep it alive manually by periodically setting data.| |[Group Member|group-member.html]] \- Group membership management. Adds this instance into a group and keeps a cache of members in the group.| http://git-wip-us.apache.org/repos/asf/curator/blob/7aa5617e/curator-recipes/src/site/confluence/persistent-ephemeral-node.confluence ---------------------------------------------------------------------- diff --git a/curator-recipes/src/site/confluence/persistent-ephemeral-node.confluence b/curator-recipes/src/site/confluence/persistent-ephemeral-node.confluence deleted file mode 100644 index 5baca09..0000000 --- a/curator-recipes/src/site/confluence/persistent-ephemeral-node.confluence +++ /dev/null @@ -1,39 +0,0 @@ -h1. Persistent Node - -h2. Description -A persistent node is a node that attempts to stay present in ZooKeeper, even through connection and session interruptions. - -h2. Participating Classes -* PersistentNode - -h2. Usage -h3. Creating a PersistentNode -{code} -public PersistentNode(CuratorFramework client, - CreateMode mode, - boolean useProtection, - String basePath, - byte[] data) -Parameters: -client - client instance -mode - creation mode -useProtection - if true, call CreateBuilder.withProtection() -basePath - the base path for the node -data - data for the node -{code} - -h3. General Usage -PersistentNodes must be started: -{code} -node.start(); -{code} - -When you are through with the PersistentNode instance, you should call close: -{code} -node.close(); -{code} - -NOTE: this will delete the node - -h2. Error Handling -PersistentNode instances internally handle all error states recreating the node as necessary. http://git-wip-us.apache.org/repos/asf/curator/blob/7aa5617e/curator-recipes/src/site/confluence/persistent-node.confluence ---------------------------------------------------------------------- diff --git a/curator-recipes/src/site/confluence/persistent-node.confluence b/curator-recipes/src/site/confluence/persistent-node.confluence new file mode 100644 index 0000000..5baca09 --- /dev/null +++ b/curator-recipes/src/site/confluence/persistent-node.confluence @@ -0,0 +1,39 @@ +h1. Persistent Node + +h2. Description +A persistent node is a node that attempts to stay present in ZooKeeper, even through connection and session interruptions. + +h2. Participating Classes +* PersistentNode + +h2. Usage +h3. Creating a PersistentNode +{code} +public PersistentNode(CuratorFramework client, + CreateMode mode, + boolean useProtection, + String basePath, + byte[] data) +Parameters: +client - client instance +mode - creation mode +useProtection - if true, call CreateBuilder.withProtection() +basePath - the base path for the node +data - data for the node +{code} + +h3. General Usage +PersistentNodes must be started: +{code} +node.start(); +{code} + +When you are through with the PersistentNode instance, you should call close: +{code} +node.close(); +{code} + +NOTE: this will delete the node + +h2. Error Handling +PersistentNode instances internally handle all error states recreating the node as necessary. http://git-wip-us.apache.org/repos/asf/curator/blob/7aa5617e/curator-recipes/src/site/confluence/persistent-ttl-node.confluence ---------------------------------------------------------------------- diff --git a/curator-recipes/src/site/confluence/persistent-ttl-node.confluence b/curator-recipes/src/site/confluence/persistent-ttl-node.confluence index acd2d33..f123c1d 100644 --- a/curator-recipes/src/site/confluence/persistent-ttl-node.confluence +++ b/curator-recipes/src/site/confluence/persistent-ttl-node.confluence @@ -3,6 +3,8 @@ h1. Persistent TTL Node h2. Description PersistentTtlNode is useful when you need to create a TTL node but don't want to keep it alive manually by periodically setting data \- PersistentTtlNode does that for you. Further the keep\-alive is done in a way that does not generate watch triggers on the parent node. +It also provides similar guarantees that a [[Persistent Node|persistent-node.html]] does: the node attempts to stay present in ZooKeeper, +even through connection and session interruptions. h2. Participating Classes * PersistentNode http://git-wip-us.apache.org/repos/asf/curator/blob/7aa5617e/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java ---------------------------------------------------------------------- diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java index 9ae8df9..848c034 100644 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java @@ -2,6 +2,9 @@ package org.apache.curator.framework.recipes.nodes; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.recipes.cache.PathChildrenCache; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.retry.RetryOneTime; import org.apache.curator.test.BaseClassForTests; import org.apache.curator.test.Timing; @@ -9,8 +12,11 @@ import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import static org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode.BUILD_INITIAL_CACHE; + public class TestPersistentTtlNode extends BaseClassForTests { private final Timing timing = new Timing(); @@ -55,4 +61,53 @@ public class TestPersistentTtlNode extends BaseClassForTests Assert.assertNull(client.checkExists().forPath("/test")); } } + + @Test + public void testEventsOnParent() throws Exception + { + try (CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1))) + { + client.start(); + + try (PersistentTtlNode node = new PersistentTtlNode(client, "/test", 10, new byte[0])) + { + try(PathChildrenCache cache = new PathChildrenCache(client, "/", true)) + { + final Semaphore changes = new Semaphore(0); + PathChildrenCacheListener listener = new PathChildrenCacheListener() + { + @Override + public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception + { + if ( event.getType() == PathChildrenCacheEvent.Type.CHILD_UPDATED ) + { + if ( event.getData().getPath().equals("/test") ) + { + changes.release(); + } + } + } + }; + cache.getListenable().addListener(listener); + + node.start(); + node.waitForInitialCreate(timing.session(), TimeUnit.MILLISECONDS); + cache.start(BUILD_INITIAL_CACHE); + + Assert.assertEquals(changes.availablePermits(), 0); + timing.sleepABit(); + Assert.assertEquals(changes.availablePermits(), 0); + + client.setData().forPath("/test", "changed".getBytes()); + Assert.assertTrue(timing.acquireSemaphore(changes)); + timing.sleepABit(); + Assert.assertEquals(changes.availablePermits(), 0); + } + } + + timing.sleepABit(); + + Assert.assertNull(client.checkExists().forPath("/test")); + } + } }