ソースを参照

ZOOKEEPER-3249: Avoid reverting the cversion and pzxid during replaying txns with fuzzy snapshot

Author: Fangmin Lyu <fangmin@apache.org>

Reviewers: andor@apache.org

Closes #780 from lvfangmin/ZOOKEEPER-3249
Fangmin Lyu 6 年 前
コミット
bc24f7c01a

+ 9 - 2
zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java

@@ -494,8 +494,15 @@ public class DataTree {
                 parentCVersion = parent.stat.getCversion();
                 parentCVersion++;
             }
-            parent.stat.setCversion(parentCVersion);
-            parent.stat.setPzxid(zxid);
+            // There is possibility that we'll replay txns for a node which
+            // was created and then deleted in the fuzzy range, and it's not
+            // exist in the snapshot, so replay the creation might revert the
+            // cversion and pzxid, need to check and only update when it's
+            // larger.
+            if (parentCVersion > parent.stat.getCversion()) {
+                parent.stat.setCversion(parentCVersion);
+                parent.stat.setPzxid(zxid);
+            }
             Long longval = aclCache.convertAcls(acl);
             DataNode child = new DataNode(data, longval, stat);
             parent.addChild(childName);

+ 16 - 0
zookeeper-server/src/test/java/org/apache/zookeeper/server/DataTreeTest.java

@@ -153,6 +153,22 @@ public class DataTreeTest extends ZKTestCase {
                 (newCversion == prevCversion + 1 && newPzxid == prevPzxid + 1));
     }
 
+    @Test
+    public void testNoCversionRevert() throws Exception {
+        DataNode parent = dt.getNode("/");
+        dt.createNode("/test", new byte[0], null, 0, parent.stat.getCversion() + 1, 1, 1);
+        int currentCversion = parent.stat.getCversion();
+        long currentPzxid = parent.stat.getPzxid();
+        dt.createNode("/test1", new byte[0], null, 0, currentCversion - 1, 1, 1);
+        parent = dt.getNode("/");
+        int newCversion = parent.stat.getCversion();
+        long newPzxid = parent.stat.getPzxid();
+        Assert.assertTrue("<cversion, pzxid> verification failed. Expected: <" +
+                currentCversion + ", " + currentPzxid + ">, found: <" +
+                newCversion + ", " + newPzxid + ">",
+                (newCversion >= currentCversion && newPzxid >= currentPzxid));
+    }
+
     @Test
     public void testPzxidUpdatedWhenDeletingNonExistNode() throws Exception {
         DataNode root = dt.getNode("/");