package com.liveramp.hank.zookeeper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; public class NodeCreationBarrier implements Watcher { private static final Logger LOG = LoggerFactory.getLogger(NodeCreationBarrier.class); private boolean waiting = true; private final String nodePath; private final ZooKeeperPlus zk; // Will block until specified node is created or connection is lost public static void block(ZooKeeperPlus zk, String nodePath) throws InterruptedException, KeeperException { new NodeCreationBarrier(zk, nodePath).block(); } // Will block until specified node is created or connection is lost or timeout is exceeded public static void block(ZooKeeperPlus zk, String nodePath, int timeoutMS) throws InterruptedException, KeeperException { new NodeCreationBarrier(zk, nodePath).block(timeoutMS); } public NodeCreationBarrier(ZooKeeperPlus zk, String nodePath) throws InterruptedException, KeeperException { this.nodePath = nodePath; this.zk = zk; } // Will block until specified node is created or connection is lost public void block() throws InterruptedException, KeeperException { block(0); } // Will block until specified node is created or connection is lost or timeout is exceeded public synchronized void block(int timeoutMS) throws InterruptedException, KeeperException { // Wait only if it doesn't exist if (waiting && zk.exists(nodePath, this) == null) { if (LOG.isDebugEnabled()) { LOG.debug("Wait for creation of node " + nodePath); } if (timeoutMS != 0) { this.wait(timeoutMS); } else { this.wait(); } } } @Override public synchronized void process(WatchedEvent watchedEvent) { // If we lose synchronization, stop waiting if (watchedEvent.getState() != Event.KeeperState.SyncConnected) { waiting = false; } else { // If the node has been created, stop waiting if (watchedEvent.getType() == Event.EventType.NodeCreated) { waiting = false; } } // Notify threads to check waiting flag notifyAll(); } }