Search in sources :

Example 26 with MockRaftActorContext

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

the class LeaderTest method testHandleInstallSnapshotReplyLastChunk.

@Test
public void testHandleInstallSnapshotReplyLastChunk() throws Exception {
    logStart("testHandleInstallSnapshotReplyLastChunk");
    MockRaftActorContext actorContext = createActorContextWithFollower();
    final int commitIndex = 3;
    final int snapshotIndex = 2;
    final int snapshotTerm = 1;
    final int currentTerm = 2;
    actorContext.setCommitIndex(commitIndex);
    leader = new Leader(actorContext);
    actorContext.setCurrentBehavior(leader);
    leader.getFollower(FOLLOWER_ID).setMatchIndex(-1);
    leader.getFollower(FOLLOWER_ID).setNextIndex(0);
    // Ignore initial heartbeat.
    MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    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);
    leader.setSnapshotHolder(new SnapshotHolder(Snapshot.create(ByteState.of(bs.toByteArray()), Collections.<ReplicatedLogEntry>emptyList(), commitIndex, snapshotTerm, commitIndex, snapshotTerm, -1, null, null), ByteSource.wrap(bs.toByteArray())));
    LeaderInstallSnapshotState fts = new LeaderInstallSnapshotState(actorContext.getConfigParams().getSnapshotChunkSize(), leader.logName());
    fts.setSnapshotBytes(ByteSource.wrap(bs.toByteArray()));
    leader.getFollower(FOLLOWER_ID).setLeaderInstallSnapshotState(fts);
    while (!fts.isLastChunk(fts.getChunkIndex())) {
        fts.getNextChunk();
        fts.incrementChunkIndex();
    }
    // clears leaders log
    actorContext.getReplicatedLog().removeFrom(0);
    RaftActorBehavior raftBehavior = leader.handleMessage(followerActor, new InstallSnapshotReply(currentTerm, FOLLOWER_ID, fts.getChunkIndex(), true));
    assertTrue(raftBehavior instanceof Leader);
    assertEquals(1, leader.followerLogSize());
    FollowerLogInformation fli = leader.getFollower(FOLLOWER_ID);
    assertNotNull(fli);
    assertNull(fli.getInstallSnapshotState());
    assertEquals(commitIndex, fli.getMatchIndex());
    assertEquals(commitIndex + 1, fli.getNextIndex());
    assertFalse(leader.hasSnapshot());
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation) HashMap(java.util.HashMap) InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) ByteString(com.google.protobuf.ByteString) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) ByteString(com.google.protobuf.ByteString) SnapshotHolder(org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader.SnapshotHolder) Test(org.junit.Test)

Example 27 with MockRaftActorContext

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

the class LeaderTest method testHandleAppendEntriesReplySuccess.

@Test
public void testHandleAppendEntriesReplySuccess() throws Exception {
    logStart("testHandleAppendEntriesReplySuccess");
    MockRaftActorContext leaderActorContext = createActorContextWithFollower();
    leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 3, 1).build());
    leaderActorContext.setCommitIndex(1);
    leaderActorContext.setLastApplied(1);
    leaderActorContext.getTermInformation().update(1, "leader");
    leader = new Leader(leaderActorContext);
    FollowerLogInformation followerInfo = leader.getFollower(FOLLOWER_ID);
    assertEquals(payloadVersion, leader.getLeaderPayloadVersion());
    assertEquals(RaftVersions.HELIUM_VERSION, followerInfo.getRaftVersion());
    AppendEntriesReply reply = new AppendEntriesReply(FOLLOWER_ID, 1, true, 2, 1, payloadVersion);
    RaftActorBehavior raftActorBehavior = leader.handleAppendEntriesReply(followerActor, reply);
    assertEquals(RaftState.Leader, raftActorBehavior.state());
    assertEquals(2, leaderActorContext.getCommitIndex());
    ApplyJournalEntries applyJournalEntries = MessageCollectorActor.expectFirstMatching(leaderActor, ApplyJournalEntries.class);
    assertEquals(2, leaderActorContext.getLastApplied());
    assertEquals(2, applyJournalEntries.getToIndex());
    List<ApplyState> applyStateList = MessageCollectorActor.getAllMatching(leaderActor, ApplyState.class);
    assertEquals(1, applyStateList.size());
    ApplyState applyState = applyStateList.get(0);
    assertEquals(2, applyState.getReplicatedLogEntry().getIndex());
    assertEquals(2, followerInfo.getMatchIndex());
    assertEquals(3, followerInfo.getNextIndex());
    assertEquals(payloadVersion, followerInfo.getPayloadVersion());
    assertEquals(RaftVersions.CURRENT_VERSION, followerInfo.getRaftVersion());
}
Also used : FollowerLogInformation(org.opendaylight.controller.cluster.raft.FollowerLogInformation) AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) ApplyJournalEntries(org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries) ApplyState(org.opendaylight.controller.cluster.raft.base.messages.ApplyState) Test(org.junit.Test)

Example 28 with MockRaftActorContext

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

the class LeaderTest method testMultipleReplicateShouldNotCauseDuplicateAppendEntriesToBeSent.

@Test
public void testMultipleReplicateShouldNotCauseDuplicateAppendEntriesToBeSent() throws Exception {
    logStart("testHandleReplicateMessageSendAppendEntriesToFollower");
    MockRaftActorContext actorContext = createActorContextWithFollower();
    actorContext.setConfigParams(new DefaultConfigParamsImpl() {

        @Override
        public FiniteDuration getHeartBeatInterval() {
            return FiniteDuration.apply(5, TimeUnit.SECONDS);
        }
    });
    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();
    for (int i = 0; i < 5; i++) {
        sendReplicate(actorContext, lastIndex + i + 1);
    }
    List<AppendEntries> allMessages = MessageCollectorActor.getAllMatching(followerActor, AppendEntries.class);
    // We expect only 1 message to be sent because of two reasons,
    // - an append entries reply was not received
    // - the heartbeat interval has not expired
    // In this scenario if multiple messages are sent they would likely be duplicates
    assertEquals("The number of append entries collected should be 1", 1, allMessages.size());
}
Also used : AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) 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) Test(org.junit.Test)

Example 29 with MockRaftActorContext

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

the class LeaderTest method testTransferLeadershipWithFollowerInSync.

@Test
public void testTransferLeadershipWithFollowerInSync() {
    logStart("testTransferLeadershipWithFollowerInSync");
    MockRaftActorContext leaderActorContext = createActorContextWithFollower();
    leaderActorContext.setLastApplied(-1);
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(1000, TimeUnit.SECONDS));
    leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().build());
    leader = new Leader(leaderActorContext);
    leaderActorContext.setCurrentBehavior(leader);
    // Initial heartbeat
    MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    leader.handleMessage(leaderActor, new AppendEntriesReply(FOLLOWER_ID, 1, true, -1, -1, (short) 0));
    MessageCollectorActor.clearMessages(followerActor);
    sendReplicate(leaderActorContext, 0);
    MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    leader.handleMessage(leaderActor, new AppendEntriesReply(FOLLOWER_ID, 1, true, 0, 1, (short) 0));
    MessageCollectorActor.expectFirstMatching(leaderActor, ApplyState.class);
    MessageCollectorActor.clearMessages(followerActor);
    RaftActorLeadershipTransferCohort mockTransferCohort = mock(RaftActorLeadershipTransferCohort.class);
    leader.transferLeadership(mockTransferCohort);
    verify(mockTransferCohort, never()).transferComplete();
    doReturn(Optional.absent()).when(mockTransferCohort).getRequestedFollowerId();
    MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    leader.handleMessage(leaderActor, new AppendEntriesReply(FOLLOWER_ID, 1, true, 0, 1, (short) 0));
    // Expect a final AppendEntries to ensure the follower's lastApplied index is up-to-date
    MessageCollectorActor.expectMatching(followerActor, AppendEntries.class, 2);
    // Leader should force an election timeout
    MessageCollectorActor.expectFirstMatching(followerActor, TimeoutNow.class);
    verify(mockTransferCohort).transferComplete();
}
Also used : AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) FiniteDuration(scala.concurrent.duration.FiniteDuration) DefaultConfigParamsImpl(org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl) RaftActorLeadershipTransferCohort(org.opendaylight.controller.cluster.raft.RaftActorLeadershipTransferCohort) Test(org.junit.Test)

Example 30 with MockRaftActorContext

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

the class LeaderTest method testInstallSnapshot.

@Test
public void testInstallSnapshot() throws Exception {
    logStart("testInstallSnapshot");
    final MockRaftActorContext actorContext = createActorContextWithFollower();
    Map<String, String> leadersSnapshot = new HashMap<>();
    leadersSnapshot.put("1", "A");
    leadersSnapshot.put("2", "B");
    leadersSnapshot.put("3", "C");
    // clears leaders log
    actorContext.getReplicatedLog().removeFrom(0);
    final int lastAppliedIndex = 3;
    final int snapshotIndex = 2;
    final int snapshotTerm = 1;
    final int currentTerm = 2;
    // set the snapshot variables in replicatedlog
    actorContext.getReplicatedLog().setSnapshotIndex(snapshotIndex);
    actorContext.getReplicatedLog().setSnapshotTerm(snapshotTerm);
    actorContext.getTermInformation().update(currentTerm, leaderActor.path().toString());
    actorContext.setCommitIndex(lastAppliedIndex);
    actorContext.setLastApplied(lastAppliedIndex);
    leader = new Leader(actorContext);
    // Initial heartbeat.
    MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    leader.getFollower(FOLLOWER_ID).setMatchIndex(-1);
    leader.getFollower(FOLLOWER_ID).setNextIndex(0);
    byte[] bytes = toByteString(leadersSnapshot).toByteArray();
    Snapshot snapshot = Snapshot.create(ByteState.of(bytes), Collections.<ReplicatedLogEntry>emptyList(), lastAppliedIndex, snapshotTerm, lastAppliedIndex, snapshotTerm, -1, null, null);
    RaftActorBehavior raftBehavior = leader.handleMessage(leaderActor, new SendInstallSnapshot(snapshot, ByteSource.wrap(bytes)));
    assertTrue(raftBehavior instanceof Leader);
    // check if installsnapshot gets called with the correct values.
    InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
    assertNotNull(installSnapshot.getData());
    assertEquals(lastAppliedIndex, installSnapshot.getLastIncludedIndex());
    assertEquals(snapshotTerm, installSnapshot.getLastIncludedTerm());
    assertEquals(currentTerm, installSnapshot.getTerm());
}
Also used : 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) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) HashMap(java.util.HashMap) MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext) ByteString(com.google.protobuf.ByteString) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) SendInstallSnapshot(org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot) 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