Don't transfer leadership to a non-voting follower 91/32191/3
authorTom Pantelis <tpanteli@brocade.com>
Wed, 6 Jan 2016 06:19:14 +0000 (01:19 -0500)
committerAnil Vishnoi <vishnoianil@gmail.com>
Fri, 8 Jan 2016 02:56:33 +0000 (02:56 +0000)
Change-Id: I5ee97f2cef50b100f21627f26ba6c339972cd677
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/LeadershipTransferIntegrationTest.java

index 21aad966cb2b7dd375b6e4667e952ab4b85891a9..c76798f3b276c602c3a0190f8749f3e1aca4de89 100644 (file)
@@ -129,11 +129,12 @@ public class Leader extends AbstractLeader {
         }
 
         long lastIndex = context.getReplicatedLog().lastIndex();
         }
 
         long lastIndex = context.getReplicatedLog().lastIndex();
+        boolean isVoting = context.getPeerInfo(followerId).isVoting();
 
 
-        LOG.debug("{}: tryToCompleteLeadershipTransfer: followerId: {}, matchIndex: {}, lastIndex: {}",
-                logName(), followerId, followerInfo.getMatchIndex(), lastIndex);
+        LOG.debug("{}: tryToCompleteLeadershipTransfer: followerId: {}, matchIndex: {}, lastIndex: {}, isVoting: {}",
+                logName(), followerId, followerInfo.getMatchIndex(), lastIndex, isVoting);
 
 
-        if(followerInfo.getMatchIndex() == lastIndex) {
+        if(isVoting && followerInfo.getMatchIndex() == lastIndex) {
             LOG.debug("{}: Follower's log matches - sending ElectionTimeout", logName());
 
             // We can't be sure if the follower has applied all its log entries to its state so send an
             LOG.debug("{}: Follower's log matches - sending ElectionTimeout", logName());
 
             // We can't be sure if the follower has applied all its log entries to its state so send an
index 3cc330a96aa101cab3c5b7c54462f3a8369b427d..e1b162fcf1f27d12dda6e19e516d08839998ecb6 100644 (file)
@@ -40,9 +40,13 @@ import scala.concurrent.duration.FiniteDuration;
  */
 public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrationTest {
 
  */
 public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrationTest {
 
+    private final String follower3Id = factory.generateActorId("follower");
     private TestActorRef<MessageCollectorActor> leaderNotifierActor;
     private TestActorRef<MessageCollectorActor> follower1NotifierActor;
     private TestActorRef<MessageCollectorActor> follower2NotifierActor;
     private TestActorRef<MessageCollectorActor> leaderNotifierActor;
     private TestActorRef<MessageCollectorActor> follower1NotifierActor;
     private TestActorRef<MessageCollectorActor> follower2NotifierActor;
+    private TestActorRef<MessageCollectorActor> follower3NotifierActor;
+    private TestActorRef<TestRaftActor> follower3Actor;
+    private ActorRef follower3CollectorActor;
 
     @Test
     public void testLeaderTransferOnShutDown() throws Throwable {
 
     @Test
     public void testLeaderTransferOnShutDown() throws Throwable {
@@ -77,6 +81,7 @@ public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrat
         clearMessages(leaderNotifierActor);
         clearMessages(follower1NotifierActor);
         clearMessages(follower2NotifierActor);
         clearMessages(leaderNotifierActor);
         clearMessages(follower1NotifierActor);
         clearMessages(follower2NotifierActor);
+        clearMessages(follower3NotifierActor);
 
         FiniteDuration duration = FiniteDuration.create(5, TimeUnit.SECONDS);
         Future<Boolean> stopFuture = Patterns.gracefulStop(leaderActor, duration, new Shutdown());
 
         FiniteDuration duration = FiniteDuration.create(5, TimeUnit.SECONDS);
         Future<Boolean> stopFuture = Patterns.gracefulStop(leaderActor, duration, new Shutdown());
@@ -84,6 +89,7 @@ public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrat
         assertNullLeaderIdChange(leaderNotifierActor);
         assertNullLeaderIdChange(follower1NotifierActor);
         assertNullLeaderIdChange(follower2NotifierActor);
         assertNullLeaderIdChange(leaderNotifierActor);
         assertNullLeaderIdChange(follower1NotifierActor);
         assertNullLeaderIdChange(follower2NotifierActor);
+        assertNullLeaderIdChange(follower3NotifierActor);
 
         verifyRaftState(follower1Actor, RaftState.Leader);
 
 
         verifyRaftState(follower1Actor, RaftState.Leader);
 
@@ -106,6 +112,7 @@ public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrat
 
         expectFirstMatching(leaderCollectorActor, ApplyState.class);
         expectFirstMatching(follower1CollectorActor, ApplyState.class);
 
         expectFirstMatching(leaderCollectorActor, ApplyState.class);
         expectFirstMatching(follower1CollectorActor, ApplyState.class);
+        expectFirstMatching(follower3CollectorActor, ApplyState.class);
 
         testLog.info("sendPayloadWithFollower2Lagging ending");
     }
 
         testLog.info("sendPayloadWithFollower2Lagging ending");
     }
@@ -116,18 +123,28 @@ public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrat
         follower1NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
                 factory.generateActorId(follower1Id + "-notifier"));
         follower1Actor = newTestRaftActor(follower1Id, TestRaftActor.newBuilder().peerAddresses(
         follower1NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
                 factory.generateActorId(follower1Id + "-notifier"));
         follower1Actor = newTestRaftActor(follower1Id, TestRaftActor.newBuilder().peerAddresses(
-                ImmutableMap.of(leaderId, testActorPath(leaderId), follower2Id, testActorPath(follower2Id))).
-                    config(newFollowerConfigParams()).roleChangeNotifier(follower1NotifierActor));
+                ImmutableMap.of(leaderId, testActorPath(leaderId), follower2Id, testActorPath(follower2Id),
+                        follower3Id, testActorPath(follower3Id))).
+                config(newFollowerConfigParams()).roleChangeNotifier(follower1NotifierActor));
 
         follower2NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
                 factory.generateActorId(follower2Id + "-notifier"));
         follower2Actor = newTestRaftActor(follower2Id,TestRaftActor.newBuilder().peerAddresses(
 
         follower2NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
                 factory.generateActorId(follower2Id + "-notifier"));
         follower2Actor = newTestRaftActor(follower2Id,TestRaftActor.newBuilder().peerAddresses(
-                ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString())).
-                    config(newFollowerConfigParams()).roleChangeNotifier(follower2NotifierActor));
+                ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString(),
+                        follower3Id, testActorPath(follower3Id))).
+                config(newFollowerConfigParams()).roleChangeNotifier(follower2NotifierActor));
+
+        follower3NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
+                factory.generateActorId(follower3Id + "-notifier"));
+        follower3Actor = newTestRaftActor(follower3Id,TestRaftActor.newBuilder().peerAddresses(
+                ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString(),
+                        follower2Id, follower2Actor.path().toString())).
+                config(newFollowerConfigParams()).roleChangeNotifier(follower3NotifierActor));
 
         peerAddresses = ImmutableMap.<String, String>builder().
                 put(follower1Id, follower1Actor.path().toString()).
 
         peerAddresses = ImmutableMap.<String, String>builder().
                 put(follower1Id, follower1Actor.path().toString()).
-                put(follower2Id, follower2Actor.path().toString()).build();
+                put(follower2Id, follower2Actor.path().toString()).
+                put(follower3Id, follower3Actor.path().toString()).build();
 
         leaderConfigParams = newLeaderConfigParams();
         leaderConfigParams.setElectionTimeoutFactor(3);
 
         leaderConfigParams = newLeaderConfigParams();
         leaderConfigParams.setElectionTimeoutFactor(3);
@@ -138,9 +155,11 @@ public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrat
 
         follower1CollectorActor = follower1Actor.underlyingActor().collectorActor();
         follower2CollectorActor = follower2Actor.underlyingActor().collectorActor();
 
         follower1CollectorActor = follower1Actor.underlyingActor().collectorActor();
         follower2CollectorActor = follower2Actor.underlyingActor().collectorActor();
+        follower3CollectorActor = follower3Actor.underlyingActor().collectorActor();
         leaderCollectorActor = leaderActor.underlyingActor().collectorActor();
 
         leaderContext = leaderActor.underlyingActor().getRaftActorContext();
         leaderCollectorActor = leaderActor.underlyingActor().collectorActor();
 
         leaderContext = leaderActor.underlyingActor().getRaftActorContext();
+        leaderContext.getPeerInfo(follower3Id).setVotingState(VotingState.NON_VOTING);
 
         waitUntilLeader(leaderActor);
 
 
         waitUntilLeader(leaderActor);
 
@@ -182,6 +201,10 @@ public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrat
 
         sendShutDown(leaderActor);
 
 
         sendShutDown(leaderActor);
 
+        verifyRaftState(follower1Actor, RaftState.Follower);
+        verifyRaftState(follower2Actor, RaftState.Follower);
+        verifyRaftState(follower3Actor, RaftState.Follower);
+
         testLog.info("testLeaderTransferOnShutDown ending");
     }
 
         testLog.info("testLeaderTransferOnShutDown ending");
     }