Search in sources :

Example 1 with UpdateElectionTerm

use of org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm in project controller by opendaylight.

the class FollowerTest method testCaptureSnapshotOnAppendEntriesWithUnapplied.

@Test
public void testCaptureSnapshotOnAppendEntriesWithUnapplied() {
    String id = "testCaptureSnapshotOnAppendEntriesWithUnapplied";
    logStart(id);
    InMemoryJournal.addEntry(id, 1, new UpdateElectionTerm(1, null));
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setSnapshotBatchCount(1);
    config.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName());
    final AtomicReference<MockRaftActor> followerRaftActor = new AtomicReference<>();
    RaftActorSnapshotCohort snapshotCohort = newRaftActorSnapshotCohort(followerRaftActor);
    Builder builder = MockRaftActor.builder().persistent(Optional.of(true)).id(id).peerAddresses(ImmutableMap.of("leader", "")).config(config).snapshotCohort(snapshotCohort);
    TestActorRef<MockRaftActor> followerActorRef = actorFactory.createTestActor(builder.props().withDispatcher(Dispatchers.DefaultDispatcherId()), id);
    followerRaftActor.set(followerActorRef.underlyingActor());
    followerRaftActor.get().waitForInitializeBehaviorComplete();
    InMemorySnapshotStore.addSnapshotSavedLatch(id);
    InMemoryJournal.addDeleteMessagesCompleteLatch(id);
    InMemoryJournal.addWriteMessagesCompleteLatch(id, 1, ApplyJournalEntries.class);
    List<ReplicatedLogEntry> entries = Arrays.asList(newReplicatedLogEntry(1, 0, "one"), newReplicatedLogEntry(1, 1, "two"), newReplicatedLogEntry(1, 2, "three"));
    AppendEntries appendEntries = new AppendEntries(1, "leader", -1, -1, entries, 0, -1, (short) 0);
    followerActorRef.tell(appendEntries, leaderActor);
    AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(leaderActor, AppendEntriesReply.class);
    assertEquals("isSuccess", true, reply.isSuccess());
    final Snapshot snapshot = InMemorySnapshotStore.waitForSavedSnapshot(id, Snapshot.class);
    InMemoryJournal.waitForDeleteMessagesComplete(id);
    InMemoryJournal.waitForWriteMessagesComplete(id);
    // We expect the ApplyJournalEntries for index 0 to remain in the persisted log b/c it's still queued for
    // persistence by the time we initiate capture so the last persisted journal sequence number doesn't include it.
    // This is OK - on recovery it will be a no-op since index 0 has already been applied.
    List<Object> journalEntries = InMemoryJournal.get(id, Object.class);
    assertEquals("Persisted journal entries size: " + journalEntries, 1, journalEntries.size());
    assertEquals("Persisted journal entry type", ApplyJournalEntries.class, journalEntries.get(0).getClass());
    assertEquals("ApplyJournalEntries index", 0, ((ApplyJournalEntries) journalEntries.get(0)).getToIndex());
    assertEquals("Snapshot unapplied size", 2, snapshot.getUnAppliedEntries().size());
    assertEquals("Snapshot unapplied entry index", 1, snapshot.getUnAppliedEntries().get(0).getIndex());
    assertEquals("Snapshot unapplied entry index", 2, snapshot.getUnAppliedEntries().get(1).getIndex());
    assertEquals("Snapshot getLastAppliedTerm", 1, snapshot.getLastAppliedTerm());
    assertEquals("Snapshot getLastAppliedIndex", 0, snapshot.getLastAppliedIndex());
    assertEquals("Snapshot getLastTerm", 1, snapshot.getLastTerm());
    assertEquals("Snapshot getLastIndex", 2, snapshot.getLastIndex());
    assertEquals("Snapshot state", ImmutableList.of(entries.get(0).getData()), MockRaftActor.fromState(snapshot.getState()));
}
Also used : Builder(org.opendaylight.controller.cluster.raft.MockRaftActor.Builder) DefaultConfigParamsImpl(org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl) AtomicReference(java.util.concurrent.atomic.AtomicReference) ByteString(com.google.protobuf.ByteString) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) MockRaftActor(org.opendaylight.controller.cluster.raft.MockRaftActor) 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) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ReplicatedLogEntry(org.opendaylight.controller.cluster.raft.ReplicatedLogEntry) RaftActorSnapshotCohort(org.opendaylight.controller.cluster.raft.RaftActorSnapshotCohort) AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply) DisableElectionsRaftPolicy(org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy) UpdateElectionTerm(org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm) Test(org.junit.Test)

Example 2 with UpdateElectionTerm

use of org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm in project controller by opendaylight.

the class RaftActorTest method testRaftActorForwardsToRaftActorRecoverySupport.

@Test
public void testRaftActorForwardsToRaftActorRecoverySupport() {
    String persistenceId = factory.generateActorId("leader-");
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
    TestActorRef<MockRaftActor> mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, Collections.<String, String>emptyMap(), config), persistenceId);
    MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
    // Wait for akka's recovery to complete so it doesn't interfere.
    mockRaftActor.waitForRecoveryComplete();
    RaftActorRecoverySupport mockSupport = mock(RaftActorRecoverySupport.class);
    mockRaftActor.setRaftActorRecoverySupport(mockSupport);
    Snapshot snapshot = Snapshot.create(ByteState.of(new byte[] { 1 }), Collections.<ReplicatedLogEntry>emptyList(), 3, 1, 3, 1, -1, null, null);
    SnapshotOffer snapshotOffer = new SnapshotOffer(new SnapshotMetadata("test", 6, 12345), snapshot);
    mockRaftActor.handleRecover(snapshotOffer);
    ReplicatedLogEntry logEntry = new SimpleReplicatedLogEntry(1, 1, new MockRaftActorContext.MockPayload("1", 5));
    mockRaftActor.handleRecover(logEntry);
    ApplyJournalEntries applyJournalEntries = new ApplyJournalEntries(2);
    mockRaftActor.handleRecover(applyJournalEntries);
    DeleteEntries deleteEntries = new DeleteEntries(1);
    mockRaftActor.handleRecover(deleteEntries);
    UpdateElectionTerm updateElectionTerm = new UpdateElectionTerm(5, "member2");
    mockRaftActor.handleRecover(updateElectionTerm);
    verify(mockSupport).handleRecoveryMessage(same(snapshotOffer), any(PersistentDataProvider.class));
    verify(mockSupport).handleRecoveryMessage(same(logEntry), any(PersistentDataProvider.class));
    verify(mockSupport).handleRecoveryMessage(same(applyJournalEntries), any(PersistentDataProvider.class));
    verify(mockSupport).handleRecoveryMessage(same(deleteEntries), any(PersistentDataProvider.class));
    verify(mockSupport).handleRecoveryMessage(same(updateElectionTerm), any(PersistentDataProvider.class));
}
Also used : DeleteEntries(org.opendaylight.controller.cluster.raft.persisted.DeleteEntries) FiniteDuration(scala.concurrent.duration.FiniteDuration) MockPayload(org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload) ByteString(com.google.protobuf.ByteString) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) GetSnapshot(org.opendaylight.controller.cluster.raft.client.messages.GetSnapshot) PersistentDataProvider(org.opendaylight.controller.cluster.PersistentDataProvider) NonPersistentDataProvider(org.opendaylight.controller.cluster.NonPersistentDataProvider) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) SnapshotMetadata(akka.persistence.SnapshotMetadata) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ApplyJournalEntries(org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries) SnapshotOffer(akka.persistence.SnapshotOffer) UpdateElectionTerm(org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm) Test(org.junit.Test)

Example 3 with UpdateElectionTerm

use of org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm in project controller by opendaylight.

the class RaftActorTest method testUpdateElectionTermPersistedWithPersistenceDisabled.

@Test
public void testUpdateElectionTermPersistedWithPersistenceDisabled() throws Exception {
    final TestKit kit = new TestKit(getSystem());
    String persistenceId = factory.generateActorId("follower-");
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setHeartBeatInterval(new FiniteDuration(100, TimeUnit.MILLISECONDS));
    config.setElectionTimeoutFactor(1);
    InMemoryJournal.addWriteMessagesCompleteLatch(persistenceId, 1);
    TestActorRef<MockRaftActor> ref = factory.createTestActor(MockRaftActor.props(persistenceId, ImmutableMap.<String, String>builder().put("member1", "address").build(), config, createProvider()).withDispatcher(Dispatchers.DefaultDispatcherId()), persistenceId);
    InMemoryJournal.waitForWriteMessagesComplete(persistenceId);
    List<UpdateElectionTerm> entries = InMemoryJournal.get(persistenceId, UpdateElectionTerm.class);
    assertEquals("UpdateElectionTerm entries", 1, entries.size());
    final UpdateElectionTerm updateEntry = entries.get(0);
    factory.killActor(ref, kit);
    config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
    ref = factory.createTestActor(MockRaftActor.props(persistenceId, ImmutableMap.<String, String>builder().put("member1", "address").build(), config, createProvider()).withDispatcher(Dispatchers.DefaultDispatcherId()), factory.generateActorId("follower-"));
    MockRaftActor actor = ref.underlyingActor();
    actor.waitForRecoveryComplete();
    RaftActorContext newContext = actor.getRaftActorContext();
    assertEquals("electionTerm", updateEntry.getCurrentTerm(), newContext.getTermInformation().getCurrentTerm());
    assertEquals("votedFor", updateEntry.getVotedFor(), newContext.getTermInformation().getVotedFor());
    entries = InMemoryJournal.get(persistenceId, UpdateElectionTerm.class);
    assertEquals("UpdateElectionTerm entries", 1, entries.size());
}
Also used : FiniteDuration(scala.concurrent.duration.FiniteDuration) TestKit(akka.testkit.javadsl.TestKit) ByteString(com.google.protobuf.ByteString) UpdateElectionTerm(org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm) Test(org.junit.Test)

Example 4 with UpdateElectionTerm

use of org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm in project controller by opendaylight.

the class RaftActorTest method testGetSnapshot.

@Test
public void testGetSnapshot() throws Exception {
    TEST_LOG.info("testGetSnapshot starting");
    final TestKit kit = new TestKit(getSystem());
    String persistenceId = factory.generateActorId("test-actor-");
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName());
    long term = 3;
    long seqN = 1;
    InMemoryJournal.addEntry(persistenceId, seqN++, new UpdateElectionTerm(term, "member-1"));
    InMemoryJournal.addEntry(persistenceId, seqN++, new SimpleReplicatedLogEntry(0, term, new MockRaftActorContext.MockPayload("A")));
    InMemoryJournal.addEntry(persistenceId, seqN++, new SimpleReplicatedLogEntry(1, term, new MockRaftActorContext.MockPayload("B")));
    InMemoryJournal.addEntry(persistenceId, seqN++, new ApplyJournalEntries(1));
    InMemoryJournal.addEntry(persistenceId, seqN++, new SimpleReplicatedLogEntry(2, term, new MockRaftActorContext.MockPayload("C")));
    TestActorRef<MockRaftActor> raftActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, ImmutableMap.<String, String>builder().put("member1", "address").build(), config).withDispatcher(Dispatchers.DefaultDispatcherId()), persistenceId);
    MockRaftActor mockRaftActor = raftActorRef.underlyingActor();
    mockRaftActor.waitForRecoveryComplete();
    mockRaftActor.snapshotCohortDelegate = mock(RaftActorSnapshotCohort.class);
    raftActorRef.tell(GetSnapshot.INSTANCE, kit.getRef());
    ArgumentCaptor<ActorRef> replyActor = ArgumentCaptor.forClass(ActorRef.class);
    verify(mockRaftActor.snapshotCohortDelegate, timeout(5000)).createSnapshot(replyActor.capture(), eq(java.util.Optional.empty()));
    byte[] stateSnapshot = new byte[] { 1, 2, 3 };
    replyActor.getValue().tell(new CaptureSnapshotReply(ByteState.of(stateSnapshot), java.util.Optional.empty()), ActorRef.noSender());
    GetSnapshotReply reply = kit.expectMsgClass(GetSnapshotReply.class);
    assertEquals("getId", persistenceId, reply.getId());
    Snapshot replySnapshot = reply.getSnapshot();
    assertEquals("getElectionTerm", term, replySnapshot.getElectionTerm());
    assertEquals("getElectionVotedFor", "member-1", replySnapshot.getElectionVotedFor());
    assertEquals("getLastAppliedIndex", 1L, replySnapshot.getLastAppliedIndex());
    assertEquals("getLastAppliedTerm", term, replySnapshot.getLastAppliedTerm());
    assertEquals("getLastIndex", 2L, replySnapshot.getLastIndex());
    assertEquals("getLastTerm", term, replySnapshot.getLastTerm());
    assertEquals("getState", ByteState.of(stateSnapshot), replySnapshot.getState());
    assertEquals("getUnAppliedEntries size", 1, replySnapshot.getUnAppliedEntries().size());
    assertEquals("UnApplied entry index ", 2L, replySnapshot.getUnAppliedEntries().get(0).getIndex());
    // Test with timeout
    mockRaftActor.getSnapshotMessageSupport().setSnapshotReplyActorTimeout(Duration.create(200, TimeUnit.MILLISECONDS));
    reset(mockRaftActor.snapshotCohortDelegate);
    raftActorRef.tell(GetSnapshot.INSTANCE, kit.getRef());
    Failure failure = kit.expectMsgClass(akka.actor.Status.Failure.class);
    assertEquals("Failure cause type", TimeoutException.class, failure.cause().getClass());
    mockRaftActor.getSnapshotMessageSupport().setSnapshotReplyActorTimeout(Duration.create(30, TimeUnit.SECONDS));
    // Test with persistence disabled.
    mockRaftActor.setPersistence(false);
    reset(mockRaftActor.snapshotCohortDelegate);
    raftActorRef.tell(GetSnapshot.INSTANCE, kit.getRef());
    reply = kit.expectMsgClass(GetSnapshotReply.class);
    verify(mockRaftActor.snapshotCohortDelegate, never()).createSnapshot(anyObject(), anyObject());
    assertEquals("getId", persistenceId, reply.getId());
    replySnapshot = reply.getSnapshot();
    assertEquals("getElectionTerm", term, replySnapshot.getElectionTerm());
    assertEquals("getElectionVotedFor", "member-1", replySnapshot.getElectionVotedFor());
    assertEquals("getLastAppliedIndex", -1L, replySnapshot.getLastAppliedIndex());
    assertEquals("getLastAppliedTerm", -1L, replySnapshot.getLastAppliedTerm());
    assertEquals("getLastIndex", -1L, replySnapshot.getLastIndex());
    assertEquals("getLastTerm", -1L, replySnapshot.getLastTerm());
    assertEquals("getState type", EmptyState.INSTANCE, replySnapshot.getState());
    assertEquals("getUnAppliedEntries size", 0, replySnapshot.getUnAppliedEntries().size());
    TEST_LOG.info("testGetSnapshot ending");
}
Also used : CaptureSnapshotReply(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) TestKit(akka.testkit.javadsl.TestKit) ByteString(com.google.protobuf.ByteString) MockPayload(org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) GetSnapshot(org.opendaylight.controller.cluster.raft.client.messages.GetSnapshot) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) DisableElectionsRaftPolicy(org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy) ApplyJournalEntries(org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries) UpdateElectionTerm(org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm) SaveSnapshotFailure(akka.persistence.SaveSnapshotFailure) Failure(akka.actor.Status.Failure) GetSnapshotReply(org.opendaylight.controller.cluster.raft.client.messages.GetSnapshotReply) Test(org.junit.Test)

Example 5 with UpdateElectionTerm

use of org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm in project controller by opendaylight.

the class ReplicationAndSnapshotsWithLaggingFollowerIntegrationTest method setup.

private void setup() {
    leaderId = factory.generateActorId("leader");
    follower1Id = factory.generateActorId("follower");
    follower2Id = factory.generateActorId("follower");
    // Setup the persistent journal for the leader - just an election term and no journal/snapshots.
    InMemoryJournal.addEntry(leaderId, 1, new UpdateElectionTerm(initialTerm, leaderId));
    // Create the leader and 2 follower actors.
    follower1Actor = newTestRaftActor(follower1Id, ImmutableMap.of(leaderId, testActorPath(leaderId), follower2Id, testActorPath(follower2Id)), newFollowerConfigParams());
    follower2Actor = newTestRaftActor(follower2Id, ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, testActorPath(follower1Id)), newFollowerConfigParams());
    Map<String, String> leaderPeerAddresses = ImmutableMap.<String, String>builder().put(follower1Id, follower1Actor.path().toString()).put(follower2Id, follower2Actor.path().toString()).build();
    leaderConfigParams = newLeaderConfigParams();
    leaderActor = newTestRaftActor(leaderId, leaderPeerAddresses, leaderConfigParams);
    waitUntilLeader(leaderActor);
    leaderContext = leaderActor.underlyingActor().getRaftActorContext();
    leader = leaderActor.underlyingActor().getCurrentBehavior();
    follower1Context = follower1Actor.underlyingActor().getRaftActorContext();
    follower1 = follower1Actor.underlyingActor().getCurrentBehavior();
    follower2Context = follower2Actor.underlyingActor().getRaftActorContext();
    follower2 = follower2Actor.underlyingActor().getCurrentBehavior();
    currentTerm = leaderContext.getTermInformation().getCurrentTerm();
    assertEquals("Current term > " + initialTerm, true, currentTerm > initialTerm);
    leaderCollectorActor = leaderActor.underlyingActor().collectorActor();
    follower1CollectorActor = follower1Actor.underlyingActor().collectorActor();
    follower2CollectorActor = follower2Actor.underlyingActor().collectorActor();
    testLog.info("Leader created and elected");
}
Also used : UpdateElectionTerm(org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm)

Aggregations

UpdateElectionTerm (org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm)21 Test (org.junit.Test)17 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)15 ApplyJournalEntries (org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries)8 DisableElectionsRaftPolicy (org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy)8 ApplySnapshot (org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)7 ServerConfigurationPayload (org.opendaylight.controller.cluster.raft.persisted.ServerConfigurationPayload)7 ServerInfo (org.opendaylight.controller.cluster.raft.persisted.ServerInfo)7 ActorRef (akka.actor.ActorRef)6 TestActorRef (akka.testkit.TestActorRef)6 ByteString (com.google.protobuf.ByteString)6 AppendEntries (org.opendaylight.controller.cluster.raft.messages.AppendEntries)6 Snapshot (org.opendaylight.controller.cluster.raft.persisted.Snapshot)6 FiniteDuration (scala.concurrent.duration.FiniteDuration)6 TestKit (akka.testkit.javadsl.TestKit)5 InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)5 ChangeServersVotingStatus (org.opendaylight.controller.cluster.raft.messages.ChangeServersVotingStatus)4 ServerChangeReply (org.opendaylight.controller.cluster.raft.messages.ServerChangeReply)4 Optional (com.google.common.base.Optional)3 ByteSource (com.google.common.io.ByteSource)3