Search in sources :

Example 11 with MockRaftActorContext

use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.

the class FollowerTest method testHandleAppendEntriesWithNewerCommitIndex.

/**
 * This test verifies that when an AppendEntries RPC is received by a RaftActor
 * with a commitIndex that is greater than what has been applied to the
 * state machine of the RaftActor, the RaftActor applies the state and
 * sets it current applied state to the commitIndex of the sender.
 */
@Test
public void testHandleAppendEntriesWithNewerCommitIndex() {
    logStart("testHandleAppendEntriesWithNewerCommitIndex");
    MockRaftActorContext context = createActorContext();
    context.setLastApplied(100);
    setLastLogEntry(context, 1, 100, new MockRaftActorContext.MockPayload(""));
    context.getReplicatedLog().setSnapshotIndex(99);
    List<ReplicatedLogEntry> entries = Arrays.<ReplicatedLogEntry>asList(newReplicatedLogEntry(2, 101, "foo"));
    // The new commitIndex is 101
    AppendEntries appendEntries = new AppendEntries(2, "leader-1", 100, 1, entries, 101, 100, (short) 0);
    follower = createBehavior(context);
    follower.handleMessage(leaderActor, appendEntries);
    assertEquals("getLastApplied", 101L, context.getLastApplied());
}
Also used : SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ReplicatedLogEntry(org.opendaylight.controller.cluster.raft.ReplicatedLogEntry) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) Test(org.junit.Test)

Example 12 with MockRaftActorContext

use of org.opendaylight.controller.cluster.raft.MockRaftActorContext 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 13 with MockRaftActorContext

use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.

the class IsolatedLeaderTest method testHandleMessageWithThreeMembers.

@Test
public void testHandleMessageWithThreeMembers() throws Exception {
    String followerAddress1 = "akka://test/user/$a";
    String followerAddress2 = "akka://test/user/$b";
    MockRaftActorContext leaderActorContext = createActorContext();
    Map<String, String> peerAddresses = new HashMap<>();
    peerAddresses.put("follower-1", followerAddress1);
    peerAddresses.put("follower-2", followerAddress2);
    leaderActorContext.setPeerAddresses(peerAddresses);
    isolatedLeader = new IsolatedLeader(leaderActorContext);
    leaderActorContext.setCurrentBehavior(isolatedLeader);
    assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
    // in a 3 node cluster, even if 1 follower is returns a reply, the isolatedLeader is not isolated
    RaftActorBehavior newBehavior = isolatedLeader.handleMessage(senderActor, new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true, isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
    assertEquals("Raft state", RaftState.Leader, newBehavior.state());
    isolatedLeader.close();
    isolatedLeader = (AbstractLeader) newBehavior;
    newBehavior = isolatedLeader.handleMessage(senderActor, new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true, isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
    assertEquals("Raft state", RaftState.Leader, newBehavior.state());
}
Also used : HashMap(java.util.HashMap) AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) Test(org.junit.Test)

Example 14 with MockRaftActorContext

use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.

the class LeaderTest method testHandleAppendEntriesReplyFailureWithFollowersLogTermDifferent.

@Test
public void testHandleAppendEntriesReplyFailureWithFollowersLogTermDifferent() {
    logStart("testHandleAppendEntriesReplyFailureWithFollowersLogTermDifferent");
    MockRaftActorContext leaderActorContext = createActorContextWithFollower();
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(1000, TimeUnit.SECONDS));
    leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 2).build());
    long leaderCommitIndex = 1;
    leaderActorContext.setCommitIndex(leaderCommitIndex);
    leaderActorContext.setLastApplied(leaderCommitIndex);
    final ReplicatedLogEntry leadersFirstLogEntry = leaderActorContext.getReplicatedLog().get(0);
    final ReplicatedLogEntry leadersSecondLogEntry = leaderActorContext.getReplicatedLog().get(1);
    MockRaftActorContext followerActorContext = createFollowerActorContextWithLeader();
    followerActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 1, 1).build());
    followerActorContext.setCommitIndex(-1);
    followerActorContext.setLastApplied(-1);
    Follower follower = new Follower(followerActorContext);
    followerActor.underlyingActor().setBehavior(follower);
    followerActorContext.setCurrentBehavior(follower);
    leader = new Leader(leaderActorContext);
    AppendEntries appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    final AppendEntriesReply appendEntriesReply = MessageCollectorActor.expectFirstMatching(leaderActor, AppendEntriesReply.class);
    MessageCollectorActor.clearMessages(followerActor);
    MessageCollectorActor.clearMessages(leaderActor);
    // Verify initial AppendEntries sent with the leader's current commit index.
    assertEquals("getLeaderCommit", -1, appendEntries.getLeaderCommit());
    assertEquals("Log entries size", 0, appendEntries.getEntries().size());
    assertEquals("getPrevLogIndex", 0, appendEntries.getPrevLogIndex());
    leaderActor.underlyingActor().setBehavior(leader);
    leaderActorContext.setCurrentBehavior(leader);
    leader.handleMessage(followerActor, appendEntriesReply);
    MessageCollectorActor.expectMatching(leaderActor, AppendEntriesReply.class, 1);
    appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    assertEquals("getLeaderCommit", leaderCommitIndex, appendEntries.getLeaderCommit());
    assertEquals("getPrevLogIndex", -1, appendEntries.getPrevLogIndex());
    assertEquals("Log entries size", 2, appendEntries.getEntries().size());
    assertEquals("First entry index", 0, appendEntries.getEntries().get(0).getIndex());
    assertEquals("First entry term", 2, appendEntries.getEntries().get(0).getTerm());
    assertEquals("First entry data", leadersFirstLogEntry.getData(), appendEntries.getEntries().get(0).getData());
    assertEquals("Second entry index", 1, appendEntries.getEntries().get(1).getIndex());
    assertEquals("Second entry term", 2, appendEntries.getEntries().get(1).getTerm());
    assertEquals("Second entry data", leadersSecondLogEntry.getData(), appendEntries.getEntries().get(1).getData());
    FollowerLogInformation followerInfo = leader.getFollower(FOLLOWER_ID);
    assertEquals("getNextIndex", 2, followerInfo.getNextIndex());
    List<ApplyState> applyStateList = MessageCollectorActor.expectMatching(followerActor, ApplyState.class, 2);
    ApplyState applyState = applyStateList.get(0);
    assertEquals("Follower's first ApplyState index", 0, applyState.getReplicatedLogEntry().getIndex());
    assertEquals("Follower's first ApplyState term", 2, applyState.getReplicatedLogEntry().getTerm());
    assertEquals("Follower's first ApplyState data", leadersFirstLogEntry.getData(), applyState.getReplicatedLogEntry().getData());
    applyState = applyStateList.get(1);
    assertEquals("Follower's second ApplyState index", 1, applyState.getReplicatedLogEntry().getIndex());
    assertEquals("Follower's second ApplyState term", 2, applyState.getReplicatedLogEntry().getTerm());
    assertEquals("Follower's second ApplyState data", leadersSecondLogEntry.getData(), applyState.getReplicatedLogEntry().getData());
    assertEquals("Follower's commit index", 1, followerActorContext.getCommitIndex());
    assertEquals("Follower's lastIndex", 1, followerActorContext.getReplicatedLog().lastIndex());
    assertEquals("Follower's lastTerm", 2, followerActorContext.getReplicatedLog().lastTerm());
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) FiniteDuration(scala.concurrent.duration.FiniteDuration) DefaultConfigParamsImpl(org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ReplicatedLogEntry(org.opendaylight.controller.cluster.raft.ReplicatedLogEntry) AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) ApplyState(org.opendaylight.controller.cluster.raft.base.messages.ApplyState) Test(org.junit.Test)

Example 15 with MockRaftActorContext

use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.

the class LeaderTest method testHandleReplicateMessageCommitIndexIncrementedBeforeConsensus.

@Test
public void testHandleReplicateMessageCommitIndexIncrementedBeforeConsensus() throws Exception {
    logStart("testHandleReplicateMessageCommitIndexIncrementedBeforeConsensus");
    MockRaftActorContext actorContext = createActorContextWithFollower();
    actorContext.setRaftPolicy(createRaftPolicy(true, true));
    long term = 1;
    actorContext.getTermInformation().update(term, "");
    leader = new Leader(actorContext);
    // Leader will send an immediate heartbeat - ignore it.
    MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    // The follower would normally reply - simulate that explicitly here.
    long lastIndex = actorContext.getReplicatedLog().lastIndex();
    leader.handleMessage(followerActor, new AppendEntriesReply(FOLLOWER_ID, term, true, lastIndex, term, (short) 0));
    assertEquals("isFollowerActive", true, leader.getFollower(FOLLOWER_ID).isFollowerActive());
    followerActor.underlyingActor().clear();
    RaftActorBehavior raftBehavior = sendReplicate(actorContext, lastIndex + 1);
    // State should not change
    assertTrue(raftBehavior instanceof Leader);
    AppendEntries appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    assertEquals("getPrevLogIndex", lastIndex, appendEntries.getPrevLogIndex());
    assertEquals("getPrevLogTerm", term, appendEntries.getPrevLogTerm());
    assertEquals("Entries size", 1, appendEntries.getEntries().size());
    assertEquals("Entry getIndex", lastIndex + 1, appendEntries.getEntries().get(0).getIndex());
    assertEquals("Entry getTerm", term, appendEntries.getEntries().get(0).getTerm());
    assertEquals("Entry payload", "foo", appendEntries.getEntries().get(0).getData().toString());
    assertEquals("Commit Index", lastIndex + 1, actorContext.getCommitIndex());
}
Also used : AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) Test(org.junit.Test)

Aggregations

MockRaftActorContext (org.opendaylight.controller.cluster.raft.MockRaftActorContext)100 Test (org.junit.Test)93 AppendEntries (org.opendaylight.controller.cluster.raft.messages.AppendEntries)44 AppendEntriesReply (org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply)40 DefaultConfigParamsImpl (org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl)30 FiniteDuration (scala.concurrent.duration.FiniteDuration)29 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)28 ReplicatedLogEntry (org.opendaylight.controller.cluster.raft.ReplicatedLogEntry)24 ByteString (com.google.protobuf.ByteString)19 HashMap (java.util.HashMap)16 InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)11 RequestVoteReply (org.opendaylight.controller.cluster.raft.messages.RequestVoteReply)11 FollowerInitialSyncUpStatus (org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus)9 RequestVote (org.opendaylight.controller.cluster.raft.messages.RequestVote)8 ArrayList (java.util.ArrayList)7 AbstractActorTest (org.opendaylight.controller.cluster.raft.AbstractActorTest)7 CaptureSnapshot (org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot)7 FollowerLogInformation (org.opendaylight.controller.cluster.raft.FollowerLogInformation)6 SendInstallSnapshot (org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot)6 InstallSnapshotReply (org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply)6