Search in sources :

Example 1 with UnInitializedFollowerSnapshotReply

use of org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply 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 2 with UnInitializedFollowerSnapshotReply

use of org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply in project controller by opendaylight.

the class RaftActorServerConfigurationSupportTest method testAddServerWithLeaderChangeDuringInstallSnapshot.

@Test
public void testAddServerWithLeaderChangeDuringInstallSnapshot() throws Exception {
    LOG.info("testAddServerWithLeaderChangeDuringInstallSnapshot starting");
    setupNewFollower();
    RaftActorContext initialActorContext = new MockRaftActorContext();
    TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
    MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
    RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setElectionTimeoutFactor(8);
    ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
    // Drop the UnInitializedFollowerSnapshotReply to delay it.
    leaderRaftActor.setDropMessageOfType(UnInitializedFollowerSnapshotReply.class);
    leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
    final UnInitializedFollowerSnapshotReply snapshotReply = expectFirstMatching(leaderCollectorActor, UnInitializedFollowerSnapshotReply.class);
    // Prevent election timeout when the leader switches to follower
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setElectionTimeoutFactor(100);
    // Change the leader behavior to follower
    leaderActor.tell(new Follower(leaderActorContext), leaderActor);
    // Send the captured UnInitializedFollowerSnapshotReply - should be a no-op
    leaderRaftActor.setDropMessageOfType(null);
    leaderActor.tell(snapshotReply, leaderActor);
    AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
    assertEquals("getStatus", ServerChangeStatus.NO_LEADER, addServerReply.getStatus());
    assertEquals("Leader peers size", 0, leaderActorContext.getPeerIds().size());
    LOG.info("testAddServerWithLeaderChangeDuringInstallSnapshot ending");
}
Also used : ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) UnInitializedFollowerSnapshotReply(org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply) Follower(org.opendaylight.controller.cluster.raft.behaviors.Follower) AddServerReply(org.opendaylight.controller.cluster.raft.messages.AddServerReply) AddServer(org.opendaylight.controller.cluster.raft.messages.AddServer) Test(org.junit.Test)

Example 3 with UnInitializedFollowerSnapshotReply

use of org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply in project controller by opendaylight.

the class RaftActorServerConfigurationSupportTest method testAddServerWithInstallSnapshotTimeout.

@Test
public void testAddServerWithInstallSnapshotTimeout() throws Exception {
    LOG.info("testAddServerWithInstallSnapshotTimeout starting");
    setupNewFollower();
    RaftActorContext initialActorContext = new MockRaftActorContext();
    TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
    MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
    RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setElectionTimeoutFactor(1);
    // Drop the InstallSnapshot message so it times out
    newFollowerRaftActor.underlyingActor().setDropMessageOfType(InstallSnapshot.class);
    leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
    leaderActor.tell(new UnInitializedFollowerSnapshotReply("bogus"), leaderActor);
    AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
    assertEquals("getStatus", ServerChangeStatus.TIMEOUT, addServerReply.getStatus());
    assertEquals("Leader peers size", 0, leaderActorContext.getPeerIds().size());
    assertEquals("Leader followers size", 0, ((AbstractLeader) leaderRaftActor.getCurrentBehavior()).getFollowerIds().size());
    LOG.info("testAddServerWithInstallSnapshotTimeout ending");
}
Also used : UnInitializedFollowerSnapshotReply(org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply) AbstractLeader(org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader) AddServerReply(org.opendaylight.controller.cluster.raft.messages.AddServerReply) AddServer(org.opendaylight.controller.cluster.raft.messages.AddServer) Test(org.junit.Test)

Aggregations

UnInitializedFollowerSnapshotReply (org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply)3 Test (org.junit.Test)2 AddServer (org.opendaylight.controller.cluster.raft.messages.AddServer)2 AddServerReply (org.opendaylight.controller.cluster.raft.messages.AddServerReply)2 ActorRef (akka.actor.ActorRef)1 ActorSelection (akka.actor.ActorSelection)1 TestActorRef (akka.testkit.TestActorRef)1 FollowerLogInformation (org.opendaylight.controller.cluster.raft.FollowerLogInformation)1 AbstractLeader (org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader)1 Follower (org.opendaylight.controller.cluster.raft.behaviors.Follower)1