Java Code Examples for org.apache.helix.model.StateModelDefinition#getStatesPriorityList()

The following examples show how to use org.apache.helix.model.StateModelDefinition#getStatesPriorityList() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: MessageSelectionStage.java    From helix with Apache License 2.0 5 votes vote down vote up
/**
 * TODO: This code is duplicate in multiple places. Can we do it in to one place in the
 * beginning and compute the stateConstraint instance once and re use at other places.
 * Each IdealState must have a constraint object associated with it
 */
private Map<String, Bounds> computeStateConstraints(StateModelDefinition stateModelDefinition,
    IdealState idealState, ResourceControllerDataProvider cache) {
  Map<String, Bounds> stateConstraints = new HashMap<String, Bounds>();

  List<String> statePriorityList = stateModelDefinition.getStatesPriorityList();
  for (String state : statePriorityList) {
    String numInstancesPerState = stateModelDefinition.getNumInstancesPerState(state);
    int max = -1;
    if ("N".equals(numInstancesPerState)) {
      max = cache.getLiveInstances().size();
    } else if ("R".equals(numInstancesPerState)) {
      // idealState is null when resource has been dropped,
      // R can't be evaluated and ignore state constraints
      //if (idealState != null) {
      //  max = cache.getReplicas(idealState.getResourceName());
      //}
    } else {
      try {
        max = Integer.parseInt(numInstancesPerState);
      } catch (Exception e) {
        // use -1
      }
    }

    if (max > -1) {
      // if state has no constraint, will not put in map
      stateConstraints.put(state, new Bounds(0, max));
    }
  }

  return stateConstraints;
}
 
Example 2
Source File: StateModelDefinitionValidator.java    From helix with Apache License 2.0 5 votes vote down vote up
/**
 * Instantiate a validator instance
 * @param stateModelDef the state model definition to validate
 */
private StateModelDefinitionValidator(StateModelDefinition stateModelDef) {
  _stateModelDef = stateModelDef;
  _statePriorityList = stateModelDef.getStatesPriorityList();
  _transitionPriorityList = stateModelDef.getStateTransitionPriorityList();
  _stateSet = Sets.newHashSet(_statePriorityList);
}
 
Example 3
Source File: RebalanceUtil.java    From helix with Apache License 2.0 5 votes vote down vote up
public static String[] parseStates(String clusterName, StateModelDefinition stateModDef) {
  String[] result = new String[2];
  String masterStateValue = null, slaveStateValue = null;

  // StateModelDefinition def = new StateModelDefinition(stateModDef);

  List<String> statePriorityList = stateModDef.getStatesPriorityList();

  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("R")) {
      if (slaveStateValue != null) {
        throw new HelixException("Invalid or unsupported state model definition");
      }
      slaveStateValue = state;
    } else if (count.equalsIgnoreCase("N")) {
      if (!(masterStateValue == null && slaveStateValue == null)) {
        throw new HelixException("Invalid or unsupported state model definition");
      }
      masterStateValue = slaveStateValue = state;
    }
  }
  if (masterStateValue == null && slaveStateValue == null) {
    throw new HelixException("Invalid or unsupported state model definition");
  }

  if (masterStateValue == null) {
    masterStateValue = slaveStateValue;
  }
  result[0] = masterStateValue;
  result[1] = slaveStateValue;
  return result;
}
 
Example 4
Source File: ZKHelixAdmin.java    From helix with Apache License 2.0 4 votes vote down vote up
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("R")) {
      if (slaveStateValue != null) {
        throw new HelixException("Invalid or unsupported state model definition");
      }
      slaveStateValue = state;
    } else if (count.equalsIgnoreCase("N")) {
      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);
}
 
Example 5
Source File: AbstractRebalancer.java    From helix with Apache License 2.0 4 votes vote down vote up
/**
 * Assign the states to the instances listed in the preference list according to inputs.
 * Note that when we choose the top-state (e.g. MASTER) replica for a partition, we prefer to
 * choose it from these replicas which are already in the secondary states (e.g, SLAVE) instead
 * of in lower-state. This is because a replica in secondary state will take shorter time to
 * transition to the top-state, which could minimize the impact to the application's availability.
 * To achieve that, we sort the preferenceList based on CurrentState, by treating top-state and
 * second-states with same priority and rely on the fact that Collections.sort() is stable.
 */
private void assignStatesToInstances(final List<String> preferenceList,
    final StateModelDefinition stateModelDef, final Map<String, String> currentStateMap,
    final Set<String> liveInstances, final Set<String> disabledInstancesForPartition,
    Map<String, String> bestPossibleStateMap) {
  // Record the assigned instances to avoid double calculating or conflict assignment.
  Set<String> assignedInstances = new HashSet<>();

  Set<String> liveAndEnabled =
      liveInstances.stream().filter(instance -> !disabledInstancesForPartition.contains(instance))
          .collect(Collectors.toSet());

  Queue<String> preferredActiveInstanceQueue = new LinkedList<>(preferenceList);
  preferredActiveInstanceQueue.retainAll(liveAndEnabled);
  int totalCandidateCount = preferredActiveInstanceQueue.size();

  // Sort the preferred instances based on replicas' state priority in the current state.
  // Note that if one instance exists in the current states but not in the preference list, then
  // it won't show in the prioritized list.
  List<String> currentStatePrioritizedList = new ArrayList<>(preferredActiveInstanceQueue);
  currentStatePrioritizedList.sort(new StatePriorityComparator(currentStateMap, stateModelDef));
  Iterator<String> currentStatePrioritizedInstanceIter = currentStatePrioritizedList.iterator();

  // Assign the states to the instances that appear in the preference list.
  for (String state : stateModelDef.getStatesPriorityList()) {
    int stateCount =
        getStateCount(state, stateModelDef, liveAndEnabled.size(), preferenceList.size());
    while (!preferredActiveInstanceQueue.isEmpty()) {
      if (stateCount <= 0) {
        break; // continue assigning for the next state
      }
      String peekInstance = preferredActiveInstanceQueue.peek();
      if (assignedInstances.contains(peekInstance)) {
        preferredActiveInstanceQueue.poll();
        continue; // continue checking for the next available instance
      }
      String proposedInstance = adjustInstanceIfNecessary(state, peekInstance,
          currentStateMap.getOrDefault(peekInstance, stateModelDef.getInitialState()),
          stateModelDef, assignedInstances, totalCandidateCount - assignedInstances.size(),
          stateCount, currentStatePrioritizedInstanceIter);

      if (proposedInstance.equals(peekInstance)) {
        // If the peeked instance is the final decision, then poll it from the queue.
        preferredActiveInstanceQueue.poll();
      }
      // else, if we found a different instance for the partition placement, then we need to
      // check the same instance again or it will not be assigned with any partitions.

      // Assign the desired state to the proposed instance if not on ERROR state.
      if (HelixDefinedState.ERROR.toString().equals(currentStateMap.get(proposedInstance))) {
        bestPossibleStateMap.put(proposedInstance, HelixDefinedState.ERROR.toString());
      } else {
        bestPossibleStateMap.put(proposedInstance, state);
        stateCount--;
      }
      // Note that in either case, the proposed instance is considered to be assigned with a state
      // by now.
      if (!assignedInstances.add(proposedInstance)) {
        throw new AssertionError(String
            .format("The proposed instance %s has been already assigned before.",
                proposedInstance));
      }
    }
  }
}
 
Example 6
Source File: ResourceAccessor.java    From helix with Apache License 2.0 4 votes vote down vote up
private Map<String, String> computePartitionHealth(String clusterId, String resourceName) {
  HelixAdmin admin = getHelixAdmin();
  IdealState idealState = admin.getResourceIdealState(clusterId, resourceName);
  ExternalView externalView = admin.getResourceExternalView(clusterId, resourceName);
  StateModelDefinition stateModelDef =
      admin.getStateModelDef(clusterId, idealState.getStateModelDefRef());
  String initialState = stateModelDef.getInitialState();
  List<String> statesPriorityList = stateModelDef.getStatesPriorityList();
  statesPriorityList = statesPriorityList.subList(0, statesPriorityList.indexOf(initialState)); // Trim
                                                                                                // stateList
                                                                                                // to
                                                                                                // initialState
                                                                                                // and
                                                                                                // above
  int minActiveReplicas = idealState.getMinActiveReplicas();

  // Start the logic that determines the health status of each partition
  Map<String, String> partitionHealthResult = new HashMap<>();
  Set<String> allPartitionNames = idealState.getPartitionSet();
  if (!allPartitionNames.isEmpty()) {
    for (String partitionName : allPartitionNames) {
      int replicaCount =
          idealState.getReplicaCount(idealState.getPreferenceList(partitionName).size());
      // Simplify expectedStateCountMap by assuming that all instances are available to reduce
      // computation load on this REST endpoint
      LinkedHashMap<String, Integer> expectedStateCountMap =
          stateModelDef.getStateCountMap(replicaCount, replicaCount);
      // Extract all states into Collections from ExternalView
      Map<String, String> stateMapInExternalView = externalView.getStateMap(partitionName);
      Collection<String> allReplicaStatesInExternalView =
          (stateMapInExternalView != null && !stateMapInExternalView.isEmpty())
              ? stateMapInExternalView.values()
              : Collections.<String> emptyList();
      int numActiveReplicasInExternalView = 0;
      HealthStatus status = HealthStatus.HEALTHY;

      // Go through all states that are "active" states (higher priority than InitialState)
      for (int statePriorityIndex = 0; statePriorityIndex < statesPriorityList
          .size(); statePriorityIndex++) {
        String currentState = statesPriorityList.get(statePriorityIndex);
        int currentStateCountInIdealState = expectedStateCountMap.get(currentState);
        int currentStateCountInExternalView =
            Collections.frequency(allReplicaStatesInExternalView, currentState);
        numActiveReplicasInExternalView += currentStateCountInExternalView;
        // Top state counts must match, if not, unhealthy
        if (statePriorityIndex == 0
            && currentStateCountInExternalView != currentStateCountInIdealState) {
          status = HealthStatus.UNHEALTHY;
          break;
        } else if (currentStateCountInExternalView < currentStateCountInIdealState) {
          // For non-top states, if count in ExternalView is less than count in IdealState,
          // partially healthy
          status = HealthStatus.PARTIAL_HEALTHY;
        }
      }
      if (numActiveReplicasInExternalView < minActiveReplicas) {
        // If this partition does not satisfy the number of minimum active replicas, unhealthy
        status = HealthStatus.UNHEALTHY;
      }
      partitionHealthResult.put(partitionName, status.name());
    }
  }
  return partitionHealthResult;
}