private boolean pingLeader() { Optional<PingableLeader> maybeLeader = getSuspectedLeader(true /* use network */); if (!maybeLeader.isPresent()) { return false; } final PingableLeader leader = maybeLeader.get(); MultiplexingCompletionService<PingableLeader, Boolean> multiplexingCompletionService = MultiplexingCompletionService.create(leaderPingExecutors); multiplexingCompletionService.submit(leader, leader::ping); try { Future<Boolean> pingFuture = multiplexingCompletionService.poll( leaderPingResponseWaitMs, TimeUnit.MILLISECONDS); return getAndRecordLeaderPingResult(pingFuture); } catch (InterruptedException ex) { return false; } }
public PaxosLeaderElectionService build() { return new PaxosLeaderElectionService( proposer, knowledge, potentialLeadersToHosts, acceptors, learners, executorServiceFactory::apply, pingRateMs, randomWaitBeforeProposingLeadershipMs, leaderPingResponseWaitMs, eventRecorder, onlyLogOnQuorumFailure); } }
@Override public StillLeadingStatus isStillLeading(LeadershipToken token) { if (!(token instanceof PaxosLeadershipToken)) { return StillLeadingStatus.NOT_LEADING; } PaxosLeadershipToken paxosToken = (PaxosLeadershipToken) token; return determineAndRecordLeadershipStatus(paxosToken); }
private StillLeadingStatus determineAndRecordLeadershipStatus( PaxosLeadershipToken paxosToken) { StillLeadingStatus status = determineLeadershipStatus(paxosToken.value); recordLeadershipStatus(paxosToken, status); return status; }
private LeadershipState determineLeadershipState() { Optional<PaxosValue> greatestLearnedValue = getGreatestLearnedPaxosValue(); StillLeadingStatus leadingStatus = determineLeadershipStatus(greatestLearnedValue); return LeadershipState.of(greatestLearnedValue, leadingStatus); }
@Override public LeadershipToken blockOnBecomingLeader() throws InterruptedException { while (true) { LeadershipState currentState = determineLeadershipState(); switch (currentState.status()) { case LEADING: log.info("Successfully became leader!"); return currentState.confirmedToken().get(); case NO_QUORUM: // If we don't have quorum we should just retry our calls. continue; case NOT_LEADING: proposeLeadershipOrWaitForBackoff(currentState); continue; default: throw new IllegalStateException("unknown status: " + currentState.status()); } } }
this.acceptors = ImmutableList.copyOf(acceptors); this.learners = ImmutableList.copyOf(learners); this.leaderPingExecutors = createLeaderPingExecutors(otherPotentialLeadersToHosts, executorServiceFactory); this.knowledgeUpdatingExecutors = createKnowledgeUpdateExecutors(learners, executorServiceFactory); this.updatePollingRateInMs = updatePollingWaitInMs; this.randomWaitBeforeProposingLeadership = randomWaitBeforeProposingLeadership; acceptors, proposer.getQuorumSize(), createLatestRoundVerifierExecutors(acceptors, executorServiceFactory), onlyLogOnQuorumFailure));
@Test public void doesNotRecordLeaderPingSuccess() throws InterruptedException { CompletableFuture<Boolean> pingFuture = CompletableFuture.completedFuture(true); boolean result = electionService.getAndRecordLeaderPingResult(pingFuture); assertThat(result).isTrue(); verifyNoMoreInteractions(recorder); }
private boolean isLatestRound(Optional<PaxosValue> valueIfAny) { return valueIfAny.equals(getGreatestLearnedPaxosValue()); }
@Override public Optional<HostAndPort> getSuspectedLeaderInMemory() { Optional<PingableLeader> maybeLeader = getSuspectedLeader(false /* use network */); if (!maybeLeader.isPresent()) { return Optional.empty(); } return Optional.of(otherPotentialLeadersToHosts.get(maybeLeader.get())); }
@Override public Optional<LeadershipToken> getCurrentTokenIfLeading() { return determineLeadershipState().confirmedToken(); }
this.acceptors = ImmutableList.copyOf(acceptors); this.learners = ImmutableList.copyOf(learners); this.leaderPingExecutors = createLeaderPingExecutors(otherPotentialLeadersToHosts, executorServiceFactory); this.knowledgeUpdatingExecutors = createKnowledgeUpdateExecutors(learners, executorServiceFactory); this.updatePollingRateInMs = updatePollingWaitInMs; this.randomWaitBeforeProposingLeadership = randomWaitBeforeProposingLeadership; acceptors, proposer.getQuorumSize(), createLatestRoundVerifierExecutors(acceptors, executorServiceFactory), onlyLogOnQuorumFailure));
@Test public void recordsLeaderPingFailure() throws InterruptedException { RuntimeException error = new RuntimeException("foo"); CompletableFuture<Boolean> pingFuture = new CompletableFuture<>(); pingFuture.completeExceptionally(error); boolean result = electionService.getAndRecordLeaderPingResult(pingFuture); assertThat(result).isFalse(); verify(recorder).recordLeaderPingFailure(error); verifyNoMoreInteractions(recorder); }
private StillLeadingStatus determineAndRecordLeadershipStatus( PaxosLeadershipToken paxosToken) { StillLeadingStatus status = determineLeadershipStatus(paxosToken.value); recordLeadershipStatus(paxosToken, status); return status; }
private LeadershipState determineLeadershipState() { Optional<PaxosValue> greatestLearnedValue = getGreatestLearnedPaxosValue(); StillLeadingStatus leadingStatus = determineLeadershipStatus(greatestLearnedValue); return LeadershipState.of(greatestLearnedValue, leadingStatus); }
@Override public LeadershipToken blockOnBecomingLeader() throws InterruptedException { while (true) { LeadershipState currentState = determineLeadershipState(); switch (currentState.status()) { case LEADING: log.info("Successfully became leader!"); return currentState.confirmedToken().get(); case NO_QUORUM: // If we don't have quorum we should just retry our calls. continue; case NOT_LEADING: proposeLeadershipOrWaitForBackoff(currentState); continue; default: throw new IllegalStateException("unknown status: " + currentState.status()); } } }
@Override public boolean ping() { return getGreatestLearnedPaxosValue() .map(this::isThisNodeTheLeaderFor) .orElse(false); }
@Override public Optional<HostAndPort> getSuspectedLeaderInMemory() { Optional<PingableLeader> maybeLeader = getSuspectedLeader(false /* use network */); if (!maybeLeader.isPresent()) { return Optional.empty(); } return Optional.of(otherPotentialLeadersToHosts.get(maybeLeader.get())); }
@Override public Optional<LeadershipToken> getCurrentTokenIfLeading() { return determineLeadershipState().confirmedToken(); }
private boolean pingLeader() { Optional<PingableLeader> maybeLeader = getSuspectedLeader(true /* use network */); if (!maybeLeader.isPresent()) { return false; } final PingableLeader leader = maybeLeader.get(); MultiplexingCompletionService<PingableLeader, Boolean> multiplexingCompletionService = MultiplexingCompletionService.create(leaderPingExecutors); multiplexingCompletionService.submit(leader, leader::ping); try { Future<Boolean> pingFuture = multiplexingCompletionService.poll( leaderPingResponseWaitMs, TimeUnit.MILLISECONDS); return getAndRecordLeaderPingResult(pingFuture); } catch (InterruptedException ex) { return false; } }