[
https://issues.apache.org/jira/browse/ZOOKEEPER-4466?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17495279#comment-17495279
]
Kezhu Wang commented on ZOOKEEPER-4466:
---------------------------------------
Hi [~eolivelli], could you assign this ticket to me ? I think we can solve this
by changes:
# Don't materialize {{ZKWatchManager.persistentRecursiveWatches}} for
{{NodeChildrenChanged}} in client side.
# Count different {{WatcherMode}} for watcher's path. Since there are only
three modes, the cost is small if we use bitwise flags to accumulate them to
{{int}}.
What do you think ?
You can check my [github
patch|https://github.com/kezhuw/zookeeper/commit/9b7cb811c3a0d8cb51809776749c69ab019246b1]
if desired before official github pull request.
> 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
> Priority: Major
>
> 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.1#820001)