/** * @return the RaftPeer (address and id) information of the followers. */ List<RaftPeer> getFollowers() { return Collections.unmodifiableList(senders.stream() .map(sender -> sender.getFollower().getPeer()) .collect(Collectors.toList())); }
while (isAppenderRunning()) { if (shouldSendRequest()) { SnapshotInfo snapshot = shouldInstallSnapshot(); if (snapshot != null) { LOG.info("{}: follower {}'s next index is {}," + raftLog.getStartIndex()); final InstallSnapshotReplyProto r = installSnapshot(snapshot); if (r != null && r.getResult() == InstallSnapshotResult.NOT_LEADER) { checkResponseTerm(r.getTerm()); final AppendEntriesReplyProto r = sendAppendEntriesWithRetries(); if (r != null) { handleReply(r); if (isAppenderRunning() && !shouldAppendEntries(follower.getNextIndex())) { final long waitTime = getHeartbeatRemainingTime(); if (waitTime > 0) { synchronized (this) { checkSlowness();
@Override public LogAppender newLogAppender( RaftServerImpl server, LeaderState state, FollowerInfo f) { return new LogAppender(server, state, f); } }
int retry = 0; AppendEntriesRequestProto request = null; while (isAppenderRunning()) { // keep retrying for IOException try { if (request == null || request.getEntriesCount() == 0) { request = createRequest(DEFAULT_CALLID); " Wait for more entries.", server.getId()); return null; } else if (!isAppenderRunning()) { LOG.debug("LogAppender {} has been stopped. Skip the request.", this); return null; follower.updateLastRpcResponseTime(); updateCommitIndex(r.getFollowerCommit()); return r; } catch (InterruptedIOException | RaftLogIOException e) { LOG.warn("{}: Failed to appendEntries (retry={}): {}", this, retry++, ioe); handleException(ioe); if (isAppenderRunning()) { leaderState.getSyncInterval().sleep();
protected AppendEntriesRequestProto createRequest(long callId) throws RaftLogIOException { final TermIndex previous = getPrevious(); final long heartbeatRemainingMs = getHeartbeatRemainingTime(); if (heartbeatRemainingMs <= 0L) { return leaderState.newAppendEntriesRequestProto( getFollowerId(), previous, Collections.emptyList(), !follower.isAttendingVote(), callId); } Preconditions.assertTrue(buffer.isEmpty(), () -> "buffer has " + buffer.getNumElements() + " elements."); final long leaderNext = raftLog.getNextIndex(); for (long next = follower.getNextIndex(); leaderNext > next; ) { if (!buffer.offer(raftLog.getEntryWithData(next++))) { break; } } if (buffer.isEmpty()) { return null; } final List<LogEntryProto> protos = buffer.pollList(heartbeatRemainingMs, EntryWithData::getEntry, (entry, time, exception) -> LOG.warn(this + ": Failed get " + entry + " in " + time, exception)); buffer.clear(); return leaderState.newAppendEntriesRequestProto( getFollowerId(), previous, protos, !follower.isAttendingVote(), callId); }
follower.updateMatchIndex(nextIndex - 1); follower.updateNextIndex(nextIndex); submitEventOnSuccessAppend(); checkResponseTerm(reply.getTerm()); break; case INCONSISTENCY:
@Override protected boolean shouldSendRequest() { return appendLogRequestObserver == null || super.shouldSendRequest(); }
protected AppendEntriesRequestProto createRequest(long callId) throws RaftLogIOException { final TermIndex previous = getPrevious(); final long leaderNext = raftLog.getNextIndex(); long next = follower.getNextIndex() + buffer.getPendingEntryNum(); final boolean toSend; if (leaderNext == next && !buffer.isEmpty()) { // no new entries, then send out the entries in the buffer toSend = true; } else if (leaderNext > next) { boolean hasSpace = true; for(; hasSpace && leaderNext > next;) { hasSpace = buffer.addEntry(raftLog.get(next++)); } // buffer is full or batch sending is disabled, send out a request toSend = !hasSpace || !batchSending; } else { toSend = false; } if (toSend || shouldHeartbeat()) { return buffer.getAppendRequest(previous, callId); } return null; }
private boolean shouldHeartbeat() { return getHeartbeatRemainingTime() <= 0; }
AppendEntriesRequestProto getAppendRequest(TermIndex previous, long callId) { final AppendEntriesRequestProto request = leaderState.newAppendEntriesRequestProto( getFollowerId(), previous, buf, !follower.isAttendingVote(), callId); buf.clear(); totalSize = 0; return request; }
int retry = 0; AppendEntriesRequestProto request = null; while (isAppenderRunning()) { // keep retrying for IOException try { if (request == null || request.getEntriesCount() == 0) { request = createRequest(DEFAULT_CALLID); " Wait for more entries.", server.getId()); return null; } else if (!isAppenderRunning()) { LOG.debug("LogAppender {} has been stopped. Skip the request.", this); return null; follower.updateLastRpcResponseTime(); updateCommitIndex(request.getLeaderCommit()); return r; } catch (InterruptedIOException | RaftLogIOException e) { LOG.warn("{}: Failed to appendEntries (retry={}): {}", this, retry++, ioe); handleException(ioe); if (isAppenderRunning()) { leaderState.getSyncInterval().sleep();
follower.updateMatchIndex(nextIndex - 1); follower.updateNextIndex(nextIndex); submitEventOnSuccessAppend(); checkResponseTerm(reply.getTerm()); break; case INCONSISTENCY:
private boolean shouldHeartbeat() { return getHeartbeatRemainingTime() <= 0; }
while (isAppenderRunning()) { if (shouldSendRequest()) { SnapshotInfo snapshot = shouldInstallSnapshot(); if (snapshot != null) { LOG.info("{}: follower {}'s next index is {}," + raftLog.getStartIndex()); final InstallSnapshotReplyProto r = installSnapshot(snapshot); if (r != null && r.getResult() == InstallSnapshotResult.NOT_LEADER) { checkResponseTerm(r.getTerm()); final AppendEntriesReplyProto r = sendAppendEntriesWithRetries(); if (r != null) { handleReply(r); if (isAppenderRunning() && !shouldAppendEntries( follower.getNextIndex() + buffer.getPendingEntryNum())) { final long waitTime = getHeartbeatRemainingTime(); if (waitTime > 0) { synchronized (this) {
/** * @return the RaftPeer (address and id) information of the followers. */ List<RaftPeer> getFollowers() { return Collections.unmodifiableList(senders.stream() .map(sender -> sender.getFollower().getPeer()) .collect(Collectors.toList())); }
@Override public LogAppender newLogAppender( RaftServerImpl server, LeaderState state, FollowerInfo f) { return new LogAppender(server, state, f); } }
private Collection<BootStrapProgress> checkAllProgress(long committed) { Preconditions.assertTrue(inStagingState()); return senders.stream() .filter(sender -> !sender.getFollower().isAttendingVote()) .map(sender -> checkProgress(sender.getFollower(), committed)) .collect(Collectors.toCollection(ArrayList::new)); }
private Collection<BootStrapProgress> checkAllProgress(long committed) { Preconditions.assertTrue(inStagingState()); return senders.stream() .filter(sender -> !sender.getFollower().isAttendingVote()) .map(sender -> checkProgress(sender.getFollower(), committed)) .collect(Collectors.toCollection(ArrayList::new)); }
RaftPeerId getFollowerId() { return getFollower().getPeer().getId(); }
private List<List<FollowerInfo>> divideFollowers(RaftConfiguration conf) { List<List<FollowerInfo>> lists = new ArrayList<>(2); List<FollowerInfo> listForNew = senders.stream() .filter(sender -> conf.containsInConf(sender.getFollower().getPeer().getId())) .map(LogAppender::getFollower) .collect(Collectors.toList()); lists.add(listForNew); if (conf.isTransitional()) { List<FollowerInfo> listForOld = senders.stream() .filter(sender -> conf.containsInOldConf(sender.getFollower().getPeer().getId())) .map(LogAppender::getFollower) .collect(Collectors.toList()); lists.add(listForOld); } return lists; }