Search in sources :

Example 1 with PartitionStateMap

use of org.apache.helix.controller.common.PartitionStateMap in project helix by apache.

the class IntermediateStateCalcStage method computeIntermediatePartitionState.

private PartitionStateMap computeIntermediatePartitionState(ClusterDataCache cache, ClusterStatusMonitor clusterStatusMonitor, IdealState idealState, Resource resource, CurrentStateOutput currentStateOutput, PartitionStateMap bestPossiblePartitionStateMap, Map<String, List<String>> preferenceLists, StateTransitionThrottleController throttleController) {
    String resourceName = resource.getResourceName();
    logger.debug("Processing resource:" + resourceName);
    if (!throttleController.isThrottleEnabled() || !IdealState.RebalanceMode.FULL_AUTO.equals(idealState.getRebalanceMode()) || cache.isTaskCache()) {
        // We only apply throttling on FULL-AUTO now.
        return bestPossiblePartitionStateMap;
    }
    String stateModelDefName = idealState.getStateModelDefRef();
    StateModelDefinition stateModelDef = cache.getStateModelDef(stateModelDefName);
    PartitionStateMap intermediatePartitionStateMap = new PartitionStateMap(resourceName);
    Set<Partition> partitionsNeedRecovery = new HashSet<>();
    Set<Partition> partitionsNeedLoadbalance = new HashSet<>();
    Set<Partition> partitionshaveErrorStateReplica = new HashSet<>();
    for (Partition partition : resource.getPartitions()) {
        Map<String, String> currentStateMap = currentStateOutput.getCurrentStateMap(resourceName, partition);
        Map<String, String> bestPossibleMap = bestPossiblePartitionStateMap.getPartitionMap(partition);
        List<String> preferenceList = preferenceLists.get(partition.getPartitionName());
        RebalanceType rebalanceType = getRebalanceType(cache, bestPossibleMap, preferenceList, stateModelDef, currentStateMap, idealState);
        // TODO refine getRebalanceType to return more accurate rebalance types.
        // So following logic doesn't need to check for more details.
        boolean rebalanceNeeded = false;
        if (rebalanceType.equals(RebalanceType.RECOVERY_BALANCE)) {
            // Check if any error exist
            if (currentStateMap.values().contains(HelixDefinedState.ERROR.name())) {
                partitionshaveErrorStateReplica.add(partition);
            }
            // Check if recovery is needed for this partition
            if (!currentStateMap.equals(bestPossibleMap)) {
                partitionsNeedRecovery.add(partition);
                rebalanceNeeded = true;
            }
        // else, if currentState == bestPossibleState, no rebalance needed
        } else if (rebalanceType.equals(RebalanceType.LOAD_BALANCE)) {
            partitionsNeedLoadbalance.add(partition);
            rebalanceNeeded = true;
        }
        if (!rebalanceNeeded) {
            // no rebalance needed.
            Map<String, String> intermediateMap = new HashMap<>(bestPossibleMap);
            intermediatePartitionStateMap.setState(partition, intermediateMap);
        }
    }
    if (!partitionsNeedRecovery.isEmpty()) {
        logger.info("recovery balance needed for " + resourceName + " partitions: " + partitionsNeedRecovery);
    }
    if (!partitionsNeedLoadbalance.isEmpty()) {
        logger.info("load balance needed for " + resourceName + " partitions: " + partitionsNeedLoadbalance);
    }
    if (!partitionshaveErrorStateReplica.isEmpty()) {
        logger.info("partition currently has ERROR replica in " + resourceName + " partitions: " + partitionshaveErrorStateReplica);
    }
    chargePendingTransition(resource, currentStateOutput, throttleController, partitionsNeedRecovery, partitionsNeedLoadbalance);
    // perform recovery rebalance
    Set<Partition> recoveryThrottledPartitions = recoveryRebalance(resource, bestPossiblePartitionStateMap, throttleController, intermediatePartitionStateMap, partitionsNeedRecovery, currentStateOutput, cache.getStateModelDef(resource.getStateModelDefRef()).getTopState());
    Set<Partition> loadbalanceThrottledPartitions = partitionsNeedLoadbalance;
    long maxAllowedErrorPartitions = cache.getClusterConfig().getErrorPartitionThresholdForLoadBalance();
    if (partitionsNeedRecovery.isEmpty() && (maxAllowedErrorPartitions < 0 || partitionshaveErrorStateReplica.size() <= maxAllowedErrorPartitions)) {
        // perform load balance only if
        // 1. no recovery operation to be scheduled.
        // 2. error partition count is less than configured limitation.
        loadbalanceThrottledPartitions = loadRebalance(resource, currentStateOutput, bestPossiblePartitionStateMap, throttleController, intermediatePartitionStateMap, partitionsNeedLoadbalance, currentStateOutput.getCurrentStateMap(resourceName));
    } else {
        // skip load balance, use current state mapping
        for (Partition p : partitionsNeedLoadbalance) {
            Map<String, String> currentStateMap = currentStateOutput.getCurrentStateMap(resourceName, p);
            intermediatePartitionStateMap.setState(p, currentStateMap);
        }
    }
    if (clusterStatusMonitor != null) {
        clusterStatusMonitor.updateRebalancerStats(resourceName, partitionsNeedRecovery.size(), partitionsNeedLoadbalance.size(), recoveryThrottledPartitions.size(), loadbalanceThrottledPartitions.size());
    }
    if (logger.isDebugEnabled()) {
        logParitionMapState(resourceName, new HashSet<>(resource.getPartitions()), partitionsNeedRecovery, recoveryThrottledPartitions, partitionsNeedLoadbalance, loadbalanceThrottledPartitions, currentStateOutput, bestPossiblePartitionStateMap, intermediatePartitionStateMap);
    }
    logger.debug("End processing resource:" + resourceName);
    return intermediatePartitionStateMap;
}
Also used : RebalanceType(org.apache.helix.api.config.StateTransitionThrottleConfig.RebalanceType) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap)

Example 2 with PartitionStateMap

use of org.apache.helix.controller.common.PartitionStateMap in project helix by apache.

the class TestRebalancerMetrics method copyCurrentStateFromBestPossible.

private CurrentStateOutput copyCurrentStateFromBestPossible(BestPossibleStateOutput bestPossibleStateOutput, String resource) {
    CurrentStateOutput currentStateOutput = new CurrentStateOutput();
    PartitionStateMap partitionStateMap = bestPossibleStateOutput.getPartitionStateMap(resource);
    for (Partition partition : partitionStateMap.partitionSet()) {
        Map<String, String> stateMap = partitionStateMap.getPartitionMap(partition);
        for (String instance : stateMap.keySet()) {
            currentStateOutput.setCurrentState(resource, partition, instance, stateMap.get(instance));
        }
    }
    return currentStateOutput;
}
Also used : PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) Partition(org.apache.helix.model.Partition) CurrentStateOutput(org.apache.helix.controller.stages.CurrentStateOutput)

Example 3 with PartitionStateMap

use of org.apache.helix.controller.common.PartitionStateMap in project helix by apache.

the class TestStateTransitionPrirority method updateCurrentStatesForRecoveryBalance.

private void updateCurrentStatesForRecoveryBalance(List<String> resourcePriority, CurrentStateOutput currentStateOutput) {
    IntermediateStateOutput output = event.getAttribute(AttributeName.INTERMEDIATE_STATE.name());
    for (PartitionStateMap partitionStateMap : output.getResourceStatesMap().values()) {
        String resourceName = partitionStateMap.getResourceName();
        Partition partition = new Partition(resourceName + "_0");
        String instanceName = HOSTNAME_PREFIX + resourceName.split("_")[1];
        if (partitionStateMap.getPartitionMap(partition).values().contains("SLAVE") && !resourcePriority.contains(resourceName)) {
            updateCurrentOutput(resourcePriority, currentStateOutput, resourceName, partition, instanceName, "SLAVE");
            break;
        }
    }
}
Also used : PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) Partition(org.apache.helix.model.Partition)

Example 4 with PartitionStateMap

use of org.apache.helix.controller.common.PartitionStateMap in project helix by apache.

the class TestStateTransitionPrirority method updateCurrentStatesForLoadBalance.

private void updateCurrentStatesForLoadBalance(List<String> resourcePriority, CurrentStateOutput currentStateOutput) {
    IntermediateStateOutput output = event.getAttribute(AttributeName.INTERMEDIATE_STATE.name());
    for (PartitionStateMap partitionStateMap : output.getResourceStatesMap().values()) {
        String resourceName = partitionStateMap.getResourceName();
        Partition partition = new Partition(resourceName + "_0");
        String oldInstance = HOSTNAME_PREFIX + resourceName.split("_")[1];
        String expectedInstance = HOSTNAME_PREFIX + (Integer.parseInt(resourceName.split("_")[1]) + 1);
        if (partitionStateMap.getPartitionMap(partition).containsKey(expectedInstance) && !resourcePriority.contains(resourceName)) {
            currentStateOutput.getCurrentStateMap(resourceName, partition).remove(oldInstance);
            updateCurrentOutput(resourcePriority, currentStateOutput, resourceName, partition, expectedInstance, "MASTER");
            break;
        }
    }
}
Also used : PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) Partition(org.apache.helix.model.Partition)

Example 5 with PartitionStateMap

use of org.apache.helix.controller.common.PartitionStateMap in project helix by apache.

the class BestPossibleExternalViewVerifier method verifyState.

@Override
protected synchronized boolean verifyState() {
    try {
        PropertyKey.Builder keyBuilder = _accessor.keyBuilder();
        // read cluster once and do verification
        ClusterDataCache cache = new ClusterDataCache();
        cache.refresh(_accessor);
        Map<String, IdealState> idealStates = cache.getIdealStates();
        if (idealStates == null) {
            // ideal state is null because ideal state is dropped
            idealStates = Collections.emptyMap();
        }
        // filter out all resources that use Task state model
        Iterator<Map.Entry<String, IdealState>> it = idealStates.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, IdealState> pair = it.next();
            if (pair.getValue().getStateModelDefRef().equals(TaskConstants.STATE_MODEL_NAME)) {
                it.remove();
            }
        }
        // verify live instances.
        if (_expectLiveInstances != null && !_expectLiveInstances.isEmpty()) {
            Set<String> actualLiveNodes = cache.getLiveInstances().keySet();
            if (!_expectLiveInstances.equals(actualLiveNodes)) {
                LOG.warn("Live instances are not as expected. Actual live nodes: " + actualLiveNodes.toString());
                return false;
            }
        }
        Map<String, ExternalView> extViews = _accessor.getChildValuesMap(keyBuilder.externalViews());
        if (extViews == null) {
            extViews = Collections.emptyMap();
        }
        // Filter resources if requested
        if (_resources != null && !_resources.isEmpty()) {
            idealStates.keySet().retainAll(_resources);
            extViews.keySet().retainAll(_resources);
        }
        // add empty idealState for the resource
        for (String resource : extViews.keySet()) {
            if (!idealStates.containsKey(resource)) {
                ExternalView ev = extViews.get(resource);
                IdealState is = new IdealState(resource);
                is.getRecord().setSimpleFields(ev.getRecord().getSimpleFields());
                idealStates.put(resource, is);
            }
        }
        // calculate best possible state
        BestPossibleStateOutput bestPossOutput = calcBestPossState(cache);
        Map<String, Map<Partition, Map<String, String>>> bestPossStateMap = bestPossOutput.getStateMap();
        // set error states
        if (_errStates != null) {
            for (String resourceName : _errStates.keySet()) {
                Map<String, String> partErrStates = _errStates.get(resourceName);
                for (String partitionName : partErrStates.keySet()) {
                    String instanceName = partErrStates.get(partitionName);
                    if (!bestPossStateMap.containsKey(resourceName)) {
                        bestPossStateMap.put(resourceName, new HashMap<Partition, Map<String, String>>());
                    }
                    Partition partition = new Partition(partitionName);
                    if (!bestPossStateMap.get(resourceName).containsKey(partition)) {
                        bestPossStateMap.get(resourceName).put(partition, new HashMap<String, String>());
                    }
                    bestPossStateMap.get(resourceName).get(partition).put(instanceName, HelixDefinedState.ERROR.toString());
                }
            }
        }
        for (String resourceName : idealStates.keySet()) {
            ExternalView extView = extViews.get(resourceName);
            IdealState is = idealStates.get(resourceName);
            if (extView == null) {
                if (is.isExternalViewDisabled()) {
                    continue;
                } else {
                    LOG.error("externalView for " + resourceName + " is not available");
                    return false;
                }
            }
            // step 0: remove empty map and DROPPED state from best possible state
            PartitionStateMap bpStateMap = bestPossOutput.getPartitionStateMap(resourceName);
            StateModelDefinition stateModelDef = cache.getStateModelDef(is.getStateModelDefRef());
            if (stateModelDef == null) {
                LOG.error("State model definition " + is.getStateModelDefRef() + " for resource not found!" + is.getResourceName());
                return false;
            }
            boolean result = verifyExternalView(extView, bpStateMap, stateModelDef);
            if (!result) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("verifyExternalView fails for " + resourceName + "! ExternalView: " + extView + " BestPossibleState: " + bpStateMap);
                } else {
                    LOG.warn("verifyExternalView fails for " + resourceName + "! ExternalView does not match BestPossibleState");
                }
                return false;
            }
        }
        return true;
    } catch (Exception e) {
        LOG.error("exception in verification", e);
        return false;
    }
}
Also used : ExternalView(org.apache.helix.model.ExternalView) Partition(org.apache.helix.model.Partition) BestPossibleStateOutput(org.apache.helix.controller.stages.BestPossibleStateOutput) ClusterDataCache(org.apache.helix.controller.stages.ClusterDataCache) IdealState(org.apache.helix.model.IdealState) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) StateModelDefinition(org.apache.helix.model.StateModelDefinition) HashMap(java.util.HashMap) Map(java.util.Map) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) PropertyKey(org.apache.helix.PropertyKey)

Aggregations

PartitionStateMap (org.apache.helix.controller.common.PartitionStateMap)10 Partition (org.apache.helix.model.Partition)6 HashMap (java.util.HashMap)3 Map (java.util.Map)3 HelixManager (org.apache.helix.HelixManager)3 PropertyKey (org.apache.helix.PropertyKey)3 List (java.util.List)2 HelixDataAccessor (org.apache.helix.HelixDataAccessor)2 ClusterConfig (org.apache.helix.model.ClusterConfig)2 ExternalView (org.apache.helix.model.ExternalView)2 IdealState (org.apache.helix.model.IdealState)2 Resource (org.apache.helix.model.Resource)2 ArrayList (java.util.ArrayList)1 HelixException (org.apache.helix.HelixException)1 ZNRecord (org.apache.helix.ZNRecord)1 RebalanceType (org.apache.helix.api.config.StateTransitionThrottleConfig.RebalanceType)1 BestPossibleStateOutput (org.apache.helix.controller.stages.BestPossibleStateOutput)1 ClusterDataCache (org.apache.helix.controller.stages.ClusterDataCache)1 CurrentStateOutput (org.apache.helix.controller.stages.CurrentStateOutput)1 StateModelDefinition (org.apache.helix.model.StateModelDefinition)1