Java Code Examples for org.apache.helix.model.ExternalView#getStateMap()

The following examples show how to use org.apache.helix.model.ExternalView#getStateMap() . 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: TestPartitionMigrationBase.java    From helix with Apache License 2.0 6 votes vote down vote up
@Override
public void onExternalViewChange(List<ExternalView> externalViewList,
    NotificationContext changeContext) {
  if (!trackEnabled) {
    return;
  }
  for (ExternalView ev : externalViewList) {
    IdealState is = _resourceMap.get(ev.getResourceName());
    if (is == null) {
      continue;
    }
    int replica = is.getReplicaCount(NUM_NODE);
    for (String p : is.getPartitionSet()) {
      Map<String, String> stateMap = ev.getStateMap(p);
      verifyPartitionCount(is.getResourceName(), p, stateMap, replica, "EV",
          is.getMinActiveReplicas());
    }
  }
}
 
Example 2
Source File: TestSemiAutoRebalance.java    From helix with Apache License 2.0 6 votes vote down vote up
@Test(dependsOnMethods = "testAddParticipant")
public void testStopAndReStartParticipant() throws InterruptedException {
  MockParticipantManager participant = _participants.get(0);
  String instance = participant.getInstanceName();

  Map<String, MasterSlaveSMD.States> affectedPartitions =
      new HashMap<String, MasterSlaveSMD.States>();

  ExternalView externalView = _accessor.getProperty(_keyBuilder.externalView(DB_NAME));

  for (String partition : externalView.getPartitionSet()) {
    Map<String, String> stateMap = externalView.getStateMap(partition);
    if (stateMap.containsKey(instance)) {
      affectedPartitions.put(partition, MasterSlaveSMD.States.valueOf(stateMap.get(instance)));
    }
  }

  stopParticipant(participant, affectedPartitions);

  // create a new participant
  participant = new MockParticipantManager(ZK_ADDR, CLUSTER_NAME, instance);
  _participants.set(0, participant);
  startParticipant(participant, affectedPartitions);
}
 
Example 3
Source File: TopicAssignmentViewBuilder.java    From uReplicator with Apache License 2.0 6 votes vote down vote up
private static JSONObject buildExternalView(String topicName, ExternalView externalViewForTopic) {
  JSONObject externalViewPartitionToServerMappingJson = new JSONObject();
  if (externalViewForTopic == null) {
    LOGGER.info("External view for topic " + topicName + " is NULL");
  } else {
    for (String partition : externalViewForTopic.getPartitionSet()) {
      Map<String, String> stateMap = externalViewForTopic.getStateMap(partition);
      for (String server : stateMap.keySet()) {
        if (!externalViewPartitionToServerMappingJson.containsKey(partition)) {
          externalViewPartitionToServerMappingJson.put(partition, new JSONObject());
        }
        externalViewPartitionToServerMappingJson.getJSONObject(partition).put(server, stateMap.get(server));
      }
    }
  }
  return externalViewPartitionToServerMappingJson;
}
 
Example 4
Source File: Task.java    From helix with Apache License 2.0 6 votes vote down vote up
private boolean isParentTaskDone(ExternalView ev) {
  Set<String> partitionSet = ev.getPartitionSet();
  if (partitionSet.isEmpty()) {
    return false;
  }

  for (String partition : partitionSet) {
    Map<String, String> stateMap = ev.getStateMap(partition);
    for (String instance : stateMap.keySet()) {
      if (!stateMap.get(instance).equalsIgnoreCase("Online")) {
        return false;
      }
    }
  }
  return true;
}
 
Example 5
Source File: MetricCollectorHAController.java    From ambari-metrics with Apache License 2.0 6 votes vote down vote up
private void getPrintableResourceState(ExternalView resourceExternalView,
                                       String resourceName,
                                       StringBuilder sb) {
  TreeSet<String> sortedSet = new TreeSet<>(resourceExternalView.getPartitionSet());
  sb.append("\nCLUSTER: ");
  sb.append(getClusterName());
  sb.append("\nRESOURCE: ");
  sb.append(resourceName);
  for (String partitionName : sortedSet) {
    sb.append("\nPARTITION: ");
    sb.append(partitionName).append("\t");
    Map<String, String> states = resourceExternalView.getStateMap(partitionName);
    for (Map.Entry<String, String> stateEntry : states.entrySet()) {
      sb.append("\t");
      sb.append(stateEntry.getKey());
      sb.append("\t");
      sb.append(stateEntry.getValue());
    }
  }
}
 
Example 6
Source File: ServiceStatus.java    From incubator-pinot with Apache License 2.0 5 votes vote down vote up
@Override
protected Map<String, String> getPartitionStateMap(ExternalView state) {
  Map<String, String> partitionState = new HashMap<>();

  for (String partition : state.getPartitionSet()) {
    Map<String, String> instanceStateMap = state.getStateMap(partition);
    if (instanceStateMap.containsKey(_instanceName)) {
      partitionState.put(partition, instanceStateMap.get(_instanceName));
    }
  }

  return partitionState;
}
 
Example 7
Source File: TestSemiAutoRebalance.java    From helix with Apache License 2.0 5 votes vote down vote up
private void stopParticipant(MockParticipantManager participant,
    Map<String, MasterSlaveSMD.States> affectedPartitions) throws InterruptedException {
  participant.syncStop();

  Thread.sleep(1000);

  ExternalView externalView = _accessor.getProperty(_keyBuilder.externalView(DB_NAME));
  // No re-assignment of partition, if a MASTER is removed, one of SLAVE would be prompted
  for (Map.Entry<String, MasterSlaveSMD.States> entry : affectedPartitions.entrySet()) {
    Map<String, String> stateMap = externalView.getStateMap(entry.getKey());
    Assert.assertEquals(stateMap.size(), REPLICA_NUMBER - 1);
    Assert.assertTrue(stateMap.values().contains(MasterSlaveSMD.States.MASTER.toString()));
  }
}
 
Example 8
Source File: TestSemiAutoRebalance.java    From helix with Apache License 2.0 5 votes vote down vote up
@Test
public void testAddParticipant() throws InterruptedException {
  String newInstance = PARTICIPANT_PREFIX + "_" + (PARTICIPANT_START_PORT + _participants.size());
  _gSetupTool.addInstanceToCluster(CLUSTER_NAME, newInstance);

  MockParticipantManager newParticipant =
      new MockParticipantManager(ZK_ADDR, CLUSTER_NAME, newInstance);
  newParticipant.syncStart();

  Thread.sleep(1000);

  List<String> instances = _accessor.getChildNames(_keyBuilder.instanceConfigs());
  Assert.assertEquals(instances.size(), _participants.size() + 1);
  Assert.assertTrue(instances.contains(newInstance));

  List<String> liveInstances = _accessor.getChildNames(_keyBuilder.liveInstances());
  Assert.assertEquals(liveInstances.size(), _participants.size() + 1);
  Assert.assertTrue(liveInstances.contains(newInstance));

  // nothing for new participant
  ExternalView externalView = _accessor.getProperty(_keyBuilder.externalView(DB_NAME));
  Assert.assertNotNull(externalView);
  for (String partition : externalView.getPartitionSet()) {
    Map<String, String> stateMap = externalView.getStateMap(partition);
    Assert.assertFalse(stateMap.containsKey(newInstance));
  }

  // clear
  newParticipant.syncStop();
  _gSetupTool.getClusterManagementTool().enableInstance(CLUSTER_NAME, newInstance, false);
  _gSetupTool.dropInstanceFromCluster(CLUSTER_NAME, newInstance);

  instances = _accessor.getChildNames(_keyBuilder.instanceConfigs());
  Assert.assertEquals(instances.size(), _participants.size());

  liveInstances = _accessor.getChildNames(_keyBuilder.liveInstances());
  Assert.assertEquals(liveInstances.size(), _participants.size());
}
 
Example 9
Source File: RoutingTable.java    From helix with Apache License 2.0 5 votes vote down vote up
private void refresh(Collection<ExternalView> externalViewList) {
  Map<String, InstanceConfig> instanceConfigMap = new HashMap<>();
  if (externalViewList != null && !externalViewList.isEmpty()) {
    for (InstanceConfig config : _instanceConfigs) {
      instanceConfigMap.put(config.getId(), config);
    }
    for (ExternalView extView : externalViewList) {
      String resourceName = extView.getId();
      for (String partitionName : extView.getPartitionSet()) {
        Map<String, String> stateMap = extView.getStateMap(partitionName);
        for (String instanceName : stateMap.keySet()) {
          String currentState = stateMap.get(instanceName);
          if (instanceConfigMap.containsKey(instanceName)) {
            InstanceConfig instanceConfig = instanceConfigMap.get(instanceName);
            if (extView.isGroupRoutingEnabled()) {
              addEntry(resourceName, extView.getResourceGroupName(),
                  extView.getInstanceGroupTag(), partitionName, currentState, instanceConfig);
            } else {
              addEntry(resourceName, partitionName, currentState, instanceConfig);
            }
          } else {
            logger.warn(
                "Participant {} is not found with proper configuration information. It might already be removed from the cluster. "
                    + "Skip recording partition assignment entry: Partition {}, Participant {}, State {}.",
                instanceName, partitionName, instanceName, stateMap.get(instanceName));
          }
        }
      }
    }
  }
}
 
Example 10
Source File: ViewInfo.java    From terrapin with Apache License 2.0 5 votes vote down vote up
public ViewInfo(ExternalView externalView) {
  this.resource = externalView.getResourceName();
  Set<String> partitionSet = externalView.getPartitionSet();
  this.partitionMap = Maps.newTreeMap();
  for (String partition : partitionSet) {
    Map<String, String> stateMap = externalView.getStateMap(partition);
    Pair<String, Integer> resourceAndPartitionNum =
        TerrapinUtil.getResourceAndPartitionNum(partition);
    if (resourceAndPartitionNum == null) {
      LOG.warn("Invalid helix partition for " + resource + " : " + partition);
      continue;
    }
    if (stateMap == null) {
      continue;
    }
    List<String> instanceList = Lists.newArrayListWithCapacity(5);
    for (Map.Entry<String, String> entry : stateMap.entrySet()) {
      if (entry.getValue().equals("ONLINE")) {
        instanceList.add(entry.getKey());
      }
    }
    // Keep the list in alphabetical order.
    if (!instanceList.isEmpty()) {
      Collections.sort(instanceList);
      this.partitionMap.put(TerrapinUtil.getViewPartitionName(resource,
              resourceAndPartitionNum.getRight()), instanceList);
    }
  }
}
 
Example 11
Source File: HelixHelper.java    From incubator-pinot with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the set of online instances from external view.
 *
 * @param resourceExternalView External view for the resource.
 * @return Set&lt;String&gt; of online instances in the external view for the resource.
 */
public static Set<String> getOnlineInstanceFromExternalView(ExternalView resourceExternalView) {
  Set<String> instanceSet = new HashSet<String>();
  if (resourceExternalView != null) {
    for (String partition : resourceExternalView.getPartitionSet()) {
      Map<String, String> stateMap = resourceExternalView.getStateMap(partition);
      for (String instance : stateMap.keySet()) {
        if (stateMap.get(instance).equalsIgnoreCase(ONLINE)) {
          instanceSet.add(instance);
        }
      }
    }
  }
  return instanceSet;
}
 
Example 12
Source File: HelixServerStarter.java    From incubator-pinot with Apache License 2.0 5 votes vote down vote up
private boolean isResourceOffline(HelixAdmin helixAdmin, String resource) {
  ExternalView externalView = helixAdmin.getResourceExternalView(_helixClusterName, resource);
  // Treat deleted resource as OFFLINE
  if (externalView == null) {
    return true;
  }
  for (String partition : externalView.getPartitionSet()) {
    Map<String, String> instanceStateMap = externalView.getStateMap(partition);
    String state = instanceStateMap.get(_instanceId);
    if (StateModel.SegmentStateModel.ONLINE.equals(state) || StateModel.SegmentStateModel.CONSUMING.equals(state)) {
      return false;
    }
  }
  return true;
}
 
Example 13
Source File: HelixHelper.java    From incubator-pinot with Apache License 2.0 5 votes vote down vote up
/**
 * Get a set of offline instance from the external view of the resource.
 *
 * @param resourceExternalView External view of the resource
 * @return Set of string instance names of the offline instances in the external view.
 */
public static Set<String> getOfflineInstanceFromExternalView(ExternalView resourceExternalView) {
  Set<String> instanceSet = new HashSet<String>();
  for (String partition : resourceExternalView.getPartitionSet()) {
    Map<String, String> stateMap = resourceExternalView.getStateMap(partition);
    for (String instance : stateMap.keySet()) {
      if (stateMap.get(instance).equalsIgnoreCase(OFFLINE)) {
        instanceSet.add(instance);
      }
    }
  }
  return instanceSet;
}
 
Example 14
Source File: NoProgressTopicPartitionRestletResource.java    From uReplicator with Apache License 2.0 5 votes vote down vote up
@Override
@Get
public Representation get() {
  JSONObject responseJson = new JSONObject();
  List<TopicAndPartition> noProgressTopicPartition = _helixMirrorMakerManager.getOffsetMonitor().getNoProgessTopicPartitions();
  if (noProgressTopicPartition == null || noProgressTopicPartition.size() == 0) {
    return new StringRepresentation(responseJson.toJSONString());
  }
  JSONArray jsonArray = new JSONArray();
  for (TopicAndPartition info : noProgressTopicPartition) {

    JSONObject node = new JSONObject();
    node.put("topic", info.topic());
    node.put("partition", info.partition());

    IdealState idealStateForTopic =
        _helixMirrorMakerManager.getIdealStateForTopic(info.topic());
    Map<String, String> idealStateMap = idealStateForTopic.getInstanceStateMap(String.valueOf(info.partition()));
    ExternalView externalViewForTopic =
        _helixMirrorMakerManager.getExternalViewForTopic(info.topic());
    Map<String, String> stateMap = externalViewForTopic.getStateMap(String.valueOf(info.partition()));
    if (idealStateMap != null && idealStateMap.keySet().size() != 0) {
      node.put("idealWorker", idealStateMap.keySet().iterator().next());
    }
    if (stateMap != null && stateMap.keySet().size() != 0) {
      node.put("actualWorker", stateMap.keySet().iterator().next());
    }
    jsonArray.add(node);

  }
  responseJson.put("topics", jsonArray);

  return new StringRepresentation(responseJson.toJSONString());
}
 
Example 15
Source File: TestSemiAutoStateTransition.java    From helix with Apache License 2.0 5 votes vote down vote up
@Test
public void testOfflineToSecondTopState() throws Exception {
  _participants[0].syncStop();
  Thread.sleep(2000L);

  ExternalView externalView =
      _accessor.getProperty(_keyBuilder.externalView(WorkflowGenerator.DEFAULT_TGT_DB + "0"));
  Map<String, String> stateMap =
      externalView.getStateMap(WorkflowGenerator.DEFAULT_TGT_DB + "0_0");
  Assert.assertEquals("MASTER", stateMap.get(PARTICIPANT_PREFIX + "_" + (_startPort + 1)));
  Assert.assertEquals("SLAVE", stateMap.get(PARTICIPANT_PREFIX + "_" + (_startPort + 2)));

  String instanceName = PARTICIPANT_PREFIX + "_" + _startPort;
  _participants[0] = new MockParticipantManager(ZK_ADDR, CLUSTER_NAME, instanceName);

  // add a state model with non-OFFLINE initial state
  StateMachineEngine stateMach = _participants[0].getStateMachineEngine();
  MockDelayMSStateModelFactory delayFactory =
      new MockDelayMSStateModelFactory().setDelay(300000L);
  stateMach.registerStateModelFactory(MASTER_SLAVE_STATE_MODEL, delayFactory);

  _participants[0].syncStart();
  Thread.sleep(2000L);

  externalView =
      _accessor.getProperty(_keyBuilder.externalView(WorkflowGenerator.DEFAULT_TGT_DB + "0"));
  stateMap = externalView.getStateMap(WorkflowGenerator.DEFAULT_TGT_DB + "0_0");
  Assert.assertEquals("OFFLINE", stateMap.get(PARTICIPANT_PREFIX + "_" + _startPort));
  Assert.assertEquals("MASTER", stateMap.get(PARTICIPANT_PREFIX + "_" + (_startPort + 1)));
  Assert.assertEquals("SLAVE", stateMap.get(PARTICIPANT_PREFIX + "_" + (_startPort + 2)));
}
 
Example 16
Source File: InstanceValidationUtil.java    From helix with Apache License 2.0 4 votes vote down vote up
/**
 * Get the problematic partitions on the to-be-stop instance
 * Requirement:
 *  If the instance gets stopped and the partitions on the instance are OFFLINE,
 *  the cluster still have enough "healthy" replicas on other sibling instances
 *
 *  - sibling instances mean those who share the same partition (replicas) of the to-be-stop instance
 *
 * @param globalPartitionHealthStatus (instance => (partition name, health status))
 * @param instanceToBeStop The instance to be stopped
 * @param dataAccessor The data accessor
 * @return A list of problematic partitions if the instance is stopped
 */
public static List<String> perPartitionHealthCheck(List<ExternalView> externalViews,
    Map<String, Map<String, Boolean>> globalPartitionHealthStatus, String instanceToBeStop,
    HelixDataAccessor dataAccessor) {
  List<String> unhealthyPartitions = new ArrayList<>();

  for (ExternalView externalView : externalViews) {
    // Skip ANY_LIVEINSTANCES resources check, since ANY_LIVEINSTANCES resources have single partition
    // with 1 replica. There is no need to check sibiling replicas.
    if (ResourceConfig.ResourceConfigConstants.ANY_LIVEINSTANCE.name()
        .equals(externalView.getReplicas())) {
      continue;
    }

    StateModelDefinition stateModelDefinition = dataAccessor
        .getProperty(dataAccessor.keyBuilder().stateModelDef(externalView.getStateModelDefRef()));
    for (String partition : externalView.getPartitionSet()) {
      Map<String, String> stateMap = externalView.getStateMap(partition);
      // Only check if instance holds top state
      if (stateMap.containsKey(instanceToBeStop)
          && stateMap.get(instanceToBeStop).equals(stateModelDefinition.getTopState())) {
        for (String siblingInstance : stateMap.keySet()) {
          // Skip this self check
          if (siblingInstance.equals(instanceToBeStop)) {
            continue;
          }

          // We are checking sibling partition healthy status. So if partition health does not
          // exist or it is not healthy. We should mark this partition is unhealthy.
          if (!globalPartitionHealthStatus.containsKey(siblingInstance)
              || !globalPartitionHealthStatus.get(siblingInstance).containsKey(partition)
              || !globalPartitionHealthStatus.get(siblingInstance).get(partition)) {
            unhealthyPartitions.add(partition);
            break;
          }
        }
      }
    }
  }

  return unhealthyPartitions;
}
 
Example 17
Source File: InstanceValidationUtil.java    From helix with Apache License 2.0 4 votes vote down vote up
/**
 * Check if sibling nodes of the instance meet min active replicas constraint
 * Two instances are sibling of each other if they host the same partition
 * WARNING: The check uses ExternalView to reduce network traffic but suffer from accuracy
 * due to external view propagation latency
 *
 * TODO: Use in memory cache and query instance's currentStates
 *
 * @param dataAccessor
 * @param instanceName
 * @return
 */
public static boolean siblingNodesActiveReplicaCheck(HelixDataAccessor dataAccessor, String instanceName) {
  PropertyKey.Builder propertyKeyBuilder = dataAccessor.keyBuilder();
  List<String> resources = dataAccessor.getChildNames(propertyKeyBuilder.idealStates());

  for (String resourceName : resources) {
    IdealState idealState = dataAccessor.getProperty(propertyKeyBuilder.idealStates(resourceName));
    if (idealState == null || !idealState.isEnabled() || !idealState.isValid()
        || TaskConstants.STATE_MODEL_NAME.equals(idealState.getStateModelDefRef())) {
      continue;
    }
    ExternalView externalView =
        dataAccessor.getProperty(propertyKeyBuilder.externalView(resourceName));
    if (externalView == null) {
      throw new HelixException(
          String.format("Resource %s does not have external view!", resourceName));
    }
    // Get the minActiveReplicas constraint for the resource
    int minActiveReplicas = externalView.getMinActiveReplicas();
    if (minActiveReplicas == -1) {
      _logger.warn("Resource " + resourceName
          + " is missing minActiveReplica field. Skip the sibling check");
      continue;
    }
    String stateModeDef = externalView.getStateModelDefRef();
    StateModelDefinition stateModelDefinition =
        dataAccessor.getProperty(propertyKeyBuilder.stateModelDef(stateModeDef));
    Set<String> unhealthyStates = new HashSet<>(UNHEALTHY_STATES);
    if (stateModelDefinition != null) {
      unhealthyStates.add(stateModelDefinition.getInitialState());
    }
    for (String partition : externalView.getPartitionSet()) {
      Map<String, String> stateByInstanceMap = externalView.getStateMap(partition);
      // found the resource hosted on the instance
      if (stateByInstanceMap.containsKey(instanceName)) {
        int numHealthySiblings = 0;
        for (Map.Entry<String, String> entry : stateByInstanceMap.entrySet()) {
          if (!entry.getKey().equals(instanceName)
              && !unhealthyStates.contains(entry.getValue())) {
            numHealthySiblings++;
          }
        }
        if (numHealthySiblings < minActiveReplicas) {
          _logger.info(
              "Partition {} doesn't have enough active replicas in sibling nodes. NumHealthySiblings: {}, minActiveReplicas: {}",
              partition, numHealthySiblings, minActiveReplicas);
          return false;
        }
      }
    }
  }

  return true;
}
 
Example 18
Source File: HelixExternalViewBasedQueryQuotaManager.java    From incubator-pinot with Apache License 2.0 4 votes vote down vote up
/**
 * Create a rate limiter for a table.
 * @param tableNameWithType table name with table type.
 * @param brokerResource broker resource which stores all the broker states of each table.
 * @param quotaConfig quota config of the table.
 */
private void createRateLimiter(String tableNameWithType, ExternalView brokerResource, QuotaConfig quotaConfig) {
  if (quotaConfig == null || quotaConfig.getMaxQueriesPerSecond() == null) {
    LOGGER.info("No qps config specified for table: {}", tableNameWithType);
    return;
  }

  if (brokerResource == null) {
    LOGGER.warn("Failed to init qps quota for table {}. No broker resource connected!", tableNameWithType);
    return;
  }

  Map<String, String> stateMap = brokerResource.getStateMap(tableNameWithType);
  int otherOnlineBrokerCount = 0;

  // If stateMap is null, that means this broker is the first broker for this table.
  if (stateMap != null) {
    for (Map.Entry<String, String> state : stateMap.entrySet()) {
      if (!_helixManager.getInstanceName().equals(state.getKey()) && state.getValue()
          .equals(CommonConstants.Helix.StateModel.SegmentStateModel.ONLINE)) {
        otherOnlineBrokerCount++;
      }
    }
  }

  int onlineCount = otherOnlineBrokerCount + 1;
  LOGGER.info("The number of online brokers for table {} is {}", tableNameWithType, onlineCount);

  // Get the dynamic rate
  double overallRate = quotaConfig.getMaxQPS();

  // Get stat from property store
  String tableConfigPath = constructTableConfigPath(tableNameWithType);
  Stat stat = _propertyStore.getStat(tableConfigPath, AccessOption.PERSISTENT);

  double perBrokerRate = overallRate / onlineCount;
  QueryQuotaEntity queryQuotaEntity =
      new QueryQuotaEntity(RateLimiter.create(perBrokerRate), new HitCounter(TIME_RANGE_IN_SECOND), onlineCount,
          overallRate, stat.getVersion());
  _rateLimiterMap.put(tableNameWithType, queryQuotaEntity);
  LOGGER.info(
      "Rate limiter for table: {} has been initialized. Overall rate: {}. Per-broker rate: {}. Number of online broker instances: {}. Table config stat version: {}",
      tableNameWithType, overallRate, perBrokerRate, onlineCount, stat.getVersion());
}
 
Example 19
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;
}
 
Example 20
Source File: ControllerLeaderLocator.java    From incubator-pinot with Apache License 2.0 4 votes vote down vote up
/**
 * Updates lead controller pairs from the external view of lead controller resource.
 */
private void refreshControllerLeaderMapFromLeadControllerResource() {
  try {
    ExternalView leadControllerResourceExternalView = _helixManager.getClusterManagmentTool()
        .getResourceExternalView(_helixManager.getClusterName(), Helix.LEAD_CONTROLLER_RESOURCE_NAME);
    if (leadControllerResourceExternalView == null) {
      LOGGER.error("External view of {} is null.", Helix.LEAD_CONTROLLER_RESOURCE_NAME);
      return;
    }
    Set<String> partitionNames = leadControllerResourceExternalView.getPartitionSet();
    if (partitionNames.size() != Helix.NUMBER_OF_PARTITIONS_IN_LEAD_CONTROLLER_RESOURCE) {
      LOGGER.error("The partition size of {} is not {}. Actual size: {}", Helix.LEAD_CONTROLLER_RESOURCE_NAME,
          Helix.NUMBER_OF_PARTITIONS_IN_LEAD_CONTROLLER_RESOURCE, partitionNames.size());
      return;
    }
    for (String partitionName : partitionNames) {
      int partitionId = LeadControllerUtils.extractPartitionId(partitionName);
      Map<String, String> partitionStateMap = leadControllerResourceExternalView.getStateMap(partitionName);
      boolean masterFound = false;
      // Get master host from partition map. Return null if no master found.
      for (Map.Entry<String, String> entry : partitionStateMap.entrySet()) {
        if (MasterSlaveSMD.States.MASTER.name().equals(entry.getValue())) {
          // Found the controller in master state.
          // Converts participant id (with Prefix "Controller_") to controller id and assigns it as the leader,
          // since realtime segment completion protocol doesn't need the prefix in controller instance id.
          String participantInstanceId = entry.getKey();
          String controllerInstanceId = LeadControllerUtils.extractControllerInstanceId(participantInstanceId);
          Pair<String, Integer> leadControllerPair = convertToHostAndPortPair(controllerInstanceId);
          masterFound = true;
          _cachedControllerLeaderMap.put(partitionId, leadControllerPair);
        }
      }
      if (!masterFound) {
        // It's ok to log a warning since we can be in this state for some small time during the migration.
        // Otherwise, we are attempted to mark this as an error.
        LOGGER.warn("There is no controller in MASTER state for partition: {} in {}", partitionName,
            Helix.LEAD_CONTROLLER_RESOURCE_NAME);
        return;
      }
    }
    _cachedControllerLeaderValid = true;
    LOGGER.info("Refreshed controller leader map successfully.");
  } catch (Exception e) {
    LOGGER.error("Caught exception when getting lead controller instance Id from external view of {}",
        Helix.LEAD_CONTROLLER_RESOURCE_NAME, e);
  }
}