@Override public boolean verify() throws Exception { ClusterAccessor clusterAccessor = new ClusterAccessor(ClusterId.from(_clusterName), _accessor); Cluster cluster = clusterAccessor.readCluster(); List<ParticipantId> liveInstances = new ArrayList<ParticipantId>(); liveInstances.addAll(cluster.getLiveParticipantMap().keySet()); boolean success = verifyLiveNodes(liveInstances); if (!success) { LOG.info( "liveNodes not match, expect: " + _expectSortedLiveNodes + ", actual: " + liveInstances); return false; } BestPossibleStateOutput bestPossbileStates = calculateBestPossibleState(cluster); Map<String, ExternalView> externalViews = _accessor.getChildValuesMap(_keyBuilder.externalViews()); // TODO all ideal-states should be included in external-views for (String resourceName : externalViews.keySet()) { ExternalView externalView = externalViews.get(resourceName); ResourceAssignment assignment = bestPossbileStates.getResourceAssignment(ResourceId.from(resourceName)); final Map<PartitionId, Map<String, String>> bestPossibleState = Maps.newHashMap(); for (PartitionId partitionId : assignment.getMappedPartitionIds()) { Map<String, String> rawStateMap = ResourceAssignment.stringMapFromReplicaMap(assignment.getReplicaMap(partitionId)); bestPossibleState.put(partitionId, rawStateMap); } success = verifyExternalView(externalView, bestPossibleState); if (!success) { LOG.info("external-view for resource: " + resourceName + " not match"); return false; } } return true; }
@Override public ResourceAssignment computeResourceMapping( RebalancerConfiguration rebalancerConfig, ResourceAssignment prevAssignment, Cluster cluster, ResourceCurrentState currentState) { FullAutoRebalancerConfig config = BasicRebalancerConfig.convert(rebalancerConfig, FullAutoRebalancerConfig.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 (partitions.size() > 0 && config.getAnyLiveParticipant(partitions.get(0))) { 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.isDebugEnabled()) { LOG.debug( "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.isDebugEnabled()) { LOG.debug("currentMapping: " + currentMapping); LOG.debug("stateCountMap: " + stateCountMap); LOG.debug("liveNodes: " + liveParticipantList); LOG.debug("allNodes: " + allParticipantList); LOG.debug("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.toString()); 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; }