| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hadoop.hdds.scm.net; |
| |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * The interface defines a network topology. |
| */ |
| public interface NetworkTopology { |
| /** Exception for invalid network topology detection. */ |
| class InvalidTopologyException extends RuntimeException { |
| private static final long serialVersionUID = 1L; |
| public InvalidTopologyException(String msg) { |
| super(msg); |
| } |
| } |
| /** |
| * Add a leaf node. This will be called when a new datanode is added. |
| * @param node node to be added; can be null |
| * @exception IllegalArgumentException if add a node to a leave or node to be |
| * added is not a leaf |
| */ |
| void add(Node node); |
| |
| /** |
| * Remove a node from the network topology. This will be called when a |
| * existing datanode is removed from the system. |
| * @param node node to be removed; cannot be null |
| */ |
| void remove(Node node); |
| |
| /** |
| * Check if the tree already contains node <i>node</i>. |
| * @param node a node |
| * @return true if <i>node</i> is already in the tree; false otherwise |
| */ |
| boolean contains(Node node); |
| |
| /** |
| * Compare the direct parent of each node for equality. |
| * @return true if their parent are the same |
| */ |
| boolean isSameParent(Node node1, Node node2); |
| |
| /** |
| * Compare the specified ancestor generation of each node for equality. |
| * ancestorGen 1 means parent. |
| * @return true if their specified generation ancestor are equal |
| */ |
| boolean isSameAncestor(Node node1, Node node2, int ancestorGen); |
| |
| /** |
| * Get the ancestor for node on generation <i>ancestorGen</i>. |
| * |
| * @param node the node to get ancestor |
| * @param ancestorGen the ancestor generation |
| * @return the ancestor. If no ancestor is found, then null is returned. |
| */ |
| Node getAncestor(Node node, int ancestorGen); |
| |
| /** |
| * Return the max level of this topology, start from 1 for ROOT. For example, |
| * topology like "/rack/node" has the max level '3'. |
| */ |
| int getMaxLevel(); |
| |
| /** |
| * Given a string representation of a node, return its reference. |
| * @param loc a path string representing a node, can be leaf or inner node |
| * @return a reference to the node; null if the node is not in the tree |
| */ |
| Node getNode(String loc); |
| |
| /** |
| * Given a string representation of a InnerNode, return its leaf nodes count. |
| * @param loc a path-like string representation of a InnerNode |
| * @return the number of leaf nodes, 0 if it's not an InnerNode or the node |
| * doesn't exist |
| */ |
| int getNumOfLeafNode(String loc); |
| |
| /** |
| * Return the node numbers at level <i>level</i>. |
| * @param level topology level, start from 1, which means ROOT |
| * @return the number of nodes on the level |
| */ |
| int getNumOfNodes(int level); |
| |
| /** |
| * Return the nodes at level <i>level</i>. |
| * @param level topology level, start from 1, which means ROOT |
| * @return the nodes on the level |
| */ |
| List<Node> getNodes(int level); |
| |
| /** |
| * Randomly choose a node in the scope. |
| * @param scope range of nodes from which a node will be chosen. If scope |
| * starts with ~, choose one from the all nodes except for the |
| * ones in <i>scope</i>; otherwise, choose one from <i>scope</i>. |
| * @return the chosen node |
| */ |
| Node chooseRandom(String scope); |
| |
| /** |
| * Randomly choose a node in the scope, ano not in the exclude scope. |
| * @param scope range of nodes from which a node will be chosen. cannot start |
| * with ~ |
| * @param excludedScopes the chosen nodes cannot be in these ranges. cannot |
| * starts with ~ |
| * @return the chosen node |
| */ |
| Node chooseRandom(String scope, List<String> excludedScopes); |
| |
| /** |
| * Randomly choose a leaf node from <i>scope</i>. |
| * |
| * If scope starts with ~, choose one from the all nodes except for the |
| * ones in <i>scope</i>; otherwise, choose nodes from <i>scope</i>. |
| * If excludedNodes is given, choose a node that's not in excludedNodes. |
| * |
| * @param scope range of nodes from which a node will be chosen |
| * @param excludedNodes nodes to be excluded |
| * |
| * @return the chosen node |
| */ |
| Node chooseRandom(String scope, Collection<Node> excludedNodes); |
| |
| /** |
| * Randomly choose a leaf node from <i>scope</i>. |
| * |
| * If scope starts with ~, choose one from the all nodes except for the |
| * ones in <i>scope</i>; otherwise, choose nodes from <i>scope</i>. |
| * If excludedNodes is given, choose a node that's not in excludedNodes. |
| * |
| * @param scope range of nodes from which a node will be chosen |
| * @param excludedNodes nodes to be excluded from. |
| * @param ancestorGen matters when excludeNodes is not null. It means the |
| * ancestor generation that's not allowed to share between chosen node and the |
| * excludedNodes. For example, if ancestorGen is 1, means chosen node |
| * cannot share the same parent with excludeNodes. If value is 2, cannot |
| * share the same grand parent, and so on. If ancestorGen is 0, then no |
| * effect. |
| * |
| * @return the chosen node |
| */ |
| Node chooseRandom(String scope, Collection<Node> excludedNodes, |
| int ancestorGen); |
| |
| /** |
| * Randomly choose one node from <i>scope</i>, share the same generation |
| * ancestor with <i>affinityNode</i>, and exclude nodes in |
| * <i>excludeScope</i> and <i>excludeNodes</i>. |
| * |
| * @param scope range of nodes from which a node will be chosen, cannot start |
| * with ~ |
| * @param excludedScopes ranges of nodes to be excluded, cannot start with ~ |
| * @param excludedNodes nodes to be excluded |
| * @param affinityNode when not null, the chosen node should share the same |
| * ancestor with this node at generation ancestorGen. |
| * Ignored when value is null |
| * @param ancestorGen If 0, then no same generation ancestor enforcement on |
| * both excludedNodes and affinityNode. If greater than 0, |
| * then apply to affinityNode(if not null), or apply to |
| * excludedNodes if affinityNode is null |
| * @return the chosen node |
| */ |
| Node chooseRandom(String scope, List<String> excludedScopes, |
| Collection<? extends Node> excludedNodes, Node affinityNode, |
| int ancestorGen); |
| |
| /** |
| * Choose the node at index <i>index</i> from <i>scope</i>, share the same |
| * generation ancestor with <i>affinityNode</i>, and exclude nodes in |
| * <i>excludeScope</i> and <i>excludeNodes</i>. |
| * |
| * @param leafIndex node index, exclude nodes in excludedScope and |
| * excludedNodes |
| * @param scope range of nodes from which a node will be chosen, cannot start |
| * with ~ |
| * @param excludedScopes ranges of nodes to be excluded, cannot start with ~ |
| * @param excludedNodes nodes to be excluded |
| * @param affinityNode when not null, the chosen node should share the same |
| * ancestor with this node at generation ancestorGen. |
| * Ignored when value is null |
| * @param ancestorGen If 0, then no same generation ancestor enforcement on |
| * both excludedNodes and affinityNode. If greater than 0, |
| * then apply to affinityNode(if not null), or apply to |
| * excludedNodes if affinityNode is null |
| * @return the chosen node |
| */ |
| Node getNode(int leafIndex, String scope, List<String> excludedScopes, |
| Collection<Node> excludedNodes, Node affinityNode, int ancestorGen); |
| |
| /** Return the distance cost between two nodes |
| * The distance cost from one node to its parent is it's parent's cost |
| * The distance cost between two nodes is calculated by summing up their |
| * distances cost to their closest common ancestor. |
| * @param node1 one node |
| * @param node2 another node |
| * @return the distance cost between node1 and node2 which is zero if they |
| * are the same or {@link Integer#MAX_VALUE} if node1 or node2 do not belong |
| * to the cluster |
| */ |
| int getDistanceCost(Node node1, Node node2); |
| |
| /** |
| * Sort nodes array by network distance to <i>reader</i> to reduces network |
| * traffic and improves performance. |
| * |
| * As an additional twist, we also randomize the nodes at each network |
| * distance. This helps with load balancing when there is data skew. |
| * |
| * @param reader Node where need the data |
| * @param nodes Available replicas with the requested data |
| * @param activeLen Number of active nodes at the front of the array |
| */ |
| List<? extends Node> sortByDistanceCost(Node reader, |
| List<? extends Node> nodes, int activeLen); |
| } |