String attemptLock(long time, TimeUnit unit, byte[] lockNodeBytes) throws Exception {
    final long startMillis = System.currentTimeMillis();
    final Long millisToWait = (unit != null) ? unit.toMillis(time) : null;
    final byte[] localLockNodeBytes = (revocable.get() != null) ? new byte[0] : lockNodeBytes;
    int retryCount = 0;

    ensurePath.ensure(client.getZookeeperClient());

    String ourPath = null;
    boolean hasTheLock = false;
    boolean isDone = false;
    while (!isDone) {
      isDone = true;
      try {
        if (localLockNodeBytes != null) {
          ourPath =
              client
                  .create()
                  .withProtection()
                  .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                  .forPath(path, localLockNodeBytes);
        } else {
          ourPath =
              client
                  .create()
                  .withProtection()
                  .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                  .forPath(path);
        }
        hasTheLock = internalLockLoop(startMillis, millisToWait, ourPath);
      } catch (KeeperException.NoNodeException e) {
        // gets thrown by StandardLockInternalsDriver when it can't find the lock node
        // this can happen when the session expires, etc. So, if the retry allows, just try it all
        // again
        if (client
            .getZookeeperClient()
            .getRetryPolicy()
            .allowRetry(retryCount++, System.currentTimeMillis() - startMillis)) {
          isDone = false;
          if (ourPath != null) {
            client.delete().inBackground().forPath(ourPath); // just in case
          }
        } else {
          throw e;
        }
      }
    }

    if (hasTheLock) {
      return ourPath;
    }

    return null;
  }
  /**
   * Add this instance to the leadership election and attempt to acquire leadership.
   *
   * @throws Exception errors
   */
  public void start() throws Exception {
    Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Already started");

    client.getConnectionStateListenable().addListener(listener);

    client.newNamespaceAwareEnsurePath(latchPath).ensure(client.getZookeeperClient());
    internalStart();
  }
 private byte[] get(final String pathSuffix) throws Exception {
   return RetryLoop.callWithRetry(
       zk.getZookeeperClient(),
       new Callable<byte[]>() {
         @Override
         public byte[] call() throws Exception {
           return zk.getData().forPath(buildZookeeperPath(pathSuffix));
         }
       });
 }
 private void watch(final String pathSuffix, final Watcher callback) throws Exception {
   RetryLoop.callWithRetry(
       zk.getZookeeperClient(),
       new Callable<Void>() {
         @Override
         public Void call() throws Exception {
           zk.checkExists().usingWatcher(callback).forPath(buildZookeeperPath(pathSuffix));
           return null;
         }
       });
 }
  /**
   * Optimistic concurrency scheme for tryAtomicUpdate. Try to update, and keep trying until
   * successful.
   *
   * @param pathSuffix suffix to use to build path in ZooKeeper.
   * @param f function used to initialize the node, or transform the data already there.
   * @throws Exception
   */
  private void atomicUpdate(final String pathSuffix, final NodeFunction f) throws Exception {
    boolean done = false;

    do {
      done =
          RetryLoop.callWithRetry(
              zk.getZookeeperClient(),
              new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                  return tryAtomicUpdate(pathSuffix, f);
                }
              });
      Thread.sleep(BASE_OPTIMISTIC_RETRY_TIME_MS + rand.nextInt(BASE_OPTIMISTIC_RETRY_TIME_MS));
    } while (!done);
  }
 private void writeDataToPath(String path, String data) throws Exception {
   ZKPaths.mkdirs(zookeeper.getZookeeperClient().getZooKeeper(), path);
   zookeeper.setData().forPath(path, data.getBytes());
 }