public synchronized byte[] blockUntilAvailable(long timeout, boolean refresh)
    throws InterruptedException {
    if (timeout < 0) {
      throw new IllegalArgumentException();
    }

    boolean notimeout = timeout == 0;
    long startTime = EnvironmentEdgeManager.currentTime();
    long remaining = timeout;
    if (refresh) {
      try {
        // This does not create a watch if the node does not exists
        this.data = ZKUtil.getDataAndWatch(watcher, node);
      } catch (KeeperException e) {
        // We use to abort here, but in some cases the abort is ignored (
        // (empty Abortable), so it's better to log...
        LOG.warn("Unexpected exception handling blockUntilAvailable", e);
        abortable.abort("Unexpected exception handling blockUntilAvailable", e);
      }
    }
    boolean nodeExistsChecked = (!refresh || data != null);
    while (!this.stopped && (notimeout || remaining > 0) && this.data == null) {
      if (!nodeExistsChecked) {
        try {
          nodeExistsChecked = (ZKUtil.checkExists(watcher, node) != -1);
        } catch (KeeperException e) {
          LOG.warn("Got exception while trying to check existence in  ZooKeeper" + " of the node: "
            + node + ", retrying if timeout not reached", e);
        }

        // It did not exists, and now it does.
        if (nodeExistsChecked) {
          LOG.debug("Node {} now exists, resetting a watcher", node);
          try {
            // This does not create a watch if the node does not exists
            this.data = ZKUtil.getDataAndWatch(watcher, node);
          } catch (KeeperException e) {
            LOG.warn("Unexpected exception handling blockUntilAvailable", e);
            abortable.abort("Unexpected exception handling blockUntilAvailable", e);
          }
        }
      }
      // We expect a notification; but we wait with a
      // a timeout to lower the impact of a race condition if any
      wait(100);
      remaining = timeout - (EnvironmentEdgeManager.currentTime() - startTime);
    }
    return this.data;
  }
Gets the data of the node, blocking until the node is available or the specified timeout has
elapsed.
@param timeout maximum time to wait for the node data to be available, n milliseconds. Pass 0
               for no timeout.
@return data of the node
@throws InterruptedException if the waiting thread is interrupted
hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKNodeTracker.java