/**
   * Return the stat of the node of the given path. Return null if no such a node exists.
   *
   * <p>If the watch is non-null and the call is successful (no exception is thrown), a watch will
   * be left on the node with the given path. The watch will be triggered by a successful operation
   * that creates/delete the node or sets the data on the node.
   *
   * @param path the node path
   * @param watcher explicit watcher
   * @return the stat of the node of the given path; return null if no such a node exists.
   * @throws KeeperException If the server signals an error
   * @throws InterruptedException If the server transaction is interrupted.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public Stat exists(final String path, Watcher watcher)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    // the watch contains the un-chroot path
    WatchRegistration wcb = null;
    if (watcher != null) {
      wcb = new ExistsWatchRegistration(watcher, clientPath);
    }

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.exists);
    ExistsRequest request = new ExistsRequest();
    request.setPath(serverPath);
    request.setWatch(watcher != null);
    SetDataResponse response = new SetDataResponse();
    ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
    if (r.getErr() != 0) {
      if (r.getErr() == KeeperException.Code.NONODE.intValue()) {
        return null;
      }
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }

    return response.getStat().getCzxid() == -1 ? null : response.getStat();
  }
  /**
   * Return the data and the stat of the node of the given path.
   *
   * <p>If the watch is non-null and the call is successful (no exception is thrown), a watch will
   * be left on the node with the given path. The watch will be triggered by a successful operation
   * that sets data on the node, or deletes the node.
   *
   * <p>A KeeperException with error code KeeperException.NoNode will be thrown if no node with the
   * given path exists.
   *
   * @param path the given path
   * @param watcher explicit watcher
   * @param stat the stat of the node
   * @return the data of the node
   * @throws KeeperException If the server signals an error with a non-zero error code
   * @throws InterruptedException If the server transaction is interrupted.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public byte[] getData(final String path, Watcher watcher, Stat stat)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    // the watch contains the un-chroot path
    WatchRegistration wcb = null;
    if (watcher != null) {
      wcb = new DataWatchRegistration(watcher, clientPath);
    }

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.getData);
    GetDataRequest request = new GetDataRequest();
    request.setPath(serverPath);
    request.setWatch(watcher != null);
    GetDataResponse response = new GetDataResponse();
    ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
    if (stat != null) {
      DataTree.copyStat(response.getStat(), stat);
    }
    return response.getData();
  }
  /**
   * Create a node with the given path. The node data will be the given data, and node acl will be
   * the given acl.
   *
   * <p>The flags argument specifies whether the created node will be ephemeral or not.
   *
   * <p>An ephemeral node will be removed by the ZooKeeper automatically when the session associated
   * with the creation of the node expires.
   *
   * <p>The flags argument can also specify to create a sequential node. The actual path name of a
   * sequential node will be the given path plus a suffix "_i" where i is the current sequential
   * number of the node. Once such a node is created, the sequential number will be incremented by
   * one.
   *
   * <p>If a node with the same actual path already exists in the ZooKeeper, a KeeperException with
   * error code KeeperException.NodeExists will be thrown. Note that since a different actual path
   * is used for each invocation of creating sequential node with the same path argument, the call
   * will never throw "file exists" KeeperException.
   *
   * <p>If the parent node does not exist in the ZooKeeper, a KeeperException with error code
   * KeeperException.NoNode will be thrown.
   *
   * <p>An ephemeral node cannot have children. If the parent node of the given path is ephemeral, a
   * KeeperException with error code KeeperException.NoChildrenForEphemerals will be thrown.
   *
   * <p>This operation, if successful, will trigger all the watches left on the node of the given
   * path by exists and getData API calls, and the watches left on the parent node by getChildren
   * API calls.
   *
   * <p>If a node is created successfully, the ZooKeeper server will trigger the watches on the path
   * left by exists calls, and the watches on the parent of the node by getChildren calls.
   *
   * <p>The maximum allowable size of the data array is 1 MB (1,048,576 bytes). Arrays larger than
   * this will cause a KeeperExecption to be thrown.
   *
   * @param path the path for the node
   * @param data the initial data for the node
   * @param acl the acl for the node
   * @param createMode specifying whether the node to be created is ephemeral and/or sequential
   * @return the actual path of the created node
   * @throws KeeperException if the server returns a non-zero error code
   * @throws KeeperException.InvalidACLException if the ACL is invalid
   * @throws InterruptedException if the transaction is interrupted
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public String create(final String path, byte data[], List<ACL> acl, CreateMode createMode)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath, createMode.isSequential());

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.create);
    CreateRequest request = new CreateRequest();
    CreateResponse response = new CreateResponse();
    request.setData(data);
    request.setFlags(createMode.toFlag());
    request.setPath(serverPath);
    if (acl != null && acl.size() == 0) {
      throw new KeeperException.InvalidACLException();
    }
    request.setAcl(acl);
    ReplyHeader r = cnxn.submitRequest(h, request, response, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
    if (cnxn.chrootPath == null) {
      return response.getPath();
    } else {
      return response.getPath().substring(cnxn.chrootPath.length());
    }
  }
  /**
   * Delete the node with the given path. The call will succeed if such a node exists, and the given
   * version matches the node's version (if the given version is -1, it matches any node's
   * versions).
   *
   * <p>A KeeperException with error code KeeperException.NoNode will be thrown if the nodes does
   * not exist.
   *
   * <p>A KeeperException with error code KeeperException.BadVersion will be thrown if the given
   * version does not match the node's version.
   *
   * <p>A KeeperException with error code KeeperException.NotEmpty will be thrown if the node has
   * children.
   *
   * <p>This operation, if successful, will trigger all the watches on the node of the given path
   * left by exists API calls, and the watches on the parent node left by getChildren API calls.
   *
   * @param path the path of the node to be deleted.
   * @param version the expected node version.
   * @throws InterruptedException IF the server transaction is interrupted
   * @throws KeeperException If the server signals an error with a non-zero return code.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public void delete(final String path, int version) throws InterruptedException, KeeperException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    final String serverPath;

    // maintain semantics even in chroot case
    // specifically - root cannot be deleted
    // I think this makes sense even in chroot case.
    if (clientPath.equals("/")) {
      // a bit of a hack, but delete(/) will never succeed and ensures
      // that the same semantics are maintained
      serverPath = clientPath;
    } else {
      serverPath = prependChroot(clientPath);
    }

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.delete);
    DeleteRequest request = new DeleteRequest();
    request.setPath(serverPath);
    request.setVersion(version);
    ReplyHeader r = cnxn.submitRequest(h, request, null, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
  }
  /**
   * Return the list of the children of the node of the given path.
   *
   * <p>If the watch is non-null and the call is successful (no exception is thrown), a watch will
   * be left on the node with the given path. The watch willbe triggered by a successful operation
   * that deletes the node of the given path or creates/delete a child under the node.
   *
   * <p>The list of children returned is not sorted and no guarantee is provided as to its natural
   * or lexical order.
   *
   * <p>A KeeperException with error code KeeperException.NoNode will be thrown if no node with the
   * given path exists.
   *
   * @param path
   * @param watcher explicit watcher
   * @return an unordered array of children of the node with the given path
   * @throws InterruptedException If the server transaction is interrupted.
   * @throws KeeperException If the server signals an error with a non-zero error code.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public List<String> getChildren(final String path, Watcher watcher)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    // the watch contains the un-chroot path
    WatchRegistration wcb = null;
    if (watcher != null) {
      wcb = new ChildWatchRegistration(watcher, clientPath);
    }

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.getChildren);
    GetChildrenRequest request = new GetChildrenRequest();
    request.setPath(serverPath);
    request.setWatch(watcher != null);
    GetChildrenResponse response = new GetChildrenResponse();
    ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
    return response.getChildren();
  }
  public void leaveServer(String host) throws InterruptedException, KeeperException {

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.leave);
    LeaveRequest request = new LeaveRequest();

    request.setHost(host);

    ReplyHeader r = cnxn.submitRequest(h, request, null, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), null);
    }
  }
  public void joinServer(String host, int port, int election_port)
      throws InterruptedException, KeeperException {

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.join);
    JoinRequest request = new JoinRequest();

    request.setPort(port);
    request.setElectionPort(election_port);
    request.setHost(host);

    ReplyHeader r = cnxn.submitRequest(h, request, null, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), null);
    }
  }
  /**
   * Return the ACL and stat of the node of the given path.
   *
   * <p>A KeeperException with error code KeeperException.NoNode will be thrown if no node with the
   * given path exists.
   *
   * @param path the given path for the node
   * @param stat the stat of the node will be copied to this parameter.
   * @return the ACL array of the given node.
   * @throws InterruptedException If the server transaction is interrupted.
   * @throws KeeperException If the server signals an error with a non-zero error code.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public List<ACL> getACL(final String path, Stat stat)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.getACL);
    GetACLRequest request = new GetACLRequest();
    request.setPath(serverPath);
    GetACLResponse response = new GetACLResponse();
    ReplyHeader r = cnxn.submitRequest(h, request, response, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
    DataTree.copyStat(response.getStat(), stat);
    return response.getAcl();
  }
  /**
   * Set the data for the node of the given path if such a node exists and the given version matches
   * the version of the node (if the given version is -1, it matches any node's versions). Return
   * the stat of the node.
   *
   * <p>This operation, if successful, will trigger all the watches on the node of the given path
   * left by getData calls.
   *
   * <p>A KeeperException with error code KeeperException.NoNode will be thrown if no node with the
   * given path exists.
   *
   * <p>A KeeperException with error code KeeperException.BadVersion will be thrown if the given
   * version does not match the node's version.
   *
   * <p>The maximum allowable size of the data array is 1 MB (1,048,576 bytes). Arrays larger than
   * this will cause a KeeperExecption to be thrown.
   *
   * @param path the path of the node
   * @param data the data to set
   * @param version the expected matching version
   * @return the state of the node
   * @throws InterruptedException If the server transaction is interrupted.
   * @throws KeeperException If the server signals an error with a non-zero error code.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public Stat setData(final String path, byte data[], int version)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.setData);
    SetDataRequest request = new SetDataRequest();
    request.setPath(serverPath);
    request.setData(data);
    request.setVersion(version);
    SetDataResponse response = new SetDataResponse();
    ReplyHeader r = cnxn.submitRequest(h, request, response, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
    return response.getStat();
  }
  /**
   * Set the ACL for the node of the given path if such a node exists and the given version matches
   * the version of the node. Return the stat of the node.
   *
   * <p>A KeeperException with error code KeeperException.NoNode will be thrown if no node with the
   * given path exists.
   *
   * <p>A KeeperException with error code KeeperException.BadVersion will be thrown if the given
   * version does not match the node's version.
   *
   * @param path
   * @param acl
   * @param version
   * @return the stat of the node.
   * @throws InterruptedException If the server transaction is interrupted.
   * @throws KeeperException If the server signals an error with a non-zero error code.
   * @throws org.apache.zookeeper.KeeperException.InvalidACLException If the acl is invalide.
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public Stat setACL(final String path, List<ACL> acl, int version)
      throws KeeperException, InterruptedException {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.setACL);
    SetACLRequest request = new SetACLRequest();
    request.setPath(serverPath);
    if (acl != null && acl.size() == 0) {
      throw new KeeperException.InvalidACLException();
    }
    request.setAcl(acl);
    request.setVersion(version);
    SetACLResponse response = new SetACLResponse();
    ReplyHeader r = cnxn.submitRequest(h, request, response, null);
    if (r.getErr() != 0) {
      throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath);
    }
    return response.getStat();
  }
Example #11
0
    @Override
    public void processResult(int rawReturnCode, String notUsed, Object parent, String notUsed2) {

      KeeperException.Code returnCode = KeeperException.Code.get(rawReturnCode);
      ClaimedCoordinate claimedCoordinate = (ClaimedCoordinate) parent;
      LOG.fine(
          "Claim callback with "
              + returnCode.name()
              + " "
              + claimedCoordinate.path
              + " synched: "
              + isSynchronizedWithZooKeeper.get()
              + " thread: "
              + this);
      switch (returnCode) {
          // The claim was successful. This means that the node was created. We need to
          // populate the status and endpoints.
        case OK:

          // We should be the first one to write to the new node, or fail.
          // This requires that the first version is 0, have not seen this documented
          // but it should be a fair assumption and is verified by unit tests.
          synchronized (lastStatusVersionMonitor) {
            lastStatusVersion = 0;
          }

          // We need to set this to synced or updateCoordinateData will complain.
          // updateCoordinateData will set it to out-of-sync in case of problems.
          isSynchronizedWithZooKeeper.set(true);

          try {
            registerWatcher();
          } catch (CloudnameException e) {
            LOG.fine(
                "Failed register watcher after claim. Going to state out of sync: "
                    + e.getMessage());

            isSynchronizedWithZooKeeper.set(false);
            return;

          } catch (InterruptedException e) {

            LOG.fine("Interrupted while setting up new watcher. Going to state out of sync.");
            isSynchronizedWithZooKeeper.set(false);
            return;
          }
          // No exceptions, let's celebrate with a log message.
          LOG.info("Claim processed ok, path: " + path);
          claimedCoordinate.sendEventToCoordinateListener(
              CoordinateListener.Event.COORDINATE_OK, "claimed");
          return;

        case NODEEXISTS:
          // Someone has already claimed the coordinate. It might have been us in a
          // different thread. If we already have claimed the coordinate then don't care.
          // Else notify the client. If everything is fine, this is not a true negative,
          // so ignore it. It might happen if two attempts to tryClaim the coordinate run
          // in parallel.
          if (isSynchronizedWithZooKeeper.get() && started.get()) {
            LOG.fine("Everything is fine, ignoring NODEEXISTS message, path: " + path);
            return;
          }

          LOG.info("Claimed fail, node already exists, will retry: " + path);
          claimedCoordinate.sendEventToCoordinateListener(
              CoordinateListener.Event.NOT_OWNER, "Node already exists.");
          LOG.info("isSynchronizedWithZooKeeper: " + isSynchronizedWithZooKeeper.get());
          checkVersion.set(true);
          return;
        case NONODE:
          LOG.info("Could not claim due to missing coordinate, path: " + path);
          claimedCoordinate.sendEventToCoordinateListener(
              CoordinateListener.Event.NOT_OWNER,
              "No node on claiming coordinate: " + returnCode.name());
          return;

        default:
          // Random problem, report the problem to the client.
          claimedCoordinate.sendEventToCoordinateListener(
              CoordinateListener.Event.NO_CONNECTION_TO_STORAGE,
              "Could not reclaim coordinate. Return code: " + returnCode.name());
          return;
      }
    }