Search in sources :

Example 1 with Request

use of org.apache.zookeeper.server.Request in project zookeeper by apache.

the class LearnerHandler method run.

/**
 * This thread will receive packets from the peer and process them and
 * also listen to new connections from new peers.
 */
@Override
public void run() {
    try {
        learnerMaster.addLearnerHandler(this);
        tickOfNextAckDeadline = learnerMaster.getTickOfInitialAckDeadline();
        ia = BinaryInputArchive.getArchive(bufferedInput);
        bufferedOutput = new BufferedOutputStream(sock.getOutputStream());
        oa = BinaryOutputArchive.getArchive(bufferedOutput);
        QuorumPacket qp = new QuorumPacket();
        ia.readRecord(qp, "packet");
        messageTracker.trackReceived(qp.getType());
        if (qp.getType() != Leader.FOLLOWERINFO && qp.getType() != Leader.OBSERVERINFO) {
            LOG.error("First packet {} is not FOLLOWERINFO or OBSERVERINFO!", qp.toString());
            return;
        }
        if (learnerMaster instanceof ObserverMaster && qp.getType() != Leader.OBSERVERINFO) {
            throw new IOException("Non observer attempting to connect to ObserverMaster. type = " + qp.getType());
        }
        byte[] learnerInfoData = qp.getData();
        if (learnerInfoData != null) {
            ByteBuffer bbsid = ByteBuffer.wrap(learnerInfoData);
            if (learnerInfoData.length >= 8) {
                this.sid = bbsid.getLong();
            }
            if (learnerInfoData.length >= 12) {
                // protocolVersion
                this.version = bbsid.getInt();
            }
            if (learnerInfoData.length >= 20) {
                long configVersion = bbsid.getLong();
                if (configVersion > learnerMaster.getQuorumVerifierVersion()) {
                    throw new IOException("Follower is ahead of the leader (has a later activated configuration)");
                }
            }
        } else {
            this.sid = learnerMaster.getAndDecrementFollowerCounter();
        }
        String followerInfo = learnerMaster.getPeerInfo(this.sid);
        if (followerInfo.isEmpty()) {
            LOG.info("Follower sid: {} not in the current config {}", this.sid, Long.toHexString(learnerMaster.getQuorumVerifierVersion()));
        } else {
            LOG.info("Follower sid: {} : info : {}", this.sid, followerInfo);
        }
        if (qp.getType() == Leader.OBSERVERINFO) {
            learnerType = LearnerType.OBSERVER;
        }
        learnerMaster.registerLearnerHandlerBean(this, sock);
        long lastAcceptedEpoch = ZxidUtils.getEpochFromZxid(qp.getZxid());
        long peerLastZxid;
        StateSummary ss = null;
        long zxid = qp.getZxid();
        long newEpoch = learnerMaster.getEpochToPropose(this.getSid(), lastAcceptedEpoch);
        long newLeaderZxid = ZxidUtils.makeZxid(newEpoch, 0);
        if (this.getVersion() < 0x10000) {
            // we are going to have to extrapolate the epoch information
            long epoch = ZxidUtils.getEpochFromZxid(zxid);
            ss = new StateSummary(epoch, zxid);
            // fake the message
            learnerMaster.waitForEpochAck(this.getSid(), ss);
        } else {
            byte[] ver = new byte[4];
            ByteBuffer.wrap(ver).putInt(0x10000);
            QuorumPacket newEpochPacket = new QuorumPacket(Leader.LEADERINFO, newLeaderZxid, ver, null);
            oa.writeRecord(newEpochPacket, "packet");
            messageTracker.trackSent(Leader.LEADERINFO);
            bufferedOutput.flush();
            QuorumPacket ackEpochPacket = new QuorumPacket();
            ia.readRecord(ackEpochPacket, "packet");
            messageTracker.trackReceived(ackEpochPacket.getType());
            if (ackEpochPacket.getType() != Leader.ACKEPOCH) {
                LOG.error("{} is not ACKEPOCH", ackEpochPacket.toString());
                return;
            }
            ByteBuffer bbepoch = ByteBuffer.wrap(ackEpochPacket.getData());
            ss = new StateSummary(bbepoch.getInt(), ackEpochPacket.getZxid());
            learnerMaster.waitForEpochAck(this.getSid(), ss);
        }
        peerLastZxid = ss.getLastZxid();
        // Take any necessary action if we need to send TRUNC or DIFF
        // startForwarding() will be called in all cases
        boolean needSnap = syncFollower(peerLastZxid, learnerMaster);
        // syncs between followers and the leader are exempt from throttling because it
        // is important to keep the state of quorum servers up-to-date. The exempted syncs
        // are counted as concurrent syncs though
        boolean exemptFromThrottle = getLearnerType() != LearnerType.OBSERVER;
        /* if we are not truncating or sending a diff just send a snapshot */
        if (needSnap) {
            syncThrottler = learnerMaster.getLearnerSnapSyncThrottler();
            syncThrottler.beginSync(exemptFromThrottle);
            ServerMetrics.getMetrics().INFLIGHT_SNAP_COUNT.add(syncThrottler.getSyncInProgress());
            try {
                long zxidToSend = learnerMaster.getZKDatabase().getDataTreeLastProcessedZxid();
                oa.writeRecord(new QuorumPacket(Leader.SNAP, zxidToSend, null, null), "packet");
                messageTracker.trackSent(Leader.SNAP);
                bufferedOutput.flush();
                LOG.info("Sending snapshot last zxid of peer is 0x{}, zxid of leader is 0x{}, " + "send zxid of db as 0x{}, {} concurrent snapshot sync, " + "snapshot sync was {} from throttle", Long.toHexString(peerLastZxid), Long.toHexString(leaderLastZxid), Long.toHexString(zxidToSend), syncThrottler.getSyncInProgress(), exemptFromThrottle ? "exempt" : "not exempt");
                // Dump data to peer
                learnerMaster.getZKDatabase().serializeSnapshot(oa);
                oa.writeString("BenWasHere", "signature");
                bufferedOutput.flush();
            } finally {
                ServerMetrics.getMetrics().SNAP_COUNT.add(1);
            }
        } else {
            syncThrottler = learnerMaster.getLearnerDiffSyncThrottler();
            syncThrottler.beginSync(exemptFromThrottle);
            ServerMetrics.getMetrics().INFLIGHT_DIFF_COUNT.add(syncThrottler.getSyncInProgress());
            ServerMetrics.getMetrics().DIFF_COUNT.add(1);
        }
        LOG.debug("Sending NEWLEADER message to {}", sid);
        // we got here, so the version was set
        if (getVersion() < 0x10000) {
            QuorumPacket newLeaderQP = new QuorumPacket(Leader.NEWLEADER, newLeaderZxid, null, null);
            oa.writeRecord(newLeaderQP, "packet");
        } else {
            QuorumPacket newLeaderQP = new QuorumPacket(Leader.NEWLEADER, newLeaderZxid, learnerMaster.getQuorumVerifierBytes(), null);
            queuedPackets.add(newLeaderQP);
        }
        bufferedOutput.flush();
        // Start thread that blast packets in the queue to learner
        startSendingPackets();
        /*
             * Have to wait for the first ACK, wait until
             * the learnerMaster is ready, and only then we can
             * start processing messages.
             */
        qp = new QuorumPacket();
        ia.readRecord(qp, "packet");
        messageTracker.trackReceived(qp.getType());
        if (qp.getType() != Leader.ACK) {
            LOG.error("Next packet was supposed to be an ACK, but received packet: {}", packetToString(qp));
            return;
        }
        LOG.debug("Received NEWLEADER-ACK message from {}", sid);
        learnerMaster.waitForNewLeaderAck(getSid(), qp.getZxid());
        syncLimitCheck.start();
        // sync ends when NEWLEADER-ACK is received
        syncThrottler.endSync();
        if (needSnap) {
            ServerMetrics.getMetrics().INFLIGHT_SNAP_COUNT.add(syncThrottler.getSyncInProgress());
        } else {
            ServerMetrics.getMetrics().INFLIGHT_DIFF_COUNT.add(syncThrottler.getSyncInProgress());
        }
        syncThrottler = null;
        // now that the ack has been processed expect the syncLimit
        sock.setSoTimeout(learnerMaster.syncTimeout());
        /*
             * Wait until learnerMaster starts up
             */
        learnerMaster.waitForStartup();
        // Mutation packets will be queued during the serialize,
        // so we need to mark when the peer can actually start
        // using the data
        // 
        LOG.debug("Sending UPTODATE message to {}", sid);
        queuedPackets.add(new QuorumPacket(Leader.UPTODATE, -1, null, null));
        while (true) {
            qp = new QuorumPacket();
            ia.readRecord(qp, "packet");
            messageTracker.trackReceived(qp.getType());
            if (LOG.isTraceEnabled()) {
                long traceMask = ZooTrace.SERVER_PACKET_TRACE_MASK;
                if (qp.getType() == Leader.PING) {
                    traceMask = ZooTrace.SERVER_PING_TRACE_MASK;
                }
                ZooTrace.logQuorumPacket(LOG, traceMask, 'i', qp);
            }
            tickOfNextAckDeadline = learnerMaster.getTickOfNextAckDeadline();
            packetsReceived.incrementAndGet();
            ByteBuffer bb;
            long sessionId;
            int cxid;
            int type;
            switch(qp.getType()) {
                case Leader.ACK:
                    if (this.learnerType == LearnerType.OBSERVER) {
                        LOG.debug("Received ACK from Observer {}", this.sid);
                    }
                    syncLimitCheck.updateAck(qp.getZxid());
                    learnerMaster.processAck(this.sid, qp.getZxid(), sock.getLocalSocketAddress());
                    break;
                case Leader.PING:
                    // Process the touches
                    ByteArrayInputStream bis = new ByteArrayInputStream(qp.getData());
                    DataInputStream dis = new DataInputStream(bis);
                    while (dis.available() > 0) {
                        long sess = dis.readLong();
                        int to = dis.readInt();
                        learnerMaster.touch(sess, to);
                    }
                    break;
                case Leader.REVALIDATE:
                    ServerMetrics.getMetrics().REVALIDATE_COUNT.add(1);
                    learnerMaster.revalidateSession(qp, this);
                    break;
                case Leader.REQUEST:
                    bb = ByteBuffer.wrap(qp.getData());
                    sessionId = bb.getLong();
                    cxid = bb.getInt();
                    type = bb.getInt();
                    bb = bb.slice();
                    Request si;
                    if (type == OpCode.sync) {
                        si = new LearnerSyncRequest(this, sessionId, cxid, type, bb, qp.getAuthinfo());
                    } else {
                        si = new Request(null, sessionId, cxid, type, bb, qp.getAuthinfo());
                    }
                    si.setOwner(this);
                    learnerMaster.submitLearnerRequest(si);
                    requestsReceived.incrementAndGet();
                    break;
                default:
                    LOG.warn("unexpected quorum packet, type: {}", packetToString(qp));
                    break;
            }
        }
    } catch (IOException e) {
        LOG.error("Unexpected exception in LearnerHandler: ", e);
        closeSocket();
    } catch (InterruptedException e) {
        LOG.error("Unexpected exception in LearnerHandler.", e);
    } catch (SyncThrottleException e) {
        LOG.error("too many concurrent sync.", e);
        syncThrottler = null;
    } catch (Exception e) {
        LOG.error("Unexpected exception in LearnerHandler.", e);
        throw e;
    } finally {
        if (syncThrottler != null) {
            syncThrottler.endSync();
            syncThrottler = null;
        }
        String remoteAddr = getRemoteAddress();
        LOG.warn("******* GOODBYE {} ********", remoteAddr);
        messageTracker.dumpToLog(remoteAddr);
        shutdown();
    }
}
Also used : Request(org.apache.zookeeper.server.Request) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) ByteBuffer(java.nio.ByteBuffer) SaslException(javax.security.sasl.SaslException) IOException(java.io.IOException) ByteArrayInputStream(java.io.ByteArrayInputStream) BufferedOutputStream(java.io.BufferedOutputStream)

Example 2 with Request

use of org.apache.zookeeper.server.Request in project zookeeper by apache.

the class Observer method processPacket.

/**
 * Controls the response of an observer to the receipt of a quorumpacket
 * @param qp
 * @throws Exception
 */
protected void processPacket(QuorumPacket qp) throws Exception {
    TxnLogEntry logEntry;
    TxnHeader hdr;
    TxnDigest digest;
    Record txn;
    switch(qp.getType()) {
        case Leader.PING:
            ping(qp);
            break;
        case Leader.PROPOSAL:
            LOG.warn("Ignoring proposal");
            break;
        case Leader.COMMIT:
            LOG.warn("Ignoring commit");
            break;
        case Leader.UPTODATE:
            LOG.error("Received an UPTODATE message after Observer started");
            break;
        case Leader.REVALIDATE:
            revalidate(qp);
            break;
        case Leader.SYNC:
            ((ObserverZooKeeperServer) zk).sync();
            break;
        case Leader.INFORM:
            ServerMetrics.getMetrics().LEARNER_COMMIT_RECEIVED_COUNT.add(1);
            logEntry = SerializeUtils.deserializeTxn(qp.getData());
            hdr = logEntry.getHeader();
            txn = logEntry.getTxn();
            digest = logEntry.getDigest();
            Request request = new Request(hdr.getClientId(), hdr.getCxid(), hdr.getType(), hdr, txn, 0);
            request.logLatency(ServerMetrics.getMetrics().COMMIT_PROPAGATION_LATENCY);
            request.setTxnDigest(digest);
            ObserverZooKeeperServer obs = (ObserverZooKeeperServer) zk;
            obs.commitRequest(request);
            break;
        case Leader.INFORMANDACTIVATE:
            // get new designated leader from (current) leader's message
            ByteBuffer buffer = ByteBuffer.wrap(qp.getData());
            long suggestedLeaderId = buffer.getLong();
            byte[] remainingdata = new byte[buffer.remaining()];
            buffer.get(remainingdata);
            logEntry = SerializeUtils.deserializeTxn(remainingdata);
            hdr = logEntry.getHeader();
            txn = logEntry.getTxn();
            digest = logEntry.getDigest();
            QuorumVerifier qv = self.configFromString(new String(((SetDataTxn) txn).getData(), UTF_8));
            request = new Request(hdr.getClientId(), hdr.getCxid(), hdr.getType(), hdr, txn, 0);
            request.setTxnDigest(digest);
            obs = (ObserverZooKeeperServer) zk;
            boolean majorChange = self.processReconfig(qv, suggestedLeaderId, qp.getZxid(), true);
            obs.commitRequest(request);
            if (majorChange) {
                throw new Exception("changes proposed in reconfig");
            }
            break;
        default:
            LOG.warn("Unknown packet type: {}", LearnerHandler.packetToString(qp));
            break;
    }
}
Also used : Request(org.apache.zookeeper.server.Request) SetDataTxn(org.apache.zookeeper.txn.SetDataTxn) ByteBuffer(java.nio.ByteBuffer) QuorumVerifier(org.apache.zookeeper.server.quorum.flexible.QuorumVerifier) TxnLogEntry(org.apache.zookeeper.server.TxnLogEntry) Record(org.apache.jute.Record) TxnDigest(org.apache.zookeeper.txn.TxnDigest) TxnHeader(org.apache.zookeeper.txn.TxnHeader)

Example 3 with Request

use of org.apache.zookeeper.server.Request in project zookeeper by apache.

the class FollowerRequestProcessor method run.

@Override
public void run() {
    try {
        while (!finished) {
            ServerMetrics.getMetrics().LEARNER_REQUEST_PROCESSOR_QUEUE_SIZE.add(queuedRequests.size());
            Request request = queuedRequests.take();
            if (LOG.isTraceEnabled()) {
                ZooTrace.logRequest(LOG, ZooTrace.CLIENT_REQUEST_TRACE_MASK, 'F', request, "");
            }
            if (request == Request.requestOfDeath) {
                break;
            }
            // Screen quorum requests against ACLs first
            if (!zks.authWriteRequest(request)) {
                continue;
            }
            // We want to queue the request to be processed before we submit
            // the request to the leader so that we are ready to receive
            // the response
            maybeSendRequestToNextProcessor(request);
            if (request.isThrottled()) {
                continue;
            }
            // add it to pendingSyncs.
            switch(request.type) {
                case OpCode.sync:
                    zks.pendingSyncs.add(request);
                    zks.getFollower().request(request);
                    break;
                case OpCode.create:
                case OpCode.create2:
                case OpCode.createTTL:
                case OpCode.createContainer:
                case OpCode.delete:
                case OpCode.deleteContainer:
                case OpCode.setData:
                case OpCode.reconfig:
                case OpCode.setACL:
                case OpCode.multi:
                case OpCode.check:
                    zks.getFollower().request(request);
                    break;
                case OpCode.createSession:
                case OpCode.closeSession:
                    // Don't forward local sessions to the leader.
                    if (!request.isLocalSession()) {
                        zks.getFollower().request(request);
                    }
                    break;
            }
        }
    } catch (RuntimeException e) {
        // spotbugs require explicit catch of RuntimeException
        handleException(this.getName(), e);
    } catch (Exception e) {
        handleException(this.getName(), e);
    }
    LOG.info("FollowerRequestProcessor exited loop!");
}
Also used : Request(org.apache.zookeeper.server.Request) KeeperException(org.apache.zookeeper.KeeperException) IOException(java.io.IOException)

Example 4 with Request

use of org.apache.zookeeper.server.Request in project zookeeper by apache.

the class FollowerZooKeeperServer method commit.

/**
 * When a COMMIT message is received, eventually this method is called,
 * which matches up the zxid from the COMMIT with (hopefully) the head of
 * the pendingTxns queue and hands it to the commitProcessor to commit.
 * @param zxid - must correspond to the head of pendingTxns if it exists
 */
public void commit(long zxid) {
    if (pendingTxns.size() == 0) {
        LOG.warn("Committing " + Long.toHexString(zxid) + " without seeing txn");
        return;
    }
    long firstElementZxid = pendingTxns.element().zxid;
    if (firstElementZxid != zxid) {
        LOG.error("Committing zxid 0x" + Long.toHexString(zxid) + " but next pending txn 0x" + Long.toHexString(firstElementZxid));
        ServiceUtils.requestSystemExit(ExitCode.UNMATCHED_TXN_COMMIT.getValue());
    }
    Request request = pendingTxns.remove();
    request.logLatency(ServerMetrics.getMetrics().COMMIT_PROPAGATION_LATENCY);
    commitProcessor.commit(request);
}
Also used : Request(org.apache.zookeeper.server.Request)

Example 5 with Request

use of org.apache.zookeeper.server.Request in project zookeeper by apache.

the class LeaderRequestProcessor method processRequest.

@Override
public void processRequest(Request request) throws RequestProcessorException {
    // Screen quorum requests against ACLs first
    if (!lzks.authWriteRequest(request)) {
        return;
    }
    // Check if this is a local session and we are trying to create
    // an ephemeral node, in which case we upgrade the session
    Request upgradeRequest = null;
    try {
        upgradeRequest = lzks.checkUpgradeSession(request);
    } catch (KeeperException ke) {
        if (request.getHdr() != null) {
            LOG.debug("Updating header");
            request.getHdr().setType(OpCode.error);
            request.setTxn(new ErrorTxn(ke.code().intValue()));
        }
        request.setException(ke);
        LOG.warn("Error creating upgrade request", ke);
    } catch (IOException ie) {
        LOG.error("Unexpected error in upgrade", ie);
    }
    if (upgradeRequest != null) {
        nextProcessor.processRequest(upgradeRequest);
    }
    nextProcessor.processRequest(request);
}
Also used : ErrorTxn(org.apache.zookeeper.txn.ErrorTxn) Request(org.apache.zookeeper.server.Request) IOException(java.io.IOException) KeeperException(org.apache.zookeeper.KeeperException)

Aggregations

Request (org.apache.zookeeper.server.Request)51 Test (org.junit.jupiter.api.Test)25 CreateRequest (org.apache.zookeeper.proto.CreateRequest)15 IOException (java.io.IOException)9 ByteBuffer (java.nio.ByteBuffer)9 GetDataRequest (org.apache.zookeeper.proto.GetDataRequest)9 SetDataRequest (org.apache.zookeeper.proto.SetDataRequest)9 TxnHeader (org.apache.zookeeper.txn.TxnHeader)9 HashSet (java.util.HashSet)8 ByteArrayOutputStream (java.io.ByteArrayOutputStream)6 BinaryOutputArchive (org.apache.jute.BinaryOutputArchive)6 Record (org.apache.jute.Record)6 KeeperException (org.apache.zookeeper.KeeperException)5 SetDataTxn (org.apache.zookeeper.txn.SetDataTxn)5 Id (org.apache.zookeeper.data.Id)4 ErrorTxn (org.apache.zookeeper.txn.ErrorTxn)4 OutputArchive (org.apache.jute.OutputArchive)3 ZooKeeper (org.apache.zookeeper.ZooKeeper)3 TxnLogEntry (org.apache.zookeeper.server.TxnLogEntry)3 QuorumVerifier (org.apache.zookeeper.server.quorum.flexible.QuorumVerifier)3