in helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java [2000:2082]
void rebalance(String clusterName, String resourceName, int replica, String keyPrefix,
List<String> instanceNames, String groupId) {
logger.info("Rebalance resource {} with replica {} in cluster {}.", resourceName, replica,
clusterName);
// ensure we get the same idealState with the same set of instances
Collections.sort(instanceNames);
IdealState idealState = getResourceIdealState(clusterName, resourceName);
if (idealState == null) {
throw new HelixException("Resource: " + resourceName + " has NOT been added yet");
}
if (groupId != null && groupId.length() > 0) {
idealState.setInstanceGroupTag(groupId);
}
idealState.setReplicas(Integer.toString(replica));
int partitions = idealState.getNumPartitions();
String stateModelName = idealState.getStateModelDefRef();
StateModelDefinition stateModDef = getStateModelDef(clusterName, stateModelName);
if (stateModDef == null) {
throw new HelixException("cannot find state model: " + stateModelName);
}
// StateModelDefinition def = new StateModelDefinition(stateModDef);
List<String> statePriorityList = stateModDef.getStatesPriorityList();
String masterStateValue = null;
String slaveStateValue = null;
replica--;
for (String state : statePriorityList) {
String count = stateModDef.getNumInstancesPerState(state);
if (count.equals("1")) {
if (masterStateValue != null) {
throw new HelixException("Invalid or unsupported state model definition");
}
masterStateValue = state;
} else if (count.equalsIgnoreCase(StateModelDefinition.STATE_REPLICA_COUNT_ALL_REPLICAS)) {
if (slaveStateValue != null) {
throw new HelixException("Invalid or unsupported state model definition");
}
slaveStateValue = state;
} else if (count.equalsIgnoreCase(
StateModelDefinition.STATE_REPLICA_COUNT_ALL_CANDIDATE_NODES)) {
if (!(masterStateValue == null && slaveStateValue == null)) {
throw new HelixException("Invalid or unsupported state model definition");
}
replica = instanceNames.size() - 1;
masterStateValue = slaveStateValue = state;
}
}
if (masterStateValue == null && slaveStateValue == null) {
throw new HelixException("Invalid or unsupported state model definition");
}
if (masterStateValue == null) {
masterStateValue = slaveStateValue;
}
if (idealState.getRebalanceMode() != RebalanceMode.FULL_AUTO
&& idealState.getRebalanceMode() != RebalanceMode.USER_DEFINED) {
ZNRecord newIdealState = DefaultIdealStateCalculator
.calculateIdealState(instanceNames, partitions, replica, keyPrefix, masterStateValue,
slaveStateValue);
// for now keep mapField in SEMI_AUTO mode and remove listField in CUSTOMIZED mode
if (idealState.getRebalanceMode() == RebalanceMode.SEMI_AUTO) {
idealState.getRecord().setListFields(newIdealState.getListFields());
// TODO: need consider to remove this.
idealState.getRecord().setMapFields(newIdealState.getMapFields());
}
if (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) {
idealState.getRecord().setMapFields(newIdealState.getMapFields());
}
} else {
for (int i = 0; i < partitions; i++) {
String partitionName = keyPrefix + "_" + i;
idealState.getRecord().setMapField(partitionName, new HashMap<String, String>());
idealState.getRecord().setListField(partitionName, new ArrayList<String>());
}
}
setResourceIdealState(clusterName, resourceName, idealState);
}