use of org.apache.ratis.proto.RaftProtos.RequestVoteReplyProto in project incubator-ratis by apache.
the class LeaderElection method waitForResults.
private ResultAndTerm waitForResults(Phase phase, long electionTerm, int submitted, RaftConfigurationImpl conf, Executor voteExecutor) throws InterruptedException {
final Timestamp timeout = Timestamp.currentTime().addTime(server.getRandomElectionTimeout());
final Map<RaftPeerId, RequestVoteReplyProto> responses = new HashMap<>();
final List<Exception> exceptions = new ArrayList<>();
int waitForNum = submitted;
Collection<RaftPeerId> votedPeers = new ArrayList<>();
Collection<RaftPeerId> rejectedPeers = new ArrayList<>();
Set<RaftPeerId> higherPriorityPeers = getHigherPriorityPeers(conf);
while (waitForNum > 0 && shouldRun(electionTerm)) {
final TimeDuration waitTime = timeout.elapsedTime().apply(n -> -n);
if (waitTime.isNonPositive()) {
if (conf.hasMajority(votedPeers, server.getId())) {
// candidate pass vote
return logAndReturn(phase, Result.PASSED, responses, exceptions);
} else {
return logAndReturn(phase, Result.TIMEOUT, responses, exceptions);
}
}
try {
final Future<RequestVoteReplyProto> future = voteExecutor.poll(waitTime);
if (future == null) {
// poll timeout, continue to return Result.TIMEOUT
continue;
}
final RequestVoteReplyProto r = future.get();
final RaftPeerId replierId = RaftPeerId.valueOf(r.getServerReply().getReplyId());
final RequestVoteReplyProto previous = responses.putIfAbsent(replierId, r);
if (previous != null) {
if (LOG.isWarnEnabled()) {
LOG.warn("{} received duplicated replies from {}, the 2nd reply is ignored: 1st={}, 2nd={}", this, replierId, ServerStringUtils.toRequestVoteReplyString(previous), ServerStringUtils.toRequestVoteReplyString(r));
}
continue;
}
if (r.getShouldShutdown()) {
return logAndReturn(phase, Result.SHUTDOWN, responses, exceptions);
}
if (r.getTerm() > electionTerm) {
return logAndReturn(phase, Result.DISCOVERED_A_NEW_TERM, responses, exceptions, r.getTerm());
}
// If any peer with higher priority rejects vote, candidate can not pass vote
if (!r.getServerReply().getSuccess() && higherPriorityPeers.contains(replierId)) {
return logAndReturn(phase, Result.REJECTED, responses, exceptions);
}
// remove higher priority peer, so that we check higherPriorityPeers empty to make sure
// all higher priority peers have replied
higherPriorityPeers.remove(replierId);
if (r.getServerReply().getSuccess()) {
votedPeers.add(replierId);
// If majority and all peers with higher priority have voted, candidate pass vote
if (higherPriorityPeers.size() == 0 && conf.hasMajority(votedPeers, server.getId())) {
return logAndReturn(phase, Result.PASSED, responses, exceptions);
}
} else {
rejectedPeers.add(replierId);
if (conf.majorityRejectVotes(rejectedPeers)) {
return logAndReturn(phase, Result.REJECTED, responses, exceptions);
}
}
} catch (ExecutionException e) {
LogUtils.infoOrTrace(LOG, () -> this + " got exception when requesting votes", e);
exceptions.add(e);
}
waitForNum--;
}
// received all the responses
if (conf.hasMajority(votedPeers, server.getId())) {
return logAndReturn(phase, Result.PASSED, responses, exceptions);
} else {
return logAndReturn(phase, Result.REJECTED, responses, exceptions);
}
}
use of org.apache.ratis.proto.RaftProtos.RequestVoteReplyProto in project incubator-ratis by apache.
the class LeaderElection method logAndReturn.
private ResultAndTerm logAndReturn(Phase phase, Result result, Map<RaftPeerId, RequestVoteReplyProto> responses, List<Exception> exceptions, Long newTerm) {
final ResultAndTerm resultAndTerm = new ResultAndTerm(result, newTerm);
LOG.info("{}: {} {} received {} response(s) and {} exception(s):", this, phase, resultAndTerm, responses.size(), exceptions.size());
int i = 0;
for (RequestVoteReplyProto reply : responses.values()) {
LOG.info(" Response {}: {}", i++, ServerStringUtils.toRequestVoteReplyString(reply));
}
for (Exception e : exceptions) {
final int j = i++;
LogUtils.infoOrTrace(LOG, () -> " Exception " + j, e);
}
return resultAndTerm;
}
Aggregations