in hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/net/NetworkTopologyImpl.java [592:704]
private Node chooseNodeInternal(String scope, int leafIndex,
List<String> excludedScopes, Collection<? extends Node> excludedNodes,
Node affinityNode, int ancestorGen) {
Preconditions.checkArgument(scope != null);
if (LOG.isDebugEnabled()) {
LOG.debug("Start choosing node[scope = {}, index = {}, excludedScopes = "
+ "{}, excludedNodes = {}, affinityNode = {}, ancestorGen = {}",
scope, leafIndex,
excludedScopes == null ? "" : excludedScopes,
excludedNodes == null ? "" : excludedNodes,
affinityNode == null ? "" : affinityNode, ancestorGen);
}
String finalScope = scope;
if (affinityNode != null && ancestorGen > 0) {
Node affinityAncestor = affinityNode.getAncestor(ancestorGen);
if (affinityAncestor == null) {
throw new IllegalArgumentException("affinityNode " +
affinityNode.getNetworkFullPath() + " doesn't have ancestor on" +
" generation " + ancestorGen);
}
// affinity ancestor should has overlap with scope
if (affinityAncestor.isDescendant(scope)) {
finalScope = affinityAncestor.getNetworkFullPath();
} else if (!scope.startsWith(affinityAncestor.getNetworkFullPath())) {
return null;
}
// reset ancestor generation since the new scope is identified now
ancestorGen = 0;
}
Node scopeNode = getNode(finalScope);
if (scopeNode == null) {
throw new IllegalArgumentException(String.format("No nodes with Scope: " +
"%s exists", finalScope));
}
// check overlap of excludedScopes and finalScope
List<String> mutableExcludedScopes = null;
if (excludedScopes != null && !excludedScopes.isEmpty()) {
mutableExcludedScopes = new ArrayList<>();
for (String s: excludedScopes) {
// excludeScope covers finalScope
if (scopeNode.isDescendant(s)) {
return null;
}
// excludeScope and finalScope share nothing case
if (scopeNode.isAncestor(s)) {
Node node = getNode(s);
if (node != null &&
mutableExcludedScopes.stream().noneMatch(node::isDescendant)) {
mutableExcludedScopes.add(s);
}
}
}
}
// clone excludedNodes before remove duplicate in it
Collection<Node> mutableExNodes = new LinkedHashSet<>();
// add affinity node to mutableExNodes
if (affinityNode != null) {
mutableExNodes.add(affinityNode);
}
// Remove duplicate in excludedNodes
if (excludedNodes != null) {
mutableExNodes.addAll(excludedNodes);
}
// remove duplicate in mutableExNodes and mutableExcludedScopes
NetUtils.removeDuplicate(this, mutableExNodes, mutableExcludedScopes,
ancestorGen);
// calculate available node count
int availableNodes = getAvailableNodesCount(
scopeNode.getNetworkFullPath(), mutableExcludedScopes, mutableExNodes,
ancestorGen);
if (availableNodes <= 0) {
LOG.info("No available node in (scope=\"{}\" excludedScope=\"{}\" " +
"excludedNodes=\"{}\" ancestorGen=\"{}\").",
scopeNode.getNetworkFullPath(), excludedScopes, excludedNodes,
ancestorGen);
return null;
}
// scope is a Leaf node
if (!(scopeNode instanceof InnerNode)) {
return scopeNode;
}
Node ret;
int nodeIndex;
if (leafIndex >= 0) {
nodeIndex = leafIndex % availableNodes;
ret = ((InnerNode)scopeNode).getLeaf(nodeIndex, mutableExcludedScopes,
mutableExNodes, ancestorGen);
} else {
nodeIndex = ThreadLocalRandom.current().nextInt(availableNodes);
ret = ((InnerNode)scopeNode).getLeaf(nodeIndex, mutableExcludedScopes,
mutableExNodes, ancestorGen);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Finish choosing node[index = {}, random = {}] from {} " +
"available nodes, scope = {}, excludedScope = {}," +
"excludeNodes = {}.",
nodeIndex, (leafIndex == -1 ? "true" : "false"), availableNodes,
scopeNode.getNetworkFullPath(), excludedScopes, excludedNodes);
LOG.debug("Chosen node = {}", (ret == null ? "not found" :
ret.toString()));
}
return ret;
}