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 aeec3096 RATIS-1594. Support ADD mode to SetConfiguration (#658)
aeec3096 is described below
commit aeec3096bc11cfcacfe1bbcc208cf4d61f648644
Author: Yaolong Liu <[email protected]>
AuthorDate: Tue Jul 5 04:17:42 2022 +0800
RATIS-1594. Support ADD mode to SetConfiguration (#658)
---
.../java/org/apache/ratis/client/api/AdminApi.java | 22 +++-
.../org/apache/ratis/client/impl/AdminImpl.java | 7 +-
.../apache/ratis/client/impl/ClientProtoUtils.java | 27 ++++-
.../ratis/protocol/SetConfigurationRequest.java | 111 +++++++++++++++++----
ratis-proto/src/main/proto/Raft.proto | 5 +
.../apache/ratis/server/impl/LeaderStateImpl.java | 5 +-
.../ratis/server/impl/RaftConfigurationImpl.java | 20 +++-
.../apache/ratis/server/impl/RaftServerImpl.java | 29 +++++-
.../apache/ratis/server/impl/MiniRaftCluster.java | 2 +-
.../server/impl/RaftReconfigurationBaseTest.java | 28 ++++++
.../ratis/server/impl/RaftServerTestUtil.java | 3 +-
11 files changed, 217 insertions(+), 42 deletions(-)
diff --git
a/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java
b/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java
index 706c917b..86e25ef9 100644
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java
+++ b/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java
@@ -20,6 +20,7 @@ package org.apache.ratis.client.api;
import org.apache.ratis.protocol.RaftClientReply;
import org.apache.ratis.protocol.RaftPeer;
import org.apache.ratis.protocol.RaftPeerId;
+import org.apache.ratis.protocol.SetConfigurationRequest;
import java.io.IOException;
import java.util.Arrays;
@@ -31,6 +32,9 @@ import java.util.List;
* such as setting raft configuration and transferring leadership.
*/
public interface AdminApi {
+ RaftClientReply setConfiguration(SetConfigurationRequest.Arguments arguments)
+ throws IOException;
+
/** The same as setConfiguration(serversInNewConf, Collections.emptyList()).
*/
default RaftClientReply setConfiguration(List<RaftPeer> serversInNewConf)
throws IOException {
return setConfiguration(serversInNewConf, Collections.emptyList());
@@ -38,17 +42,27 @@ public interface AdminApi {
/** The same as setConfiguration(Arrays.asList(serversInNewConf)). */
default RaftClientReply setConfiguration(RaftPeer[] serversInNewConf) throws
IOException {
- return setConfiguration(Arrays.asList(serversInNewConf));
+ return setConfiguration(Arrays.asList(serversInNewConf),
Collections.emptyList());
}
/** Set the configuration request to the raft service. */
- RaftClientReply setConfiguration(List<RaftPeer> serversInNewConf,
List<RaftPeer> listenersInNewConf)
- throws IOException;
+ default RaftClientReply setConfiguration(List<RaftPeer> serversInNewConf,
List<RaftPeer> listenersInNewConf)
+ throws IOException {
+ return setConfiguration(SetConfigurationRequest.Arguments
+ .newBuilder()
+ .setServersInNewConf(serversInNewConf)
+ .setListenersInNewConf(listenersInNewConf)
+ .build());
+ }
/** The same as setConfiguration(Arrays.asList(serversInNewConf),
Arrays.asList(listenersInNewConf)). */
default RaftClientReply setConfiguration(RaftPeer[] serversInNewConf,
RaftPeer[] listenersInNewConf)
throws IOException {
- return setConfiguration(Arrays.asList(serversInNewConf),
Arrays.asList(listenersInNewConf));
+ return setConfiguration(SetConfigurationRequest.Arguments
+ .newBuilder()
+ .setListenersInNewConf(serversInNewConf)
+ .setListenersInNewConf(listenersInNewConf)
+ .build());
}
/** Transfer leadership to the given server.*/
diff --git
a/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java
b/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java
index 1bb5cee8..44551543 100644
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java
+++ b/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java
@@ -36,16 +36,15 @@ class AdminImpl implements AdminApi {
this.client = Objects.requireNonNull(client, "client == null");
}
- @Override
- public RaftClientReply setConfiguration(List<RaftPeer> peersInNewConf,
List<RaftPeer> listenersInNewConf)
- throws IOException {
+ public RaftClientReply setConfiguration(SetConfigurationRequest.Arguments
arguments) throws IOException {
+ List<RaftPeer> peersInNewConf = arguments.getServersInNewConf();
Objects.requireNonNull(peersInNewConf, "peersInNewConf == null");
final long callId = CallId.getAndIncrement();
// also refresh the rpc proxies for these peers
client.getClientRpc().addRaftPeers(peersInNewConf);
return client.io().sendRequestWithRetry(() -> new SetConfigurationRequest(
- client.getId(), client.getLeaderId(), client.getGroupId(), callId,
peersInNewConf, listenersInNewConf));
+ client.getId(), client.getLeaderId(), client.getGroupId(), callId,
arguments));
}
@Override
diff --git
a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
index 3f8fa459..fd9f49f5 100644
---
a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
+++
b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
@@ -499,22 +499,39 @@ public interface ClientProtoUtils {
static SetConfigurationRequest toSetConfigurationRequest(
SetConfigurationRequestProto p) {
+ final SetConfigurationRequest.Arguments arguments =
SetConfigurationRequest.Arguments.newBuilder()
+ .setServersInNewConf(ProtoUtils.toRaftPeers(p.getPeersList()))
+ .setListenersInNewConf(ProtoUtils.toRaftPeers(p.getListenersList()))
+ .setMode(toSetConfigurationMode(p.getMode()))
+ .build();
final RaftRpcRequestProto m = p.getRpcRequest();
- final List<RaftPeer> peers = ProtoUtils.toRaftPeers(p.getPeersList());
- final List<RaftPeer> listeners =
ProtoUtils.toRaftPeers(p.getListenersList());
return new SetConfigurationRequest(
ClientId.valueOf(m.getRequestorId()),
RaftPeerId.valueOf(m.getReplyId()),
ProtoUtils.toRaftGroupId(m.getRaftGroupId()),
- p.getRpcRequest().getCallId(), peers, listeners);
+ p.getRpcRequest().getCallId(), arguments);
+ }
+
+ static SetConfigurationRequest.Mode toSetConfigurationMode(
+ SetConfigurationRequestProto.Mode p) {
+ switch (p) {
+ case SET_UNCONDITIONALLY:
+ return SetConfigurationRequest.Mode.SET_UNCONDITIONALLY;
+ case ADD:
+ return SetConfigurationRequest.Mode.ADD;
+ default:
+ throw new IllegalArgumentException("Unexpected mode " + p);
+ }
}
static SetConfigurationRequestProto toSetConfigurationRequestProto(
SetConfigurationRequest request) {
+ final SetConfigurationRequest.Arguments arguments = request.getArguments();
return SetConfigurationRequestProto.newBuilder()
.setRpcRequest(toRaftRpcRequestProtoBuilder(request))
- .addAllPeers(ProtoUtils.toRaftPeerProtos(request.getPeersInNewConf()))
-
.addAllListeners(ProtoUtils.toRaftPeerProtos(request.getListenersInNewConf()))
+
.addAllPeers(ProtoUtils.toRaftPeerProtos(arguments.getPeersInNewConf(RaftPeerRole.FOLLOWER)))
+
.addAllListeners(ProtoUtils.toRaftPeerProtos(arguments.getPeersInNewConf(RaftPeerRole.LISTENER)))
+
.setMode(SetConfigurationRequestProto.Mode.valueOf(arguments.getMode().name()))
.build();
}
diff --git
a/ratis-common/src/main/java/org/apache/ratis/protocol/SetConfigurationRequest.java
b/ratis-common/src/main/java/org/apache/ratis/protocol/SetConfigurationRequest.java
index da551f2d..ef3cee92 100644
---
a/ratis-common/src/main/java/org/apache/ratis/protocol/SetConfigurationRequest.java
+++
b/ratis-common/src/main/java/org/apache/ratis/protocol/SetConfigurationRequest.java
@@ -17,39 +17,116 @@
*/
package org.apache.ratis.protocol;
+import org.apache.ratis.proto.RaftProtos;
import org.apache.ratis.util.Preconditions;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
public class SetConfigurationRequest extends RaftClientRequest {
- private final List<RaftPeer> peers;
- private final List<RaftPeer> listeners;
- public SetConfigurationRequest(ClientId clientId, RaftPeerId serverId,
- RaftGroupId groupId, long callId, List<RaftPeer> peers) {
- this(clientId, serverId, groupId, callId, peers, Collections.emptyList());
+ public enum Mode {
+ SET_UNCONDITIONALLY,
+ ADD
}
- public SetConfigurationRequest(ClientId clientId, RaftPeerId serverId,
- RaftGroupId groupId, long callId, List<RaftPeer> peers, List<RaftPeer>
listeners) {
- super(clientId, serverId, groupId, callId, true, writeRequestType());
- this.peers = peers != null? Collections.unmodifiableList(peers):
Collections.emptyList();
- this.listeners = listeners != null?
Collections.unmodifiableList(listeners) : Collections.emptyList();
- Preconditions.assertUnique(this.peers);
- Preconditions.assertUnique(this.listeners);
+ public static final class Arguments {
+ private final List<RaftPeer> serversInNewConf;
+ private final List<RaftPeer> listenersInNewConf;
+ private final Mode mode;
+
+ private Arguments(List<RaftPeer> serversInNewConf, List<RaftPeer>
listenersInNewConf,Mode mode) {
+ this.serversInNewConf = Optional.ofNullable(serversInNewConf)
+ .map(Collections::unmodifiableList)
+ .orElseGet(Collections::emptyList);
+ this.listenersInNewConf = Optional.ofNullable(listenersInNewConf)
+ .map(Collections::unmodifiableList)
+ .orElseGet(Collections::emptyList);
+ this.mode = mode;
+
+ Preconditions.assertUnique(serversInNewConf);
+ Preconditions.assertUnique(listenersInNewConf);
+ }
+
+ public List<RaftPeer> getPeersInNewConf(RaftProtos.RaftPeerRole role) {
+ switch (role) {
+ case FOLLOWER: return serversInNewConf;
+ case LISTENER: return listenersInNewConf;
+ default:
+ throw new IllegalArgumentException("Unexpected role " + role);
+ }
+ }
+
+ public List<RaftPeer> getServersInNewConf() {
+ return serversInNewConf;
+ }
+
+ public Mode getMode() {
+ return mode;
+ }
+ @Override
+ public String toString() {
+ return getMode()
+ + ", servers:" + getPeersInNewConf(RaftProtos.RaftPeerRole.FOLLOWER)
+ + ", listeners:" +
getPeersInNewConf(RaftProtos.RaftPeerRole.LISTENER);
+
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private List<RaftPeer> serversInNewConf;
+ private List<RaftPeer> listenersInNewConf = Collections.emptyList();
+ private Mode mode = Mode.SET_UNCONDITIONALLY;
+
+ public Builder setServersInNewConf(List<RaftPeer> serversInNewConf) {
+ this.serversInNewConf = serversInNewConf;
+ return this;
+ }
+
+ public Builder setListenersInNewConf(List<RaftPeer> listenersInNewConf) {
+ this.listenersInNewConf = listenersInNewConf;
+ return this;
+ }
+
+ public Builder setServersInNewConf(RaftPeer[] serversInNewConfArray) {
+ this.serversInNewConf = Arrays.asList(serversInNewConfArray);
+ return this;
+ }
+
+ public Builder setListenersInNewConf(RaftPeer[] listenersInNewConfArray)
{
+ this.listenersInNewConf = Arrays.asList(listenersInNewConfArray);
+ return this;
+ }
+
+ public Builder setMode(Mode mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ public Arguments build() {
+ return new Arguments(serversInNewConf, listenersInNewConf, mode);
+ }
+ }
}
+ private final Arguments arguments;
- public List<RaftPeer> getPeersInNewConf() {
- return peers;
+ public SetConfigurationRequest(ClientId clientId, RaftPeerId serverId,
+ RaftGroupId groupId, long callId, Arguments arguments) {
+ super(clientId, serverId, groupId, callId, true, writeRequestType());
+ this.arguments = arguments;
}
- public List<RaftPeer> getListenersInNewConf() {
- return listeners;
+ public Arguments getArguments() {
+ return arguments;
}
@Override
public String toString() {
- return super.toString() + ", peers:" + getPeersInNewConf();
+ return super.toString() + ", " + getArguments();
}
}
diff --git a/ratis-proto/src/main/proto/Raft.proto
b/ratis-proto/src/main/proto/Raft.proto
index df2c3d88..f6b38c14 100644
--- a/ratis-proto/src/main/proto/Raft.proto
+++ b/ratis-proto/src/main/proto/Raft.proto
@@ -406,9 +406,14 @@ message RaftClientReplyProto {
// setConfiguration request
message SetConfigurationRequestProto {
+ enum Mode {
+ SET_UNCONDITIONALLY = 0;
+ ADD = 1;
+ }
RaftRpcRequestProto rpcRequest = 1;
repeated RaftPeerProto peers = 2;
repeated RaftPeerProto listeners = 3;
+ optional Mode mode = 4;
}
// transfer leadership request
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 7265f3a8..648a0eb3 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
@@ -364,12 +364,11 @@ class LeaderStateImpl implements LeaderState {
/**
* Start bootstrapping new peers
*/
- PendingRequest startSetConfiguration(SetConfigurationRequest request) {
+ PendingRequest startSetConfiguration(SetConfigurationRequest request,
List<RaftPeer> peersInNewConf) {
LOG.info("{}: startSetConfiguration {}", this, request);
Preconditions.assertTrue(running && !inStagingState());
- final List<RaftPeer> peersInNewConf = request.getPeersInNewConf();
- final List<RaftPeer> listenersInNewConf = request.getListenersInNewConf();
+ final List<RaftPeer> listenersInNewConf =
request.getArguments().getPeersInNewConf(RaftPeerRole.LISTENER);
final Collection<RaftPeer> peersToBootStrap =
server.getRaftConf().filterNotContainedInConf(peersInNewConf);
final Collection<RaftPeer> listenersToBootStrap=
server.getRaftConf().filterNotContainedInConf(listenersInNewConf);
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 ed661a99..9f203b23 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
@@ -242,12 +242,26 @@ final class RaftConfigurationImpl implements
RaftConfiguration {
return logEntryIndex + ": " + conf + ", old=" + oldConf;
}
- boolean hasNoChange(Collection<RaftPeer> newMembers) {
- if (!isStable() || conf.size() != newMembers.size()) {
+ boolean hasNoChange(Collection<RaftPeer> newMembers, Collection<RaftPeer>
newListeners) {
+ if (!isStable() || conf.size() != newMembers.size()
+ || conf.getPeers(RaftPeerRole.LISTENER).size() != newListeners.size())
{
return false;
}
for (RaftPeer peer : newMembers) {
- if (!conf.contains(peer.getId()) ||
conf.getPeer(peer.getId()).getPriority() != peer.getPriority()) {
+ final RaftPeer inConf = conf.getPeer(peer.getId());
+ if (inConf == null) {
+ return false;
+ }
+ if (inConf.getPriority() != peer.getPriority()) {
+ return false;
+ }
+ }
+ for (RaftPeer peer : newListeners) {
+ final RaftPeer inConf = conf.getPeer(peer.getId(),
RaftPeerRole.LISTENER);
+ if (inConf == null) {
+ return false;
+ }
+ if (inConf.getPriority() != peer.getPriority()) {
return false;
}
}
diff --git
a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
index fe54dd08..5b7be2e2 100644
---
a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
+++
b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
@@ -78,6 +78,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static
org.apache.ratis.proto.RaftProtos.AppendEntriesReplyProto.AppendResult.INCONSISTENCY;
import static
org.apache.ratis.proto.RaftProtos.AppendEntriesReplyProto.AppendResult.NOT_LEADER;
@@ -1086,7 +1087,7 @@ class RaftServerImpl implements RaftServer.Division,
return reply;
}
- final List<RaftPeer> peersInNewConf = request.getPeersInNewConf();
+ final SetConfigurationRequest.Arguments arguments = request.getArguments();
final PendingRequest pending;
synchronized (this) {
reply = checkLeaderState(request, null, false);
@@ -1102,20 +1103,40 @@ class RaftServerImpl implements RaftServer.Division,
"Reconfiguration is already in progress: " + current);
}
+ final List<RaftPeer> serversInNewConf;
+ final List<RaftPeer> listenersInNewConf;
+ if (arguments.getMode() == SetConfigurationRequest.Mode.ADD) {
+ serversInNewConf = add(RaftPeerRole.FOLLOWER, current, arguments);
+ listenersInNewConf = add(RaftPeerRole.LISTENER, current, arguments);
+ } else {
+ serversInNewConf = arguments.getPeersInNewConf(RaftPeerRole.FOLLOWER);
+ listenersInNewConf =
arguments.getPeersInNewConf(RaftPeerRole.LISTENER);
+ }
+
// return success with a null message if the new conf is the same as the
current
- if (current.hasNoChange(peersInNewConf)) {
+ if (current.hasNoChange(serversInNewConf, listenersInNewConf)) {
pending = new PendingRequest(request);
pending.setReply(newSuccessReply(request));
return pending.getFuture();
}
- getRaftServer().addRaftPeers(peersInNewConf);
+ getRaftServer().addRaftPeers(serversInNewConf);
// add staging state into the leaderState
- pending = leaderState.startSetConfiguration(request);
+ pending = leaderState.startSetConfiguration(request, serversInNewConf);
}
return pending.getFuture();
}
+ static List<RaftPeer> add(RaftPeerRole role, RaftConfigurationImpl conf,
SetConfigurationRequest.Arguments args) {
+ final Map<RaftPeerId, RaftPeer> inConfs = conf.getAllPeers(role).stream()
+ .collect(Collectors.toMap(RaftPeer::getId, Function.identity()));
+
+ final List<RaftPeer> toAdds = args.getPeersInNewConf(role);
+ toAdds.stream().map(RaftPeer::getId).forEach(inConfs::remove);
+
+ return Stream.concat(toAdds.stream(),
inConfs.values().stream()).collect(Collectors.toList());
+ }
+
/**
* check if the remote peer is not included in the current conf
* and should shutdown. should shutdown if all the following stands:
diff --git
a/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
b/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
index 6ac14d73..61db4936 100644
---
a/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
+++
b/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
@@ -740,7 +740,7 @@ public abstract class MiniRaftCluster implements Closeable {
ClientId clientId, RaftPeerId leaderId,
RaftPeer... peers) {
return new SetConfigurationRequest(clientId, leaderId, getGroupId(),
CallId.getDefault(),
- Arrays.asList(peers), Collections.emptyList());
+
SetConfigurationRequest.Arguments.newBuilder().setServersInNewConf(peers).build());
}
public void setConfiguration(RaftPeer... peers) throws IOException {
diff --git
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
index f6580e84..d764988e 100644
---
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
+++
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
@@ -190,6 +190,34 @@ public abstract class RaftReconfigurationBaseTest<CLUSTER
extends MiniRaftCluste
waitAndCheckNewConf(cluster, allPeers, 2, null);
}
+ @Test
+ public void testSetConfigurationInAddMode() throws Exception {
+ runWithNewCluster(2, this::runTestSetConfigurationInAddMode);
+ }
+
+ private void runTestSetConfigurationInAddMode(CLUSTER cluster) throws
Exception {
+ final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
+
+ PeerChanges change = cluster.addNewPeers(1, true);
+ List<RaftPeer> peers = Arrays.asList(change.newPeers);
+
+ try (final RaftClient client = cluster.createClient(leader.getId())) {
+ for (int i = 0; i < 10; i++) {
+ RaftClientReply reply = client.io().send(new SimpleMessage("m" + i));
+ Assert.assertTrue(reply.isSuccess());
+ }
+ RaftClientReply reply = client.admin().setConfiguration(
+ SetConfigurationRequest.Arguments.newBuilder()
+ .setServersInNewConf(peers)
+ .setMode(SetConfigurationRequest.Mode.ADD).build());
+ Assert.assertTrue(reply.isSuccess());
+ waitAndCheckNewConf(cluster, change.allPeersInNewConf, 0, null);
+ }
+ cluster.close();
+ }
+
+
+
@Test(timeout = 30000)
public void testReconfTwice() throws Exception {
runWithNewCluster(3, this::runTestReconfTwice);
diff --git
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftServerTestUtil.java
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftServerTestUtil.java
index f3cc38c9..e6e60eb1 100644
---
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftServerTestUtil.java
+++
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftServerTestUtil.java
@@ -46,6 +46,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;
@@ -99,7 +100,7 @@ public class RaftServerTestUtil {
if (current.containsInConf(server.getId())) {
numIncluded++;
Assert.assertTrue(conf.isStable());
- Assert.assertTrue(conf.hasNoChange(peers));
+ Assert.assertTrue(conf.hasNoChange(peers, Collections.emptyList()));
} else if (server.getInfo().isAlive()) {
// The server is successfully removed from the conf
// It may not be shutdown since it may not be able to talk to the new
leader (who is not in its conf).