コード例 #1
0
 public static String buildPath(String parent, String firstPart, String... restOfParts) {
   PathUtils.validatePath(parent);
   if (firstPart.contains("/"))
     throw new IllegalArgumentException("only parent may contain / character");
   String path = (parent.equals("/") ? parent : parent + "/") + firstPart;
   for (String part : restOfParts) {
     if (part.contains("/"))
       throw new IllegalArgumentException("only parent may contain / character");
     path = path + "/" + part;
   }
   PathUtils.validatePath(path);
   return path;
 }
コード例 #2
0
  /**
   * 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();
  }
コード例 #3
0
  /**
   * 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());
    }
  }
コード例 #4
0
  /**
   * 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();
  }
コード例 #5
0
  /**
   * 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);
    }
  }
コード例 #6
0
  /**
   * 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();
  }
コード例 #7
0
 public static String getName(String path) {
   PathUtils.validatePath(path);
   if (path.equals("/")) {
     throw new IllegalArgumentException("name of / is undefined");
   }
   final int index = path.lastIndexOf('/');
   return path.substring(index + 1);
 }
コード例 #8
0
 public static String getParent(String path) {
   PathUtils.validatePath(path);
   if (path.equals("/")) {
     throw new IllegalArgumentException("parent of / is undefined");
   }
   final int index = path.lastIndexOf('/');
   if (index == 0) {
     return "/";
   }
   return path.substring(0, index);
 }
コード例 #9
0
  /**
   * Asynchronous sync. Flushes channel between process and leader.
   *
   * @param path
   * @param cb a handler for the callback
   * @param ctx context to be provided to the callback
   * @throws IllegalArgumentException if an invalid path is specified
   */
  public void sync(final String path, VoidCallback cb, Object ctx) {
    final String clientPath = path;
    PathUtils.validatePath(clientPath);

    final String serverPath = prependChroot(clientPath);

    RequestHeader h = new RequestHeader();
    h.setType(ZooDefs.OpCode.sync);
    SyncRequest request = new SyncRequest();
    SyncResponse response = new SyncResponse();
    request.setPath(serverPath);
    cnxn.queuePacket(
        h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, null);
  }
コード例 #10
0
  /**
   * The Asynchronous version of setData. The request doesn't actually until the asynchronous
   * callback is called.
   *
   * @see #setData(String, byte[], int)
   */
  public void setData(final String path, byte data[], int version, StatCallback cb, Object ctx) {
    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();
    cnxn.queuePacket(
        h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, null);
  }
コード例 #11
0
  LockInternals(
      CuratorFramework client,
      LockInternalsDriver driver,
      String path,
      String lockName,
      int maxLeases) {
    this.driver = driver;
    this.lockName = lockName;
    this.maxLeases = maxLeases;
    PathUtils.validatePath(path);

    this.client = client;
    this.basePath = path;
    this.path = ZKPaths.makePath(path, lockName);

    ensurePath = client.newNamespaceAwareEnsurePath(basePath);
  }
コード例 #12
0
  /**
   * 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();
  }
コード例 #13
0
  /**
   * 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();
  }
コード例 #14
0
  /**
   * The Asynchronous version of getData. The request doesn't actually until the asynchronous
   * callback is called.
   *
   * @see #getData(String, Watcher, Stat)
   */
  public void getData(final String path, Watcher watcher, DataCallback cb, Object ctx) {
    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();
    cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, wcb);
  }
コード例 #15
0
  /**
   * 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();
  }
コード例 #16
0
  /**
   * The Asynchronous version of create. The request doesn't actually until the asynchronous
   * callback is called.
   *
   * @see #create(String, byte[], List, CreateMode)
   */
  public void create(
      final String path,
      byte data[],
      List<ACL> acl,
      CreateMode createMode,
      StringCallback cb,
      Object ctx) {
    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();
    ReplyHeader r = new ReplyHeader();
    request.setData(data);
    request.setFlags(createMode.toFlag());
    request.setPath(serverPath);
    request.setAcl(acl);
    cnxn.queuePacket(h, r, request, response, cb, clientPath, serverPath, ctx, null);
  }
コード例 #17
0
  /**
   * The Asynchronous version of delete. The request doesn't actually until the asynchronous
   * callback is called.
   *
   * @see #delete(String, int)
   */
  public void delete(final String path, int version, VoidCallback cb, Object ctx) {
    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);
    cnxn.queuePacket(h, new ReplyHeader(), request, null, cb, clientPath, serverPath, ctx, null);
  }
コード例 #18
0
  /**
   * This method will be called inside the ProcessRequestThread, which is a singleton, so there will
   * be a single thread calling this code.
   *
   * @param request
   */
  @SuppressWarnings("unchecked")
  protected void pRequest(Request request) throws RequestProcessorException {
    // LOG.info("Prep>>> cxid = " + request.cxid + " type = " +
    // request.type + " id = 0x" + Long.toHexString(request.sessionId));
    TxnHeader txnHeader = null;
    Record txn = null;
    try {
      switch (request.type) {
        case OpCode.create:
          txnHeader =
              new TxnHeader(
                  request.sessionId, request.cxid, zks.getNextZxid(), zks.getTime(), OpCode.create);
          zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
          CreateRequest createRequest = new CreateRequest();
          ZooKeeperServer.byteBuffer2Record(request.request, createRequest);
          String path = createRequest.getPath();
          int lastSlash = path.lastIndexOf('/');
          if (lastSlash == -1 || path.indexOf('\0') != -1 || failCreate) {
            LOG.info(
                "Invalid path " + path + " with session 0x" + Long.toHexString(request.sessionId));
            throw new KeeperException.BadArgumentsException(path);
          }
          if (!fixupACL(request.authInfo, createRequest.getAcl())) {
            throw new KeeperException.InvalidACLException(path);
          }
          String parentPath = path.substring(0, lastSlash);
          ChangeRecord parentRecord = getRecordForPath(parentPath);

          checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo);
          int parentCVersion = parentRecord.stat.getCversion();
          CreateMode createMode = CreateMode.fromFlag(createRequest.getFlags());
          if (createMode.isSequential()) {
            path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion);
          }
          try {
            PathUtils.validatePath(path);
          } catch (IllegalArgumentException ie) {
            LOG.info(
                "Invalid path " + path + " with session 0x" + Long.toHexString(request.sessionId));
            throw new KeeperException.BadArgumentsException(path);
          }
          try {
            if (getRecordForPath(path) != null) {
              throw new KeeperException.NodeExistsException(path);
            }
          } catch (KeeperException.NoNodeException e) {
            // ignore this one
          }
          boolean ephemeralParent = parentRecord.stat.getEphemeralOwner() != 0;
          if (ephemeralParent) {
            throw new KeeperException.NoChildrenForEphemeralsException(path);
          }
          txn =
              new CreateTxn(
                  path, createRequest.getData(), createRequest.getAcl(), createMode.isEphemeral());
          StatPersisted s = new StatPersisted();
          if (createMode.isEphemeral()) {
            s.setEphemeralOwner(request.sessionId);
          }
          parentRecord = parentRecord.duplicate(txnHeader.getZxid());
          parentRecord.childCount++;
          parentRecord.stat.setCversion(parentRecord.stat.getCversion() + 1);
          addChangeRecord(parentRecord);
          addChangeRecord(
              new ChangeRecord(txnHeader.getZxid(), path, s, 0, createRequest.getAcl()));

          break;
        case OpCode.delete:
          txnHeader =
              new TxnHeader(
                  request.sessionId, request.cxid, zks.getNextZxid(), zks.getTime(), OpCode.delete);
          zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
          DeleteRequest deleteRequest = new DeleteRequest();
          ZooKeeperServer.byteBuffer2Record(request.request, deleteRequest);
          path = deleteRequest.getPath();
          lastSlash = path.lastIndexOf('/');
          if (lastSlash == -1
              || path.indexOf('\0') != -1
              || zks.getZKDatabase().isSpecialPath(path)) {
            throw new KeeperException.BadArgumentsException(path);
          }
          parentPath = path.substring(0, lastSlash);
          parentRecord = getRecordForPath(parentPath);
          ChangeRecord nodeRecord = getRecordForPath(path);
          checkACL(zks, parentRecord.acl, ZooDefs.Perms.DELETE, request.authInfo);
          int version = deleteRequest.getVersion();
          if (version != -1 && nodeRecord.stat.getVersion() != version) {
            throw new KeeperException.BadVersionException(path);
          }
          if (nodeRecord.childCount > 0) {
            throw new KeeperException.NotEmptyException(path);
          }
          txn = new DeleteTxn(path);
          parentRecord = parentRecord.duplicate(txnHeader.getZxid());
          parentRecord.childCount--;
          parentRecord.stat.setCversion(parentRecord.stat.getCversion() + 1);
          addChangeRecord(parentRecord);
          addChangeRecord(new ChangeRecord(txnHeader.getZxid(), path, null, -1, null));
          break;
        case OpCode.setData:
          txnHeader =
              new TxnHeader(
                  request.sessionId,
                  request.cxid,
                  zks.getNextZxid(),
                  zks.getTime(),
                  OpCode.setData);
          zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
          SetDataRequest setDataRequest = new SetDataRequest();
          ZooKeeperServer.byteBuffer2Record(request.request, setDataRequest);
          path = setDataRequest.getPath();
          nodeRecord = getRecordForPath(path);
          checkACL(zks, nodeRecord.acl, ZooDefs.Perms.WRITE, request.authInfo);
          version = setDataRequest.getVersion();
          int currentVersion = nodeRecord.stat.getVersion();
          if (version != -1 && version != currentVersion) {
            throw new KeeperException.BadVersionException(path);
          }
          version = currentVersion + 1;
          txn = new SetDataTxn(path, setDataRequest.getData(), version);
          nodeRecord = nodeRecord.duplicate(txnHeader.getZxid());
          nodeRecord.stat.setVersion(version);
          addChangeRecord(nodeRecord);
          break;
        case OpCode.setACL:
          txnHeader =
              new TxnHeader(
                  request.sessionId, request.cxid, zks.getNextZxid(), zks.getTime(), OpCode.setACL);
          zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
          SetACLRequest setAclRequest = new SetACLRequest();
          ZooKeeperServer.byteBuffer2Record(request.request, setAclRequest);
          path = setAclRequest.getPath();
          if (!fixupACL(request.authInfo, setAclRequest.getAcl())) {
            throw new KeeperException.InvalidACLException(path);
          }
          nodeRecord = getRecordForPath(path);
          checkACL(zks, nodeRecord.acl, ZooDefs.Perms.ADMIN, request.authInfo);
          version = setAclRequest.getVersion();
          currentVersion = nodeRecord.stat.getAversion();
          if (version != -1 && version != currentVersion) {
            throw new KeeperException.BadVersionException(path);
          }
          version = currentVersion + 1;
          txn = new SetACLTxn(path, setAclRequest.getAcl(), version);
          nodeRecord = nodeRecord.duplicate(txnHeader.getZxid());
          nodeRecord.stat.setAversion(version);
          addChangeRecord(nodeRecord);
          break;
        case OpCode.createSession:
          txnHeader =
              new TxnHeader(
                  request.sessionId,
                  request.cxid,
                  zks.getNextZxid(),
                  zks.getTime(),
                  OpCode.createSession);
          request.request.rewind();
          int to = request.request.getInt();
          txn = new CreateSessionTxn(to);
          request.request.rewind();
          zks.sessionTracker.addSession(request.sessionId, to);
          zks.setOwner(request.sessionId, request.getOwner());
          break;
        case OpCode.closeSession:
          txnHeader =
              new TxnHeader(
                  request.sessionId,
                  request.cxid,
                  zks.getNextZxid(),
                  zks.getTime(),
                  OpCode.closeSession);
          // We don't want to do this check since the session expiration thread
          // queues up this operation without being the session owner.
          // this request is the last of the session so it should be ok
          // zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
          HashSet<String> es = zks.getZKDatabase().getEphemerals(request.sessionId);
          synchronized (zks.outstandingChanges) {
            for (ChangeRecord c : zks.outstandingChanges) {
              if (c.stat == null) {
                // Doing a delete
                es.remove(c.path);
              } else if (c.stat.getEphemeralOwner() == request.sessionId) {
                es.add(c.path);
              }
            }
            for (String path2Delete : es) {
              addChangeRecord(new ChangeRecord(txnHeader.getZxid(), path2Delete, null, 0, null));
            }

            zks.sessionTracker.setSessionClosing(request.sessionId);
          }

          LOG.info(
              "Processed session termination for sessionid: 0x"
                  + Long.toHexString(request.sessionId));
          break;
        case OpCode.sync:
        case OpCode.exists:
        case OpCode.getData:
        case OpCode.getACL:
        case OpCode.getChildren:
        case OpCode.getChildren2:
        case OpCode.ping:
        case OpCode.setWatches:
          zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
          break;
      }
    } catch (KeeperException e) {
      if (txnHeader != null) {
        txnHeader.setType(OpCode.error);
        txn = new ErrorTxn(e.code().intValue());
      }
      LOG.info(
          "Got user-level KeeperException when processing "
              + request.toString()
              + " Error Path:"
              + e.getPath()
              + " Error:"
              + e.getMessage());
      request.setException(e);
    } catch (Exception e) {
      // log at error level as we are returning a marshalling
      // error to the user
      LOG.error("Failed to process " + request, e);

      StringBuilder sb = new StringBuilder();
      ByteBuffer bb = request.request;
      if (bb != null) {
        bb.rewind();
        while (bb.hasRemaining()) {
          sb.append(Integer.toHexString(bb.get() & 0xff));
        }
      } else {
        sb.append("request buffer is null");
      }

      LOG.error("Dumping request buffer: 0x" + sb.toString());
      if (txnHeader != null) {
        txnHeader.setType(OpCode.error);
        txn = new ErrorTxn(Code.MARSHALLINGERROR.intValue());
      }
    }
    request.hdr = txnHeader;
    request.txn = txn;
    request.zxid = zks.getZxid();
    nextProcessor.processRequest(request);
  }