static Collection<RaftPeer> computeNewPeers(RaftPeer[] newMembers, RaftConfiguration old) { List<RaftPeer> peers = new ArrayList<>(); for (RaftPeer p : newMembers) { if (!old.containsInConf(p.getId())) { peers.add(p); } } return peers; }
/** * @return true iff the given peer is contained in conf and, * if old conf exists, is contained in old conf. */ boolean contains(RaftPeerId peerId) { return containsInConf(peerId) && (oldConf == null || containsInOldConf(peerId)); }
static Collection<RaftPeer> computeNewPeers(RaftPeer[] newMembers, RaftConfiguration old) { List<RaftPeer> peers = new ArrayList<>(); for (RaftPeer p : newMembers) { if (!old.containsInConf(p.getId())) { peers.add(p); } } return peers; }
/** * @return true iff the given peer is contained in conf and, * if old conf exists, is contained in old conf. */ boolean contains(RaftPeerId peerId) { return containsInConf(peerId) && (oldConf == null || containsInOldConf(peerId)); }
/** * Check if the candidate's term is acceptable */ boolean recognizeCandidate(RaftPeerId candidateId, long candidateTerm) { if (!getRaftConf().containsInConf(candidateId)) { return false; } if (candidateTerm > currentTerm) { return true; } else if (candidateTerm == currentTerm) { // has not voted yet or this is a retry return votedFor == null || votedFor.equals(candidateId); } return false; }
/** * Check if the candidate's term is acceptable */ boolean recognizeCandidate(RaftPeerId candidateId, long candidateTerm) { if (!getRaftConf().containsInConf(candidateId)) { return false; } if (candidateTerm > currentTerm) { return true; } else if (candidateTerm == currentTerm) { // has not voted yet or this is a retry return votedFor == null || votedFor.equals(candidateId); } return false; }
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; }
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; }
private Optional<MinMajorityMax> getMajorityMin(ToLongFunction<FollowerInfo> followerIndex, LongSupplier logIndex) { final RaftPeerId selfId = server.getId(); final RaftConfiguration conf = server.getRaftConf(); final List<FollowerInfo> followers = voterLists.get(0); final boolean includeSelf = conf.containsInConf(selfId); if (followers.isEmpty() && !includeSelf) { return Optional.empty(); } final long[] indicesInNewConf = getSorted(followers, includeSelf, followerIndex, logIndex); final MinMajorityMax newConf = MinMajorityMax.valueOf(indicesInNewConf); if (!conf.isTransitional()) { return Optional.of(newConf); } else { // configuration is in transitional state final List<FollowerInfo> oldFollowers = voterLists.get(1); final boolean includeSelfInOldConf = conf.containsInOldConf(selfId); if (oldFollowers.isEmpty() && !includeSelfInOldConf) { return Optional.empty(); } final long[] indicesInOldConf = getSorted(oldFollowers, includeSelfInOldConf, followerIndex, logIndex); final MinMajorityMax oldConf = MinMajorityMax.valueOf(indicesInOldConf); return Optional.of(newConf.combine(oldConf)); } }
private void checkAndUpdateConfiguration(TermIndex[] entriesToCheck) { final RaftConfiguration conf = server.getRaftConf(); if (committedConf(entriesToCheck)) { if (conf.isTransitional()) { replicateNewConf(); } else { // the (new) log entry has been committed LOG.debug("{} sends success to setConfiguration request", server.getId()); pendingRequests.replySetConfiguration(); // if the leader is not included in the current configuration, step down if (!conf.containsInConf(server.getId())) { LOG.info("{} is not included in the new configuration {}. Step down.", server.getId(), conf); try { // leave some time for all RPC senders to send out new conf entry Thread.sleep(server.getMinTimeoutMs()); } catch (InterruptedException ignored) { } // the pending request handler will send NotLeaderException for // pending client requests when it stops server.shutdown(); } } } }
private void checkAndUpdateConfiguration(TermIndex[] entriesToCheck) { final RaftConfiguration conf = server.getRaftConf(); if (committedConf(entriesToCheck)) { if (conf.isTransitional()) { replicateNewConf(); } else { // the (new) log entry has been committed pendingRequests.replySetConfiguration(server::getCommitInfos); // if the leader is not included in the current configuration, step down if (!conf.containsInConf(server.getId())) { LOG.info("{} is not included in the new configuration {}. Step down.", server.getId(), conf); try { // leave some time for all RPC senders to send out new conf entry Thread.sleep(server.getMinTimeoutMs()); } catch (InterruptedException ignored) { } // the pending request handler will send NotLeaderException for // pending client requests when it stops server.shutdown(false); } } } }
/** * Update the RpcSender list based on the current configuration */ private void updateSenders(RaftConfiguration conf) { Preconditions.assertTrue(conf.isStable() && !inStagingState()); stopAndRemoveSenders(s -> !conf.containsInConf(s.getFollower().getPeer().getId())); }
final boolean includeSelf = conf.containsInConf(selfId); if (followers.isEmpty() && !includeSelf) { return;
/** * Update the RpcSender list based on the current configuration */ private void updateSenders(RaftConfiguration conf) { Preconditions.assertTrue(conf.isStable() && !inStagingState()); stopAndRemoveSenders(s -> !conf.containsInConf(s.getFollower().getPeer().getId())); }
/** * check if the remote peer is not included in the current conf * and should shutdown. should shutdown if all the following stands: * 1. this is a leader * 2. current conf is stable and has been committed * 3. candidate id is not included in conf * 4. candidate's last entry's index < conf's index */ private boolean shouldSendShutdown(RaftPeerId candidateId, TermIndex candidateLastEntry) { return isLeader() && getRaftConf().isStable() && getState().isConfCommitted() && !getRaftConf().containsInConf(candidateId) && candidateLastEntry.getIndex() < getRaftConf().getLogEntryIndex() && role.getLeaderState().map(ls -> !ls.isBootStrappingPeer(candidateId)).orElse(false); }
/** * check if the remote peer is not included in the current conf * and should shutdown. should shutdown if all the following stands: * 1. this is a leader * 2. current conf is stable and has been committed * 3. candidate id is not included in conf * 4. candidate's last entry's index < conf's index */ private boolean shouldSendShutdown(RaftPeerId candidateId, TermIndex candidateLastEntry) { return isLeader() && getRaftConf().isStable() && getState().isConfCommitted() && !getRaftConf().containsInConf(candidateId) && candidateLastEntry.getIndex() < getRaftConf().getLogEntryIndex() && !leaderState.isBootStrappingPeer(candidateId); }
private static void waitAndCheckNewConf(MiniRaftCluster cluster, RaftPeer[] peers, Collection<RaftPeerId> deadPeers) { LOG.info("waitAndCheckNewConf: peers={}, deadPeers={}, {}", Arrays.asList(peers), deadPeers, cluster.printServers()); Assert.assertNotNull(cluster.getLeader()); int numIncluded = 0; int deadIncluded = 0; final RaftConfiguration current = RaftConfiguration.newBuilder() .setConf(peers).setLogEntryIndex(0).build(); for (RaftServerImpl server : cluster.iterateServerImpls()) { LOG.info("checking {}", server); if (deadPeers != null && deadPeers.contains(server.getId())) { if (current.containsInConf(server.getId())) { deadIncluded++; } continue; } if (current.containsInConf(server.getId())) { numIncluded++; Assert.assertTrue(server.getRaftConf().isStable()); Assert.assertTrue(server.getRaftConf().hasNoChange(peers)); } else if (server.isAlive()) { // The server is successfully removed from the conf // It may not be shutdown since it may not be able to talk to the new leader (who is not in its conf). Assert.assertTrue(server.getRaftConf().isStable()); Assert.assertFalse(server.getRaftConf().containsInConf(server.getId())); } } Assert.assertEquals(peers.length, numIncluded + deadIncluded); }
private static void waitAndCheckNewConf(MiniRaftCluster cluster, RaftPeer[] peers, Collection<String> deadPeers) throws Exception { LOG.info(cluster.printServers()); Assert.assertNotNull(cluster.getLeader()); int numIncluded = 0; int deadIncluded = 0; final RaftConfiguration current = RaftConfiguration.newBuilder() .setConf(peers).setLogEntryIndex(0).build(); for (RaftServerImpl server : cluster.iterateServerImpls()) { if (deadPeers != null && deadPeers.contains(server.getId().toString())) { if (current.containsInConf(server.getId())) { deadIncluded++; } continue; } if (current.containsInConf(server.getId())) { numIncluded++; Assert.assertTrue(server.getRaftConf().isStable()); Assert.assertTrue(server.getRaftConf().hasNoChange(peers)); } else { Assert.assertFalse(server.getId() + " is still running: " + server, server.isAlive()); } } Assert.assertEquals(peers.length, numIncluded + deadIncluded); }