Search in sources :

Example 1 with ApplySnapshot

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

the class Follower method handleInstallSnapshot.

private void handleInstallSnapshot(final ActorRef sender, final InstallSnapshot installSnapshot) {
    log.debug("{}: handleInstallSnapshot: {}", logName(), installSnapshot);
    leaderId = installSnapshot.getLeaderId();
    if (snapshotTracker == null) {
        snapshotTracker = new SnapshotTracker(log, installSnapshot.getTotalChunks(), installSnapshot.getLeaderId(), context);
    }
    updateInitialSyncStatus(installSnapshot.getLastIncludedIndex(), installSnapshot.getLeaderId());
    try {
        final InstallSnapshotReply reply = new InstallSnapshotReply(currentTerm(), context.getId(), installSnapshot.getChunkIndex(), true);
        if (snapshotTracker.addChunk(installSnapshot.getChunkIndex(), installSnapshot.getData(), installSnapshot.getLastChunkHashCode())) {
            log.info("{}: Snapshot installed from leader: {}", logName(), installSnapshot.getLeaderId());
            Snapshot snapshot = Snapshot.create(context.getSnapshotManager().convertSnapshot(snapshotTracker.getSnapshotBytes()), new ArrayList<>(), installSnapshot.getLastIncludedIndex(), installSnapshot.getLastIncludedTerm(), installSnapshot.getLastIncludedIndex(), installSnapshot.getLastIncludedTerm(), context.getTermInformation().getCurrentTerm(), context.getTermInformation().getVotedFor(), installSnapshot.getServerConfig().orNull());
            ApplySnapshot.Callback applySnapshotCallback = new ApplySnapshot.Callback() {

                @Override
                public void onSuccess() {
                    log.debug("{}: handleInstallSnapshot returning: {}", logName(), reply);
                    sender.tell(reply, actor());
                }

                @Override
                public void onFailure() {
                    sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(), -1, false), actor());
                }
            };
            actor().tell(new ApplySnapshot(snapshot, applySnapshotCallback), actor());
            closeSnapshotTracker();
        } else {
            log.debug("{}: handleInstallSnapshot returning: {}", logName(), reply);
            sender.tell(reply, actor());
        }
    } catch (IOException e) {
        log.debug("{}: Exception in InstallSnapshot of follower", logName(), e);
        sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(), -1, false), actor());
        closeSnapshotTracker();
    }
}
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) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) IOException(java.io.IOException)

Example 2 with ApplySnapshot

use of org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot 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 3 with ApplySnapshot

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

the class RaftActorTest method testRaftActorForwardsToRaftActorSnapshotMessageSupport.

@Test
public void testRaftActorForwardsToRaftActorSnapshotMessageSupport() {
    String persistenceId = factory.generateActorId("leader-");
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
    RaftActorSnapshotMessageSupport mockSupport = mock(RaftActorSnapshotMessageSupport.class);
    TestActorRef<MockRaftActor> mockActorRef = factory.createTestActor(MockRaftActor.builder().id(persistenceId).config(config).snapshotMessageSupport(mockSupport).props());
    MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
    // Wait for akka's recovery to complete so it doesn't interfere.
    mockRaftActor.waitForRecoveryComplete();
    ApplySnapshot applySnapshot = new ApplySnapshot(mock(Snapshot.class));
    doReturn(true).when(mockSupport).handleSnapshotMessage(same(applySnapshot), any(ActorRef.class));
    mockRaftActor.handleCommand(applySnapshot);
    CaptureSnapshotReply captureSnapshotReply = new CaptureSnapshotReply(ByteState.empty(), java.util.Optional.empty());
    doReturn(true).when(mockSupport).handleSnapshotMessage(same(captureSnapshotReply), any(ActorRef.class));
    mockRaftActor.handleCommand(captureSnapshotReply);
    SaveSnapshotSuccess saveSnapshotSuccess = new SaveSnapshotSuccess(new SnapshotMetadata("", 0L, 0L));
    doReturn(true).when(mockSupport).handleSnapshotMessage(same(saveSnapshotSuccess), any(ActorRef.class));
    mockRaftActor.handleCommand(saveSnapshotSuccess);
    SaveSnapshotFailure saveSnapshotFailure = new SaveSnapshotFailure(new SnapshotMetadata("", 0L, 0L), new Throwable());
    doReturn(true).when(mockSupport).handleSnapshotMessage(same(saveSnapshotFailure), any(ActorRef.class));
    mockRaftActor.handleCommand(saveSnapshotFailure);
    doReturn(true).when(mockSupport).handleSnapshotMessage(same(RaftActorSnapshotMessageSupport.COMMIT_SNAPSHOT), any(ActorRef.class));
    mockRaftActor.handleCommand(RaftActorSnapshotMessageSupport.COMMIT_SNAPSHOT);
    doReturn(true).when(mockSupport).handleSnapshotMessage(same(GetSnapshot.INSTANCE), any(ActorRef.class));
    mockRaftActor.handleCommand(GetSnapshot.INSTANCE);
    verify(mockSupport).handleSnapshotMessage(same(applySnapshot), any(ActorRef.class));
    verify(mockSupport).handleSnapshotMessage(same(captureSnapshotReply), any(ActorRef.class));
    verify(mockSupport).handleSnapshotMessage(same(saveSnapshotSuccess), any(ActorRef.class));
    verify(mockSupport).handleSnapshotMessage(same(saveSnapshotFailure), any(ActorRef.class));
    verify(mockSupport).handleSnapshotMessage(same(RaftActorSnapshotMessageSupport.COMMIT_SNAPSHOT), any(ActorRef.class));
    verify(mockSupport).handleSnapshotMessage(same(GetSnapshot.INSTANCE), any(ActorRef.class));
}
Also used : CaptureSnapshotReply(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) FiniteDuration(scala.concurrent.duration.FiniteDuration) ByteString(com.google.protobuf.ByteString) SaveSnapshotFailure(akka.persistence.SaveSnapshotFailure) 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) SnapshotMetadata(akka.persistence.SnapshotMetadata) SaveSnapshotSuccess(akka.persistence.SaveSnapshotSuccess) Test(org.junit.Test)

Example 4 with ApplySnapshot

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

the class RaftActorTest method testRestoreFromSnapshot.

@Test
public void testRestoreFromSnapshot() throws Exception {
    TEST_LOG.info("testRestoreFromSnapshot starting");
    String persistenceId = factory.generateActorId("test-actor-");
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName());
    List<ReplicatedLogEntry> snapshotUnappliedEntries = new ArrayList<>();
    snapshotUnappliedEntries.add(new SimpleReplicatedLogEntry(4, 1, new MockRaftActorContext.MockPayload("E")));
    int snapshotLastApplied = 3;
    int snapshotLastIndex = 4;
    MockSnapshotState snapshotState = new MockSnapshotState(Arrays.asList(new MockRaftActorContext.MockPayload("A"), new MockRaftActorContext.MockPayload("B"), new MockRaftActorContext.MockPayload("C"), new MockRaftActorContext.MockPayload("D")));
    Snapshot snapshot = Snapshot.create(snapshotState, snapshotUnappliedEntries, snapshotLastIndex, 1, snapshotLastApplied, 1, 1, "member-1", null);
    InMemorySnapshotStore.addSnapshotSavedLatch(persistenceId);
    TestActorRef<MockRaftActor> raftActorRef = factory.createTestActor(MockRaftActor.builder().id(persistenceId).config(config).restoreFromSnapshot(snapshot).props().withDispatcher(Dispatchers.DefaultDispatcherId()), persistenceId);
    MockRaftActor mockRaftActor = raftActorRef.underlyingActor();
    mockRaftActor.waitForRecoveryComplete();
    Snapshot savedSnapshot = InMemorySnapshotStore.waitForSavedSnapshot(persistenceId, Snapshot.class);
    assertEquals("getElectionTerm", snapshot.getElectionTerm(), savedSnapshot.getElectionTerm());
    assertEquals("getElectionVotedFor", snapshot.getElectionVotedFor(), savedSnapshot.getElectionVotedFor());
    assertEquals("getLastAppliedIndex", snapshot.getLastAppliedIndex(), savedSnapshot.getLastAppliedIndex());
    assertEquals("getLastAppliedTerm", snapshot.getLastAppliedTerm(), savedSnapshot.getLastAppliedTerm());
    assertEquals("getLastIndex", snapshot.getLastIndex(), savedSnapshot.getLastIndex());
    assertEquals("getLastTerm", snapshot.getLastTerm(), savedSnapshot.getLastTerm());
    assertEquals("getState", snapshot.getState(), savedSnapshot.getState());
    assertEquals("getUnAppliedEntries", snapshot.getUnAppliedEntries(), savedSnapshot.getUnAppliedEntries());
    verify(mockRaftActor.snapshotCohortDelegate, timeout(5000)).applySnapshot(any(Snapshot.State.class));
    RaftActorContext context = mockRaftActor.getRaftActorContext();
    assertEquals("Journal log size", 1, context.getReplicatedLog().size());
    assertEquals("Last index", snapshotLastIndex, context.getReplicatedLog().lastIndex());
    assertEquals("Last applied", snapshotLastApplied, context.getLastApplied());
    assertEquals("Commit index", snapshotLastApplied, context.getCommitIndex());
    assertEquals("Recovered state", snapshotState.getState(), mockRaftActor.getState());
    assertEquals("Current term", 1L, context.getTermInformation().getCurrentTerm());
    assertEquals("Voted for", "member-1", context.getTermInformation().getVotedFor());
    // Test with data persistence disabled
    snapshot = Snapshot.create(EmptyState.INSTANCE, Collections.<ReplicatedLogEntry>emptyList(), -1, -1, -1, -1, 5, "member-1", null);
    persistenceId = factory.generateActorId("test-actor-");
    raftActorRef = factory.createTestActor(MockRaftActor.builder().id(persistenceId).config(config).restoreFromSnapshot(snapshot).persistent(Optional.of(Boolean.FALSE)).props().withDispatcher(Dispatchers.DefaultDispatcherId()), persistenceId);
    mockRaftActor = raftActorRef.underlyingActor();
    mockRaftActor.waitForRecoveryComplete();
    assertEquals("snapshot committed", true, Uninterruptibles.awaitUninterruptibly(mockRaftActor.snapshotCommitted, 5, TimeUnit.SECONDS));
    context = mockRaftActor.getRaftActorContext();
    assertEquals("Current term", 5L, context.getTermInformation().getCurrentTerm());
    assertEquals("Voted for", "member-1", context.getTermInformation().getVotedFor());
    TEST_LOG.info("testRestoreFromSnapshot ending");
}
Also used : MockSnapshotState(org.opendaylight.controller.cluster.raft.MockRaftActor.MockSnapshotState) ArrayList(java.util.ArrayList) 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) 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 5 with ApplySnapshot

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

the class RaftActorServerConfigurationSupportTest method testAddServerWithNoExistingFollower.

@Test
public void testAddServerWithNoExistingFollower() throws Exception {
    LOG.info("testAddServerWithNoExistingFollower starting");
    setupNewFollower();
    RaftActorContext initialActorContext = new MockRaftActorContext();
    initialActorContext.setCommitIndex(1);
    initialActorContext.setLastApplied(1);
    initialActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).build());
    TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
    MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
    final RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
    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);
    assertEquals("Leader journal last index", 2, leaderActorContext.getReplicatedLog().lastIndex());
    assertEquals("Leader commit index", 2, leaderActorContext.getCommitIndex());
    assertEquals("Leader last applied index", 2, leaderActorContext.getLastApplied());
    verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID));
    // Verify ServerConfigurationPayload entry in the new follower
    expectFirstMatching(newFollowerCollectorActor, ApplyState.class);
    assertEquals("New follower journal last index", 2, newFollowerActorContext.getReplicatedLog().lastIndex());
    verifyServerConfigurationPayloadEntry(newFollowerActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID));
    // Verify new server config was applied in the new follower
    assertEquals("New follower peers", Sets.newHashSet(LEADER_ID), newFollowerActorContext.getPeerIds());
    LOG.info("testAddServerWithNoExistingFollower ending");
}
Also used : ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) AddServerReply(org.opendaylight.controller.cluster.raft.messages.AddServerReply) AddServer(org.opendaylight.controller.cluster.raft.messages.AddServer) Test(org.junit.Test)

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