QuorumServerConfigBuilder.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zookeeper.server.quorum;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.zookeeper.PortAssignment;
/*
* Helper class to build / change Quorum Config String, like:
* server.1=127.0.0.1:11228:11231|127.0.0.1:11230:11229;11227
* server.2=127.0.0.1:11338:11331|127.0.0.1:11330:11229;11337
*
*/
public class QuorumServerConfigBuilder {
// map of (serverId -> clientPort)
private final Map<Integer, Integer> clientIds = new HashMap<>();
// map of (serverId -> (ServerAddress=host,quorumPort,electionPort) )
private final Map<Integer, List<ServerAddress>> serverAddresses = new HashMap<>();
private final String hostName;
private final int numberOfServers;
public QuorumServerConfigBuilder(String hostName, int numberOfServers, int numberOfServerAddresses) {
this.numberOfServers = numberOfServers;
this.hostName = hostName;
for (int serverId = 0; serverId < numberOfServers; serverId++) {
clientIds.put(serverId, PortAssignment.unique());
List<ServerAddress> addresses = new ArrayList<>();
serverAddresses.put(serverId, addresses);
for (int serverAddressId = 0; serverAddressId < numberOfServerAddresses; serverAddressId++) {
addresses.add(new ServerAddress(hostName));
}
}
}
public QuorumServerConfigBuilder(QuorumServerConfigBuilder otherBuilder) {
this.numberOfServers = otherBuilder.clientIds.size();
this.clientIds.putAll(otherBuilder.clientIds);
this.hostName = otherBuilder.hostName;
for (int i : otherBuilder.serverAddresses.keySet()) {
List<ServerAddress> clonedServerAddresses = otherBuilder.serverAddresses.get(i).stream()
.map(ServerAddress::clone).collect(Collectors.toList());
this.serverAddresses.put(i, clonedServerAddresses);
}
}
public int getClientPort(int serverId) {
return clientIds.get(serverId);
}
public ServerAddress getServerAddress(int serverId, int addressId) {
return serverAddresses.get(serverId).get(addressId);
}
public QuorumServerConfigBuilder changeHostName(int serverId, int addressId, String hostName) {
serverAddresses.get(serverId).get(addressId).setHost(hostName);
return this;
}
public QuorumServerConfigBuilder changeQuorumPort(int serverId, int addressId, int quorumPort) {
serverAddresses.get(serverId).get(addressId).setQuorumPort(quorumPort);
return this;
}
public QuorumServerConfigBuilder changeElectionPort(int serverId, int addressId, int electionPort) {
serverAddresses.get(serverId).get(addressId).setElectionPort(electionPort);
return this;
}
public QuorumServerConfigBuilder addNewServerAddress(int serverId) {
serverAddresses.get(serverId).add(new ServerAddress(hostName));
return this;
}
public QuorumServerConfigBuilder deleteLastServerAddress(int serverId) {
serverAddresses.get(serverId).remove(serverAddresses.get(serverId).size() - 1);
return this;
}
public String build() {
return String.join("\n", buildAsStringList());
}
public List<String> buildAsStringList() {
List<String> result = new ArrayList<>(numberOfServers);
for (int serverId = 0; serverId < numberOfServers; serverId++) {
String s = serverAddresses.get(serverId).stream()
.map(ServerAddress::toString)
.collect(Collectors.joining("|"));
result.add(String.format("server.%d=%s;%d", serverId, s, clientIds.get(serverId)));
}
return result;
}
public static class ServerAddress {
private String host;
private int quorumPort;
private int electionPort;
private ServerAddress(String host) {
this(host, PortAssignment.unique(), PortAssignment.unique());
}
private ServerAddress(String host, int quorumPort, int electionPort) {
this.host = host;
this.quorumPort = quorumPort;
this.electionPort = electionPort;
}
public String getHost() {
return host;
}
private void setHost(String host) {
this.host = host;
}
private void setQuorumPort(int quorumPort) {
this.quorumPort = quorumPort;
}
private void setElectionPort(int electionPort) {
this.electionPort = electionPort;
}
@Override
public ServerAddress clone() {
return new ServerAddress(host, quorumPort, electionPort);
}
@Override
public String toString() {
return String.format("%s:%d:%d", host, quorumPort, electionPort);
}
}
}