Search in sources :

Example 6 with ApplySnapshot

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

the class RaftActorSnapshotMessageSupportTest method testOnApplySnapshot.

@Test
public void testOnApplySnapshot() {
    long lastAppliedDuringSnapshotCapture = 1;
    long lastIndexDuringSnapshotCapture = 2;
    byte[] snapshotBytes = { 1, 2, 3, 4, 5 };
    Snapshot snapshot = Snapshot.create(ByteState.of(snapshotBytes), Collections.<ReplicatedLogEntry>emptyList(), lastIndexDuringSnapshotCapture, 1, lastAppliedDuringSnapshotCapture, 1, -1, null, null);
    ApplySnapshot applySnapshot = new ApplySnapshot(snapshot);
    sendMessageToSupport(applySnapshot);
    verify(mockSnapshotManager).apply(applySnapshot);
}
Also used : ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Test(org.junit.Test)

Example 7 with ApplySnapshot

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

the class RaftActorServerConfigurationSupportTest method testAddServerWithExistingFollower.

@Test
public void testAddServerWithExistingFollower() throws Exception {
    LOG.info("testAddServerWithExistingFollower starting");
    setupNewFollower();
    RaftActorContextImpl followerActorContext = newFollowerContext(FOLLOWER_ID, followerActor);
    followerActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 3, 1).build());
    followerActorContext.setCommitIndex(2);
    followerActorContext.setLastApplied(2);
    Follower follower = new Follower(followerActorContext);
    followerActor.underlyingActor().setBehavior(follower);
    followerActorContext.setCurrentBehavior(follower);
    TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.of(FOLLOWER_ID, followerActor.path().toString()), followerActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
    // Expect initial heartbeat from the leader.
    expectFirstMatching(followerActor, AppendEntries.class);
    clearMessages(followerActor);
    MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
    final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
    leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
    // Leader should install snapshot - capture and verify ApplySnapshot contents
    ApplySnapshot applySnapshot = expectFirstMatching(newFollowerCollectorActor, ApplySnapshot.class);
    List<Object> snapshotState = MockRaftActor.fromState(applySnapshot.getSnapshot().getState());
    assertEquals("Snapshot state", snapshotState, leaderRaftActor.getState());
    AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
    assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
    assertEquals("getLeaderHint", LEADER_ID, addServerReply.getLeaderHint().get());
    // Verify ServerConfigurationPayload entry in leader's log
    expectFirstMatching(leaderCollectorActor, ApplyState.class);
    RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
    assertEquals("Leader journal last index", 3, leaderActorContext.getReplicatedLog().lastIndex());
    assertEquals("Leader commit index", 3, leaderActorContext.getCommitIndex());
    assertEquals("Leader last applied index", 3, leaderActorContext.getLastApplied());
    verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(FOLLOWER_ID), votingServer(NEW_SERVER_ID));
    // Verify ServerConfigurationPayload entry in both followers
    expectFirstMatching(followerActor, ApplyState.class);
    assertEquals("Follower journal last index", 3, followerActorContext.getReplicatedLog().lastIndex());
    verifyServerConfigurationPayloadEntry(followerActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(FOLLOWER_ID), votingServer(NEW_SERVER_ID));
    expectFirstMatching(newFollowerCollectorActor, ApplyState.class);
    assertEquals("New follower journal last index", 3, newFollowerActorContext.getReplicatedLog().lastIndex());
    verifyServerConfigurationPayloadEntry(newFollowerActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(FOLLOWER_ID), votingServer(NEW_SERVER_ID));
    // Verify new server config was applied in both followers
    assertEquals("Follower peers", Sets.newHashSet(LEADER_ID, NEW_SERVER_ID), followerActorContext.getPeerIds());
    assertEquals("New follower peers", Sets.newHashSet(LEADER_ID, FOLLOWER_ID), newFollowerActorContext.getPeerIds());
    assertEquals("Follower commit index", 3, followerActorContext.getCommitIndex());
    assertEquals("Follower last applied index", 3, followerActorContext.getLastApplied());
    assertEquals("New follower commit index", 3, newFollowerActorContext.getCommitIndex());
    assertEquals("New follower last applied index", 3, newFollowerActorContext.getLastApplied());
    assertEquals("Leader persisted ReplicatedLogImplEntry entries", 0, InMemoryJournal.get(LEADER_ID, SimpleReplicatedLogEntry.class).size());
    assertEquals("Leader persisted ServerConfigurationPayload entries", 1, InMemoryJournal.get(LEADER_ID, ServerConfigurationPayload.class).size());
    assertEquals("New follower persisted ReplicatedLogImplEntry entries", 0, InMemoryJournal.get(NEW_SERVER_ID, SimpleReplicatedLogEntry.class).size());
    assertEquals("New follower persisted ServerConfigurationPayload entries", 1, InMemoryJournal.get(NEW_SERVER_ID, ServerConfigurationPayload.class).size());
    LOG.info("testAddServerWithExistingFollower ending");
}
Also used : ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) Follower(org.opendaylight.controller.cluster.raft.behaviors.Follower) AddServer(org.opendaylight.controller.cluster.raft.messages.AddServer) AddServerReply(org.opendaylight.controller.cluster.raft.messages.AddServerReply) Test(org.junit.Test)

Example 8 with ApplySnapshot

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

the class RaftActorTest method testRestoreFromSnapshotWithRecoveredData.

@Test
public void testRestoreFromSnapshotWithRecoveredData() throws Exception {
    TEST_LOG.info("testRestoreFromSnapshotWithRecoveredData starting");
    String persistenceId = factory.generateActorId("test-actor-");
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName());
    List<MockPayload> state = Arrays.asList(new MockRaftActorContext.MockPayload("A"));
    Snapshot snapshot = Snapshot.create(ByteState.of(fromObject(state).toByteArray()), Arrays.<ReplicatedLogEntry>asList(), 5, 2, 5, 2, 2, "member-1", null);
    InMemoryJournal.addEntry(persistenceId, 1, new SimpleReplicatedLogEntry(0, 1, new MockRaftActorContext.MockPayload("B")));
    TestActorRef<MockRaftActor> raftActorRef = factory.createTestActor(MockRaftActor.builder().id(persistenceId).config(config).restoreFromSnapshot(snapshot).props().withDispatcher(Dispatchers.DefaultDispatcherId()), persistenceId);
    MockRaftActor mockRaftActor = raftActorRef.underlyingActor();
    mockRaftActor.waitForRecoveryComplete();
    Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
    verify(mockRaftActor.snapshotCohortDelegate, never()).applySnapshot(any(Snapshot.State.class));
    RaftActorContext context = mockRaftActor.getRaftActorContext();
    assertEquals("Journal log size", 1, context.getReplicatedLog().size());
    assertEquals("Last index", 0, context.getReplicatedLog().lastIndex());
    assertEquals("Last applied", -1, context.getLastApplied());
    assertEquals("Commit index", -1, context.getCommitIndex());
    assertEquals("Current term", 0, context.getTermInformation().getCurrentTerm());
    assertEquals("Voted for", null, context.getTermInformation().getVotedFor());
    TEST_LOG.info("testRestoreFromSnapshotWithRecoveredData ending");
}
Also used : MockPayload(org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload) 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) EmptyState(org.opendaylight.controller.cluster.raft.persisted.EmptyState) ApplyState(org.opendaylight.controller.cluster.raft.base.messages.ApplyState) MockSnapshotState(org.opendaylight.controller.cluster.raft.MockRaftActor.MockSnapshotState) ByteState(org.opendaylight.controller.cluster.raft.persisted.ByteState) DisableElectionsRaftPolicy(org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy) Test(org.junit.Test)

Example 9 with ApplySnapshot

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

the class ReplicationAndSnapshotsWithLaggingFollowerIntegrationTest method verifyInstallSnapshotToLaggingFollower.

/**
 * Resume the lagging follower 2 and verify it receives an install snapshot from the leader.
 */
private void verifyInstallSnapshotToLaggingFollower(long lastAppliedIndex, @Nullable ServerConfigurationPayload expServerConfig) throws Exception {
    testLog.info("verifyInstallSnapshotToLaggingFollower starting");
    MessageCollectorActor.clearMessages(leaderCollectorActor);
    // Now stop dropping AppendEntries in follower 2.
    follower2Actor.underlyingActor().stopDropMessages(AppendEntries.class);
    MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
    // Verify the leader's persisted snapshot. The previous snapshot (currently) won't be deleted from
    // the snapshot store because the second snapshot was initiated by the follower install snapshot and
    // not because the batch count was reached so the persisted journal sequence number wasn't advanced
    // far enough to cause the previous snapshot to be deleted. This is because
    // RaftActor#trimPersistentData subtracts the snapshotBatchCount from the snapshot's sequence number.
    // This is OK - the next snapshot should delete it. In production, even if the system restarted
    // before another snapshot, they would both get applied which wouldn't hurt anything.
    List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
    Assert.assertTrue("Expected at least 1 persisted snapshots", persistedSnapshots.size() > 0);
    Snapshot persistedSnapshot = persistedSnapshots.get(persistedSnapshots.size() - 1);
    verifySnapshot("Persisted", persistedSnapshot, currentTerm, lastAppliedIndex, currentTerm, lastAppliedIndex);
    List<ReplicatedLogEntry> unAppliedEntry = persistedSnapshot.getUnAppliedEntries();
    assertEquals("Persisted Snapshot getUnAppliedEntries size", 0, unAppliedEntry.size());
    int snapshotSize = SerializationUtils.serialize(persistedSnapshot.getState()).length;
    final int expTotalChunks = snapshotSize / SNAPSHOT_CHUNK_SIZE + (snapshotSize % SNAPSHOT_CHUNK_SIZE > 0 ? 1 : 0);
    InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, InstallSnapshot.class);
    assertEquals("InstallSnapshot getTerm", currentTerm, installSnapshot.getTerm());
    assertEquals("InstallSnapshot getLeaderId", leaderId, installSnapshot.getLeaderId());
    assertEquals("InstallSnapshot getChunkIndex", 1, installSnapshot.getChunkIndex());
    assertEquals("InstallSnapshot getTotalChunks", expTotalChunks, installSnapshot.getTotalChunks());
    assertEquals("InstallSnapshot getLastIncludedTerm", currentTerm, installSnapshot.getLastIncludedTerm());
    assertEquals("InstallSnapshot getLastIncludedIndex", lastAppliedIndex, installSnapshot.getLastIncludedIndex());
    // assertArrayEquals("InstallSnapshot getData", snapshot, installSnapshot.getData().toByteArray());
    List<InstallSnapshotReply> installSnapshotReplies = MessageCollectorActor.expectMatching(leaderCollectorActor, InstallSnapshotReply.class, expTotalChunks);
    int index = 1;
    for (InstallSnapshotReply installSnapshotReply : installSnapshotReplies) {
        assertEquals("InstallSnapshotReply getTerm", currentTerm, installSnapshotReply.getTerm());
        assertEquals("InstallSnapshotReply getChunkIndex", index++, installSnapshotReply.getChunkIndex());
        assertEquals("InstallSnapshotReply getFollowerId", follower2Id, installSnapshotReply.getFollowerId());
        assertEquals("InstallSnapshotReply isSuccess", true, installSnapshotReply.isSuccess());
    }
    // Verify follower 2 applies the snapshot.
    ApplySnapshot applySnapshot = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, ApplySnapshot.class);
    verifySnapshot("Follower 2", applySnapshot.getSnapshot(), currentTerm, lastAppliedIndex, currentTerm, lastAppliedIndex);
    assertEquals("Persisted Snapshot getUnAppliedEntries size", 0, applySnapshot.getSnapshot().getUnAppliedEntries().size());
    // Wait for the snapshot to complete.
    MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
    // Ensure there's at least 1 more heartbeat.
    MessageCollectorActor.clearMessages(leaderCollectorActor);
    MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
    // The leader should now have performed fake snapshots to advance the snapshot index and to trim
    // the log. In addition replicatedToAllIndex should've advanced.
    verifyLeadersTrimmedLog(lastAppliedIndex);
    if (expServerConfig != null) {
        Set<ServerInfo> expServerInfo = new HashSet<>(expServerConfig.getServerConfig());
        assertEquals("Leader snapshot server config", expServerInfo, new HashSet<>(persistedSnapshot.getServerConfiguration().getServerConfig()));
        assertEquals("Follower 2 snapshot server config", expServerInfo, new HashSet<>(applySnapshot.getSnapshot().getServerConfiguration().getServerConfig()));
        ServerConfigurationPayload follower2ServerConfig = follower2Context.getPeerServerInfo(true);
        assertNotNull("Follower 2 server config is null", follower2ServerConfig);
        assertEquals("Follower 2 server config", expServerInfo, new HashSet<>(follower2ServerConfig.getServerConfig()));
    }
    MessageCollectorActor.clearMessages(leaderCollectorActor);
    MessageCollectorActor.clearMessages(follower1CollectorActor);
    MessageCollectorActor.clearMessages(follower2CollectorActor);
    testLog.info("verifyInstallSnapshotToLaggingFollower complete");
}
Also used : InstallSnapshotReply(org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) ServerInfo(org.opendaylight.controller.cluster.raft.persisted.ServerInfo) InstallSnapshot(org.opendaylight.controller.cluster.raft.messages.InstallSnapshot) CaptureSnapshot(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot) 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) ServerConfigurationPayload(org.opendaylight.controller.cluster.raft.persisted.ServerConfigurationPayload) HashSet(java.util.HashSet)

Example 10 with ApplySnapshot

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

the class RaftActorRecoverySupport method possiblyRestoreFromSnapshot.

@SuppressWarnings("checkstyle:IllegalCatch")
private void possiblyRestoreFromSnapshot() {
    Snapshot restoreFromSnapshot = cohort.getRestoreFromSnapshot();
    if (restoreFromSnapshot == null) {
        return;
    }
    if (anyDataRecovered) {
        log.warn("{}: The provided restore snapshot was not applied because the persistence store is not empty", context.getId());
        return;
    }
    log.debug("{}: Restore snapshot: {}", context.getId(), restoreFromSnapshot);
    context.getSnapshotManager().apply(new ApplySnapshot(restoreFromSnapshot));
}
Also used : Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)

Aggregations

ApplySnapshot (org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)11 Snapshot (org.opendaylight.controller.cluster.raft.persisted.Snapshot)9 Test (org.junit.Test)8 ByteString (com.google.protobuf.ByteString)4 ActorRef (akka.actor.ActorRef)3 TestActorRef (akka.testkit.TestActorRef)3 GetSnapshot (org.opendaylight.controller.cluster.raft.client.messages.GetSnapshot)3 InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)3 InstallSnapshotReply (org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply)3 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)3 MockSnapshotState (org.opendaylight.controller.cluster.raft.MockRaftActor.MockSnapshotState)2 MockPayload (org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload)2 ApplyState (org.opendaylight.controller.cluster.raft.base.messages.ApplyState)2 AddServer (org.opendaylight.controller.cluster.raft.messages.AddServer)2 AddServerReply (org.opendaylight.controller.cluster.raft.messages.AddServerReply)2 ByteState (org.opendaylight.controller.cluster.raft.persisted.ByteState)2 EmptyState (org.opendaylight.controller.cluster.raft.persisted.EmptyState)2 DisableElectionsRaftPolicy (org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy)2 SaveSnapshotFailure (akka.persistence.SaveSnapshotFailure)1 SaveSnapshotSuccess (akka.persistence.SaveSnapshotSuccess)1