Search in sources :

Example 66 with MockRaftActorContext

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

the class LeaderTest method testHandleAppendEntriesReplyFailureWithFollowersLogBehindTheLeader.

@Test
public void testHandleAppendEntriesReplyFailureWithFollowersLogBehindTheLeader() {
    logStart("testHandleAppendEntriesReplyFailureWithFollowersLogBehindTheLeader");
    MockRaftActorContext leaderActorContext = createActorContextWithFollower();
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(1000, TimeUnit.SECONDS));
    leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 3, 1).build());
    long leaderCommitIndex = 2;
    leaderActorContext.setCommitIndex(leaderCommitIndex);
    leaderActorContext.setLastApplied(leaderCommitIndex);
    final ReplicatedLogEntry leadersSecondLogEntry = leaderActorContext.getReplicatedLog().get(1);
    final ReplicatedLogEntry leadersThirdLogEntry = leaderActorContext.getReplicatedLog().get(2);
    MockRaftActorContext followerActorContext = createFollowerActorContextWithLeader();
    followerActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 1, 1).build());
    followerActorContext.setCommitIndex(0);
    followerActorContext.setLastApplied(0);
    Follower follower = new Follower(followerActorContext);
    followerActor.underlyingActor().setBehavior(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.
    assertEquals("getLeaderCommit", -1, appendEntries.getLeaderCommit());
    assertEquals("Log entries size", 0, appendEntries.getEntries().size());
    assertEquals("getPrevLogIndex", 1, appendEntries.getPrevLogIndex());
    leaderActor.underlyingActor().setBehavior(leader);
    leader.handleMessage(followerActor, appendEntriesReply);
    MessageCollectorActor.expectMatching(leaderActor, AppendEntriesReply.class, 1);
    appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
    assertEquals("getLeaderCommit", leaderCommitIndex, appendEntries.getLeaderCommit());
    assertEquals("getPrevLogIndex", 0, appendEntries.getPrevLogIndex());
    assertEquals("Log entries size", 2, appendEntries.getEntries().size());
    assertEquals("First entry index", 1, appendEntries.getEntries().get(0).getIndex());
    assertEquals("First entry data", leadersSecondLogEntry.getData(), appendEntries.getEntries().get(0).getData());
    assertEquals("Second entry index", 2, appendEntries.getEntries().get(1).getIndex());
    assertEquals("Second entry data", leadersThirdLogEntry.getData(), appendEntries.getEntries().get(1).getData());
    FollowerLogInformation followerInfo = leader.getFollower(FOLLOWER_ID);
    assertEquals("getNextIndex", 3, followerInfo.getNextIndex());
    List<ApplyState> applyStateList = MessageCollectorActor.expectMatching(followerActor, ApplyState.class, 2);
    ApplyState applyState = applyStateList.get(0);
    assertEquals("Follower's first ApplyState index", 1, applyState.getReplicatedLogEntry().getIndex());
    assertEquals("Follower's first ApplyState term", 1, applyState.getReplicatedLogEntry().getTerm());
    assertEquals("Follower's first ApplyState data", leadersSecondLogEntry.getData(), applyState.getReplicatedLogEntry().getData());
    applyState = applyStateList.get(1);
    assertEquals("Follower's second ApplyState index", 2, applyState.getReplicatedLogEntry().getIndex());
    assertEquals("Follower's second ApplyState term", 1, applyState.getReplicatedLogEntry().getTerm());
    assertEquals("Follower's second ApplyState data", leadersThirdLogEntry.getData(), applyState.getReplicatedLogEntry().getData());
    assertEquals("Follower's commit index", 2, followerActorContext.getCommitIndex());
    assertEquals("Follower's lastIndex", 2, followerActorContext.getReplicatedLog().lastIndex());
}
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 67 with MockRaftActorContext

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

the class LeaderTest method testHandleAppendEntriesReplyFailureWithFollowersLogEmpty.

@Test
public void testHandleAppendEntriesReplyFailureWithFollowersLogEmpty() {
    logStart("testHandleAppendEntriesReplyFailureWithFollowersLogEmpty");
    MockRaftActorContext leaderActorContext = createActorContextWithFollower();
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(1000, TimeUnit.SECONDS));
    leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).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().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 data", leadersFirstLogEntry.getData(), appendEntries.getEntries().get(0).getData());
    assertEquals("Second entry index", 1, appendEntries.getEntries().get(1).getIndex());
    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", 1, 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", 1, 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());
}
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 68 with MockRaftActorContext

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

the class LeaderTest method createActorContextWithFollower.

private MockRaftActorContext createActorContextWithFollower() {
    MockRaftActorContext actorContext = createActorContext();
    actorContext.setPeerAddresses(ImmutableMap.<String, String>builder().put(FOLLOWER_ID, followerActor.path().toString()).build());
    return actorContext;
}
Also used : MockRaftActorContext(org.opendaylight.controller.cluster.raft.MockRaftActorContext)

Example 69 with MockRaftActorContext

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

the class LeaderTest method testTransferLeadershipWithFollowerSyncTimeout.

@Test
public void testTransferLeadershipWithFollowerSyncTimeout() {
    logStart("testTransferLeadershipWithFollowerSyncTimeout");
    MockRaftActorContext leaderActorContext = createActorContextWithFollower();
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(200, TimeUnit.MILLISECONDS));
    ((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setElectionTimeoutFactor(2);
    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);
    MessageCollectorActor.clearMessages(followerActor);
    RaftActorLeadershipTransferCohort mockTransferCohort = mock(RaftActorLeadershipTransferCohort.class);
    leader.transferLeadership(mockTransferCohort);
    verify(mockTransferCohort, never()).transferComplete();
    // Send heartbeats to time out the transfer.
    for (int i = 0; i < leaderActorContext.getConfigParams().getElectionTimeoutFactor(); i++) {
        Uninterruptibles.sleepUninterruptibly(leaderActorContext.getConfigParams().getHeartBeatInterval().toMillis() + 1, TimeUnit.MILLISECONDS);
        leader.handleMessage(leaderActor, SendHeartBeat.INSTANCE);
    }
    verify(mockTransferCohort).abortTransfer();
    verify(mockTransferCohort, never()).transferComplete();
    MessageCollectorActor.assertNoneMatching(followerActor, ElectionTimeout.class, 100);
}
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 70 with MockRaftActorContext

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

the class LeaderTest method testMultipleReplicateWithReplyShouldResultInAppendEntries.

@Test
public void testMultipleReplicateWithReplyShouldResultInAppendEntries() throws Exception {
    logStart("testMultipleReplicateWithReplyShouldResultInAppendEntries");
    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 < 3; i++) {
        sendReplicate(actorContext, lastIndex + i + 1);
        leader.handleMessage(followerActor, new AppendEntriesReply(FOLLOWER_ID, term, true, lastIndex + i + 1, term, (short) 0));
    }
    for (int i = 3; i < 5; i++) {
        sendReplicate(actorContext, lastIndex + i + 1);
    }
    List<AppendEntries> allMessages = MessageCollectorActor.getAllMatching(followerActor, AppendEntries.class);
    // We expect 4 here because the first 3 replicate got a reply and so the 4th entry would
    // get sent to the follower - but not the 5th
    assertEquals("The number of append entries collected should be 4", 4, allMessages.size());
    for (int i = 0; i < 4; i++) {
        long expected = allMessages.get(i).getEntries().get(0).getIndex();
        assertEquals(expected, i + 2);
    }
}
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)

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