Skip to content

Commit 4222b62

Browse files
ChenSammixiaoyuyao
authored andcommitted
HDDS-1879. Support multiple excluded scopes when choosing datanodes in NetworkTopology (#1194)
1 parent c8d61ff commit 4222b62

File tree

9 files changed

+247
-195
lines changed

9 files changed

+247
-195
lines changed

hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/net/InnerNode.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.hadoop.hdds.scm.net;
1919

2020
import java.util.Collection;
21+
import java.util.List;
2122

2223
/**
2324
* The interface defines an inner node in a network topology.
@@ -72,13 +73,13 @@ N newInnerNode(String name, String location, InnerNode parent, int level,
7273
*
7374
* @param leafIndex ode's index, start from 0, skip the nodes in
7475
* excludedScope and excludedNodes with ancestorGen
75-
* @param excludedScope the excluded scope
76+
* @param excludedScopes the excluded scopes
7677
* @param excludedNodes nodes to be excluded. If ancestorGen is not 0,
7778
* the chosen node will not share same ancestor with
7879
* those in excluded nodes at the specified generation
7980
* @param ancestorGen ignored with value is 0
8081
* @return the leaf node corresponding to the given index
8182
*/
82-
Node getLeaf(int leafIndex, String excludedScope,
83+
Node getLeaf(int leafIndex, List<String> excludedScopes,
8384
Collection<Node> excludedNodes, int ancestorGen);
8485
}

hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/net/InnerNodeImpl.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.HashMap;
2323
import java.util.Iterator;
2424
import java.util.LinkedHashMap;
25+
import java.util.List;
2526
import java.util.Map;
2627

2728
import com.google.common.base.Preconditions;
@@ -276,7 +277,7 @@ public Node getLeaf(int leafIndex) {
276277
*
277278
* @param leafIndex node's index, start from 0, skip the nodes in
278279
* excludedScope and excludedNodes with ancestorGen
279-
* @param excludedScope the exclude scope
280+
* @param excludedScopes the exclude scopes
280281
* @param excludedNodes nodes to be excluded from. If ancestorGen is not 0,
281282
* the chosen node will not share same ancestor with
282283
* those in excluded nodes at the specified generation
@@ -300,7 +301,7 @@ public Node getLeaf(int leafIndex) {
300301
*
301302
* Input:
302303
* leafIndex = 2
303-
* excludedScope = /dc2
304+
* excludedScope = /dc2/rack2
304305
* excludedNodes = {/dc1/rack1/n1}
305306
* ancestorGen = 1
306307
*
@@ -313,12 +314,12 @@ public Node getLeaf(int leafIndex) {
313314
* means picking the 3th available node, which is n5.
314315
*
315316
*/
316-
public Node getLeaf(int leafIndex, String excludedScope,
317+
public Node getLeaf(int leafIndex, List<String> excludedScopes,
317318
Collection<Node> excludedNodes, int ancestorGen) {
318319
Preconditions.checkArgument(leafIndex >= 0 && ancestorGen >= 0);
319320
// come to leaf parent layer
320321
if (isLeafParent()) {
321-
return getLeafOnLeafParent(leafIndex, excludedScope, excludedNodes);
322+
return getLeafOnLeafParent(leafIndex, excludedScopes, excludedNodes);
322323
}
323324

324325
int maxLevel = NodeSchemaManager.getInstance().getMaxLevel();
@@ -328,22 +329,24 @@ public Node getLeaf(int leafIndex, String excludedScope,
328329
Map<Node, Integer> countMap =
329330
getAncestorCountMap(excludedNodes, ancestorGen, currentGen);
330331
// nodes covered by excluded scope
331-
int excludedNodeCount = getExcludedScopeNodeCount(excludedScope);
332+
Map<String, Integer> excludedNodeCount =
333+
getExcludedScopeNodeCount(excludedScopes);
332334

333-
for(Node child : childrenMap.values()) {
335+
for (Node child : childrenMap.values()) {
334336
int leafCount = child.getNumOfLeaves();
335-
// skip nodes covered by excluded scope
336-
if (excludedScope != null &&
337-
excludedScope.startsWith(child.getNetworkFullPath())) {
338-
leafCount -= excludedNodeCount;
337+
// skip nodes covered by excluded scopes
338+
for (Map.Entry<String, Integer> entry: excludedNodeCount.entrySet()) {
339+
if (entry.getKey().startsWith(child.getNetworkFullPath())) {
340+
leafCount -= entry.getValue();
341+
}
339342
}
340343
// skip nodes covered by excluded nodes and ancestorGen
341344
Integer count = countMap.get(child);
342345
if (count != null) {
343346
leafCount -= count;
344347
}
345348
if (leafIndex < leafCount) {
346-
return ((InnerNode)child).getLeaf(leafIndex, excludedScope,
349+
return ((InnerNode)child).getLeaf(leafIndex, excludedScopes,
347350
excludedNodes, ancestorGen);
348351
} else {
349352
leafIndex -= leafCount;
@@ -424,18 +427,22 @@ private Map<Node, Integer> getAncestorCountMap(Collection<Node> nodes,
424427
* Get the node with leafIndex, considering skip nodes in excludedScope
425428
* and in excludeNodes list.
426429
*/
427-
private Node getLeafOnLeafParent(int leafIndex, String excludedScope,
430+
private Node getLeafOnLeafParent(int leafIndex, List<String> excludedScopes,
428431
Collection<Node> excludedNodes) {
429432
Preconditions.checkArgument(isLeafParent() && leafIndex >= 0);
430433
if (leafIndex >= getNumOfChildren()) {
431434
return null;
432435
}
433436
for(Node node : childrenMap.values()) {
434-
if ((excludedNodes != null && (excludedNodes.contains(node))) ||
435-
(excludedScope != null &&
436-
(node.getNetworkFullPath().startsWith(excludedScope)))) {
437+
if (excludedNodes != null && excludedNodes.contains(node)) {
437438
continue;
438439
}
440+
if (excludedScopes != null && excludedScopes.size() > 0) {
441+
if (excludedScopes.stream().anyMatch(scope ->
442+
node.getNetworkFullPath().startsWith(scope))) {
443+
continue;
444+
}
445+
}
439446
if (leafIndex == 0) {
440447
return node;
441448
}
@@ -484,12 +491,19 @@ private Node getChildNode(int index) {
484491
return node;
485492
}
486493

487-
/** Get how many leaf nodes are covered by the excludedScope. */
488-
private int getExcludedScopeNodeCount(String excludedScope) {
489-
if (excludedScope == null) {
490-
return 0;
494+
/** Get how many leaf nodes are covered by the excludedScopes(no overlap). */
495+
private Map<String, Integer> getExcludedScopeNodeCount(
496+
List<String> excludedScopes) {
497+
HashMap<String, Integer> nodeCounts = new HashMap<>();
498+
if (excludedScopes == null || excludedScopes.isEmpty()) {
499+
return nodeCounts;
500+
}
501+
502+
for (String scope: excludedScopes) {
503+
Node excludedScopeNode = getNode(scope);
504+
nodeCounts.put(scope, excludedScopeNode == null ? 0 :
505+
excludedScopeNode.getNumOfLeaves());
491506
}
492-
Node excludedScopeNode = getNode(excludedScope);
493-
return excludedScopeNode == null ? 0 : excludedScopeNode.getNumOfLeaves();
507+
return nodeCounts;
494508
}
495509
}

hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/net/NetUtils.java

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
*/
1818
package org.apache.hadoop.hdds.scm.net;
1919

20+
import org.apache.commons.collections.CollectionUtils;
2021
import org.slf4j.Logger;
2122
import org.slf4j.LoggerFactory;
2223

2324
import java.util.ArrayList;
2425
import java.util.Collection;
2526
import java.util.Iterator;
2627
import java.util.List;
28+
import java.util.stream.Collectors;
2729

2830
/**
2931
* Utility class to facilitate network topology functions.
@@ -71,35 +73,38 @@ public static int locationToDepth(String location) {
7173
* Remove node from mutableExcludedNodes if it's covered by excludedScope.
7274
* Please noted that mutableExcludedNodes content might be changed after the
7375
* function call.
74-
* @return the new excludedScope
7576
*/
76-
public static String removeDuplicate(NetworkTopology topology,
77-
Collection<Node> mutableExcludedNodes, String excludedScope,
77+
public static void removeDuplicate(NetworkTopology topology,
78+
Collection<Node> mutableExcludedNodes, List<String> mutableExcludedScopes,
7879
int ancestorGen) {
79-
if (mutableExcludedNodes == null || mutableExcludedNodes.size() == 0 ||
80-
excludedScope == null || topology == null) {
81-
return excludedScope;
80+
if (CollectionUtils.isEmpty(mutableExcludedNodes) ||
81+
CollectionUtils.isEmpty(mutableExcludedScopes) || topology == null) {
82+
return;
8283
}
8384

8485
Iterator<Node> iterator = mutableExcludedNodes.iterator();
85-
while (iterator.hasNext()) {
86+
while (iterator.hasNext() && (!mutableExcludedScopes.isEmpty())) {
8687
Node node = iterator.next();
8788
Node ancestor = topology.getAncestor(node, ancestorGen);
8889
if (ancestor == null) {
8990
LOG.warn("Fail to get ancestor generation " + ancestorGen +
9091
" of node :" + node);
9192
continue;
9293
}
93-
if (excludedScope.startsWith(ancestor.getNetworkFullPath())) {
94-
// reset excludedScope if it's covered by exclude node's ancestor
95-
return null;
96-
}
97-
if (ancestor.getNetworkFullPath().startsWith(excludedScope)) {
98-
// remove exclude node if it's covered by excludedScope
99-
iterator.remove();
100-
}
94+
// excludedScope is child of ancestor
95+
List<String> duplicateList = mutableExcludedScopes.stream()
96+
.filter(scope -> scope.startsWith(ancestor.getNetworkFullPath()))
97+
.collect(Collectors.toList());
98+
mutableExcludedScopes.removeAll(duplicateList);
99+
100+
// ancestor is covered by excludedScope
101+
mutableExcludedScopes.stream().forEach(scope -> {
102+
if (ancestor.getNetworkFullPath().startsWith(scope)) {
103+
// remove exclude node if it's covered by excludedScope
104+
iterator.remove();
105+
}
106+
});
101107
}
102-
return excludedScope;
103108
}
104109

105110
/**
@@ -109,7 +114,7 @@ public static String removeDuplicate(NetworkTopology topology,
109114
*/
110115
public static void removeOutscope(Collection<Node> mutableExcludedNodes,
111116
String scope) {
112-
if (mutableExcludedNodes == null || scope == null) {
117+
if (CollectionUtils.isEmpty(mutableExcludedNodes) || scope == null) {
113118
return;
114119
}
115120
synchronized (mutableExcludedNodes) {
@@ -134,7 +139,7 @@ public static void removeOutscope(Collection<Node> mutableExcludedNodes,
134139
public static List<Node> getAncestorList(NetworkTopology topology,
135140
Collection<Node> nodes, int generation) {
136141
List<Node> ancestorList = new ArrayList<>();
137-
if (topology == null ||nodes == null || nodes.size() == 0 ||
142+
if (topology == null || CollectionUtils.isEmpty(nodes) ||
138143
generation == 0) {
139144
return ancestorList;
140145
}

hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/net/NetworkTopology.java

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@ public InvalidTopologyException(String msg) {
3939
*/
4040
void add(Node node);
4141

42-
4342
/**
4443
* Remove a node from the network topology. This will be called when a
4544
* existing datanode is removed from the system.
4645
* @param node node to be removed; cannot be null
4746
*/
4847
void remove(Node node);
4948

50-
5149
/**
5250
* Check if the tree already contains node <i>node</i>.
5351
* @param node a node
@@ -68,7 +66,6 @@ public InvalidTopologyException(String msg) {
6866
*/
6967
boolean isSameAncestor(Node node1, Node node2, int ancestorGen);
7068

71-
7269
/**
7370
* Get the ancestor for node on generation <i>ancestorGen</i>.
7471
*
@@ -119,11 +116,11 @@ public InvalidTopologyException(String msg) {
119116
* Randomly choose a node in the scope, ano not in the exclude scope.
120117
* @param scope range of nodes from which a node will be chosen. cannot start
121118
* with ~
122-
* @param excludedScope the chosen node cannot be in this range. cannot
119+
* @param excludedScopes the chosen nodes cannot be in these ranges. cannot
123120
* starts with ~
124121
* @return the chosen node
125122
*/
126-
Node chooseRandom(String scope, String excludedScope);
123+
Node chooseRandom(String scope, List<String> excludedScopes);
127124

128125
/**
129126
* Randomly choose a leaf node from <i>scope</i>.
@@ -160,34 +157,14 @@ public InvalidTopologyException(String msg) {
160157
Node chooseRandom(String scope, Collection<Node> excludedNodes,
161158
int ancestorGen);
162159

163-
164-
/**
165-
* Randomly choose a leaf node.
166-
*
167-
* @param scope range from which a node will be chosen, cannot start with ~
168-
* @param excludedNodes nodes to be excluded
169-
* @param excludedScope excluded node range. Cannot start with ~
170-
* @param ancestorGen matters when excludeNodes is not null. It means the
171-
* ancestor generation that's not allowed to share between chosen node and the
172-
* excludedNodes. For example, if ancestorGen is 1, means chosen node
173-
* cannot share the same parent with excludeNodes. If value is 2, cannot
174-
* share the same grand parent, and so on. If ancestorGen is 0, then no
175-
* effect.
176-
*
177-
* @return the chosen node
178-
*/
179-
Node chooseRandom(String scope, String excludedScope,
180-
Collection<Node> excludedNodes, int ancestorGen);
181-
182-
183160
/**
184161
* Randomly choose one node from <i>scope</i>, share the same generation
185162
* ancestor with <i>affinityNode</i>, and exclude nodes in
186163
* <i>excludeScope</i> and <i>excludeNodes</i>.
187164
*
188165
* @param scope range of nodes from which a node will be chosen, cannot start
189166
* with ~
190-
* @param excludedScope range of nodes to be excluded, cannot start with ~
167+
* @param excludedScopes ranges of nodes to be excluded, cannot start with ~
191168
* @param excludedNodes nodes to be excluded
192169
* @param affinityNode when not null, the chosen node should share the same
193170
* ancestor with this node at generation ancestorGen.
@@ -198,7 +175,7 @@ Node chooseRandom(String scope, String excludedScope,
198175
* excludedNodes if affinityNode is null
199176
* @return the chosen node
200177
*/
201-
Node chooseRandom(String scope, String excludedScope,
178+
Node chooseRandom(String scope, List<String> excludedScopes,
202179
Collection<Node> excludedNodes, Node affinityNode, int ancestorGen);
203180

204181
/**
@@ -210,7 +187,7 @@ Node chooseRandom(String scope, String excludedScope,
210187
* excludedNodes
211188
* @param scope range of nodes from which a node will be chosen, cannot start
212189
* with ~
213-
* @param excludedScope range of nodes to be excluded, cannot start with ~
190+
* @param excludedScopes ranges of nodes to be excluded, cannot start with ~
214191
* @param excludedNodes nodes to be excluded
215192
* @param affinityNode when not null, the chosen node should share the same
216193
* ancestor with this node at generation ancestorGen.
@@ -221,7 +198,7 @@ Node chooseRandom(String scope, String excludedScope,
221198
* excludedNodes if affinityNode is null
222199
* @return the chosen node
223200
*/
224-
Node getNode(int leafIndex, String scope, String excludedScope,
201+
Node getNode(int leafIndex, String scope, List<String> excludedScopes,
225202
Collection<Node> excludedNodes, Node affinityNode, int ancestorGen);
226203

227204
/** Return the distance cost between two nodes

0 commit comments

Comments
 (0)