zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cami...@apache.org
Subject svn commit: r1569588 - in /zookeeper/branches/branch-3.4: CHANGES.txt src/java/main/org/apache/zookeeper/server/DataTree.java src/java/test/org/apache/zookeeper/server/DataTreeTest.java src/java/test/org/apache/zookeeper/test/DataTreeTest.java
Date Wed, 19 Feb 2014 01:29:44 GMT
Author: camille
Date: Wed Feb 19 01:29:43 2014
New Revision: 1569588

URL: http://svn.apache.org/r1569588
Log:
ZOOKEEPER-1755. Concurrent operations of four letter 'dump' ephemeral 
  command and killSession causing NPE (Rakesh R via camille)

Added:
    zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/DataTreeTest.java
  (with props)
Removed:
    zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/test/DataTreeTest.java
Modified:
    zookeeper/branches/branch-3.4/CHANGES.txt
    zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/DataTree.java

Modified: zookeeper/branches/branch-3.4/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/CHANGES.txt?rev=1569588&r1=1569587&r2=1569588&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/CHANGES.txt (original)
+++ zookeeper/branches/branch-3.4/CHANGES.txt Wed Feb 19 01:29:43 2014
@@ -245,6 +245,9 @@ BUGFIXES:
   unregister failed jmxbeans (Rakesh R via michim)
 
   ZOOKEEPER-1844. TruncateTest fails on windows (Rakesh R via fpj)
+  
+  ZOOKEEPER-1755. Concurrent operations of four letter 'dump' ephemeral 
+  command and killSession causing NPE (Rakesh R via camille)
 
 IMPROVEMENTS:
 

Modified: zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/DataTree.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/DataTree.java?rev=1569588&r1=1569587&r2=1569588&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/DataTree.java
(original)
+++ zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/DataTree.java
Wed Feb 19 01:29:43 2014
@@ -1253,9 +1253,11 @@ public class DataTree {
             pwriter.print("0x" + Long.toHexString(k));
             pwriter.println(":");
             HashSet<String> tmp = ephemerals.get(k);
-            synchronized (tmp) {
-                for (String path : tmp) {
-                    pwriter.println("\t" + path);
+            if (tmp != null) {
+                synchronized (tmp) {
+                    for (String path : tmp) {
+                        pwriter.println("\t" + path);
+                    }
                 }
             }
         }

Added: zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/DataTreeTest.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/DataTreeTest.java?rev=1569588&view=auto
==============================================================================
--- zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/DataTreeTest.java
(added)
+++ zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/DataTreeTest.java
Wed Feb 19 01:29:43 2014
@@ -0,0 +1,179 @@
+/**
+ * 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.zookeeper.server;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.KeeperException.NoNodeException;
+import org.apache.zookeeper.KeeperException.NodeExistsException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.DataTree;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.zookeeper.server.DataNode;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.apache.zookeeper.Quotas;
+import org.apache.jute.BinaryInputArchive;
+import org.apache.jute.BinaryOutputArchive;
+import org.apache.zookeeper.common.PathTrie;
+import java.lang.reflect.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class DataTreeTest extends ZKTestCase {
+    protected static final Logger LOG = LoggerFactory.getLogger(DataTreeTest.class);
+
+    private DataTree dt;
+
+    @Before
+    public void setUp() throws Exception {
+        dt=new DataTree();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        dt=null;
+    }
+
+    /**
+     * For ZOOKEEPER-1755 - Test race condition when taking dumpEphemerals and
+     * removing the session related ephemerals from DataTree structure
+     */
+    @Test(timeout = 60000)
+    public void testDumpEphemerals() throws Exception {
+        int count = 1000;
+        long session = 1000;
+        long zxid = 2000;
+        final DataTree dataTree = new DataTree();
+        LOG.info("Create {} zkclient sessions and its ephemeral nodes", count);
+        createEphemeralNode(session, dataTree, count);
+        final AtomicBoolean exceptionDuringDumpEphemerals = new AtomicBoolean(
+                false);
+        final AtomicBoolean running = new AtomicBoolean(true);
+        Thread thread = new Thread() {
+            public void run() {
+                PrintWriter pwriter = new PrintWriter(new StringWriter());
+                try {
+                    while (running.get()) {
+                        dataTree.dumpEphemerals(pwriter);
+                    }
+                } catch (Exception e) {
+                    LOG.error("Received exception while dumpEphemerals!", e);
+                    exceptionDuringDumpEphemerals.set(true);
+                }
+            };
+        };
+        thread.start();
+        LOG.debug("Killing {} zkclient sessions and its ephemeral nodes", count);
+        killZkClientSession(session, zxid, dataTree, count);
+        running.set(false);
+        thread.join();
+        Assert.assertFalse("Should have got exception while dumpEphemerals!",
+                exceptionDuringDumpEphemerals.get());
+    }
+
+    private void killZkClientSession(long session, long zxid,
+            final DataTree dataTree, int count) {
+        for (int i = 0; i < count; i++) {
+            dataTree.killSession(session + i, zxid);
+        }
+    }
+
+    private void createEphemeralNode(long session, final DataTree dataTree,
+            int count) throws NoNodeException, NodeExistsException {
+        for (int i = 0; i < count; i++) {
+            dataTree.createNode("/test" + i, new byte[0], null, session + i,
+                    dataTree.getNode("/").stat.getCversion() + 1, 1, 1);
+        }
+    }
+    
+    @Test(timeout = 60000)
+    public void testRootWatchTriggered() throws Exception {
+        class MyWatcher implements Watcher{
+            boolean fired=false;
+            public void process(WatchedEvent event) {
+                if(event.getPath().equals("/"))
+                    fired=true;
+            }
+        }
+        MyWatcher watcher=new MyWatcher();
+        // set a watch on the root node
+        dt.getChildren("/", new Stat(), watcher);
+        // add a new node, should trigger a watch
+        dt.createNode("/xyz", new byte[0], null, 0, dt.getNode("/").stat.getCversion()+1,
1, 1);
+        Assert.assertFalse("Root node watch not triggered",!watcher.fired);
+    }
+
+    /**
+     * For ZOOKEEPER-1046 test if cversion is getting incremented correctly.
+     */
+    @Test(timeout = 60000)
+    public void testIncrementCversion() throws Exception {
+        dt.createNode("/test", new byte[0], null, 0, dt.getNode("/").stat.getCversion()+1,
1, 1);
+        DataNode zk = dt.getNode("/test");
+        int prevCversion = zk.stat.getCversion();
+        long prevPzxid = zk.stat.getPzxid();
+        dt.setCversionPzxid("/test/",  prevCversion + 1, prevPzxid + 1);
+        int newCversion = zk.stat.getCversion();
+        long newPzxid = zk.stat.getPzxid();
+        Assert.assertTrue("<cversion, pzxid> verification failed. Expected: <" +
+                (prevCversion + 1) + ", " + (prevPzxid + 1) + ">, found: <" +
+                newCversion + ", " + newPzxid + ">",
+                (newCversion == prevCversion + 1 && newPzxid == prevPzxid + 1));
+    }
+   
+    @Test(timeout = 60000)
+    public void testPathTrieClearOnDeserialize() throws Exception {
+
+        //Create a DataTree with quota nodes so PathTrie get updated
+        DataTree dserTree = new DataTree();
+        
+        dserTree.createNode("/bug", new byte[20], null, -1, 1, 1, 1);
+        dserTree.createNode(Quotas.quotaZookeeper+"/bug", null, null, -1, 1, 1, 1);
+        dserTree.createNode(Quotas.quotaPath("/bug"), new byte[20], null, -1, 1, 1, 1);
+        dserTree.createNode(Quotas.statPath("/bug"), new byte[20], null, -1, 1, 1, 1);
+        
+        //deserialize a DataTree; this should clear the old /bug nodes and pathTrie
+        DataTree tree = new DataTree();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        BinaryOutputArchive oa = BinaryOutputArchive.getArchive(baos);
+        tree.serialize(oa, "test");
+        baos.flush();
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        BinaryInputArchive ia = BinaryInputArchive.getArchive(bais);
+        dserTree.deserialize(ia, "test");
+
+        Field pfield = DataTree.class.getDeclaredField("pTrie");
+        pfield.setAccessible(true);
+        PathTrie pTrie = (PathTrie)pfield.get(dserTree);
+
+        //Check that the node path is removed from pTrie
+        Assert.assertEquals("/bug is still in pTrie", "", pTrie.findMaxPrefix("/bug")); 
     
+    }
+}

Propchange: zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/DataTreeTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message