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);
+        }
+    }
 }

Reply via email to