/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.zookeeper.server; import java.nio.ByteBuffer; import java.util.List; import org.apache.jute.Record; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs.OpCode; import org.apache.zookeeper.data.Id; import org.apache.zookeeper.txn.TxnHeader; /** * This is the structure that represents a request moving through a chain of * RequestProcessors. There are various pieces of information that is tacked * onto the request as it is processed. */ public class Request { private static final Logger LOG = LoggerFactory.getLogger(Request.class); public final static Request requestOfDeath = new Request(null, 0, 0, 0, null, null); /** * @param cnxn * @param sessionId * @param xid * @param type * @param bb */ public Request(ServerCnxn cnxn, long sessionId, int xid, int type, ByteBuffer bb, List<Id> authInfo) { this.cnxn = cnxn; this.sessionId = sessionId; this.cxid = xid; this.type = type; this.request = bb; this.authInfo = authInfo; } public final long sessionId; public final int cxid; public final int type; public final ByteBuffer request; public final ServerCnxn cnxn; public TxnHeader hdr; public Record txn; public long zxid = -1; public final List<Id> authInfo; public final long createTime = System.currentTimeMillis(); private Object owner; private KeeperException e; public Object getOwner() { return owner; } public void setOwner(Object owner) { this.owner = owner; } /** * is the packet type a valid packet in zookeeper * * @param type * the type of the packet * @return true if a valid packet, false if not */ static boolean isValid(int type) { // make sure this is always synchronized with Zoodefs!! switch (type) { case OpCode.notification: return false; case OpCode.create: case OpCode.delete: case OpCode.createSession: case OpCode.exists: case OpCode.getData: case OpCode.check: case OpCode.multi: case OpCode.setData: case OpCode.sync: case OpCode.getACL: case OpCode.setACL: case OpCode.getChildren: case OpCode.getChildren2: case OpCode.ping: case OpCode.closeSession: case OpCode.setWatches: return true; default: return false; } } static boolean isQuorum(int type) { switch (type) { case OpCode.exists: case OpCode.getACL: case OpCode.getChildren: case OpCode.getChildren2: case OpCode.getData: return false; case OpCode.error: case OpCode.closeSession: case OpCode.create: case OpCode.createSession: case OpCode.delete: case OpCode.setACL: case OpCode.setData: case OpCode.check: case OpCode.multi: return true; default: return false; } } static String op2String(int op) { switch (op) { case OpCode.notification: return "notification"; case OpCode.create: return "create"; case OpCode.setWatches: return "setWatches"; case OpCode.delete: return "delete"; case OpCode.exists: return "exists"; case OpCode.getData: return "getData"; case OpCode.check: return "check"; case OpCode.multi: return "multi"; case OpCode.setData: return "setData"; case OpCode.sync: return "sync:"; case OpCode.getACL: return "getACL"; case OpCode.setACL: return "setACL"; case OpCode.getChildren: return "getChildren"; case OpCode.getChildren2: return "getChildren2"; case OpCode.ping: return "ping"; case OpCode.createSession: return "createSession"; case OpCode.closeSession: return "closeSession"; case OpCode.error: return "error"; default: return "unknown " + op; } } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("sessionid:0x").append(Long.toHexString(sessionId)) .append(" type:").append(op2String(type)) .append(" cxid:0x").append(Long.toHexString(cxid)) .append(" zxid:0x").append(Long.toHexString(hdr == null ? -2 : hdr.getZxid())) .append(" txntype:").append(hdr == null ? "unknown" : "" + hdr.getType()); // best effort to print the path assoc with this request String path = "n/a"; if (type != OpCode.createSession && type != OpCode.setWatches && type != OpCode.closeSession && request != null && request.remaining() >= 4) { try { // make sure we don't mess with request itself ByteBuffer rbuf = request.asReadOnlyBuffer(); rbuf.clear(); int pathLen = rbuf.getInt(); // sanity check if (pathLen >= 0 && pathLen < 4096 && rbuf.remaining() >= pathLen) { byte b[] = new byte[pathLen]; rbuf.get(b); path = new String(b); } } catch (Exception e) { // ignore - can't find the path, will output "n/a" instead } } sb.append(" reqpath:").append(path); return sb.toString(); } public void setException(KeeperException e) { this.e = e; } public KeeperException getException() { return e; } }