use of org.apache.ratis.util.Timestamp in project incubator-ratis by apache.
the class LeaderStateImpl method addSenders.
Collection<LogAppender> addSenders(Collection<RaftPeer> newPeers, long nextIndex, boolean attendVote) {
final Timestamp t = Timestamp.currentTime().addTimeMs(-server.getMaxTimeoutMs());
final List<LogAppender> newAppenders = newPeers.stream().map(peer -> {
final FollowerInfo f = new FollowerInfoImpl(server.getMemberId(), peer, t, nextIndex, attendVote);
LogAppender logAppender = server.newLogAppender(this, f);
peerIdFollowerInfoMap.put(peer.getId(), f);
raftServerMetrics.addFollower(peer.getId());
logAppenderMetrics.addFollowerGauges(peer.getId(), f::getNextIndex, f::getMatchIndex, f::getLastRpcTime);
return logAppender;
}).collect(Collectors.toList());
senders.addAll(newAppenders);
return newAppenders;
}
use of org.apache.ratis.util.Timestamp in project incubator-ratis by apache.
the class LeaderStateImpl method checkProgress.
/**
* So far we use a simple implementation for catchup checking:
* 1. If the latest rpc time of the remote peer is before 3 * max_timeout,
* the peer made no progress for that long. We should fail the whole
* setConfiguration request.
* 2. If the peer's matching index is just behind for a small gap, and the
* peer was updated recently (within max_timeout), declare the peer as
* caught-up.
* 3. Otherwise the peer is making progressing. Keep waiting.
*/
private BootStrapProgress checkProgress(FollowerInfo follower, long committed) {
Preconditions.assertTrue(!isAttendingVote(follower));
final Timestamp progressTime = Timestamp.currentTime().addTimeMs(-server.getMaxTimeoutMs());
final Timestamp timeoutTime = Timestamp.currentTime().addTimeMs(-3L * server.getMaxTimeoutMs());
if (follower.getLastRpcResponseTime().compareTo(timeoutTime) < 0) {
LOG.debug("{} detects a follower {} timeout ({}) for bootstrapping", this, follower, timeoutTime);
return BootStrapProgress.NOPROGRESS;
} else if (follower.getMatchIndex() + stagingCatchupGap > committed && follower.getLastRpcResponseTime().compareTo(progressTime) > 0 && follower.hasAttemptedToInstallSnapshot()) {
return BootStrapProgress.CAUGHTUP;
} else {
return BootStrapProgress.PROGRESSING;
}
}
use of org.apache.ratis.util.Timestamp 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.util.Timestamp in project incubator-ratis by apache.
the class TestClientProtoUtils method runTestToRaftClientRequestProto.
void runTestToRaftClientRequestProto(int n, SizeInBytes messageSize) throws Exception {
final ClientId clientId = ClientId.randomId();
final RaftPeerId leaderId = RaftPeerId.valueOf("s0");
final RaftGroupId groupId = RaftGroupId.randomId();
TimeDuration toProto = TimeDuration.ZERO;
TimeDuration toRequest = TimeDuration.ZERO;
for (int i = 0; i < n; i++) {
final ByteString bytes = newByteString(messageSize.getSizeInt(), i);
final RaftClientRequest request = RaftClientRequest.newBuilder().setClientId(clientId).setServerId(leaderId).setGroupId(groupId).setCallId(1).setMessage(() -> bytes).setType(RaftClientRequest.writeRequestType()).build();
final Timestamp startTime = Timestamp.currentTime();
final RaftClientRequestProto proto = ClientProtoUtils.toRaftClientRequestProto(request);
final TimeDuration p = startTime.elapsedTime();
final RaftClientRequest computed = ClientProtoUtils.toRaftClientRequest(proto);
final TimeDuration r = startTime.elapsedTime().subtract(p);
Assert.assertEquals(request.getMessage().getContent(), computed.getMessage().getContent());
toProto = toProto.add(p);
toRequest = toRequest.add(r);
}
System.out.printf("%nmessageSize=%s, n=%d%n", messageSize, n);
print("toProto ", toProto, n);
print("toRequest", toRequest, n);
}
use of org.apache.ratis.util.Timestamp in project incubator-ratis by apache.
the class RaftBasicTests method testRequestTimeout.
public static void testRequestTimeout(boolean async, MiniRaftCluster cluster, Logger LOG) throws Exception {
waitForLeader(cluster);
final Timestamp startTime = Timestamp.currentTime();
try (final RaftClient client = cluster.createClient()) {
// Get the next callId to be used by the client
final ClientInvocationId invocationId = RaftClientTestUtil.getClientInvocationId(client);
// Create an entry corresponding to the callId and clientId
// in each server's retry cache.
cluster.getServerAliveStream().forEach(raftServer -> RetryCacheTestUtil.getOrCreateEntry(raftServer, invocationId));
// The retry is successful when the retry cache entry for the corresponding callId and clientId expires.
if (async) {
CompletableFuture<RaftClientReply> replyFuture = client.async().send(new SimpleMessage("abc"));
replyFuture.get();
} else {
client.io().send(new SimpleMessage("abc"));
}
// Eventually the request would be accepted by the server
// when the retry cache entry is invalidated.
// The duration for which the client waits should be more than the retryCacheExpiryDuration.
final TimeDuration duration = startTime.elapsedTime();
TimeDuration retryCacheExpiryDuration = RaftServerConfigKeys.RetryCache.expiryTime(cluster.getProperties());
Assert.assertTrue(duration.compareTo(retryCacheExpiryDuration) >= 0);
}
}
Aggregations