private synchronized QuorumPacket removeProposedPacket(long zxid) { QuorumPacket pkt = proposedPkts.peek(); if (pkt == null || pkt.getZxid() > zxid) { LOG.debug("ignore missing proposal packet for {}", Long.toHexString(zxid)); return null; } if (pkt.getZxid() != zxid) { final String m = String.format("Unexpected proposal packet on commit ack, expected zxid 0x%d got zxid 0x%d", zxid, pkt.getZxid()); LOG.error(m); throw new RuntimeException(m); } proposedPkts.remove(); return pkt; }
@Override public String toString() { return packet.getType() + ", " + packet.getZxid() + ", " + request; } }
private synchronized void sendPacket(final QuorumPacket pkt) { for (LearnerHandler lh: activeObservers) { lh.queuePacket(pkt); } lastProposedZxid = pkt.getZxid(); }
@Override public String toString() { return packet.getType() + ", " + packet.getZxid() + ", " + request; } }
void proposalReceived(QuorumPacket qp) { proposedPkts.add(new QuorumPacket(Leader.INFORM, qp.getZxid(), qp.getData(), null)); }
public long getmaxCommittedLog() { if (!committedLog.isEmpty()) { return committedLog.getLast().packet.getZxid(); } return 0; }
public long getminCommittedLog() { if (!committedLog.isEmpty()) { return committedLog.getFirst().packet.getZxid(); } return 0; }
/** * maintains a list of last <i>committedLog</i> * or so committed requests. This is used for * fast follower synchronization. * @param request committed request */ public void addCommittedProposal(Request request) { WriteLock wl = logLock.writeLock(); try { wl.lock(); if (committedLog.size() > commitLogCount) { committedLog.removeFirst(); minCommittedLog = committedLog.getFirst().packet.getZxid(); } if (committedLog.isEmpty()) { minCommittedLog = request.zxid; maxCommittedLog = request.zxid; } byte[] data = SerializeUtils.serializeRequest(request); QuorumPacket pp = new QuorumPacket(Leader.PROPOSAL, request.zxid, data, null); Proposal p = new Proposal(); p.packet = pp; p.request = request; committedLog.add(p); maxCommittedLog = p.packet.getZxid(); } finally { wl.unlock(); } }
if (itr.hasNext()) { QuorumPacket packet = itr.next(); if (packet.getZxid() > lastSeenZxid + 1) { LOG.error("LearnerHandler is too far behind ({} < {}), disconnecting {} at {}", Long.toHexString(lastSeenZxid + 1), Long.toHexString(packet.getZxid()), learnerHandler.getSid(), learnerHandler.getRemoteAddress()); learnerHandler.shutdown(); return -1; } else if (packet.getZxid() == lastSeenZxid + 1) { learnerHandler.queuePacket(packet); long queueHeadZxid = packet.getZxid(); long queueBytesUsed = LearnerHandler.packetSize(packet); while (itr.hasNext()) { packet = itr.next(); if (packet.getZxid() <= lastSeenZxid) { continue; learnerHandler.getSid(), Long.toHexString(queueHeadZxid), Long.toHexString(packet.getZxid()), Long.toHexString(lastSeenZxid), packet.getZxid() - lastSeenZxid, queueBytesUsed);
public Iterator<Proposal> getProposalsFromTxnLog(long peerZxid, long limit) { if (peerZxid >= txnLog.peekFirst().packet.getZxid()) { return txnLog.iterator(); } else { return (new LinkedList<Proposal>()).iterator(); } }
boolean revalidateLearnerSession(QuorumPacket qp) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream(qp.getData()); DataInputStream dis = new DataInputStream(bis); long id = dis.readLong(); boolean valid = dis.readBoolean(); Iterator<Revalidation> itr = pendingRevalidations.iterator(); if (!itr.hasNext()) { // not a learner session, handle locally return false; } Revalidation revalidation = itr.next(); if (revalidation.sessionId != id) { // not a learner session, handle locally return false; } itr.remove(); LearnerHandler learnerHandler = revalidation.handler; // create a copy here as the qp object is reused by the Follower and may be mutated QuorumPacket deepCopy = new QuorumPacket(qp.getType(), qp.getZxid(), Arrays.copyOf(qp.getData(), qp.getData().length), qp.getAuthinfo() == null ? null : new ArrayList<>(qp.getAuthinfo())); learnerHandler.queuePacket(deepCopy); // To keep consistent as leader, touch the session when it's // revalidating the session, only update if it's a valid session. if (valid) { touch(revalidation.sessionId, revalidation.timeout); } return true; }
/** * Check if op packet (first packet in the queue) match the expected value * @param type - type of packet * @param zxid - zxid in the op packet * @param currentZxid - last packet queued by syncFollower, * before invoking startForwarding() */ public void assertOpType(int type, long zxid, long currentZxid) { Queue<QuorumPacket> packets = learnerHandler.getQueuedPackets(); assertTrue(packets.size() > 0); assertEquals(type, packets.peek().getType()); assertZxidEquals(zxid, packets.peek().getZxid()); assertZxidEquals(currentZxid, this.currentZxid); }
/** * Validate that queued packets contains proposal in the following orders as * a given array of zxids * * @param zxids */ public void queuedPacketMatches(long[] zxids) { int index = 0; for (QuorumPacket qp : learnerHandler.getQueuedPackets()) { if (qp.getType() == Leader.PROPOSAL) { assertZxidEquals(zxids[index++], qp.getZxid()); } } }
private void proposeSetData(QuorumPacket qp, long zxid, String data, int version) throws IOException { qp.setType(Leader.PROPOSAL); qp.setZxid(zxid); TxnHeader hdr = new TxnHeader(4, 1414, qp.getZxid(), 55, ZooDefs.OpCode.setData); SetDataTxn sdt = new SetDataTxn("/foo", data.getBytes(), version); ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputArchive boa = BinaryOutputArchive.getArchive(baos); boa.writeRecord(hdr, null); boa.writeRecord(sdt, null); qp.setData(baos.toByteArray()); } });
private void proposeSetData(QuorumPacket qp, String path, long zxid, String data, int version) throws IOException { qp.setType(Leader.PROPOSAL); qp.setZxid(zxid); TxnHeader hdr = new TxnHeader(4, 1414, qp.getZxid(), 55, ZooDefs.OpCode.setData); SetDataTxn sdt = new SetDataTxn(path, data.getBytes(), version); ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputArchive boa = BinaryOutputArchive.getArchive(baos); boa.writeRecord(hdr, null); boa.writeRecord(sdt, null); qp.setData(baos.toByteArray()); } });
private void proposeNewSession(QuorumPacket qp, long zxid, long sessionId) throws IOException { qp.setType(Leader.PROPOSAL); qp.setZxid(zxid); TxnHeader hdr = new TxnHeader(4, 1414, qp.getZxid(), 55, ZooDefs.OpCode.createSession); CreateSessionTxn cst = new CreateSessionTxn(30000); ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputArchive boa = BinaryOutputArchive.getArchive(baos); boa.writeRecord(hdr, null); boa.writeRecord(cst, null); qp.setData(baos.toByteArray()); } });
public void converseWithLeader(InputArchive ia, OutputArchive oa, Leader l) throws IOException, InterruptedException { /* we test a normal run. everything should work out well. */ LearnerInfo li = new LearnerInfo(1, 0x10000, 0); byte liBytes[] = new byte[20]; ByteBufferOutputStream.record2ByteBuffer(li, ByteBuffer.wrap(liBytes)); QuorumPacket qp = new QuorumPacket(Leader.FOLLOWERINFO, 0, liBytes, null); oa.writeRecord(qp, null); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.LEADERINFO, qp.getType()); Assert.assertEquals(ZxidUtils.makeZxid(1, 0), qp.getZxid()); Assert.assertEquals(ByteBuffer.wrap(qp.getData()).getInt(), 0x10000); Thread.sleep(l.self.getInitLimit()*l.self.getTickTime() + 5000); // The leader didn't get a quorum of acks - make sure that leader's current epoch is not advanced Assert.assertEquals(0, l.self.getCurrentEpoch()); } });
public void converseWithLeader(InputArchive ia, OutputArchive oa, Leader l) throws IOException { /* we test a normal run. everything should work out well. */ LearnerInfo li = new LearnerInfo(1, 0x10000, 0); byte liBytes[] = new byte[20]; ByteBufferOutputStream.record2ByteBuffer(li, ByteBuffer.wrap(liBytes)); /* we are going to say we last acked epoch 20 */ QuorumPacket qp = new QuorumPacket(Leader.FOLLOWERINFO, ZxidUtils.makeZxid(20, 0), liBytes, null); oa.writeRecord(qp, null); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.LEADERINFO, qp.getType()); Assert.assertEquals(ZxidUtils.makeZxid(21, 0), qp.getZxid()); Assert.assertEquals(ByteBuffer.wrap(qp.getData()).getInt(), 0x10000); qp = new QuorumPacket(Leader.ACKEPOCH, 0, new byte[4], null); oa.writeRecord(qp, null); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.DIFF, qp.getType()); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.NEWLEADER, qp.getType()); Assert.assertEquals(ZxidUtils.makeZxid(21, 0), qp.getZxid()); qp = new QuorumPacket(Leader.ACK, qp.getZxid(), null, null); oa.writeRecord(qp, null); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.UPTODATE, qp.getType()); } });
@Override public void converseWithLeader(InputArchive ia, OutputArchive oa, Leader l, long zxid) throws Exception { Assert.assertEquals(1, l.self.getAcceptedEpoch()); Assert.assertEquals(1, l.self.getCurrentEpoch()); /* we test a normal run. everything should work out well. */ LearnerInfo li = new LearnerInfo(1, 0x10000, 0); byte liBytes[] = new byte[20]; ByteBufferOutputStream.record2ByteBuffer(li, ByteBuffer.wrap(liBytes)); QuorumPacket qp = new QuorumPacket(Leader.FOLLOWERINFO, 1, liBytes, null); oa.writeRecord(qp, null); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.LEADERINFO, qp.getType()); Assert.assertEquals(ZxidUtils.makeZxid(2, 0), qp.getZxid()); Assert.assertEquals(ByteBuffer.wrap(qp.getData()).getInt(), 0x10000); Assert.assertEquals(2, l.self.getAcceptedEpoch()); Assert.assertEquals(1, l.self.getCurrentEpoch()); byte epochBytes[] = new byte[4]; final ByteBuffer wrappedEpochBytes = ByteBuffer.wrap(epochBytes); wrappedEpochBytes.putInt(1); qp = new QuorumPacket(Leader.ACKEPOCH, zxid, epochBytes, null); oa.writeRecord(qp, null); readPacketSkippingPing(ia, qp); Assert.assertEquals(Leader.DIFF, qp.getType()); } }, 2);
Assert.assertEquals(ZxidUtils.makeZxid(1, 0), qp.getZxid()); Assert.assertEquals(ByteBuffer.wrap(qp.getData()).getInt(), 0x10000); Assert.assertEquals(ZxidUtils.makeZxid(1, 0), qp.getZxid()); Assert.assertEquals(1, l.self.getAcceptedEpoch()); Assert.assertEquals(1, l.self.getCurrentEpoch()); qp = new QuorumPacket(Leader.ACK, qp.getZxid(), null, null); oa.writeRecord(qp, null);