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/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new c8f4c46b0 RATIS-1870. Refactor hasMajority code during configuration 
changes. (#902)
c8f4c46b0 is described below

commit c8f4c46b06c85cf4ab950d33fc447eb01f71e953
Author: William Song <[email protected]>
AuthorDate: Tue Aug 15 02:15:39 2023 +0800

    RATIS-1870. Refactor hasMajority code during configuration changes. (#902)
---
 .../apache/ratis/server/impl/LeaderStateImpl.java  | 33 ++--------------------
 .../ratis/server/impl/PeerConfiguration.java       | 16 +++++++----
 .../ratis/server/impl/RaftConfigurationImpl.java   | 20 +++++++++++++
 3 files changed, 33 insertions(+), 36 deletions(-)

diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
index 7ea4d738d..5dfbc009b 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
@@ -875,36 +875,7 @@ class LeaderStateImpl implements LeaderState {
 
   private boolean hasMajority(Predicate<RaftPeerId> isAcked) {
     final RaftPeerId selfId = server.getId();
-    final RaftConfigurationImpl conf = server.getRaftConf();
-
-    final CurrentOldFollowerInfos infos = 
followerInfoMap.getFollowerInfos(conf);
-    final List<FollowerInfo> followers = infos.getCurrent();
-    final boolean includeSelf = conf.containsInConf(selfId);
-    final boolean newConf = hasMajority(isAcked, followers, includeSelf);
-
-    if (!conf.isTransitional()) {
-      return newConf;
-    } else {
-      final List<FollowerInfo> oldFollowers = infos.getOld();
-      final boolean includeSelfInOldConf = conf.containsInOldConf(selfId);
-      final boolean oldConf = hasMajority(isAcked, oldFollowers, 
includeSelfInOldConf);
-      return newConf && oldConf;
-    }
-  }
-
-  private boolean hasMajority(Predicate<RaftPeerId> isAcked, 
List<FollowerInfo> followers, boolean includeSelf) {
-    if (followers.isEmpty() && !includeSelf) {
-      return true;
-    }
-
-    int count = includeSelf ? 1 : 0;
-    for (FollowerInfo follower: followers) {
-      if (isAcked.test(follower.getId())) {
-        count++;
-      }
-    }
-    final int size = includeSelf ? followers.size() + 1 : followers.size();
-    return count > size / 2;
+    return server.getRaftConf().hasMajority(isAcked, selfId);
   }
 
   private void updateCommit(LogEntryHeader[] entriesToCommit) {
@@ -1094,7 +1065,7 @@ class LeaderStateImpl implements LeaderState {
     final long readIndex = server.getRaftLog().getLastCommittedIndex();
 
     // if group contains only one member, fast path
-    if (server.getRaftConf().getCurrentPeers().size() == 1) {
+    if (server.getRaftConf().isSingleton()) {
       return CompletableFuture.completedFuture(readIndex);
     }
 
diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/PeerConfiguration.java
 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/PeerConfiguration.java
index 38e3602e8..600667c38 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/PeerConfiguration.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/PeerConfiguration.java
@@ -31,6 +31,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 /**
@@ -150,12 +151,17 @@ class PeerConfiguration {
 
   boolean hasMajority(Collection<RaftPeerId> others, RaftPeerId selfId) {
     Preconditions.assertTrue(!others.contains(selfId));
-    int num = 0;
-    if (contains(selfId)) {
-      num++;
+    return hasMajority(others::contains, contains(selfId));
+  }
+
+  boolean hasMajority(Predicate<RaftPeerId> activePeers, boolean includeSelf) {
+    if (peers.isEmpty() && !includeSelf) {
+      return true;
     }
-    for (RaftPeerId other : others) {
-      if (contains(other)) {
+
+    int num = includeSelf ? 1 : 0;
+    for (RaftPeerId peerId: peers.keySet()) {
+      if (activePeers.test(peerId)) {
         num++;
       }
     }
diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftConfigurationImpl.java
 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftConfigurationImpl.java
index da9481a2e..aba5ae176 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftConfigurationImpl.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftConfigurationImpl.java
@@ -30,6 +30,7 @@ import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
@@ -238,6 +239,20 @@ final class RaftConfigurationImpl implements 
RaftConfiguration {
         (oldConf == null || oldConf.hasMajority(others, selfId));
   }
 
+  /** @return true if the self id together with the acknowledged followers 
reach majority. */
+  boolean hasMajority(Predicate<RaftPeerId> followers, RaftPeerId selfId) {
+    final boolean includeInCurrent = containsInConf(selfId);
+    final boolean hasMajorityInNewConf = conf.hasMajority(followers, 
includeInCurrent);
+
+    if (!isTransitional()) {
+      return hasMajorityInNewConf;
+    } else {
+      final boolean includeInOldConf = containsInOldConf(selfId);
+      final boolean hasMajorityInOldConf = oldConf.hasMajority(followers, 
includeInOldConf);
+      return hasMajorityInOldConf && hasMajorityInNewConf;
+    }
+  }
+
   int getMajorityCount() {
     return conf.getMajorityCount();
   }
@@ -248,6 +263,11 @@ final class RaftConfigurationImpl implements 
RaftConfiguration {
             (oldConf != null && oldConf.majorityRejectVotes(rejects));
   }
 
+  /** @return true if only one voting member (the leader) in the cluster */
+  boolean isSingleton() {
+    return getCurrentPeers().size() == 1 && getPreviousPeers().size() <= 1;
+  }
+
   @Override
   public String toString() {
     return logEntryIndex + ": " + conf + ", old=" + oldConf;

Reply via email to