Search in sources :

Example 1 with ChangeRecord

use of org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord in project zookeeper by apache.

the class PrepRequestProcessor method getPendingChanges.

/**
 * Grab current pending change records for each op in a multi-op.
 *
 * This is used inside MultiOp error code path to rollback in the event
 * of a failed multi-op.
 *
 * @param multiRequest
 * @return a map that contains previously existed records that probably need to be
 *         rolled back in any failure.
 */
private Map<String, ChangeRecord> getPendingChanges(MultiTransactionRecord multiRequest) {
    Map<String, ChangeRecord> pendingChangeRecords = new HashMap<String, ChangeRecord>();
    for (Op op : multiRequest) {
        String path = op.getPath();
        ChangeRecord cr = getOutstandingChange(path);
        // only previously existing records need to be rolled back.
        if (cr != null) {
            pendingChangeRecords.put(path, cr);
        }
        /*
             * ZOOKEEPER-1624 - We need to store for parent's ChangeRecord
             * of the parent node of a request. So that if this is a
             * sequential node creation request, rollbackPendingChanges()
             * can restore previous parent's ChangeRecord correctly.
             *
             * Otherwise, sequential node name generation will be incorrect
             * for a subsequent request.
             */
        int lastSlash = path.lastIndexOf('/');
        if (lastSlash == -1 || path.indexOf('\0') != -1) {
            continue;
        }
        String parentPath = path.substring(0, lastSlash);
        ChangeRecord parentCr = getOutstandingChange(parentPath);
        if (parentCr != null) {
            pendingChangeRecords.put(parentPath, parentCr);
        }
    }
    return pendingChangeRecords;
}
Also used : Op(org.apache.zookeeper.Op) HashMap(java.util.HashMap) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord)

Example 2 with ChangeRecord

use of org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord in project fabric8 by jboss-fuse.

the class PrepRequestProcessor method getPendingChanges.

/**
 * Grab current pending change records for each op in a multi-op.
 *
 * This is used inside MultiOp error code path to rollback in the event
 * of a failed multi-op.
 *
 * @param multiRequest
 * @return a map that contains previously existed records that probably need to be
 *         rolled back in any failure.
 */
HashMap<String, ChangeRecord> getPendingChanges(MultiTransactionRecord multiRequest) {
    HashMap<String, ChangeRecord> pendingChangeRecords = new HashMap<String, ChangeRecord>();
    for (Op op : multiRequest) {
        String path = op.getPath();
        ChangeRecord cr = getOutstandingChange(path);
        // only previously existing records need to be rolled back.
        if (cr != null) {
            pendingChangeRecords.put(path, cr);
        }
        /*
             * ZOOKEEPER-1624 - We need to store for parent's ChangeRecord
             * of the parent node of a request. So that if this is a
             * sequential node creation request, rollbackPendingChanges()
             * can restore previous parent's ChangeRecord correctly.
             *
             * Otherwise, sequential node name generation will be incorrect
             * for a subsequent request.
             */
        int lastSlash = path.lastIndexOf('/');
        if (lastSlash == -1 || path.indexOf('\0') != -1) {
            continue;
        }
        String parentPath = path.substring(0, lastSlash);
        ChangeRecord parentCr = getOutstandingChange(parentPath);
        if (parentCr != null) {
            pendingChangeRecords.put(parentPath, parentCr);
        }
    }
    return pendingChangeRecords;
}
Also used : Op(org.apache.zookeeper.Op) HashMap(java.util.HashMap) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord)

Example 3 with ChangeRecord

use of org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord in project fabric8 by jboss-fuse.

the class PrepRequestProcessor method pRequest.

/**
 * 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));
    request.hdr = null;
    request.txn = null;
    try {
        switch(request.type) {
            case OpCode.create:
                CreateRequest createRequest = new CreateRequest();
                pRequest2Txn(request.type, zks.getNextZxid(), request, createRequest, true);
                break;
            case OpCode.delete:
                DeleteRequest deleteRequest = new DeleteRequest();
                pRequest2Txn(request.type, zks.getNextZxid(), request, deleteRequest, true);
                break;
            case OpCode.setData:
                SetDataRequest setDataRequest = new SetDataRequest();
                pRequest2Txn(request.type, zks.getNextZxid(), request, setDataRequest, true);
                break;
            case OpCode.setACL:
                SetACLRequest setAclRequest = new SetACLRequest();
                pRequest2Txn(request.type, zks.getNextZxid(), request, setAclRequest, true);
                break;
            case OpCode.check:
                CheckVersionRequest checkRequest = new CheckVersionRequest();
                pRequest2Txn(request.type, zks.getNextZxid(), request, checkRequest, true);
                break;
            case OpCode.multi:
                MultiTransactionRecord multiRequest = new MultiTransactionRecord();
                try {
                    ByteBufferInputStream.byteBuffer2Record(request.request, multiRequest);
                } catch (IOException e) {
                    request.hdr = new TxnHeader(request.sessionId, request.cxid, zks.getNextZxid(), zks.getTime(), OpCode.multi);
                    throw e;
                }
                List<Txn> txns = new ArrayList<Txn>();
                // Each op in a multi-op must have the same zxid!
                long zxid = zks.getNextZxid();
                KeeperException ke = null;
                // Store off current pending change records in case we need to rollback
                HashMap<String, ChangeRecord> pendingChanges = getPendingChanges(multiRequest);
                int index = 0;
                for (Op op : multiRequest) {
                    Record subrequest = op.toRequestRecord();
                    /* If we've already failed one of the ops, don't bother
                     * trying the rest as we know it's going to fail and it
                     * would be confusing in the logfiles.
                     */
                    if (ke != null) {
                        request.hdr.setType(OpCode.error);
                        request.txn = new ErrorTxn(Code.RUNTIMEINCONSISTENCY.intValue());
                    } else /* Prep the request and convert to a Txn */
                    {
                        try {
                            pRequest2Txn(op.getType(), zxid, request, subrequest, false);
                        } catch (KeeperException e) {
                            if (ke == null) {
                                ke = e;
                            }
                            request.hdr.setType(OpCode.error);
                            request.txn = new ErrorTxn(e.code().intValue());
                            if (!(request.type == OpCode.exists)) {
                                // INFO log only if we're not asking for existence of a node
                                // as this is absolutely normal to ask if a node exists and it doesn't exist
                                LOG.info("Got user-level KeeperException when processing " + request.toString() + " aborting remaining multi ops." + " Error Path:" + e.getPath() + " Error:" + e.getMessage());
                            }
                            request.setException(e);
                            /* Rollback change records from failed multi-op */
                            rollbackPendingChanges(zxid, pendingChanges);
                        }
                    }
                    // FIXME: I don't want to have to serialize it here and then
                    // immediately deserialize in next processor. But I'm
                    // not sure how else to get the txn stored into our list.
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
                    request.txn.serialize(boa, "request");
                    ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
                    txns.add(new Txn(request.hdr.getType(), bb.array()));
                    index++;
                }
                request.hdr = new TxnHeader(request.sessionId, request.cxid, zxid, zks.getTime(), request.type);
                request.txn = new MultiTxn(txns);
                break;
            // create/close session don't require request record
            case OpCode.createSession:
            case OpCode.closeSession:
                pRequest2Txn(request.type, zks.getNextZxid(), request, null, true);
                break;
            // All the rest don't need to create a Txn - just verify session
            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 (request.hdr != null) {
            request.hdr.setType(OpCode.error);
            request.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 (request.hdr != null) {
            request.hdr.setType(OpCode.error);
            request.txn = new ErrorTxn(Code.MARSHALLINGERROR.intValue());
        }
    }
    request.zxid = zks.getZxid();
    nextProcessor.processRequest(request);
}
Also used : Op(org.apache.zookeeper.Op) BinaryOutputArchive(org.apache.jute.BinaryOutputArchive) CheckVersionRequest(org.apache.zookeeper.proto.CheckVersionRequest) MultiTxn(org.apache.zookeeper.txn.MultiTxn) CreateRequest(org.apache.zookeeper.proto.CreateRequest) ArrayList(java.util.ArrayList) SetACLTxn(org.apache.zookeeper.txn.SetACLTxn) SetDataTxn(org.apache.zookeeper.txn.SetDataTxn) CheckVersionTxn(org.apache.zookeeper.txn.CheckVersionTxn) CreateSessionTxn(org.apache.zookeeper.txn.CreateSessionTxn) CreateTxn(org.apache.zookeeper.txn.CreateTxn) Txn(org.apache.zookeeper.txn.Txn) MultiTxn(org.apache.zookeeper.txn.MultiTxn) ErrorTxn(org.apache.zookeeper.txn.ErrorTxn) DeleteTxn(org.apache.zookeeper.txn.DeleteTxn) MultiTransactionRecord(org.apache.zookeeper.MultiTransactionRecord) Record(org.apache.jute.Record) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord) SetACLRequest(org.apache.zookeeper.proto.SetACLRequest) SetDataRequest(org.apache.zookeeper.proto.SetDataRequest) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteBuffer(java.nio.ByteBuffer) XidRolloverException(org.apache.zookeeper.server.quorum.Leader.XidRolloverException) BadArgumentsException(org.apache.zookeeper.KeeperException.BadArgumentsException) KeeperException(org.apache.zookeeper.KeeperException) IOException(java.io.IOException) MultiTransactionRecord(org.apache.zookeeper.MultiTransactionRecord) ErrorTxn(org.apache.zookeeper.txn.ErrorTxn) DeleteRequest(org.apache.zookeeper.proto.DeleteRequest) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord) KeeperException(org.apache.zookeeper.KeeperException) TxnHeader(org.apache.zookeeper.txn.TxnHeader)

Example 4 with ChangeRecord

use of org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord in project zookeeper by apache.

the class PrepRequestProcessor method rollbackPendingChanges.

/**
 * Rollback pending changes records from a failed multi-op.
 *
 * If a multi-op fails, we can't leave any invalid change records we created
 * around. We also need to restore their prior value (if any) if their prior
 * value is still valid.
 *
 * @param zxid
 * @param pendingChangeRecords
 */
void rollbackPendingChanges(long zxid, Map<String, ChangeRecord> pendingChangeRecords) {
    synchronized (zks.outstandingChanges) {
        // Grab a list iterator starting at the END of the list so we can iterate in reverse
        Iterator<ChangeRecord> iter = zks.outstandingChanges.descendingIterator();
        while (iter.hasNext()) {
            ChangeRecord c = iter.next();
            if (c.zxid == zxid) {
                iter.remove();
                // Remove all outstanding changes for paths of this multi.
                // Previous records will be added back later.
                zks.outstandingChangesForPath.remove(c.path);
            } else {
                break;
            }
        }
        // we don't need to roll back any records because there is nothing left.
        if (zks.outstandingChanges.isEmpty()) {
            return;
        }
        long firstZxid = zks.outstandingChanges.peek().zxid;
        for (ChangeRecord c : pendingChangeRecords.values()) {
            // once they are completed.
            if (c.zxid < firstZxid) {
                continue;
            }
            // add previously existing records back.
            zks.outstandingChangesForPath.put(c.path, c);
        }
    }
}
Also used : ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord)

Example 5 with ChangeRecord

use of org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord in project zookeeper by apache.

the class PrepRequestProcessor method getRecordForPath.

private ChangeRecord getRecordForPath(String path) throws KeeperException.NoNodeException {
    ChangeRecord lastChange = null;
    synchronized (zks.outstandingChanges) {
        lastChange = zks.outstandingChangesForPath.get(path);
        if (lastChange == null) {
            DataNode n = zks.getZKDatabase().getNode(path);
            if (n != null) {
                Set<String> children;
                synchronized (n) {
                    children = n.getChildren();
                }
                lastChange = new ChangeRecord(-1, path, n.stat, children.size(), zks.getZKDatabase().aclForNode(n));
                if (digestEnabled) {
                    lastChange.precalculatedDigest = new PrecalculatedDigest(digestCalculator.calculateDigest(path, n), 0);
                }
                lastChange.data = n.getData();
            }
        }
    }
    if (lastChange == null || lastChange.stat == null) {
        throw new KeeperException.NoNodeException(path);
    }
    return lastChange;
}
Also used : PrecalculatedDigest(org.apache.zookeeper.server.ZooKeeperServer.PrecalculatedDigest) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord)

Aggregations

ChangeRecord (org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord)14 KeeperException (org.apache.zookeeper.KeeperException)6 Op (org.apache.zookeeper.Op)6 TxnHeader (org.apache.zookeeper.txn.TxnHeader)6 BadArgumentsException (org.apache.zookeeper.KeeperException.BadArgumentsException)5 CheckVersionRequest (org.apache.zookeeper.proto.CheckVersionRequest)5 CreateRequest (org.apache.zookeeper.proto.CreateRequest)5 DeleteRequest (org.apache.zookeeper.proto.DeleteRequest)5 SetACLRequest (org.apache.zookeeper.proto.SetACLRequest)5 SetDataRequest (org.apache.zookeeper.proto.SetDataRequest)5 CheckVersionTxn (org.apache.zookeeper.txn.CheckVersionTxn)5 CreateSessionTxn (org.apache.zookeeper.txn.CreateSessionTxn)5 CreateTxn (org.apache.zookeeper.txn.CreateTxn)5 DeleteTxn (org.apache.zookeeper.txn.DeleteTxn)5 SetACLTxn (org.apache.zookeeper.txn.SetACLTxn)5 SetDataTxn (org.apache.zookeeper.txn.SetDataTxn)5 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4 HashMap (java.util.HashMap)4 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3