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()); }