Search in sources :

Example 1 with InstallSnapshot

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

the class Follower method handleMessage.

@Override
public RaftActorBehavior handleMessage(final ActorRef sender, final Object message) {
    if (message instanceof ElectionTimeout || message instanceof TimeoutNow) {
        return handleElectionTimeout(message);
    }
    if (appendEntriesMessageAssembler.handleMessage(message, actor())) {
        return this;
    }
    if (!(message instanceof RaftRPC)) {
        // The rest of the processing requires the message to be a RaftRPC
        return null;
    }
    final 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 follower's term {} - updating term", logName(), rpc.getTerm(), rpc, context.getTermInformation().getCurrentTerm());
        context.getTermInformation().updateAndPersist(rpc.getTerm(), null);
    }
    if (rpc instanceof InstallSnapshot) {
        handleInstallSnapshot(sender, (InstallSnapshot) rpc);
        restartLastLeaderMessageTimer();
        scheduleElection(electionDuration());
        return this;
    }
    if (!(rpc instanceof RequestVote) || canGrantVote((RequestVote) rpc)) {
        restartLastLeaderMessageTimer();
        scheduleElection(electionDuration());
    }
    return super.handleMessage(sender, rpc);
}
Also used : RaftRPC(org.opendaylight.controller.cluster.raft.messages.RaftRPC) TimeoutNow(org.opendaylight.controller.cluster.raft.base.messages.TimeoutNow) ElectionTimeout(org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout) RequestVote(org.opendaylight.controller.cluster.raft.messages.RequestVote) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)

Example 2 with InstallSnapshot

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

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

the class DummyShard method onReceive.

@Override
public void onReceive(Object message) throws Exception {
    if (message instanceof RequestVote) {
        RequestVote req = (RequestVote) message;
        sender().tell(new RequestVoteReply(req.getTerm(), true), self());
    } else if (message instanceof AppendEntries) {
        handleAppendEntries((AppendEntries) message);
    } else if (message instanceof InstallSnapshot) {
        handleInstallSnapshot((InstallSnapshot) message);
    } else {
        LOG.error("Unknown message : {}", message.getClass());
    }
}
Also used : RequestVoteReply(org.opendaylight.controller.cluster.raft.messages.RequestVoteReply) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) RequestVote(org.opendaylight.controller.cluster.raft.messages.RequestVote) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)

Example 4 with InstallSnapshot

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

the class FollowerTest method testInitialSyncUpWithHandleInstallSnapshotFollowedByAppendEntries.

@Test
public void testInitialSyncUpWithHandleInstallSnapshotFollowedByAppendEntries() {
    logStart("testInitialSyncUpWithHandleInstallSnapshot");
    MockRaftActorContext context = createActorContext();
    context.setCommitIndex(-1);
    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++;
    }
    FollowerInitialSyncUpStatus syncStatus = MessageCollectorActor.expectFirstMatching(followerActor, FollowerInitialSyncUpStatus.class);
    assertFalse(syncStatus.isInitialSyncDone());
    // Clear all the messages
    MessageCollectorActor.clearMessages(followerActor);
    context.setLastApplied(101);
    context.setCommitIndex(101);
    setLastLogEntry(context, 1, 101, new MockRaftActorContext.MockPayload(""));
    List<ReplicatedLogEntry> entries = Arrays.asList(newReplicatedLogEntry(2, 101, "foo"));
    // The new commitIndex is 101
    AppendEntries appendEntries = new AppendEntries(2, "leader", 101, 1, entries, 102, 101, (short) 0);
    follower.handleMessage(leaderActor, appendEntries);
    syncStatus = MessageCollectorActor.expectFirstMatching(followerActor, FollowerInitialSyncUpStatus.class);
    assertTrue(syncStatus.isInitialSyncDone());
}
Also used : SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ReplicatedLogEntry(org.opendaylight.controller.cluster.raft.ReplicatedLogEntry) ByteString(com.google.protobuf.ByteString) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) FollowerInitialSyncUpStatus(org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) Test(org.junit.Test)

Example 5 with InstallSnapshot

use of org.opendaylight.controller.cluster.raft.messages.InstallSnapshot 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)

Aggregations

InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)18 Test (org.junit.Test)14 ByteString (com.google.protobuf.ByteString)11 MockRaftActorContext (org.opendaylight.controller.cluster.raft.MockRaftActorContext)11 Snapshot (org.opendaylight.controller.cluster.raft.persisted.Snapshot)9 CaptureSnapshot (org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot)7 InstallSnapshotReply (org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply)7 HashMap (java.util.HashMap)6 SendInstallSnapshot (org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot)6 AppendEntries (org.opendaylight.controller.cluster.raft.messages.AppendEntries)5 ApplySnapshot (org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)4 DefaultConfigParamsImpl (org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl)3 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)3 MockPayload (org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload)2 ApplyState (org.opendaylight.controller.cluster.raft.base.messages.ApplyState)2 AppendEntriesReply (org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply)2 RequestVote (org.opendaylight.controller.cluster.raft.messages.RequestVote)2 ActorRef (akka.actor.ActorRef)1 TestActorRef (akka.testkit.TestActorRef)1 TestKit (akka.testkit.javadsl.TestKit)1