X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-akka-raft%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fraft%2FRaftActorServerConfigurationSupport.java;h=2fa700256a598834f5b63050f9242eb6f027a679;hb=a7740542c8ce1985c0a35767966c781805dfad84;hp=7012e0db86f8847b3660f78de8cefb3a1f8c7a6a;hpb=24ace09aacc620fd9768e0a7004e802f9385bcfc;p=controller.git diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorServerConfigurationSupport.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorServerConfigurationSupport.java index 7012e0db86..2fa700256a 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorServerConfigurationSupport.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorServerConfigurationSupport.java @@ -20,10 +20,9 @@ import java.util.Map; import java.util.Queue; import java.util.UUID; import javax.annotation.Nullable; -import org.opendaylight.controller.cluster.raft.ServerConfigurationPayload.ServerInfo; import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; -import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout; import org.opendaylight.controller.cluster.raft.base.messages.SnapshotComplete; +import org.opendaylight.controller.cluster.raft.base.messages.TimeoutNow; import org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader; import org.opendaylight.controller.cluster.raft.messages.AddServer; import org.opendaylight.controller.cluster.raft.messages.AddServerReply; @@ -34,7 +33,11 @@ import org.opendaylight.controller.cluster.raft.messages.ServerChangeReply; import org.opendaylight.controller.cluster.raft.messages.ServerChangeStatus; import org.opendaylight.controller.cluster.raft.messages.ServerRemoved; import org.opendaylight.controller.cluster.raft.messages.UnInitializedFollowerSnapshotReply; +import org.opendaylight.controller.cluster.raft.persisted.ServerConfigurationPayload; +import org.opendaylight.controller.cluster.raft.persisted.ServerInfo; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; +import org.opendaylight.yangtools.concepts.Identifier; +import org.opendaylight.yangtools.util.AbstractUUIDIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import scala.concurrent.duration.FiniteDuration; @@ -522,6 +525,14 @@ class RaftActorServerConfigurationSupport { } } + private static final class ServerOperationContextIdentifier extends AbstractUUIDIdentifier { + private static final long serialVersionUID = 1L; + + ServerOperationContextIdentifier() { + super(UUID.randomUUID()); + } + } + /** * Stores context information for a server operation. * @@ -530,15 +541,15 @@ class RaftActorServerConfigurationSupport { private static abstract class ServerOperationContext { private final T operation; private final ActorRef clientRequestor; - private final String contextId; + private final Identifier contextId; ServerOperationContext(T operation, ActorRef clientRequestor){ this.operation = operation; this.clientRequestor = clientRequestor; - contextId = UUID.randomUUID().toString(); + contextId = new ServerOperationContextIdentifier(); } - String getContextId() { + Identifier getContextId() { return contextId; } @@ -678,28 +689,9 @@ class RaftActorServerConfigurationSupport { // leadership. boolean localServerChangedToNonVoting = Boolean.FALSE.equals(getOperation(). getServerVotingStatusMap().get(raftActor.getRaftActorContext().getId())); - if(succeeded && localServerChangedToNonVoting && raftActor.isLeader()) { - raftActor.initiateLeadershipTransfer(new RaftActorLeadershipTransferCohort.OnComplete() { - @Override - public void onSuccess(ActorRef raftActorRef, ActorRef replyTo) { - LOG.debug("{}: leader transfer succeeded after change to non-voting", raftActor.persistenceId()); - ensureFollowerState(raftActor); - } - - @Override - public void onFailure(ActorRef raftActorRef, ActorRef replyTo) { - LOG.debug("{}: leader transfer failed after change to non-voting", raftActor.persistenceId()); - ensureFollowerState(raftActor); - } - - private void ensureFollowerState(RaftActor raftActor) { - // Whether or not leadership transfer succeeded, we have to step down as leader and - // switch to Follower so ensure that. - if(raftActor.getRaftState() != RaftState.Follower) { - raftActor.initializeBehavior(); - } - } - }); + if (succeeded && localServerChangedToNonVoting) { + LOG.debug("Leader changed to non-voting - trying leadership transfer"); + raftActor.becomeNonVoting(); } } @@ -725,9 +717,7 @@ class RaftActorServerConfigurationSupport { if(tryToElectLeader) { initiateLocalLeaderElection(); - } else { - updateLocalPeerInfo(); - + } else if(updateLocalPeerInfo()) { persistNewServerConfiguration(changeVotingStatusContext); } } @@ -736,21 +726,39 @@ class RaftActorServerConfigurationSupport { LOG.debug("{}: Sending local ElectionTimeout to start leader election", raftContext.getId()); ServerConfigurationPayload previousServerConfig = raftContext.getPeerServerInfo(true); - updateLocalPeerInfo(); + if(!updateLocalPeerInfo()) { + return; + } - raftContext.getActor().tell(ElectionTimeout.INSTANCE, raftContext.getActor()); + raftContext.getActor().tell(TimeoutNow.INSTANCE, raftContext.getActor()); currentOperationState = new WaitingForLeaderElected(changeVotingStatusContext, previousServerConfig); } - private void updateLocalPeerInfo() { + private boolean updateLocalPeerInfo() { List newServerInfoList = newServerInfoList(); + // Check if new voting state would leave us with no voting members. + boolean atLeastOneVoting = false; + for(ServerInfo info: newServerInfoList) { + if(info.isVoting()) { + atLeastOneVoting = true; + break; + } + } + + if(!atLeastOneVoting) { + operationComplete(changeVotingStatusContext, ServerChangeStatus.INVALID_REQUEST); + return false; + } + raftContext.updatePeerIds(new ServerConfigurationPayload(newServerInfoList)); if(raftActor.getCurrentBehavior() instanceof AbstractLeader) { AbstractLeader leader = (AbstractLeader) raftActor.getCurrentBehavior(); leader.updateMinReplicaCount(); } + + return true; } private List newServerInfoList() { @@ -784,6 +792,10 @@ class RaftActorServerConfigurationSupport { @Override void onNewLeader(String newLeader) { + if(newLeader == null) { + return; + } + LOG.debug("{}: New leader {} elected", raftContext.getId(), newLeader); timer.cancel();