}
@Override
public ResourceAssignment computeResourceMapping(RebalancerConfig rebalancerConfig,
Cluster cluster, ResourceCurrentState currentState) {
FullAutoRebalancerContext config =
rebalancerConfig.getRebalancerContext(FullAutoRebalancerContext.class);
StateModelDefinition stateModelDef =
cluster.getStateModelMap().get(config.getStateModelDefId());
// Compute a preference list based on the current ideal state
List<PartitionId> partitions = new ArrayList<PartitionId>(config.getPartitionSet());
Map<ParticipantId, Participant> liveParticipants = cluster.getLiveParticipantMap();
Map<ParticipantId, Participant> allParticipants = cluster.getParticipantMap();
int replicas = -1;
if (config.anyLiveParticipant()) {
replicas = liveParticipants.size();
} else {
replicas = config.getReplicaCount();
}
// count how many replicas should be in each state
Map<State, String> upperBounds =
ConstraintBasedAssignment.stateConstraints(stateModelDef, config.getResourceId(),
cluster.getConfig());
LinkedHashMap<State, Integer> stateCountMap =
ConstraintBasedAssignment.stateCount(upperBounds, stateModelDef, liveParticipants.size(),
replicas);
// get the participant lists
List<ParticipantId> liveParticipantList =
new ArrayList<ParticipantId>(liveParticipants.keySet());
List<ParticipantId> allParticipantList =
new ArrayList<ParticipantId>(cluster.getParticipantMap().keySet());
// compute the current mapping from the current state
Map<PartitionId, Map<ParticipantId, State>> currentMapping =
currentMapping(config, currentState, stateCountMap);
// If there are nodes tagged with resource, use only those nodes
// If there are nodes tagged with resource name, use only those nodes
Set<ParticipantId> taggedNodes = new HashSet<ParticipantId>();
Set<ParticipantId> taggedLiveNodes = new HashSet<ParticipantId>();
if (config.getParticipantGroupTag() != null) {
for (ParticipantId participantId : allParticipantList) {
if (cluster.getParticipantMap().get(participantId).hasTag(config.getParticipantGroupTag())) {
taggedNodes.add(participantId);
if (liveParticipants.containsKey(participantId)) {
taggedLiveNodes.add(participantId);
}
}
}
if (!taggedLiveNodes.isEmpty()) {
// live nodes exist that have this tag
if (LOG.isInfoEnabled()) {
LOG.info("found the following participants with tag " + config.getParticipantGroupTag()
+ " for " + config.getResourceId() + ": " + taggedLiveNodes);
}
} else if (taggedNodes.isEmpty()) {
// no live nodes and no configured nodes have this tag
LOG.warn("Resource " + config.getResourceId() + " has tag "
+ config.getParticipantGroupTag() + " but no configured participants have this tag");
} else {
// configured nodes have this tag, but no live nodes have this tag
LOG.warn("Resource " + config.getResourceId() + " has tag "
+ config.getParticipantGroupTag() + " but no live participants have this tag");
}
allParticipantList = new ArrayList<ParticipantId>(taggedNodes);
liveParticipantList = new ArrayList<ParticipantId>(taggedLiveNodes);
}
// determine which nodes the replicas should live on
int maxPartition = config.getMaxPartitionsPerParticipant();
if (LOG.isInfoEnabled()) {
LOG.info("currentMapping: " + currentMapping);
LOG.info("stateCountMap: " + stateCountMap);
LOG.info("liveNodes: " + liveParticipantList);
LOG.info("allNodes: " + allParticipantList);
LOG.info("maxPartition: " + maxPartition);
}
ReplicaPlacementScheme placementScheme = new DefaultPlacementScheme();
_algorithm =
new AutoRebalanceStrategy(config.getResourceId(), partitions, stateCountMap, maxPartition,
placementScheme);
ZNRecord newMapping =
_algorithm.typedComputePartitionAssignment(liveParticipantList, currentMapping,
allParticipantList);
if (LOG.isInfoEnabled()) {
LOG.info("newMapping: " + newMapping);
}
// compute a full partition mapping for the resource
if (LOG.isDebugEnabled()) {
LOG.debug("Processing resource:" + config.getResourceId());
}
ResourceAssignment partitionMapping = new ResourceAssignment(config.getResourceId());
for (PartitionId partition : partitions) {
Set<ParticipantId> disabledParticipantsForPartition =
ConstraintBasedAssignment.getDisabledParticipants(allParticipants, partition);
List<String> rawPreferenceList = newMapping.getListField(partition.stringify());
if (rawPreferenceList == null) {
rawPreferenceList = Collections.emptyList();
}
List<ParticipantId> preferenceList =
Lists.transform(rawPreferenceList, new Function<String, ParticipantId>() {
@Override
public ParticipantId apply(String participantName) {
return ParticipantId.from(participantName);
}
});
preferenceList =
ConstraintBasedAssignment.getPreferenceList(cluster, partition, preferenceList);
Map<ParticipantId, State> bestStateForPartition =
ConstraintBasedAssignment.computeAutoBestStateForPartition(upperBounds,
liveParticipants.keySet(), stateModelDef, preferenceList,
currentState.getCurrentStateMap(config.getResourceId(), partition),
disabledParticipantsForPartition);
partitionMapping.addReplicaMap(partition, bestStateForPartition);
}
return partitionMapping;
}