Search in sources :

Example 1 with InstallSnapshotReply

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

the class AbstractLeader method handleMessage.

@Override
public RaftActorBehavior handleMessage(final ActorRef sender, final Object message) {
    Preconditions.checkNotNull(sender, "sender should not be null");
    if (appendEntriesMessageSlicer.handleMessage(message)) {
        return this;
    }
    if (message instanceof RaftRPC) {
        RaftRPC rpc = (RaftRPC) message;
        // This applies to all RPC messages and responses
        if (rpc.getTerm() > context.getTermInformation().getCurrentTerm()) {
            log.info("{}: Term {} in \"{}\" message is greater than leader's term {} - switching to Follower", logName(), rpc.getTerm(), rpc, context.getTermInformation().getCurrentTerm());
            context.getTermInformation().updateAndPersist(rpc.getTerm(), null);
            // leadership, we should make every effort to get the requesting node elected.
            if (message instanceof RequestVote && context.getRaftActorLeadershipTransferCohort() != null) {
                log.debug("{}: Leadership transfer in progress - processing RequestVote", logName());
                super.handleMessage(sender, message);
            }
            return internalSwitchBehavior(RaftState.Follower);
        }
    }
    if (message instanceof SendHeartBeat) {
        beforeSendHeartbeat();
        sendHeartBeat();
        scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
    } else if (message instanceof SendInstallSnapshot) {
        SendInstallSnapshot sendInstallSnapshot = (SendInstallSnapshot) message;
        setSnapshotHolder(new SnapshotHolder(sendInstallSnapshot.getSnapshot(), sendInstallSnapshot.getSnapshotBytes()));
        sendInstallSnapshot();
    } else if (message instanceof Replicate) {
        replicate((Replicate) message);
    } else if (message instanceof InstallSnapshotReply) {
        handleInstallSnapshotReply((InstallSnapshotReply) message);
    } else if (message instanceof CheckConsensusReached) {
        possiblyUpdateCommitIndex();
    } else {
        return super.handleMessage(sender, message);
    }
    return this;
}
Also used : RaftRPC(org.opendaylight.controller.cluster.raft.messages.RaftRPC) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) Replicate(org.opendaylight.controller.cluster.raft.base.messages.Replicate) CheckConsensusReached(org.opendaylight.controller.cluster.raft.base.messages.CheckConsensusReached) InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) SendHeartBeat(org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat) RequestVote(org.opendaylight.controller.cluster.raft.messages.RequestVote)

Example 2 with InstallSnapshotReply

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

the class Follower method handleInstallSnapshot.

private void handleInstallSnapshot(final ActorRef sender, final InstallSnapshot installSnapshot) {
    log.debug("{}: handleInstallSnapshot: {}", logName(), installSnapshot);
    leaderId = installSnapshot.getLeaderId();
    if (snapshotTracker == null) {
        snapshotTracker = new SnapshotTracker(log, installSnapshot.getTotalChunks(), installSnapshot.getLeaderId(), context);
    }
    updateInitialSyncStatus(installSnapshot.getLastIncludedIndex(), installSnapshot.getLeaderId());
    try {
        final InstallSnapshotReply reply = new InstallSnapshotReply(currentTerm(), context.getId(), installSnapshot.getChunkIndex(), true);
        if (snapshotTracker.addChunk(installSnapshot.getChunkIndex(), installSnapshot.getData(), installSnapshot.getLastChunkHashCode())) {
            log.info("{}: Snapshot installed from leader: {}", logName(), installSnapshot.getLeaderId());
            Snapshot snapshot = Snapshot.create(context.getSnapshotManager().convertSnapshot(snapshotTracker.getSnapshotBytes()), new ArrayList<>(), installSnapshot.getLastIncludedIndex(), installSnapshot.getLastIncludedTerm(), installSnapshot.getLastIncludedIndex(), installSnapshot.getLastIncludedTerm(), context.getTermInformation().getCurrentTerm(), context.getTermInformation().getVotedFor(), installSnapshot.getServerConfig().orNull());
            ApplySnapshot.Callback applySnapshotCallback = new ApplySnapshot.Callback() {

                @Override
                public void onSuccess() {
                    log.debug("{}: handleInstallSnapshot returning: {}", logName(), reply);
                    sender.tell(reply, actor());
                }

                @Override
                public void onFailure() {
                    sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(), -1, false), actor());
                }
            };
            actor().tell(new ApplySnapshot(snapshot, applySnapshotCallback), actor());
            closeSnapshotTracker();
        } else {
            log.debug("{}: handleInstallSnapshot returning: {}", logName(), reply);
            sender.tell(reply, actor());
        }
    } catch (IOException e) {
        log.debug("{}: Exception in InstallSnapshot of follower", logName(), e);
        sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(), -1, false), actor());
        closeSnapshotTracker();
    }
}
Also used : ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) IOException(java.io.IOException)

Example 3 with InstallSnapshotReply

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

the class FollowerTest method testHandleInstallSnapshot.

/**
 * This test verifies that when InstallSnapshot is received by
 * the follower its applied correctly.
 */
@Test
public void testHandleInstallSnapshot() {
    logStart("testHandleInstallSnapshot");
    MockRaftActorContext context = createActorContext();
    context.getTermInformation().update(1, "leader");
    follower = createBehavior(context);
    ByteString bsSnapshot = createSnapshot();
    int offset = 0;
    int snapshotLength = bsSnapshot.size();
    int chunkSize = 50;
    int totalChunks = snapshotLength / chunkSize + (snapshotLength % chunkSize > 0 ? 1 : 0);
    int lastIncludedIndex = 1;
    int chunkIndex = 1;
    InstallSnapshot lastInstallSnapshot = null;
    for (int i = 0; i < totalChunks; i++) {
        byte[] chunkData = getNextChunk(bsSnapshot, offset, chunkSize);
        lastInstallSnapshot = new InstallSnapshot(1, "leader", lastIncludedIndex, 1, chunkData, chunkIndex, totalChunks);
        follower.handleMessage(leaderActor, lastInstallSnapshot);
        offset = offset + 50;
        lastIncludedIndex++;
        chunkIndex++;
    }
    ApplySnapshot applySnapshot = MessageCollectorActor.expectFirstMatching(followerActor, ApplySnapshot.class);
    Snapshot snapshot = applySnapshot.getSnapshot();
    assertNotNull(lastInstallSnapshot);
    assertEquals("getLastIndex", lastInstallSnapshot.getLastIncludedIndex(), snapshot.getLastIndex());
    assertEquals("getLastIncludedTerm", lastInstallSnapshot.getLastIncludedTerm(), snapshot.getLastAppliedTerm());
    assertEquals("getLastAppliedIndex", lastInstallSnapshot.getLastIncludedIndex(), snapshot.getLastAppliedIndex());
    assertEquals("getLastTerm", lastInstallSnapshot.getLastIncludedTerm(), snapshot.getLastTerm());
    assertEquals("getState type", ByteState.class, snapshot.getState().getClass());
    Assert.assertArrayEquals("getState", bsSnapshot.toByteArray(), ((ByteState) snapshot.getState()).getBytes());
    assertEquals("getElectionTerm", 1, snapshot.getElectionTerm());
    assertEquals("getElectionVotedFor", "leader", snapshot.getElectionVotedFor());
    applySnapshot.getCallback().onSuccess();
    List<InstallSnapshotReply> replies = MessageCollectorActor.getAllMatching(leaderActor, InstallSnapshotReply.class);
    assertEquals("InstallSnapshotReply count", totalChunks, replies.size());
    chunkIndex = 1;
    for (InstallSnapshotReply reply : replies) {
        assertEquals("getChunkIndex", chunkIndex++, reply.getChunkIndex());
        assertEquals("getTerm", 1, reply.getTerm());
        assertEquals("isSuccess", true, reply.isSuccess());
        assertEquals("getFollowerId", context.getId(), reply.getFollowerId());
    }
    assertNull("Expected null SnapshotTracker", follower.getSnapshotTracker());
}
Also used : ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) ByteString(com.google.protobuf.ByteString) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) Test(org.junit.Test)

Example 4 with InstallSnapshotReply

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

the class LeaderTest method testHandleInstallSnapshotReplyWithInvalidChunkIndex.

@Test
public void testHandleInstallSnapshotReplyWithInvalidChunkIndex() throws Exception {
    logStart("testHandleInstallSnapshotReplyWithInvalidChunkIndex");
    MockRaftActorContext actorContext = createActorContextWithFollower();
    final int commitIndex = 3;
    final int snapshotIndex = 2;
    final int snapshotTerm = 1;
    final int currentTerm = 2;
    actorContext.setConfigParams(new DefaultConfigParamsImpl() {

        @Override
        public int getSnapshotChunkSize() {
            return 50;
        }
    });
    actorContext.setCommitIndex(commitIndex);
    leader = new Leader(actorContext);
    leader.getFollower(FOLLOWER_ID).setMatchIndex(-1);
    leader.getFollower(FOLLOWER_ID).setNextIndex(0);
    Map<String, String> leadersSnapshot = new HashMap<>();
    leadersSnapshot.put("1", "A");
    leadersSnapshot.put("2", "B");
    leadersSnapshot.put("3", "C");
    // set the snapshot variables in replicatedlog
    actorContext.getReplicatedLog().setSnapshotIndex(snapshotIndex);
    actorContext.getReplicatedLog().setSnapshotTerm(snapshotTerm);
    actorContext.getTermInformation().update(currentTerm, leaderActor.path().toString());
    ByteString bs = toByteString(leadersSnapshot);
    Snapshot snapshot = Snapshot.create(ByteState.of(bs.toByteArray()), Collections.<ReplicatedLogEntry>emptyList(), commitIndex, snapshotTerm, commitIndex, snapshotTerm, -1, null, null);
    Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
    leader.handleMessage(leaderActor, new SendInstallSnapshot(snapshot, ByteSource.wrap(bs.toByteArray())));
    InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
    assertEquals(1, installSnapshot.getChunkIndex());
    assertEquals(3, installSnapshot.getTotalChunks());
    followerActor.underlyingActor().clear();
    leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(), FOLLOWER_ID, -1, false));
    Uninterruptibles.sleepUninterruptibly(actorContext.getConfigParams().getHeartBeatInterval().toMillis(), TimeUnit.MILLISECONDS);
    leader.handleMessage(leaderActor, SendHeartBeat.INSTANCE);
    installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
    assertEquals(1, installSnapshot.getChunkIndex());
    assertEquals(3, installSnapshot.getTotalChunks());
}
Also used : SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) HashMap(java.util.HashMap) InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) ByteString(com.google.protobuf.ByteString) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) DefaultConfigParamsImpl(org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl) ByteString(com.google.protobuf.ByteString) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) CaptureSnapshot(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) Test(org.junit.Test)

Example 5 with InstallSnapshotReply

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

the class LeaderTest method testSendSnapshotfromInstallSnapshotReply.

@Test
public void testSendSnapshotfromInstallSnapshotReply() throws Exception {
    logStart("testSendSnapshotfromInstallSnapshotReply");
    MockRaftActorContext actorContext = createActorContextWithFollower();
    final int commitIndex = 3;
    final int snapshotIndex = 2;
    final int snapshotTerm = 1;
    final int currentTerm = 2;
    DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl() {

        @Override
        public int getSnapshotChunkSize() {
            return 50;
        }
    };
    configParams.setHeartBeatInterval(new FiniteDuration(9, TimeUnit.SECONDS));
    configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(10, TimeUnit.SECONDS));
    actorContext.setConfigParams(configParams);
    actorContext.setCommitIndex(commitIndex);
    leader = new Leader(actorContext);
    actorContext.setCurrentBehavior(leader);
    leader.getFollower(FOLLOWER_ID).setMatchIndex(-1);
    leader.getFollower(FOLLOWER_ID).setNextIndex(0);
    Map<String, String> leadersSnapshot = new HashMap<>();
    leadersSnapshot.put("1", "A");
    leadersSnapshot.put("2", "B");
    leadersSnapshot.put("3", "C");
    // set the snapshot variables in replicatedlog
    actorContext.getReplicatedLog().setSnapshotIndex(snapshotIndex);
    actorContext.getReplicatedLog().setSnapshotTerm(snapshotTerm);
    actorContext.getTermInformation().update(currentTerm, leaderActor.path().toString());
    ByteString bs = toByteString(leadersSnapshot);
    Snapshot snapshot = Snapshot.create(ByteState.of(bs.toByteArray()), Collections.<ReplicatedLogEntry>emptyList(), commitIndex, snapshotTerm, commitIndex, snapshotTerm, -1, null, null);
    leader.handleMessage(leaderActor, new SendInstallSnapshot(snapshot, ByteSource.wrap(bs.toByteArray())));
    InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
    assertEquals(1, installSnapshot.getChunkIndex());
    assertEquals(3, installSnapshot.getTotalChunks());
    followerActor.underlyingActor().clear();
    leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(), FOLLOWER_ID, installSnapshot.getChunkIndex(), true));
    installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
    assertEquals(2, installSnapshot.getChunkIndex());
    assertEquals(3, installSnapshot.getTotalChunks());
    followerActor.underlyingActor().clear();
    leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(), FOLLOWER_ID, installSnapshot.getChunkIndex(), true));
    installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
    // Send snapshot reply one more time and make sure that a new snapshot message should not be sent to follower
    followerActor.underlyingActor().clear();
    leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(), FOLLOWER_ID, installSnapshot.getChunkIndex(), true));
    installSnapshot = MessageCollectorActor.getFirstMatching(followerActor, InstallSnapshot.class);
    assertNull(installSnapshot);
}
Also used : SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) HashMap(java.util.HashMap) InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) ByteString(com.google.protobuf.ByteString) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) FiniteDuration(scala.concurrent.duration.FiniteDuration) DefaultConfigParamsImpl(org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl) ByteString(com.google.protobuf.ByteString) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) CaptureSnapshot(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) Test(org.junit.Test)

Aggregations

InstallSnapshotReply (org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply)9 InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)7 ByteString (com.google.protobuf.ByteString)6 Test (org.junit.Test)6 MockRaftActorContext (org.opendaylight.controller.cluster.raft.MockRaftActorContext)6 Snapshot (org.opendaylight.controller.cluster.raft.persisted.Snapshot)6 HashMap (java.util.HashMap)4 CaptureSnapshot (org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot)4 SendInstallSnapshot (org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot)4 DefaultConfigParamsImpl (org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl)3 ApplySnapshot (org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)3 IOException (java.io.IOException)1 HashSet (java.util.HashSet)1 FollowerLogInformation (org.opendaylight.controller.cluster.raft.FollowerLogInformation)1 CheckConsensusReached (org.opendaylight.controller.cluster.raft.base.messages.CheckConsensusReached)1 Replicate (org.opendaylight.controller.cluster.raft.base.messages.Replicate)1 SendHeartBeat (org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat)1 SnapshotHolder (org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader.SnapshotHolder)1 RaftRPC (org.opendaylight.controller.cluster.raft.messages.RaftRPC)1 RequestVote (org.opendaylight.controller.cluster.raft.messages.RequestVote)1