[ https://issues.apache.org/jira/browse/ZOOKEEPER-4466?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Zili Chen resolved ZOOKEEPER-4466. ---------------------------------- Fix Version/s: 3.9.0 Resolution: Fixed master via a64dbf5b06ca1a73dc2ad6c7d31e679e312082aa > Watchers of different modes interfere on overlapping pathes > ----------------------------------------------------------- > > Key: ZOOKEEPER-4466 > URL: https://issues.apache.org/jira/browse/ZOOKEEPER-4466 > Project: ZooKeeper > Issue Type: Bug > Components: java client, server > Affects Versions: 3.6.3, 3.7, 3.6.4 > Reporter: Kezhu Wang > Assignee: Kezhu Wang > Priority: Major > Labels: pull-request-available > Fix For: 3.9.0 > > Time Spent: 3h 10m > Remaining Estimate: 0h > > I used to think watchers of different modes are orthogonal. I found there are > not, when I wrote tests for unfinished rust client. And I wrote [test > cases|https://github.com/kezhuw/zookeeper/commit/79b05a95d2669a4acd16a4d544f24e2083a264f2#diff-8d31d27ea951fbc1f4fbda48d45748318f7124502839d825b77ad3fb8551bf43L152] > in java and confirmed. > I copied test case here for evaluation. You also clone from [my > fork|https://github.com/kezhuw/zookeeper/tree/watch-overlapping-path-with-different-modes-test-case]. > {code:java} > // > zookeeper-server/src/test/java/org/apache/zookeeper/test/PersistentRecursiveWatcherTest.java > @Test > public void testPathOverlapWithStandardWatcher() throws Exception { > try (ZooKeeper zk = createClient(new CountdownWatcher(), hostPort)) { > CountDownLatch nodeCreated = new CountDownLatch(1); > zk.addWatch("/a", persistentWatcher, PERSISTENT_RECURSIVE); > zk.exists("/a", event -> nodeCreated.countDown()); > zk.create("/a", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, > CreateMode.PERSISTENT); > zk.create("/a/b", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, > CreateMode.PERSISTENT); > zk.delete("/a/b", -1); > zk.delete("/a", -1); > assertEvent(events, Watcher.Event.EventType.NodeCreated, "/a"); > assertEvent(events, Watcher.Event.EventType.NodeCreated, "/a/b"); > assertEvent(events, Watcher.Event.EventType.NodeDeleted, "/a/b"); > assertEvent(events, Watcher.Event.EventType.NodeDeleted, "/a"); > assertTrue(nodeCreated.await(5, TimeUnit.SECONDS)); > } > } > @Test > public void testPathOverlapWithPersistentWatcher() throws Exception { > try (ZooKeeper zk = createClient(new CountdownWatcher(), hostPort)) { > zk.addWatch("/a", persistentWatcher, PERSISTENT_RECURSIVE); > zk.addWatch("/a/b", event -> {}, PERSISTENT); > zk.create("/a", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, > CreateMode.PERSISTENT); > zk.create("/a/b", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, > CreateMode.PERSISTENT); > zk.create("/a/b/c", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, > CreateMode.PERSISTENT); > zk.delete("/a/b/c", -1); > zk.delete("/a/b", -1); > zk.delete("/a", -1); > assertEvent(events, Watcher.Event.EventType.NodeCreated, "/a"); > assertEvent(events, Watcher.Event.EventType.NodeCreated, "/a/b"); > assertEvent(events, Watcher.Event.EventType.NodeCreated, > "/a/b/c"); > assertEvent(events, Watcher.Event.EventType.NodeDeleted, > "/a/b/c"); > assertEvent(events, Watcher.Event.EventType.NodeDeleted, "/a/b"); > assertEvent(events, Watcher.Event.EventType.NodeDeleted, "/a"); > } > } > {code} > I skimmed the code and found two possible causes: > # {{ZKWatchManager.materialize}} materializes all persistent watchers(include > recursive ones) for {{NodeChildrenChanged}} event. > # {{WatcherModeManager}} trackes only one watcher mode. -- This message was sent by Atlassian Jira (v8.20.10#820010)