From 281b5ff13f000350fe88f186897eb7d4b4e1e0b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andor=20Moln=C3=A1r?= Date: Tue, 11 Feb 2025 10:43:20 -0600 Subject: [PATCH] ZOOKEEPER-4846: Failure to reload database due to missing ACL ZOOKEEPER-4846. Fix ACL reference on existing znode when trying to create Reviewers: cnauroth, eolivelli, ztzg Author: anmolnar Closes #2222 from anmolnar/ZOOKEEPER-4846 (cherry picked from commit 8532163df198466913f26141c0278dc11dbf53ab) Signed-off-by: Andor Molnar --- .../org/apache/zookeeper/server/DataTree.java | 5 +++-- .../org/apache/zookeeper/server/DataTreeTest.java | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java index 3febd7fd504..81789d642f1 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java @@ -467,8 +467,9 @@ public void createNode(final String path, byte[] data, List acl, long ephem // we did for the global sessions. Long longval = aclCache.convertAcls(acl); - Set children = parent.getChildren(); - if (children.contains(childName)) { + DataNode existingChild = nodes.get(path); + if (existingChild != null) { + existingChild.acl = longval; throw new KeeperException.NodeExistsException(); } diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/DataTreeTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/DataTreeTest.java index 151e87343d0..7095aae117c 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/DataTreeTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/DataTreeTest.java @@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -616,4 +617,18 @@ public void testDigest() throws Exception { } } + @Test + public void testCreateNodeFixMissingACL() throws Exception { + DataTree dt = new DataTree(); + ReferenceCountedACLCache aclCache = dt.getReferenceCountedAclCache(); + + dt.createNode("/the_parent", new byte[0], ZooDefs.Ids.CREATOR_ALL_ACL, -1, 1, 1, 0); + Long aclId = dt.getNode("/the_parent").acl; + aclCache.removeUsage(aclId); + aclCache.purgeUnused(); + // try to re-create the parent -> throws NodeExistsException, but fixes the deleted ACL + assertThrows(NodeExistsException.class, () -> + dt.createNode("/the_parent", new byte[0], ZooDefs.Ids.CREATOR_ALL_ACL, -1, 1, 1, 0)); + dt.createNode("/the_parent/the_child", new byte[0], ZooDefs.Ids.CREATOR_ALL_ACL, -1, 2, 2, 2); + } }