Search in sources :

Example 36 with Snapshot

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

the class RaftActorRecoverySupport method onRecoveryCompletedMessage.

private void onRecoveryCompletedMessage(PersistentDataProvider persistentProvider) {
    if (currentRecoveryBatchCount > 0) {
        endCurrentLogRecoveryBatch();
    }
    String recoveryTime = "";
    if (recoveryTimer != null) {
        recoveryTimer.stop();
        recoveryTime = " in " + recoveryTimer.toString();
        recoveryTimer = null;
    }
    log.info("Recovery completed" + recoveryTime + " - Switching actor to Follower - " + "Persistence Id =  " + context.getId() + " Last index in log = {}, snapshotIndex = {}, snapshotTerm = {}, " + "journal-size = {}", replicatedLog().lastIndex(), replicatedLog().getSnapshotIndex(), replicatedLog().getSnapshotTerm(), replicatedLog().size());
    if (dataRecoveredWithPersistenceDisabled || hasMigratedDataRecovered && !context.getPersistenceProvider().isRecoveryApplicable()) {
        if (hasMigratedDataRecovered) {
            log.info("{}: Saving snapshot after recovery due to migrated messages", context.getId());
        } else {
            log.info("{}: Saving snapshot after recovery due to data persistence disabled", context.getId());
        }
        // Either data persistence is disabled and we recovered some data entries (ie we must have just
        // transitioned to disabled or a persistence backup was restored) or we recovered migrated
        // messages. Either way, we persist a snapshot and delete all the messages from the akka journal
        // to clean out unwanted messages.
        Snapshot snapshot = Snapshot.create(EmptyState.INSTANCE, Collections.<ReplicatedLogEntry>emptyList(), -1, -1, -1, -1, context.getTermInformation().getCurrentTerm(), context.getTermInformation().getVotedFor(), context.getPeerServerInfo(true));
        persistentProvider.saveSnapshot(snapshot);
        persistentProvider.deleteMessages(persistentProvider.getLastSequenceNumber());
    } else if (hasMigratedDataRecovered) {
        log.info("{}: Snapshot capture initiated after recovery due to migrated messages", context.getId());
        context.getSnapshotManager().capture(replicatedLog().last(), -1);
    } else {
        possiblyRestoreFromSnapshot();
    }
}
Also used : Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)

Example 37 with Snapshot

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

the class RaftActorRecoverySupport method onRecoveredSnapshot.

private void onRecoveredSnapshot(SnapshotOffer offer) {
    log.debug("{}: SnapshotOffer called.", context.getId());
    initRecoveryTimer();
    Snapshot snapshot = (Snapshot) offer.snapshot();
    for (ReplicatedLogEntry entry : snapshot.getUnAppliedEntries()) {
        if (isMigratedPayload(entry)) {
            hasMigratedDataRecovered = true;
        }
    }
    if (!context.getPersistenceProvider().isRecoveryApplicable()) {
        // We may have just transitioned to disabled and have a snapshot containing state data and/or log
        // entries - we don't want to preserve these, only the server config and election term info.
        snapshot = Snapshot.create(EmptyState.INSTANCE, Collections.emptyList(), -1, -1, -1, -1, snapshot.getElectionTerm(), snapshot.getElectionVotedFor(), snapshot.getServerConfiguration());
    }
    // Create a replicated log with the snapshot information
    // The replicated log can be used later on to retrieve this snapshot
    // when we need to install it on a peer
    context.setReplicatedLog(ReplicatedLogImpl.newInstance(snapshot, context));
    context.setLastApplied(snapshot.getLastAppliedIndex());
    context.setCommitIndex(snapshot.getLastAppliedIndex());
    context.getTermInformation().update(snapshot.getElectionTerm(), snapshot.getElectionVotedFor());
    Stopwatch timer = Stopwatch.createStarted();
    // Apply the snapshot to the actors state
    if (!(snapshot.getState() instanceof EmptyState)) {
        cohort.applyRecoverySnapshot(snapshot.getState());
    }
    if (snapshot.getServerConfiguration() != null) {
        context.updatePeerIds(snapshot.getServerConfiguration());
    }
    timer.stop();
    log.info("Recovery snapshot applied for {} in {}: snapshotIndex={}, snapshotTerm={}, journal-size={}", context.getId(), timer.toString(), replicatedLog().getSnapshotIndex(), replicatedLog().getSnapshotTerm(), replicatedLog().size());
}
Also used : Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) EmptyState(org.opendaylight.controller.cluster.raft.persisted.EmptyState) Stopwatch(com.google.common.base.Stopwatch)

Example 38 with Snapshot

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

the class GetSnapshotReplyActor method onReceive.

@Override
public void onReceive(final Object message) {
    if (message instanceof CaptureSnapshotReply) {
        Snapshot snapshot = Snapshot.create(((CaptureSnapshotReply) message).getSnapshotState(), params.captureSnapshot.getUnAppliedEntries(), params.captureSnapshot.getLastIndex(), params.captureSnapshot.getLastTerm(), params.captureSnapshot.getLastAppliedIndex(), params.captureSnapshot.getLastAppliedTerm(), params.electionTerm.getCurrentTerm(), params.electionTerm.getVotedFor(), params.peerInformation);
        LOG.debug("{}: Received CaptureSnapshotReply, sending {}", params.id, snapshot);
        params.replyToActor.tell(new GetSnapshotReply(params.id, snapshot), getSelf());
        getSelf().tell(PoisonPill.getInstance(), getSelf());
    } else if (message instanceof ReceiveTimeout) {
        LOG.warn("{}: Got ReceiveTimeout for inactivity - did not receive CaptureSnapshotReply within {} ms", params.id, params.receiveTimeout.toMillis());
        params.replyToActor.tell(new akka.actor.Status.Failure(new TimeoutException(String.format("Timed out after %d ms while waiting for CaptureSnapshotReply", params.receiveTimeout.toMillis()))), getSelf());
        getSelf().tell(PoisonPill.getInstance(), getSelf());
    }
}
Also used : CaptureSnapshotReply(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply) CaptureSnapshot(org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) ReceiveTimeout(akka.actor.ReceiveTimeout) GetSnapshotReply(org.opendaylight.controller.cluster.raft.client.messages.GetSnapshotReply) TimeoutException(java.util.concurrent.TimeoutException)

Example 39 with Snapshot

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

the class ShardTest method testCreateSnapshot.

private void testCreateSnapshot(final boolean persistent, final String shardActorName) throws Exception {
    final AtomicReference<CountDownLatch> latch = new AtomicReference<>(new CountDownLatch(1));
    final AtomicReference<Object> savedSnapshot = new AtomicReference<>();
    class TestPersistentDataProvider extends DelegatingPersistentDataProvider {

        TestPersistentDataProvider(final DataPersistenceProvider delegate) {
            super(delegate);
        }

        @Override
        public void saveSnapshot(final Object obj) {
            savedSnapshot.set(obj);
            super.saveSnapshot(obj);
        }
    }
    dataStoreContextBuilder.persistent(persistent);
    class TestShard extends Shard {

        protected TestShard(final AbstractBuilder<?, ?> builder) {
            super(builder);
            setPersistence(new TestPersistentDataProvider(super.persistence()));
        }

        @Override
        public void handleCommand(final Object message) {
            super.handleCommand(message);
            // XXX:  commit_snapshot equality check references RaftActorSnapshotMessageSupport.COMMIT_SNAPSHOT
            if (message instanceof SaveSnapshotSuccess || "commit_snapshot".equals(message.toString())) {
                latch.get().countDown();
            }
        }

        @Override
        public RaftActorContext getRaftActorContext() {
            return super.getRaftActorContext();
        }
    }
    new ShardTestKit(getSystem()) {

        {
            final Creator<Shard> creator = () -> new TestShard(newShardBuilder());
            final TestActorRef<Shard> shard = actorFactory.createTestActor(Props.create(new DelegatingShardCreator(creator)).withDispatcher(Dispatchers.DefaultDispatcherId()), shardActorName);
            waitUntilLeader(shard);
            writeToStore(shard, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
            final NormalizedNode<?, ?> expectedRoot = readStore(shard, YangInstanceIdentifier.EMPTY);
            // Trigger creation of a snapshot by ensuring
            final RaftActorContext raftActorContext = ((TestShard) shard.underlyingActor()).getRaftActorContext();
            raftActorContext.getSnapshotManager().capture(mock(ReplicatedLogEntry.class), -1);
            awaitAndValidateSnapshot(expectedRoot);
            raftActorContext.getSnapshotManager().capture(mock(ReplicatedLogEntry.class), -1);
            awaitAndValidateSnapshot(expectedRoot);
        }

        private void awaitAndValidateSnapshot(final NormalizedNode<?, ?> expectedRoot) throws InterruptedException, IOException {
            assertEquals("Snapshot saved", true, latch.get().await(5, TimeUnit.SECONDS));
            assertTrue("Invalid saved snapshot " + savedSnapshot.get(), savedSnapshot.get() instanceof Snapshot);
            verifySnapshot((Snapshot) savedSnapshot.get(), expectedRoot);
            latch.set(new CountDownLatch(1));
            savedSnapshot.set(null);
        }

        private void verifySnapshot(final Snapshot snapshot, final NormalizedNode<?, ?> expectedRoot) throws IOException {
            final NormalizedNode<?, ?> actual = ((ShardSnapshotState) snapshot.getState()).getSnapshot().getRootNode().get();
            assertEquals("Root node", expectedRoot, actual);
        }
    };
}
Also used : ShardSnapshotState(org.opendaylight.controller.cluster.datastore.persisted.ShardSnapshotState) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) MetadataShardDataTreeSnapshot(org.opendaylight.controller.cluster.datastore.persisted.MetadataShardDataTreeSnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ReplicatedLogEntry(org.opendaylight.controller.cluster.raft.ReplicatedLogEntry) DataPersistenceProvider(org.opendaylight.controller.cluster.DataPersistenceProvider) DelegatingPersistentDataProvider(org.opendaylight.controller.cluster.DelegatingPersistentDataProvider) RaftActorContext(org.opendaylight.controller.cluster.raft.RaftActorContext) NormalizedNode(org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode) SaveSnapshotSuccess(akka.persistence.SaveSnapshotSuccess)

Example 40 with Snapshot

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

the class ShardTest method testApplySnapshot.

@Test
public void testApplySnapshot() throws Exception {
    final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testApplySnapshot");
    ShardTestKit.waitUntilLeader(shard);
    final DataTree store = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL, SCHEMA_CONTEXT);
    final ContainerNode container = ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME)).withChild(ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).addChild(ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1)).build()).build();
    writeToStore(store, TestModel.TEST_PATH, container);
    final YangInstanceIdentifier root = YangInstanceIdentifier.EMPTY;
    final NormalizedNode<?, ?> expected = readStore(store, root);
    final Snapshot snapshot = Snapshot.create(new ShardSnapshotState(new MetadataShardDataTreeSnapshot(expected)), Collections.<ReplicatedLogEntry>emptyList(), 1, 2, 3, 4, -1, null, null);
    shard.tell(new ApplySnapshot(snapshot), ActorRef.noSender());
    final Stopwatch sw = Stopwatch.createStarted();
    while (sw.elapsed(TimeUnit.SECONDS) <= 5) {
        Uninterruptibles.sleepUninterruptibly(75, TimeUnit.MILLISECONDS);
        try {
            assertEquals("Root node", expected, readStore(shard, root));
            return;
        } catch (final AssertionError e) {
        // try again
        }
    }
    fail("Snapshot was not applied");
}
Also used : ShardSnapshotState(org.opendaylight.controller.cluster.datastore.persisted.ShardSnapshotState) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) MetadataShardDataTreeSnapshot(org.opendaylight.controller.cluster.datastore.persisted.MetadataShardDataTreeSnapshot) Stopwatch(com.google.common.base.Stopwatch) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) InMemoryDataTreeFactory(org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory) ApplySnapshot(org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot) MetadataShardDataTreeSnapshot(org.opendaylight.controller.cluster.datastore.persisted.MetadataShardDataTreeSnapshot) Snapshot(org.opendaylight.controller.cluster.raft.persisted.Snapshot) DataTree(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree) ContainerNode(org.opendaylight.yangtools.yang.data.api.schema.ContainerNode) Test(org.junit.Test)

Aggregations

Snapshot (org.opendaylight.controller.cluster.raft.persisted.Snapshot)42 Test (org.junit.Test)28 ApplySnapshot (org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)23 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)21 InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)16 ByteString (com.google.protobuf.ByteString)14 CaptureSnapshot (org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot)14 MockPayload (org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload)12 ApplyState (org.opendaylight.controller.cluster.raft.base.messages.ApplyState)8 DisableElectionsRaftPolicy (org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy)8 ActorRef (akka.actor.ActorRef)7 InstallSnapshotReply (org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply)7 DefaultConfigParamsImpl (org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl)6 MockSnapshotState (org.opendaylight.controller.cluster.raft.MockRaftActor.MockSnapshotState)6 SendInstallSnapshot (org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot)6 GetSnapshot (org.opendaylight.controller.cluster.raft.client.messages.GetSnapshot)6 ApplyJournalEntries (org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries)6 ByteState (org.opendaylight.controller.cluster.raft.persisted.ByteState)6 UpdateElectionTerm (org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm)6 TestActorRef (akka.testkit.TestActorRef)5