use of org.opendaylight.controller.cluster.raft.FollowerLogInformation in project controller by opendaylight.
the class AbstractLeader method printFollowerStates.
// called from example-actor for printing the follower-states
public String printFollowerStates() {
final StringBuilder sb = new StringBuilder();
sb.append('[');
for (FollowerLogInformation followerLogInformation : followerToLog.values()) {
sb.append('{');
sb.append(followerLogInformation.getId());
sb.append(" state:");
sb.append(followerLogInformation.isFollowerActive());
sb.append("},");
}
sb.append(']');
return sb.toString();
}
use of org.opendaylight.controller.cluster.raft.FollowerLogInformation in project controller by opendaylight.
the class AbstractLeader method addFollower.
public void addFollower(final String followerId) {
FollowerLogInformation followerLogInformation = new FollowerLogInformation(context.getPeerInfo(followerId), context);
followerToLog.put(followerId, followerLogInformation);
if (heartbeatSchedule == null) {
scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
}
}
use of org.opendaylight.controller.cluster.raft.FollowerLogInformation in project controller by opendaylight.
the class AbstractLeader method handleInstallSnapshotReply.
private void handleInstallSnapshotReply(final InstallSnapshotReply reply) {
log.debug("{}: handleInstallSnapshotReply: {}", logName(), reply);
String followerId = reply.getFollowerId();
FollowerLogInformation followerLogInformation = followerToLog.get(followerId);
if (followerLogInformation == null) {
// This can happen during AddServer if it times out.
log.error("{}: FollowerLogInformation not found for follower {} in InstallSnapshotReply", logName(), followerId);
return;
}
LeaderInstallSnapshotState installSnapshotState = followerLogInformation.getInstallSnapshotState();
if (installSnapshotState == null) {
log.error("{}: LeaderInstallSnapshotState not found for follower {} in InstallSnapshotReply", logName(), followerId);
return;
}
followerLogInformation.markFollowerActive();
if (installSnapshotState.getChunkIndex() == reply.getChunkIndex()) {
boolean wasLastChunk = false;
if (reply.isSuccess()) {
if (installSnapshotState.isLastChunk(reply.getChunkIndex())) {
// this was the last chunk reply
long followerMatchIndex = snapshotHolder.get().getLastIncludedIndex();
followerLogInformation.setMatchIndex(followerMatchIndex);
followerLogInformation.setNextIndex(followerMatchIndex + 1);
followerLogInformation.clearLeaderInstallSnapshotState();
log.info("{}: Snapshot successfully installed on follower {} (last chunk {}) - " + "matchIndex set to {}, nextIndex set to {}", logName(), followerId, reply.getChunkIndex(), followerLogInformation.getMatchIndex(), followerLogInformation.getNextIndex());
if (!anyFollowersInstallingSnapshot()) {
// once there are no pending followers receiving snapshots
// we can remove snapshot from the memory
setSnapshotHolder(null);
}
wasLastChunk = true;
if (context.getPeerInfo(followerId).getVotingState() == VotingState.VOTING_NOT_INITIALIZED) {
UnInitializedFollowerSnapshotReply unInitFollowerSnapshotSuccess = new UnInitializedFollowerSnapshotReply(followerId);
context.getActor().tell(unInitFollowerSnapshotSuccess, context.getActor());
log.debug("Sent message UnInitializedFollowerSnapshotReply to self");
}
} else {
installSnapshotState.markSendStatus(true);
}
} else {
log.warn("{}: Received failed InstallSnapshotReply - will retry: {}", logName(), reply);
installSnapshotState.markSendStatus(false);
}
if (wasLastChunk) {
if (!context.getSnapshotManager().isCapturing()) {
// Since the follower is now caught up try to purge the log.
purgeInMemoryLog();
}
} else {
ActorSelection followerActor = context.getPeerActorSelection(followerId);
if (followerActor != null) {
sendSnapshotChunk(followerActor, followerLogInformation);
}
}
} else {
log.error("{}: Chunk index {} in InstallSnapshotReply from follower {} does not match expected index {}", logName(), reply.getChunkIndex(), followerId, installSnapshotState.getChunkIndex());
if (reply.getChunkIndex() == LeaderInstallSnapshotState.INVALID_CHUNK_INDEX) {
// Since the Follower did not find this index to be valid we should reset the follower snapshot
// so that Installing the snapshot can resume from the beginning
installSnapshotState.reset();
}
}
}
use of org.opendaylight.controller.cluster.raft.FollowerLogInformation in project controller by opendaylight.
the class AbstractLeader method sendInstallSnapshot.
private void sendInstallSnapshot() {
log.debug("{}: sendInstallSnapshot", logName());
for (Entry<String, FollowerLogInformation> e : followerToLog.entrySet()) {
String followerId = e.getKey();
ActorSelection followerActor = context.getPeerActorSelection(followerId);
FollowerLogInformation followerLogInfo = e.getValue();
if (followerActor != null) {
long nextIndex = followerLogInfo.getNextIndex();
if (followerLogInfo.getInstallSnapshotState() != null || context.getPeerInfo(followerId).getVotingState() == VotingState.VOTING_NOT_INITIALIZED || canInstallSnapshot(nextIndex)) {
sendSnapshotChunk(followerActor, followerLogInfo);
}
}
}
}
use of org.opendaylight.controller.cluster.raft.FollowerLogInformation in project controller by opendaylight.
the class Leader method tryToCompleteLeadershipTransfer.
private void tryToCompleteLeadershipTransfer(String followerId) {
if (leadershipTransferContext == null) {
return;
}
final Optional<String> requestedFollowerIdOptional = leadershipTransferContext.transferCohort.getRequestedFollowerId();
if (requestedFollowerIdOptional.isPresent() && !requestedFollowerIdOptional.get().equals(followerId)) {
// we want to transfer leadership to specific follower
return;
}
FollowerLogInformation followerInfo = getFollower(followerId);
if (followerInfo == null) {
return;
}
long lastIndex = context.getReplicatedLog().lastIndex();
boolean isVoting = context.getPeerInfo(followerId).isVoting();
log.debug("{}: tryToCompleteLeadershipTransfer: followerId: {}, matchIndex: {}, lastIndex: {}, isVoting: {}", logName(), followerId, followerInfo.getMatchIndex(), lastIndex, isVoting);
if (isVoting && followerInfo.getMatchIndex() == lastIndex) {
log.debug("{}: Follower's log matches - sending ElectionTimeout", logName());
// We can't be sure if the follower has applied all its log entries to its state so send an
// additional AppendEntries with the latest commit index.
sendAppendEntries(0, false);
// Now send a TimeoutNow message to the matching follower to immediately start an election.
ActorSelection followerActor = context.getPeerActorSelection(followerId);
followerActor.tell(TimeoutNow.INSTANCE, context.getActor());
log.debug("{}: Leader transfer complete", logName());
leadershipTransferContext.transferCohort.transferComplete();
leadershipTransferContext = null;
}
}
Aggregations