Repository: curator Updated Branches: refs/heads/CURATOR-3.0 1f866815a -> 4e4072b08
Because start() creates the node async, if close is called immediately, it might occur before the node creation. Handle this edge case by having the background response delete (async) the node if the instance has been closed Project: http://git-wip-us.apache.org/repos/asf/curator/repo Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/e5afda58 Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/e5afda58 Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/e5afda58 Branch: refs/heads/CURATOR-3.0 Commit: e5afda580e2c7540f5095e1894c6866ce4ace8db Parents: 4b59a5b Author: randgalt <[email protected]> Authored: Tue Feb 2 13:26:13 2016 -0500 Committer: randgalt <[email protected]> Committed: Tue Feb 2 13:26:13 2016 -0500 ---------------------------------------------------------------------- .../framework/recipes/nodes/PersistentNode.java | 99 ++++++++++++++------ .../recipes/nodes/TestPersistentNode.java | 46 +++++++++ 2 files changed, 114 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/e5afda58/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentNode.java ---------------------------------------------------------------------- diff --git a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentNode.java b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentNode.java index 0d7ab9d..c472fdd 100644 --- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentNode.java +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentNode.java @@ -159,41 +159,13 @@ public class PersistentNode implements Closeable @Override public void processResult(CuratorFramework client, CuratorEvent event) throws Exception { - String path = null; - boolean nodeExists = false; - if ( event.getResultCode() == KeeperException.Code.NODEEXISTS.intValue() ) + if ( state.get() == State.STARTED ) { - path = event.getPath(); - nodeExists = true; - } - else if ( event.getResultCode() == KeeperException.Code.OK.intValue() ) - { - path = event.getName(); - } - else if ( event.getResultCode() == KeeperException.Code.NOAUTH.intValue() ) - { - log.warn("Client does not have authorisation to write node at path {}", event.getPath()); - authFailure.set(true); - return; - } - if ( path != null ) - { - authFailure.set(false); - nodePath.set(path); - watchNode(); - - if ( nodeExists ) - { - client.setData().inBackground(setDataCallback).forPath(getActualPath(), getData()); - } - else - { - initialisationComplete(); - } + processBackgroundCallback(event); } else { - createNode(); + processBackgroundCallbackClosedState(event); } } }; @@ -202,6 +174,71 @@ public class PersistentNode implements Closeable this.data.set(Arrays.copyOf(data, data.length)); } + private void processBackgroundCallbackClosedState(CuratorEvent event) + { + String path = null; + if ( event.getResultCode() == KeeperException.Code.NODEEXISTS.intValue() ) + { + path = event.getPath(); + } + else if ( event.getResultCode() == KeeperException.Code.OK.intValue() ) + { + path = event.getName(); + } + + if ( path != null ) + { + try + { + client.delete().guaranteed().inBackground().forPath(path); + } + catch ( Exception e ) + { + log.error("Could not delete node after close", e); + } + } + } + + private void processBackgroundCallback(CuratorEvent event) throws Exception + { + String path = null; + boolean nodeExists = false; + if ( event.getResultCode() == KeeperException.Code.NODEEXISTS.intValue() ) + { + path = event.getPath(); + nodeExists = true; + } + else if ( event.getResultCode() == KeeperException.Code.OK.intValue() ) + { + path = event.getName(); + } + else if ( event.getResultCode() == KeeperException.Code.NOAUTH.intValue() ) + { + log.warn("Client does not have authorisation to write node at path {}", event.getPath()); + authFailure.set(true); + return; + } + if ( path != null ) + { + authFailure.set(false); + nodePath.set(path); + watchNode(); + + if ( nodeExists ) + { + client.setData().inBackground(setDataCallback).forPath(getActualPath(), getData()); + } + else + { + initialisationComplete(); + } + } + else + { + createNode(); + } + } + private void initialisationComplete() { CountDownLatch localLatch = initialCreateLatch.getAndSet(null); http://git-wip-us.apache.org/repos/asf/curator/blob/e5afda58/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentNode.java ---------------------------------------------------------------------- diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentNode.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentNode.java index c006dd7..386a0fe 100644 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentNode.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentNode.java @@ -59,4 +59,50 @@ public class TestPersistentNode extends BaseClassForTests CloseableUtils.closeQuietly(client); } } + + @Test + public void testQuickClose() throws Exception + { + Timing timing = new Timing(); + PersistentNode pen = null; + CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); + try + { + client.start(); + pen = new PersistentNode(client, CreateMode.PERSISTENT, false, "/test/one/two", new byte[0]); + pen.start(); + pen.close(); + timing.sleepABit(); + Assert.assertNull(client.checkExists().forPath("/test/one/two")); + } + finally + { + CloseableUtils.closeQuietly(pen); + CloseableUtils.closeQuietly(client); + } + } + + @Test + public void testQuickCloseNodeExists() throws Exception + { + Timing timing = new Timing(); + PersistentNode pen = null; + CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); + try + { + client.start(); + client.create().creatingParentsIfNeeded().forPath("/test/one/two"); + + pen = new PersistentNode(client, CreateMode.PERSISTENT, false, "/test/one/two", new byte[0]); + pen.start(); + pen.close(); + timing.sleepABit(); + Assert.assertNull(client.checkExists().forPath("/test/one/two")); + } + finally + { + CloseableUtils.closeQuietly(pen); + CloseableUtils.closeQuietly(client); + } + } }
