Search in sources :

Example 1 with RequestVoteReplyProto

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);
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) RequestVoteReplyProto(org.apache.ratis.proto.RaftProtos.RequestVoteReplyProto) Timestamp(org.apache.ratis.util.Timestamp) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) TimeDuration(org.apache.ratis.util.TimeDuration) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) ExecutionException(java.util.concurrent.ExecutionException)

Example 2 with RequestVoteReplyProto

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;
}
Also used : RequestVoteReplyProto(org.apache.ratis.proto.RaftProtos.RequestVoteReplyProto) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

IOException (java.io.IOException)2 ExecutionException (java.util.concurrent.ExecutionException)2 RequestVoteReplyProto (org.apache.ratis.proto.RaftProtos.RequestVoteReplyProto)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 RaftPeerId (org.apache.ratis.protocol.RaftPeerId)1 TimeDuration (org.apache.ratis.util.TimeDuration)1 Timestamp (org.apache.ratis.util.Timestamp)1