/** * convert the old stat to new stat * * @param oldStat the old stat * @return the new stat */ private StatPersisted convertStat(StatPersistedV1 oldStat) { StatPersisted stat = new StatPersisted(); stat.setAversion(oldStat.getAversion()); stat.setCtime(oldStat.getCtime()); stat.setCversion(oldStat.getCversion()); stat.setCzxid(oldStat.getCzxid()); stat.setEphemeralOwner(oldStat.getEphemeralOwner()); stat.setMtime(oldStat.getMtime()); stat.setMzxid(oldStat.getMzxid()); stat.setVersion(oldStat.getVersion()); return stat; }
public static void copyStatPersisted(StatPersisted from, StatPersisted to) { to.setAversion(from.getAversion()); to.setCtime(from.getCtime()); to.setCversion(from.getCversion()); to.setCzxid(from.getCzxid()); to.setMtime(from.getMtime()); to.setMzxid(from.getMzxid()); to.setPzxid(from.getPzxid()); to.setVersion(from.getVersion()); to.setEphemeralOwner(from.getEphemeralOwner()); }
/** * @param path * @param data * @param acl * @param ephemeralOwner the session id that owns this node. -1 indicates this is not an ephemeral * node. * @param zxid * @param time * @return the patch of the created node * @throws KeeperException */ public String createNode( String path, byte data[], List<ACL> acl, long ephemeralOwner, long zxid, long time) throws KeeperException.NoNodeException, KeeperException.NodeExistsException { int lastSlash = path.lastIndexOf('/'); String parentName = path.substring(0, lastSlash); String childName = path.substring(lastSlash + 1); StatPersisted stat = new StatPersisted(); stat.setCtime(time); stat.setMtime(time); stat.setCzxid(zxid); stat.setMzxid(zxid); stat.setPzxid(zxid); stat.setVersion(0); stat.setAversion(0); stat.setEphemeralOwner(ephemeralOwner); DataNode parent = nodes.get(parentName); if (parent == null) { throw new KeeperException.NoNodeException(); } synchronized (parent) { if (parent.children.contains(childName)) { throw new KeeperException.NodeExistsException(); } int cver = parent.stat.getCversion(); cver++; parent.stat.setCversion(cver); parent.stat.setPzxid(zxid); Long longval = convertAcls(acl); DataNode child = new DataNode(parent, data, longval, stat); parent.children.add(childName); nodes.put(path, child); if (ephemeralOwner != 0) { HashSet<String> list = ephemerals.get(ephemeralOwner); if (list == null) { list = new HashSet<String>(); ephemerals.put(ephemeralOwner, list); } synchronized (list) { list.add(path); } } } // now check if its one of the zookeeper node child if (parentName.startsWith(quotaZookeeper)) { // now check if its the limit node if (Quotas.limitNode.equals(childName)) { // this is the limit node // get the parent and add it to the trie pTrie.addPath(parentName.substring(quotaZookeeper.length())); } if (Quotas.statNode.equals(childName)) { updateQuotaForPath(parentName.substring(quotaZookeeper.length())); } } // also check to update the quotas for this node String lastPrefix = pTrie.findMaxPrefix(path); if (!rootZookeeper.equals(lastPrefix) && !("".equals(lastPrefix))) { // ok we have some match and need to update updateCount(lastPrefix, 1); updateBytes(lastPrefix, data == null ? 0 : data.length); } dataWatches.triggerWatch(path, Event.EventType.NodeCreated); childWatches.triggerWatch( parentName.equals("") ? "/" : parentName, Event.EventType.NodeChildrenChanged); return path; }
/** * 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); }