in helix-core/src/main/java/org/apache/helix/tools/ClusterStateVerifier.java [203:343]
private boolean verifyBestPossAndExtView(HelixDataAccessor accessor,
Map<String, Map<String, String>> errStates, String clusterName, Set<String> resources) {
try {
PropertyKey.Builder keyBuilder = accessor.keyBuilder();
// read cluster once and do verification
ResourceControllerDataProvider cache = new ResourceControllerDataProvider(clusterName);
cache.refresh(accessor);
Map<String, IdealState> idealStates = new HashMap<>(cache.getIdealStates());
// 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();
}
}
Map<String, ExternalView> extViews =
accessor.getChildValuesMap(keyBuilder.externalViews(), true);
if (extViews == null) {
extViews = Collections.emptyMap();
}
// Filter resources if requested
if (resources != null && !resources.isEmpty()) {
idealStates.keySet().retainAll(resources);
extViews.keySet().retainAll(resources);
}
// if externalView is not empty and idealState doesn't exist
// add empty idealState for the resource
for (String resource : extViews.keySet()) {
if (!idealStates.containsKey(resource)) {
idealStates.put(resource, new IdealState(resource));
}
}
// calculate best possible state
BestPossibleStateOutput bestPossOutput = calcBestPossState(cache, resources);
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());
}
}
}
// System.out.println("stateMap: " + bestPossStateMap);
for (String resourceName : idealStates.keySet()) {
ExternalView extView = extViews.get(resourceName);
if (extView == null) {
IdealState is = idealStates.get(resourceName);
if (is.isExternalViewDisabled()) {
continue;
} else {
LOG.info("externalView for " + resourceName + " is not available");
return false;
}
}
// step 0: remove empty map and DROPPED state from best possible state
Map<Partition, Map<String, String>> bpStateMap =
bestPossOutput.getResourceMap(resourceName);
Iterator<Map.Entry<Partition, Map<String, String>>> iter = bpStateMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Partition, Map<String, String>> entry = iter.next();
Map<String, String> instanceStateMap = entry.getValue();
if (instanceStateMap.isEmpty()) {
iter.remove();
} else {
// remove instances with DROPPED state
Iterator<Map.Entry<String, String>> insIter = instanceStateMap.entrySet().iterator();
while (insIter.hasNext()) {
Map.Entry<String, String> insEntry = insIter.next();
String state = insEntry.getValue();
if (state.equalsIgnoreCase(HelixDefinedState.DROPPED.toString())) {
insIter.remove();
}
}
}
}
// System.err.println("resource: " + resourceName + ", bpStateMap: " + bpStateMap);
// step 1: externalView and bestPossibleState has equal size
int extViewSize = extView.getRecord().getMapFields().size();
int bestPossStateSize = bestPossOutput.getResourceMap(resourceName).size();
if (extViewSize != bestPossStateSize) {
LOG.info("exterView size (" + extViewSize + ") is different from bestPossState size ("
+ bestPossStateSize + ") for resource: " + resourceName);
// System.err.println("exterView size (" + extViewSize
// + ") is different from bestPossState size (" + bestPossStateSize
// + ") for resource: " + resourceName);
// System.out.println("extView: " + extView.getRecord().getMapFields());
// System.out.println("bestPossState: " +
// bestPossOutput.getResourceMap(resourceName));
return false;
}
// step 2: every entry in external view is contained in best possible state
for (String partition : extView.getRecord().getMapFields().keySet()) {
Map<String, String> evInstanceStateMap = extView.getRecord().getMapField(partition);
Map<String, String> bpInstanceStateMap =
bestPossOutput.getInstanceStateMap(resourceName, new Partition(partition));
boolean result = compareMap(evInstanceStateMap, bpInstanceStateMap);
if (result == false) {
LOG.info("externalView is different from bestPossibleState for partition:" + partition);
// System.err.println("externalView is different from bestPossibleState for partition: "
// + partition + ", actual: " + evInstanceStateMap + ", bestPoss: " +
// bpInstanceStateMap);
return false;
}
}
}
return true;
} catch (Exception e) {
LOG.error("exception in verification", e);
return false;
}
}