Search in sources :

Example 1 with LeaderTransitioning

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

the class LeadershipTransferIntegrationTest method sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1.

private void sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1() throws Exception {
    testLog.info("sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1 starting");
    clearMessages(leaderNotifierActor);
    clearMessages(follower1NotifierActor);
    clearMessages(follower2NotifierActor);
    clearMessages(follower3NotifierActor);
    // Simulate a delay for follower2 in receiving the LeaderTransitioning message with null leader id.
    final TestRaftActor follower2Instance = follower2Actor.underlyingActor();
    follower2Instance.startDropMessages(LeaderTransitioning.class);
    FiniteDuration duration = FiniteDuration.create(5, TimeUnit.SECONDS);
    final Future<Boolean> stopFuture = Patterns.gracefulStop(leaderActor, duration, Shutdown.INSTANCE);
    verifyRaftState(follower1Actor, RaftState.Leader);
    Boolean stopped = Await.result(stopFuture, duration);
    assertEquals("Stopped", Boolean.TRUE, stopped);
    // Re-enable LeaderTransitioning messages to follower2.
    final LeaderTransitioning leaderTransitioning = expectFirstMatching(follower2CollectorActor, LeaderTransitioning.class);
    follower2Instance.stopDropMessages(LeaderTransitioning.class);
    follower2Instance.stopDropMessages(AppendEntries.class);
    ApplyState applyState = expectFirstMatching(follower2CollectorActor, ApplyState.class);
    assertEquals("Apply sate index", 0, applyState.getReplicatedLogEntry().getIndex());
    // Now send the LeaderTransitioning to follower2 after it has received AppendEntries from the new leader.
    follower2Actor.tell(leaderTransitioning, ActorRef.noSender());
    verifyLeaderStateChangedMessages(leaderNotifierActor, null, follower1Id);
    verifyLeaderStateChangedMessages(follower1NotifierActor, null, follower1Id);
    // follower2 should only get 1 LeaderStateChanged with the new leaderId - the LeaderTransitioning message
    // should not generate a LeaderStateChanged with null leaderId since it arrived after the new leaderId was set.
    verifyLeaderStateChangedMessages(follower2NotifierActor, follower1Id);
    verifyLeaderStateChangedMessages(follower3NotifierActor, null, follower1Id);
    testLog.info("sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1 ending");
}
Also used : FiniteDuration(scala.concurrent.duration.FiniteDuration) LeaderTransitioning(org.opendaylight.controller.cluster.raft.base.messages.LeaderTransitioning) ApplyState(org.opendaylight.controller.cluster.raft.base.messages.ApplyState)

Example 2 with LeaderTransitioning

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

the class RaftActorTest method testLeaderTransitioning.

@Test
public void testLeaderTransitioning() throws Exception {
    TEST_LOG.info("testLeaderTransitioning starting");
    ActorRef notifierActor = factory.createActor(MessageCollectorActor.props());
    DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
    config.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName());
    String persistenceId = factory.generateActorId("test-actor-");
    TestActorRef<MockRaftActor> raftActorRef = factory.createTestActor(MockRaftActor.builder().id(persistenceId).config(config).roleChangeNotifier(notifierActor).props().withDispatcher(Dispatchers.DefaultDispatcherId()), persistenceId);
    MockRaftActor mockRaftActor = raftActorRef.underlyingActor();
    mockRaftActor.waitForInitializeBehaviorComplete();
    raftActorRef.tell(new AppendEntries(1L, "leader", 0L, 1L, Collections.<ReplicatedLogEntry>emptyList(), 0L, -1L, (short) 1), ActorRef.noSender());
    LeaderStateChanged leaderStateChange = MessageCollectorActor.expectFirstMatching(notifierActor, LeaderStateChanged.class);
    assertEquals("getLeaderId", "leader", leaderStateChange.getLeaderId());
    MessageCollectorActor.clearMessages(notifierActor);
    raftActorRef.tell(new LeaderTransitioning("leader"), ActorRef.noSender());
    leaderStateChange = MessageCollectorActor.expectFirstMatching(notifierActor, LeaderStateChanged.class);
    assertEquals("getMemberId", persistenceId, leaderStateChange.getMemberId());
    assertEquals("getLeaderId", null, leaderStateChange.getLeaderId());
    TEST_LOG.info("testLeaderTransitioning ending");
}
Also used : SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) DisableElectionsRaftPolicy(org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy) ByteString(com.google.protobuf.ByteString) AppendEntries(org.opendaylight.controller.cluster.raft.messages.AppendEntries) LeaderTransitioning(org.opendaylight.controller.cluster.raft.base.messages.LeaderTransitioning) LeaderStateChanged(org.opendaylight.controller.cluster.notifications.LeaderStateChanged) Test(org.junit.Test)

Example 3 with LeaderTransitioning

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

the class RaftActor method handleCommand.

/**
 * Handles a message.
 *
 * @deprecated This method is not final for testing purposes. DO NOT OVERRIDE IT, override
 * {@link #handleNonRaftCommand(Object)} instead.
 */
@Deprecated
@Override
protected // FIXME: make this method final once our unit tests do not need to override it
void handleCommand(final Object message) {
    if (serverConfigurationSupport.handleMessage(message, getSender())) {
        return;
    }
    if (snapshotSupport.handleSnapshotMessage(message, getSender())) {
        return;
    }
    if (message instanceof ApplyState) {
        ApplyState applyState = (ApplyState) message;
        if (!hasFollowers()) {
            // for single node, the capture should happen after the apply state
            // as we delete messages from the persistent journal which have made it to the snapshot
            // capturing the snapshot before applying makes the persistent journal and snapshot out of sync
            // and recovery shows data missing
            context.getReplicatedLog().captureSnapshotIfReady(applyState.getReplicatedLogEntry());
            context.getSnapshotManager().trimLog(context.getLastApplied());
        }
        possiblyHandleBehaviorMessage(message);
    } else if (message instanceof ApplyJournalEntries) {
        ApplyJournalEntries applyEntries = (ApplyJournalEntries) message;
        LOG.debug("{}: Persisting ApplyJournalEntries with index={}", persistenceId(), applyEntries.getToIndex());
        persistence().persistAsync(applyEntries, NoopProcedure.instance());
    } else if (message instanceof FindLeader) {
        getSender().tell(new FindLeaderReply(getLeaderAddress()), getSelf());
    } else if (message instanceof GetOnDemandRaftState) {
        onGetOnDemandRaftStats();
    } else if (message instanceof InitiateCaptureSnapshot) {
        captureSnapshot();
    } else if (message instanceof SwitchBehavior) {
        switchBehavior((SwitchBehavior) message);
    } else if (message instanceof LeaderTransitioning) {
        onLeaderTransitioning((LeaderTransitioning) message);
    } else if (message instanceof Shutdown) {
        onShutDown();
    } else if (message instanceof Runnable) {
        ((Runnable) message).run();
    } else if (message instanceof NoopPayload) {
        persistData(null, null, (NoopPayload) message, false);
    } else if (message instanceof RequestLeadership) {
        onRequestLeadership((RequestLeadership) message);
    } else if (!possiblyHandleBehaviorMessage(message)) {
        handleNonRaftCommand(message);
    }
}
Also used : InitiateCaptureSnapshot(org.opendaylight.controller.cluster.raft.base.messages.InitiateCaptureSnapshot) FindLeaderReply(org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply) Shutdown(org.opendaylight.controller.cluster.raft.client.messages.Shutdown) RequestLeadership(org.opendaylight.controller.cluster.raft.messages.RequestLeadership) FindLeader(org.opendaylight.controller.cluster.raft.client.messages.FindLeader) NoopPayload(org.opendaylight.controller.cluster.raft.persisted.NoopPayload) ApplyJournalEntries(org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries) GetOnDemandRaftState(org.opendaylight.controller.cluster.raft.client.messages.GetOnDemandRaftState) LeaderTransitioning(org.opendaylight.controller.cluster.raft.base.messages.LeaderTransitioning) SwitchBehavior(org.opendaylight.controller.cluster.raft.base.messages.SwitchBehavior) ApplyState(org.opendaylight.controller.cluster.raft.base.messages.ApplyState)

Example 4 with LeaderTransitioning

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

the class RaftActorLeadershipTransferCohort method init.

void init() {
    RaftActorContext context = raftActor.getRaftActorContext();
    RaftActorBehavior currentBehavior = raftActor.getCurrentBehavior();
    transferTimer.start();
    Optional<ActorRef> roleChangeNotifier = raftActor.getRoleChangeNotifier();
    if (roleChangeNotifier.isPresent()) {
        roleChangeNotifier.get().tell(raftActor.newLeaderStateChanged(context.getId(), null, currentBehavior.getLeaderPayloadVersion()), raftActor.self());
    }
    for (String peerId : context.getPeerIds()) {
        ActorSelection followerActor = context.getPeerActorSelection(peerId);
        if (followerActor != null) {
            followerActor.tell(new LeaderTransitioning(context.getId()), context.getActor());
        }
    }
    raftActor.pauseLeader(new TimedRunnable(context.getConfigParams().getElectionTimeOutInterval(), raftActor) {

        @Override
        protected void doRun() {
            LOG.debug("{}: pauseLeader successfully completed - doing transfer", raftActor.persistenceId());
            doTransfer();
        }

        @Override
        protected void doCancel() {
            LOG.debug("{}: pauseLeader timed out - continuing with transfer", raftActor.persistenceId());
            doTransfer();
        }
    });
}
Also used : ActorSelection(akka.actor.ActorSelection) ActorRef(akka.actor.ActorRef) RaftActorBehavior(org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior) LeaderTransitioning(org.opendaylight.controller.cluster.raft.base.messages.LeaderTransitioning)

Aggregations

LeaderTransitioning (org.opendaylight.controller.cluster.raft.base.messages.LeaderTransitioning)4 ActorRef (akka.actor.ActorRef)2 ApplyState (org.opendaylight.controller.cluster.raft.base.messages.ApplyState)2 ActorSelection (akka.actor.ActorSelection)1 TestActorRef (akka.testkit.TestActorRef)1 ByteString (com.google.protobuf.ByteString)1 Test (org.junit.Test)1 LeaderStateChanged (org.opendaylight.controller.cluster.notifications.LeaderStateChanged)1 InitiateCaptureSnapshot (org.opendaylight.controller.cluster.raft.base.messages.InitiateCaptureSnapshot)1 SwitchBehavior (org.opendaylight.controller.cluster.raft.base.messages.SwitchBehavior)1 RaftActorBehavior (org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior)1 FindLeader (org.opendaylight.controller.cluster.raft.client.messages.FindLeader)1 FindLeaderReply (org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply)1 GetOnDemandRaftState (org.opendaylight.controller.cluster.raft.client.messages.GetOnDemandRaftState)1 Shutdown (org.opendaylight.controller.cluster.raft.client.messages.Shutdown)1 AppendEntries (org.opendaylight.controller.cluster.raft.messages.AppendEntries)1 RequestLeadership (org.opendaylight.controller.cluster.raft.messages.RequestLeadership)1 ApplyJournalEntries (org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries)1 NoopPayload (org.opendaylight.controller.cluster.raft.persisted.NoopPayload)1 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)1