This is an automated email from the ASF dual-hosted git repository. szetszwo pushed a commit to branch branch-2_readIndex in repository https://gitbox.apache.org/repos/asf/ratis.git
commit ee8aef255cf622c49297ca7b90d44db06c5dfe6d Author: Kaijie Chen <[email protected]> AuthorDate: Tue Mar 14 10:18:23 2023 +0800 RATIS-1796. Fix TransferLeadership stopped by heartbeat from old leader (#844) (cherry picked from commit 05c0db0444eaade1b18e49465c3cde2ea5336485) --- .../org/apache/ratis/server/impl/LeaderElection.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 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 5f79940cb..86ec62325 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 @@ -187,16 +187,23 @@ class LeaderElection implements Runnable { private final RaftServerImpl server; private final boolean skipPreVote; + private final ConfAndTerm round0; - LeaderElection(RaftServerImpl server, boolean skipPreVote) { + LeaderElection(RaftServerImpl server, boolean force) { this.name = server.getMemberId() + "-" + JavaUtils.getClassSimpleName(getClass()) + COUNT.incrementAndGet(); this.lifeCycle = new LifeCycle(this); this.daemon = Daemon.newBuilder().setName(name).setRunnable(this) .setThreadGroup(server.getThreadGroup()).build(); this.server = server; - this.skipPreVote = skipPreVote || + this.skipPreVote = force || !RaftServerConfigKeys.LeaderElection.preVote( server.getRaftServer().getProperties()); + try { + // increase term of the candidate in advance if it's forced to election + this.round0 = force ? server.getState().initElection(Phase.ELECTION) : null; + } catch (IOException e) { + throw new IllegalStateException(name + ": Failed to initialize election", e); + } } void start() { @@ -303,7 +310,10 @@ class LeaderElection implements Runnable { if (!shouldRun()) { return false; } - final ConfAndTerm confAndTerm = server.getState().initElection(phase); + // If round0 is non-null, we have already called initElection in the constructor, + // reuse round0 to avoid initElection again for the first round + final ConfAndTerm confAndTerm = (round == 0 && round0 != null) ? + round0 : server.getState().initElection(phase); electionTerm = confAndTerm.getTerm(); conf = confAndTerm.getConf(); }
