This is an automated email from the ASF dual-hosted git repository.

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new 499f1d8  RATIS-578. Illegal State transition in LeaderElection.
499f1d8 is described below

commit 499f1d83707a88482c9e1341dd841200cc7e7d88
Author: Tsz Wo Nicholas Sze <[email protected]>
AuthorDate: Fri Aug 2 12:56:10 2019 -0700

    RATIS-578. Illegal State transition in LeaderElection.
---
 .../apache/ratis/server/impl/LeaderElection.java   | 10 ++--
 .../impl/RaftStateMachineExceptionTests.java       | 53 ++++++++++------------
 2 files changed, 27 insertions(+), 36 deletions(-)

diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderElection.java 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderElection.java
index b0b3113..8a8dc07 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderElection.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderElection.java
@@ -110,14 +110,16 @@ class LeaderElection implements Runnable {
   private final RaftServerImpl server;
 
   LeaderElection(RaftServerImpl server) {
-    this.name = server.getId() + ":" + server.getGroupId() + ":" + 
getClass().getSimpleName() + COUNT.incrementAndGet();
+    this.name = server.getMemberId() + ":" + getClass().getSimpleName() + 
COUNT.incrementAndGet();
     this.lifeCycle = new LifeCycle(this);
     this.daemon = new Daemon(this);
     this.server = server;
   }
 
   void start() {
-    lifeCycle.startAndTransition(daemon::start);
+    lifeCycle.transition(LifeCycle.State.STARTING);
+    lifeCycle.transition(LifeCycle.State.RUNNING);
+    daemon.start();
   }
 
   void shutdown() {
@@ -128,10 +130,6 @@ class LeaderElection implements Runnable {
   public void run() {
     try {
       askForVotes();
-    } catch (InterruptedException e) {
-      // the leader election thread is interrupted. The peer may already step
-      // down to a follower. The leader election should skip.
-      LOG.info("{} thread is interrupted gracefully; server={}", this, server);
     } catch(Throwable e) {
       final LifeCycle.State state = lifeCycle.getCurrentState();
       final String message = "Failed " + this + ", state=" + state;
diff --git 
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftStateMachineExceptionTests.java
 
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftStateMachineExceptionTests.java
index 7e6b376..f89699e 100644
--- 
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftStateMachineExceptionTests.java
+++ 
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftStateMachineExceptionTests.java
@@ -71,14 +71,17 @@ public abstract class 
RaftStateMachineExceptionTests<CLUSTER extends MiniRaftClu
     }
   }
 
+  {
+    final RaftProperties prop = getProperties();
+    prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY, 
StateMachineWithException.class, StateMachine.class);
+  }
+
   @Test
   public void testHandleStateMachineException() throws Exception {
-    final RaftProperties prop = getProperties();
-    prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
-        StateMachineWithException.class, StateMachine.class);
-    final MiniRaftCluster cluster = newCluster(3);
-    cluster.start();
+    runWithNewCluster(3, this::runTestHandleStateMachineException);
+  }
 
+  private void runTestHandleStateMachineException(CLUSTER cluster) throws 
Exception {
     RaftPeerId leaderId = RaftTestUtil.waitForLeader(cluster).getId();
 
     try(final RaftClient client = cluster.createClient(leaderId)) {
@@ -93,12 +96,10 @@ public abstract class 
RaftStateMachineExceptionTests<CLUSTER extends MiniRaftClu
 
   @Test
   public void testRetryOnStateMachineException() throws Exception {
-    final RaftProperties prop = getProperties();
-    prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
-        StateMachineWithException.class, StateMachine.class);
-    final MiniRaftCluster cluster = newCluster(3);
-    cluster.start();
+    runWithNewCluster(3, this::runTestRetryOnStateMachineException);
+  }
 
+  private void runTestRetryOnStateMachineException(CLUSTER cluster) throws 
Exception {
     RaftPeerId leaderId = RaftTestUtil.waitForLeader(cluster).getId();
 
     cluster.getLeaderAndSendFirstMessage(true);
@@ -141,38 +142,30 @@ public abstract class 
RaftStateMachineExceptionTests<CLUSTER extends MiniRaftClu
 
   @Test
   public void testRetryOnExceptionDuringReplication() throws Exception {
-    final RaftProperties prop = getProperties();
-    prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
-        StateMachineWithException.class, StateMachine.class);
-    final MiniRaftCluster cluster = newCluster(3);
-    cluster.start();
-    RaftTestUtil.waitForLeader(cluster);
-    RaftServerImpl leader = cluster.getLeader();
-    RaftPeerId leaderId = leader.getId();
+    runWithNewCluster(3, this::runTestRetryOnExceptionDuringReplication);
+  }
+
+  private void runTestRetryOnExceptionDuringReplication(CLUSTER cluster) 
throws Exception {
+    final RaftServerImpl oldLeader = RaftTestUtil.waitForLeader(cluster);
     cluster.getLeaderAndSendFirstMessage(true);
     // turn on the preAppend failure switch
     failPreAppend = true;
-    final RaftClient client = cluster.createClient(leaderId);
+    final RaftClient client = cluster.createClient(oldLeader.getId());
     final RaftClientRpc rpc = client.getClientRpc();
     final long callId = 999;
-    RaftClientRequest r = cluster.newRaftClientRequest(client.getId(), 
leaderId,
-        callId, new RaftTestUtil.SimpleMessage("message"));
+    final SimpleMessage message = new SimpleMessage("message");
+    RaftClientRequest r = cluster.newRaftClientRequest(client.getId(), 
oldLeader.getId(), callId, message);
     RaftClientReply reply = rpc.sendRequest(r);
     Objects.requireNonNull(reply.getStateMachineException());
 
-    RetryCache.CacheEntry oldEntry = RaftServerTestUtil.getRetryEntry(
-        leader, client.getId(), callId);
+    final RetryCache.CacheEntry oldEntry = 
RaftServerTestUtil.getRetryEntry(oldLeader, client.getId(), callId);
     Assert.assertNotNull(oldEntry);
     Assert.assertTrue(RaftServerTestUtil.isRetryCacheEntryFailed(oldEntry));
 
-    // At this point of time the old leader would have stepped down. wait for
-    // leader election to complete
-    RaftTestUtil.waitForLeader(cluster);
-    leader = cluster.getLeader();
-    leaderId = leader.getId();
+    // At this point of time the old leader would have stepped down. wait for 
leader election to complete
+    final RaftServerImpl leader = RaftTestUtil.waitForLeader(cluster);
     // retry
-    r = cluster.newRaftClientRequest(client.getId(), leaderId,
-        callId, new RaftTestUtil.SimpleMessage("message"));
+    r = cluster.newRaftClientRequest(client.getId(), leader.getId(), callId, 
message);
     reply = rpc.sendRequest(r);
     Objects.requireNonNull(reply.getStateMachineException());
 

Reply via email to