Example usage for org.apache.zookeeper KeeperException create

List of usage examples for org.apache.zookeeper KeeperException create

Introduction

In this page you can find the example usage for org.apache.zookeeper KeeperException create.

Prototype

public static KeeperException create(Code code) 

Source Link

Document

All non-specific keeper exceptions should be constructed via this factory method in order to guarantee consistency in error codes and such.

Usage

From source file:org.apache.distributedlog.impl.federated.FederatedZKLogMetadataStore.java

License:Apache License

private CompletableFuture<Optional<URI>> fetchLogLocation(final URI uri, String logName) {
    final CompletableFuture<Optional<URI>> fetchPromise = new CompletableFuture<Optional<URI>>();
    final String logRootPath = uri.getPath() + "/" + logName;
    try {//from   w w  w  . j  a  v a2s .c o m
        zkc.get().exists(logRootPath, false, new AsyncCallback.StatCallback() {
            @Override
            public void processResult(int rc, String path, Object ctx, Stat stat) {
                if (Code.OK.intValue() == rc) {
                    fetchPromise.complete(Optional.of(uri));
                } else if (Code.NONODE.intValue() == rc) {
                    fetchPromise.complete(Optional.<URI>absent());
                } else {
                    fetchPromise.completeExceptionally(KeeperException.create(Code.get(rc)));
                }
            }
        }, null);
    } catch (ZooKeeperClient.ZooKeeperConnectionException e) {
        fetchPromise.completeExceptionally(e);
    } catch (InterruptedException e) {
        fetchPromise.completeExceptionally(e);
    }
    return fetchPromise;
}

From source file:org.apache.distributedlog.impl.metadata.ZKLogStreamMetadataStore.java

License:Apache License

@Override
public CompletableFuture<Void> logExists(URI uri, final String logName) {
    final String logSegmentsPath = LogMetadata.getLogSegmentsPath(uri, logName,
            conf.getUnpartitionedStreamName());
    final CompletableFuture<Void> promise = new CompletableFuture<Void>();
    try {/* www  .  ja  v a  2s.  c  om*/
        final ZooKeeper zk = zooKeeperClient.get();
        zk.sync(logSegmentsPath, new AsyncCallback.VoidCallback() {
            @Override
            public void processResult(int syncRc, String path, Object syncCtx) {
                if (KeeperException.Code.NONODE.intValue() == syncRc) {
                    promise.completeExceptionally(new LogNotFoundException(
                            String.format("Log %s does not exist or has been deleted", logName)));
                    return;
                } else if (KeeperException.Code.OK.intValue() != syncRc) {
                    promise.completeExceptionally(
                            new ZKException("Error on checking log existence for " + logName,
                                    KeeperException.create(KeeperException.Code.get(syncRc))));
                    return;
                }
                zk.exists(logSegmentsPath, false, new AsyncCallback.StatCallback() {
                    @Override
                    public void processResult(int rc, String path, Object ctx, Stat stat) {
                        if (KeeperException.Code.OK.intValue() == rc) {
                            promise.complete(null);
                        } else if (KeeperException.Code.NONODE.intValue() == rc) {
                            promise.completeExceptionally(new LogNotFoundException(
                                    String.format("Log %s does not exist or has been deleted", logName)));
                        } else {
                            promise.completeExceptionally(
                                    new ZKException("Error on checking log existence for " + logName,
                                            KeeperException.create(KeeperException.Code.get(rc))));
                        }
                    }
                }, null);
            }
        }, null);

    } catch (InterruptedException ie) {
        LOG.error("Interrupted while reading {}", logSegmentsPath, ie);
        promise.completeExceptionally(
                new DLInterruptedException("Interrupted while checking " + logSegmentsPath, ie));
    } catch (ZooKeeperClient.ZooKeeperConnectionException e) {
        promise.completeExceptionally(e);
    }
    return promise;
}

From source file:org.apache.distributedlog.impl.metadata.ZKLogStreamMetadataStore.java

License:Apache License

private CompletableFuture<Void> ensureReadLockPathExist(final LogMetadata logMetadata,
        final String readLockPath) {
    final CompletableFuture<Void> promise = new CompletableFuture<Void>();
    promise.whenComplete((value, cause) -> {
        if (cause instanceof CancellationException) {
            FutureUtils.completeExceptionally(promise,
                    new LockCancelledException(readLockPath, "Could not ensure read lock path", cause));
        }//  ww  w  .  j av a  2  s .co  m
    });
    Optional<String> parentPathShouldNotCreate = Optional.of(logMetadata.getLogRootPath());
    Utils.zkAsyncCreateFullPathOptimisticRecursive(zooKeeperClient, readLockPath, parentPathShouldNotCreate,
            new byte[0], zooKeeperClient.getDefaultACL(), CreateMode.PERSISTENT,
            new org.apache.zookeeper.AsyncCallback.StringCallback() {
                @Override
                public void processResult(final int rc, final String path, Object ctx, String name) {
                    if (KeeperException.Code.NONODE.intValue() == rc) {
                        FutureUtils.completeExceptionally(promise,
                                new LogNotFoundException(
                                        String.format("Log %s does not exist or has been deleted",
                                                logMetadata.getFullyQualifiedName())));
                    } else if (KeeperException.Code.OK.intValue() == rc) {
                        FutureUtils.complete(promise, null);
                        LOG.trace("Created path {}.", path);
                    } else if (KeeperException.Code.NODEEXISTS.intValue() == rc) {
                        FutureUtils.complete(promise, null);
                        LOG.trace("Path {} is already existed.", path);
                    } else if (DistributedLogConstants.ZK_CONNECTION_EXCEPTION_RESULT_CODE == rc) {
                        FutureUtils.completeExceptionally(promise,
                                new ZooKeeperClient.ZooKeeperConnectionException(path));
                    } else if (DistributedLogConstants.DL_INTERRUPTED_EXCEPTION_RESULT_CODE == rc) {
                        FutureUtils.completeExceptionally(promise, new DLInterruptedException(path));
                    } else {
                        FutureUtils.completeExceptionally(promise,
                                KeeperException.create(KeeperException.Code.get(rc)));
                    }
                }
            }, null);
    return promise;
}

From source file:org.apache.distributedlog.lock.ZKSessionLock.java

License:Apache License

/**
 * Get client id and its ephemeral owner.
 *
 * @param zkClient//from  w  ww  . j a va  2  s  .  c  o  m
 *          zookeeper client
 * @param lockPath
 *          lock path
 * @param nodeName
 *          node name
 * @return client id and its ephemeral owner.
 */
static CompletableFuture<Pair<String, Long>> asyncParseClientID(ZooKeeper zkClient, String lockPath,
        String nodeName) {
    String[] parts = nodeName.split("_");
    // member_<clientid>_s<owner_session>_
    if (4 == parts.length && parts[2].startsWith("s")) {
        long sessionOwner = Long.parseLong(parts[2].substring(1));
        String clientId;
        try {
            clientId = URLDecoder.decode(parts[1], UTF_8.name());
            return FutureUtils.value(Pair.of(clientId, sessionOwner));
        } catch (UnsupportedEncodingException e) {
            // if failed to parse client id, we have to get client id by zookeeper#getData.
        }
    }
    final CompletableFuture<Pair<String, Long>> promise = new CompletableFuture<Pair<String, Long>>();
    zkClient.getData(lockPath + "/" + nodeName, false, new AsyncCallback.DataCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
            if (KeeperException.Code.OK.intValue() != rc) {
                promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc)));
            } else {
                promise.complete(Pair.of(deserializeClientId(data), stat.getEphemeralOwner()));
            }
        }
    }, null);
    return promise;
}

From source file:org.apache.distributedlog.lock.ZKSessionLock.java

License:Apache License

@Override
public CompletableFuture<LockWaiter> asyncTryLock(final long timeout, final TimeUnit unit) {
    final CompletableFuture<String> result = new CompletableFuture<String>();
    final boolean wait = DistributedLogConstants.LOCK_IMMEDIATE != timeout;
    if (wait) {/*from   ww  w . jav  a 2 s  .  c  o m*/
        asyncTryLock(wait, result);
    } else {
        // try to check locks first
        zk.getChildren(lockPath, null, new AsyncCallback.Children2Callback() {
            @Override
            public void processResult(final int rc, String path, Object ctx, final List<String> children,
                    Stat stat) {
                lockStateExecutor.submit(lockPath, new SafeRunnable() {
                    @Override
                    public void safeRun() {
                        if (!lockState.inState(State.INIT)) {
                            result.completeExceptionally(new LockStateChangedException(lockPath, lockId,
                                    State.INIT, lockState.getState()));
                            return;
                        }
                        if (KeeperException.Code.OK.intValue() != rc) {
                            result.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc)));
                            return;
                        }

                        FailpointUtils.checkFailPointNoThrow(FailpointUtils.FailPointName.FP_LockTryAcquire);

                        Collections.sort(children, MEMBER_COMPARATOR);
                        if (children.size() > 0) {
                            asyncParseClientID(zk, lockPath, children.get(0))
                                    .whenCompleteAsync(new FutureEventListener<Pair<String, Long>>() {
                                        @Override
                                        public void onSuccess(Pair<String, Long> owner) {
                                            if (!checkOrClaimLockOwner(owner, result)) {
                                                acquireFuture.complete(false);
                                            }
                                        }

                                        @Override
                                        public void onFailure(final Throwable cause) {
                                            result.completeExceptionally(cause);
                                        }
                                    }, lockStateExecutor.chooseExecutor(lockPath));
                        } else {
                            asyncTryLock(wait, result);
                        }
                    }
                });
            }
        }, null);
    }

    final CompletableFuture<Boolean> waiterAcquireFuture = FutureUtils.createFuture();
    waiterAcquireFuture.whenComplete((value, cause) -> acquireFuture.completeExceptionally(cause));
    return result.thenApply(new Function<String, LockWaiter>() {
        @Override
        public LockWaiter apply(final String currentOwner) {
            final Exception acquireException = new OwnershipAcquireFailedException(lockPath, currentOwner);
            FutureUtils.within(acquireFuture, timeout, unit, acquireException, lockStateExecutor, lockPath)
                    .whenComplete(new FutureEventListener<Boolean>() {

                        @Override
                        public void onSuccess(Boolean acquired) {
                            completeOrFail(acquireException);
                        }

                        @Override
                        public void onFailure(final Throwable acquireCause) {
                            completeOrFail(acquireException);
                        }

                        private void completeOrFail(final Throwable acquireCause) {
                            if (isLockHeld()) {
                                waiterAcquireFuture.complete(true);
                            } else {
                                asyncUnlock().whenComplete(new FutureEventListener<Void>() {
                                    @Override
                                    public void onSuccess(Void value) {
                                        waiterAcquireFuture.completeExceptionally(acquireCause);
                                    }

                                    @Override
                                    public void onFailure(Throwable cause) {
                                        waiterAcquireFuture.completeExceptionally(acquireCause);
                                    }
                                });
                            }
                        }
                    });
            return new LockWaiter(lockId.getLeft(), currentOwner, waiterAcquireFuture);
        }
    });
}

From source file:org.apache.distributedlog.lock.ZKSessionLock.java

License:Apache License

/**
 * Try lock. If wait is true, it would wait and watch sibling to acquire lock when
 * the sibling is dead. <i>acquireCompletableFuture</i> will be notified either it locked successfully
 * or the lock failed. The promise will only satisfy with current lock owner.
 *
 * <p>NOTE: the <i>promise</i> is only satisfied on <i>lockStateExecutor</i>, so any
 * transformations attached on promise will be executed in order.</p>
 *
 * @param wait/*from  w  w  w  .ja  va 2 s. com*/
 *          whether to wait for ownership.
 * @param promise
 *          promise to satisfy with current lock owner.
 */
private void asyncTryLockWithoutCleanup(final boolean wait, final CompletableFuture<String> promise) {
    executeLockAction(epoch.get(), new LockAction() {
        @Override
        public void execute() {
            if (!lockState.inState(State.INIT)) {
                promise.completeExceptionally(
                        new LockStateChangedException(lockPath, lockId, State.INIT, lockState.getState()));
                return;
            }
            lockState.transition(State.PREPARING);

            final int curEpoch = epoch.incrementAndGet();
            watcher = new LockWatcher(curEpoch);
            // register watcher for session expires
            zkClient.register(watcher);
            // Encode both client id and session in the lock node
            String myPath;
            try {
                // member_<clientid>_s<owner_session>_
                myPath = getLockPathPrefixV3(lockPath, lockId.getLeft(), lockId.getRight());
            } catch (UnsupportedEncodingException uee) {
                myPath = getLockPathPrefixV1(lockPath);
            }
            zk.create(myPath, serializeClientId(lockId.getLeft()), zkClient.getDefaultACL(),
                    CreateMode.EPHEMERAL_SEQUENTIAL, new AsyncCallback.StringCallback() {
                        @Override
                        public void processResult(final int rc, String path, Object ctx, final String name) {
                            executeLockAction(curEpoch, new LockAction() {
                                @Override
                                public void execute() {
                                    if (KeeperException.Code.OK.intValue() != rc) {
                                        KeeperException ke = KeeperException
                                                .create(KeeperException.Code.get(rc));
                                        promise.completeExceptionally(ke);
                                        return;
                                    }

                                    if (FailpointUtils.checkFailPointNoThrow(
                                            FailpointUtils.FailPointName.FP_LockTryCloseRaceCondition)) {
                                        lockState.transition(State.CLOSING);
                                        lockState.transition(State.CLOSED);
                                    }

                                    if (null != currentNode) {
                                        LOG.error("Current node for {} overwritten current = {} new = {}",
                                                new Object[] { lockPath, lockId,
                                                        getLockIdFromPath(currentNode) });
                                    }

                                    currentNode = name;
                                    currentId = getLockIdFromPath(currentNode);
                                    LOG.trace("{} received member id for lock {}", lockId, currentId);

                                    if (lockState.isExpiredOrClosing()) {
                                        // Delete node attempt may have come after PREPARING but before create node,
                                        // in which case we'd be left with a dangling node unless we clean up.
                                        CompletableFuture<Void> deletePromise = new CompletableFuture<Void>();
                                        deleteLockNode(deletePromise);
                                        FutureUtils
                                                .ensure(deletePromise,
                                                        () -> promise.completeExceptionally(
                                                                new LockClosedException(lockPath, lockId,
                                                                        lockState.getState())));
                                        return;
                                    }

                                    lockState.transition(State.PREPARED);
                                    checkLockOwnerAndWaitIfPossible(watcher, wait, promise);
                                }

                                @Override
                                public String getActionName() {
                                    return "postPrepare(wait=" + wait + ")";
                                }
                            });
                        }
                    }, null);
        }

        @Override
        public String getActionName() {
            return "prepare(wait=" + wait + ")";
        }
    }, promise);
}

From source file:org.apache.distributedlog.lock.ZKSessionLock.java

License:Apache License

/**
 * Check Lock Owner Phase 2 : check all lock waiters to get current owner and wait for ownership if necessary.
 *
 * @param lockWatcher//from w  w w.  ja v  a2s . co m
 *          lock watcher.
 * @param wait
 *          whether to wait for ownership.
 * @param getChildrenRc
 *          result of getting all lock waiters
 * @param children
 *          current lock waiters.
 * @param promise
 *          promise to satisfy with current lock owner.
 */
private void processLockWaiters(final LockWatcher lockWatcher, final boolean wait, final int getChildrenRc,
        final List<String> children, final CompletableFuture<String> promise) {
    executeLockAction(lockWatcher.epoch, new LockAction() {
        @Override
        public void execute() {
            if (!lockState.inState(State.PREPARED)) { // e.g. lock closed or session expired after prepared
                promise.completeExceptionally(
                        new LockStateChangedException(lockPath, lockId, State.PREPARED, lockState.getState()));
                return;
            }

            if (KeeperException.Code.OK.intValue() != getChildrenRc) {
                promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(getChildrenRc)));
                return;
            }
            if (children.isEmpty()) {
                LOG.error("Error, member list is empty for lock {}.", lockPath);
                promise.completeExceptionally(
                        new UnexpectedException("Empty member list for lock " + lockPath));
                return;
            }

            // sort the children
            Collections.sort(children, MEMBER_COMPARATOR);
            final String cid = currentId;
            final int memberIndex = children.indexOf(cid);
            if (LOG.isDebugEnabled()) {
                LOG.debug("{} is the number {} member in the list.", cid, memberIndex);
            }
            // If we hold the lock
            if (memberIndex == 0) {
                LOG.info("{} acquired the lock {}.", cid, lockPath);
                claimOwnership(lockWatcher.epoch);
                promise.complete(cid);
            } else if (memberIndex > 0) { // we are in the member list but we didn't hold the lock
                // get ownership of current owner
                asyncParseClientID(zk, lockPath, children.get(0))
                        .whenComplete(new FutureEventListener<Pair<String, Long>>() {
                            @Override
                            public void onSuccess(Pair<String, Long> currentOwner) {
                                watchLockOwner(lockWatcher, wait, cid, children.get(memberIndex - 1),
                                        children.get(0), currentOwner, promise);
                            }

                            @Override
                            public void onFailure(final Throwable cause) {
                                // ensure promise is satisfied in lock thread
                                executeLockAction(lockWatcher.epoch, new LockAction() {
                                    @Override
                                    public void execute() {
                                        promise.completeExceptionally(cause);
                                    }

                                    @Override
                                    public String getActionName() {
                                        return "handleFailureOnParseClientID(lockPath=" + lockPath + ")";
                                    }
                                }, promise);
                            }
                        });
            } else {
                LOG.error("Member {} doesn't exist in the members list {} for lock {}.",
                        new Object[] { cid, children, lockPath });
                promise.completeExceptionally(new UnexpectedException("Member " + cid
                        + " doesn't exist in member list " + children + " for lock " + lockPath));
            }
        }

        @Override
        public String getActionName() {
            return "processLockWaiters(rc=" + getChildrenRc + ", waiters=" + children + ")";
        }
    }, promise);
}

From source file:org.apache.distributedlog.lock.ZKSessionLock.java

License:Apache License

/**
 * Check Lock Owner Phase 3: watch sibling node for lock ownership.
 *
 * @param lockWatcher/*from ww  w  . ja  va 2  s .com*/
 *          lock watcher.
 * @param wait
 *          whether to wait for ownership.
 * @param myNode
 *          my lock node.
 * @param siblingNode
 *          my sibling lock node.
 * @param ownerNode
 *          owner lock node.
 * @param currentOwner
 *          current owner info.
 * @param promise
 *          promise to satisfy with current lock owner.
 */
private void watchLockOwner(final LockWatcher lockWatcher, final boolean wait, final String myNode,
        final String siblingNode, final String ownerNode, final Pair<String, Long> currentOwner,
        final CompletableFuture<String> promise) {
    executeLockAction(lockWatcher.epoch, new LockAction() {
        @Override
        public void execute() {
            boolean shouldWatch;
            final boolean shouldClaimOwnership;
            if (lockContext.hasLockId(currentOwner) && siblingNode.equals(ownerNode)) {
                // if the current owner is the znode left from previous session
                // we should watch it and claim ownership
                shouldWatch = true;
                shouldClaimOwnership = true;
                LOG.info(
                        "LockWatcher {} for {} found its previous session {} held lock,"
                                + " watch it to claim ownership.",
                        new Object[] { myNode, lockPath, currentOwner });
            } else if (lockId.compareTo(currentOwner) == 0
                    && areLockWaitersInSameSession(siblingNode, ownerNode)) {
                // I found that my sibling is the current owner with same lock id (client id & session id)
                // It must be left by any race condition from same zookeeper client
                shouldWatch = true;
                shouldClaimOwnership = true;
                LOG.info(
                        "LockWatcher {} for {} found itself {} already held lock at sibling node {},"
                                + " watch it to claim ownership.",
                        new Object[] { myNode, lockPath, lockId, siblingNode });
            } else {
                shouldWatch = wait;
                if (wait) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(
                                "Current LockWatcher for {} with ephemeral node {}, "
                                        + "is waiting for {} to release lock at {}.",
                                new Object[] { lockPath, myNode, siblingNode, System.currentTimeMillis() });
                    }
                }
                shouldClaimOwnership = false;
            }

            // watch sibling for lock ownership
            if (shouldWatch) {
                watchedNode = String.format("%s/%s", lockPath, siblingNode);
                zk.exists(watchedNode, lockWatcher, new AsyncCallback.StatCallback() {
                    @Override
                    public void processResult(final int rc, String path, Object ctx, final Stat stat) {
                        executeLockAction(lockWatcher.epoch, new LockAction() {
                            @Override
                            public void execute() {
                                if (!lockState.inState(State.PREPARED)) {
                                    promise.completeExceptionally(new LockStateChangedException(lockPath,
                                            lockId, State.PREPARED, lockState.getState()));
                                    return;
                                }

                                if (KeeperException.Code.OK.intValue() == rc) {
                                    if (shouldClaimOwnership) {
                                        // watch owner successfully
                                        LOG.info(
                                                "LockWatcher {} claimed ownership for {} after set watcher on {}.",
                                                new Object[] { myNode, lockPath, ownerNode });
                                        claimOwnership(lockWatcher.epoch);
                                        promise.complete(currentOwner.getLeft());
                                    } else {
                                        // watch sibling successfully
                                        lockState.transition(State.WAITING);
                                        promise.complete(currentOwner.getLeft());
                                    }
                                } else if (KeeperException.Code.NONODE.intValue() == rc) {
                                    // sibling just disappeared, it might be the chance to claim ownership
                                    checkLockOwnerAndWaitIfPossible(lockWatcher, wait, promise);
                                } else {
                                    promise.completeExceptionally(
                                            KeeperException.create(KeeperException.Code.get(rc)));
                                }
                            }

                            @Override
                            public String getActionName() {
                                StringBuilder sb = new StringBuilder();
                                sb.append("postWatchLockOwner(myNode=").append(myNode).append(", siblingNode=")
                                        .append(siblingNode).append(", ownerNode=").append(ownerNode)
                                        .append(")");
                                return sb.toString();
                            }
                        }, promise);
                    }
                }, null);
            } else {
                promise.complete(currentOwner.getLeft());
            }
        }

        @Override
        public String getActionName() {
            StringBuilder sb = new StringBuilder();
            sb.append("watchLockOwner(myNode=").append(myNode).append(", siblingNode=").append(siblingNode)
                    .append(", ownerNode=").append(ownerNode).append(")");
            return sb.toString();
        }
    }, promise);
}

From source file:org.apache.distributedlog.util.Utils.java

License:Apache License

/**
 * Retrieve data from zookeeper <code>path</code>.
 *
 * @param path/*from   w  w  w . j  a  v a 2  s  .  c om*/
 *          zookeeper path to retrieve data
 * @param watch
 *          whether to watch the path
 * @return future representing the versioned value. null version or null value means path doesn't exist.
 */
public static CompletableFuture<Versioned<byte[]>> zkGetData(ZooKeeper zk, String path, boolean watch) {
    final CompletableFuture<Versioned<byte[]>> promise = new CompletableFuture<Versioned<byte[]>>();
    zk.getData(path, watch, new AsyncCallback.DataCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
            if (KeeperException.Code.OK.intValue() == rc) {
                if (null == stat) {
                    promise.complete(new Versioned<byte[]>(null, null));
                } else {
                    promise.complete(new Versioned<byte[]>(data, new LongVersion(stat.getVersion())));
                }
            } else if (KeeperException.Code.NONODE.intValue() == rc) {
                promise.complete(new Versioned<byte[]>(null, null));
            } else {
                promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc)));
            }
        }
    }, null);
    return promise;
}

From source file:org.apache.distributedlog.util.Utils.java

License:Apache License

/**
 * Set <code>data</code> to zookeeper <code>path</code>.
 *
 * @param zk/*from   w  w w  .  j a va2s. c  om*/
 *          zookeeper client
 * @param path
 *          path to set data
 * @param data
 *          data to set
 * @param version
 *          version used to set data
 * @return future representing the version after this operation.
 */
public static CompletableFuture<LongVersion> zkSetData(ZooKeeper zk, String path, byte[] data,
        LongVersion version) {
    final CompletableFuture<LongVersion> promise = new CompletableFuture<LongVersion>();
    zk.setData(path, data, (int) version.getLongVersion(), new AsyncCallback.StatCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, Stat stat) {
            if (KeeperException.Code.OK.intValue() == rc) {
                promise.complete(new LongVersion(stat.getVersion()));
                return;
            }
            promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc)));
            return;
        }
    }, null);
    return promise;
}