Search in sources :

Example 1 with FollowerLogInformation

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();
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation)

Example 2 with FollowerLogInformation

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());
    }
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation)

Example 3 with FollowerLogInformation

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();
        }
    }
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation) ActorSelection(akka.actor.ActorSelection) UnInitializedFollowerSnapshotReply(org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply)

Example 4 with FollowerLogInformation

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);
            }
        }
    }
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation) ActorSelection(akka.actor.ActorSelection)

Example 5 with FollowerLogInformation

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;
    }
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation) ActorSelection(akka.actor.ActorSelection)

Aggregations

FollowerLogInformation (org.opendaylight.controller.cluster.raft.FollowerLogInformation)16 Test (org.junit.Test)6 MockRaftActorContext (org.opendaylight.controller.cluster.raft.MockRaftActorContext)6 ReplicatedLogEntry (org.opendaylight.controller.cluster.raft.ReplicatedLogEntry)5 AppendEntriesReply (org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply)5 ActorSelection (akka.actor.ActorSelection)4 DefaultConfigParamsImpl (org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl)4 ApplyState (org.opendaylight.controller.cluster.raft.base.messages.ApplyState)4 AppendEntries (org.opendaylight.controller.cluster.raft.messages.AppendEntries)4 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)4 FiniteDuration (scala.concurrent.duration.FiniteDuration)4 ByteString (com.google.protobuf.ByteString)1 HashMap (java.util.HashMap)1 PeerInfo (org.opendaylight.controller.cluster.raft.PeerInfo)1 SnapshotHolder (org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader.SnapshotHolder)1 InstallSnapshotReply (org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply)1 UnInitializedFollowerSnapshotReply (org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply)1 ApplyJournalEntries (org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries)1