private Node chooseNodeInternal()

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;
  }