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=bbc692e885c66a92fdfa8c01a0423cba56a4cc26;hb=61e85d54cfcd70053993f910092eba1ab3fcc850;hp=46fe6269e37a907db36fe3d0ca7a5b9b9b52bd58;hpb=d639c62a1e743ec846b15bf755b830b00f4cc7eb;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 46fe6269e3..bbc692e885 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 @@ -35,6 +35,8 @@ 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.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 +524,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 +540,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; } @@ -679,7 +689,8 @@ class RaftActorServerConfigurationSupport { boolean localServerChangedToNonVoting = Boolean.FALSE.equals(getOperation(). getServerVotingStatusMap().get(raftActor.getRaftActorContext().getId())); if (succeeded && localServerChangedToNonVoting) { - raftActor.becomeNonVoting(); + LOG.debug("Leader changed to non-voting - trying leadership transfer"); + raftActor.becomeNonVoting(); } } @@ -705,9 +716,7 @@ class RaftActorServerConfigurationSupport { if(tryToElectLeader) { initiateLocalLeaderElection(); - } else { - updateLocalPeerInfo(); - + } else if(updateLocalPeerInfo()) { persistNewServerConfiguration(changeVotingStatusContext); } } @@ -716,21 +725,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()); 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() {