X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fmd-sal%2Fsal-akka-raft%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fraft%2Fbehaviors%2FLeader.java;h=58cf7161062c1eb67568930fb15252aadd21a23e;hb=8beb0dc3d3727608acddf77889cc0a5275e415af;hp=ebcdcd40fb078ebcc16439ec2feaa87b6f62eca4;hpb=69343f4c1b9fee2e28186fb7bd4482bf7d4614cd;p=controller.git diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java index ebcdcd40fb..58cf716106 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java @@ -8,12 +8,19 @@ package org.opendaylight.controller.cluster.raft.behaviors; import akka.actor.ActorRef; +import akka.actor.ActorSelection; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.controller.cluster.raft.FollowerLogInformation; import org.opendaylight.controller.cluster.raft.RaftActorContext; -import org.opendaylight.controller.cluster.raft.base.messages.IsolatedLeaderCheck; +import org.opendaylight.controller.cluster.raft.RaftActorLeadershipTransferCohort; +import org.opendaylight.controller.cluster.raft.RaftState; +import org.opendaylight.controller.cluster.raft.base.messages.TimeoutNow; +import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; /** * The behavior of a RaftActor when it is in the Leader state @@ -38,27 +45,39 @@ import org.opendaylight.controller.cluster.raft.base.messages.IsolatedLeaderChec * set commitIndex = N (§5.3, §5.4). */ public class Leader extends AbstractLeader { - private static final IsolatedLeaderCheck ISOLATED_LEADER_CHECK = new IsolatedLeaderCheck(); - private final Stopwatch isolatedLeaderCheck; + /** + * Internal message sent to periodically check if this leader has become isolated and should transition + * to {@link IsolatedLeader}. + */ + @VisibleForTesting + static final Object ISOLATED_LEADER_CHECK = new Object(); + + private final Stopwatch isolatedLeaderCheck = Stopwatch.createStarted(); + private @Nullable LeadershipTransferContext leadershipTransferContext; + + Leader(RaftActorContext context, @Nullable AbstractLeader initializeFromLeader) { + super(context, RaftState.Leader, initializeFromLeader); + } public Leader(RaftActorContext context) { - super(context); - isolatedLeaderCheck = Stopwatch.createStarted(); + this(context, null); } - @Override public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) { + @Override + public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) { Preconditions.checkNotNull(sender, "sender should not be null"); - if (originalMessage instanceof IsolatedLeaderCheck) { + if (ISOLATED_LEADER_CHECK.equals(originalMessage)) { if (isLeaderIsolated()) { LOG.warn("{}: At least {} followers need to be active, Switching {} from Leader to IsolatedLeader", - context.getId(), minIsolatedLeaderPeerCount, leaderId); - - return switchBehavior(new IsolatedLeader(context)); + context.getId(), getMinIsolatedLeaderPeerCount(), getLeaderId()); + return internalSwitchBehavior(RaftState.IsolatedLeader); + } else { + return this; } + } else { + return super.handleMessage(sender, originalMessage); } - - return super.handleMessage(sender, originalMessage); } @Override @@ -68,10 +87,89 @@ public class Leader extends AbstractLeader { isolatedLeaderCheck.reset().start(); } + if(leadershipTransferContext != null && leadershipTransferContext.isExpired( + context.getConfigParams().getElectionTimeOutInterval().toMillis())) { + LOG.debug("{}: Leadership transfer expired", logName()); + leadershipTransferContext = null; + } + } + + @Override + protected RaftActorBehavior handleAppendEntriesReply(ActorRef sender, AppendEntriesReply appendEntriesReply) { + RaftActorBehavior returnBehavior = super.handleAppendEntriesReply(sender, appendEntriesReply); + tryToCompleteLeadershipTransfer(appendEntriesReply.getFollowerId()); + return returnBehavior; + } + + /** + * Attempts to transfer leadership to a follower as per the raft paper (§3.10) as follows: + *