0
votes

One of the ZooKeeper guarantees about watches says:

A client will see a watch event for a znode it is watching before seeing the new data that corresponds to that node.

"Seeing the the new data" I think it means the API can seeing the now data. But which of the following does "see a watch event" mean?

  • The point at which the ZooKeeper sending the notification.
  • The point at which the watch callback is called.
  • The point at which the watch callback is returned.
1

1 Answers

0
votes

I wrote a test.

package com.zookeeper.study.distributed.app;

import org.apache.logging.log4j.*;
import org.apache.zookeeper.*;

import java.io.*;

public class WatcherTestApp {
    private final ZooKeeper zooKeeper;
    private final String root;
    private final int count;
    private static final Logger logger = LogManager.getLogger(DistributedDoubleBarrierApp.class);

    public WatcherTestApp(ZooKeeper zooKeeper, String root, int count) {
        this.zooKeeper = zooKeeper;
        this.root = root;
        this.count = count;
    }

    private static class ChildWatcher implements Watcher {
        private final ZooKeeper zk;
        private final String root;

        public ChildWatcher(ZooKeeper zk, String root) {
            this.zk = zk;
            this.root = root;
        }
        @Override
        public void process(WatchedEvent event) {
            logger.info("Children watch start.");
            try {
                zk.getChildren(root, this);
            } catch (KeeperException | InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("Children watch end.");
        }
    }

    public void test() {
        try {
            zooKeeper.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            zooKeeper.getChildren(root, new ChildWatcher(zooKeeper, root));
            for (int i = 0; i < count; i++) {
                zooKeeper.create(root + "/child", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
                logger.info("Children created.");
            }
        } catch (InterruptedException | KeeperException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
            var zk = ZookeeperAppHelper.zookeeperInstance();
            var app = new WatcherTestApp(zk, "/parent", 10);
            app.test();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

The output is:

Children watch start.
Children created.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.
Children watch start.
Children created.
Children watch end.

So I think this guarantee is from ZooKeeper's perspective. Client code may see both create() return first or watcher start first.