19
19
20
20
import org .apache .hadoop .thirdparty .com .google .common .annotations .VisibleForTesting ;
21
21
import org .apache .hadoop .thirdparty .com .google .common .base .Preconditions ;
22
- import org .apache .hadoop .thirdparty .com .google .common .collect .Lists ;
23
22
import org .apache .hadoop .classification .InterfaceAudience ;
24
23
import org .apache .hadoop .classification .InterfaceStability ;
25
24
import org .apache .hadoop .conf .Configuration ;
29
28
import org .slf4j .LoggerFactory ;
30
29
31
30
import java .util .*;
31
+ import java .util .concurrent .ThreadLocalRandom ;
32
+ import java .util .concurrent .atomic .AtomicReference ;
32
33
import java .util .concurrent .locks .ReadWriteLock ;
33
34
import java .util .concurrent .locks .ReentrantReadWriteLock ;
34
35
import java .util .function .Consumer ;
@@ -52,6 +53,8 @@ public class NetworkTopology {
52
53
private static final char PATH_SEPARATOR = '/' ;
53
54
private static final String PATH_SEPARATOR_STR = "/" ;
54
55
private static final String ROOT = "/" ;
56
+ private static final AtomicReference <Random > RANDOM_REF =
57
+ new AtomicReference <>();
55
58
56
59
public static class InvalidTopologyException extends RuntimeException {
57
60
private static final long serialVersionUID = 1L ;
@@ -394,17 +397,12 @@ static public int getDistanceByPath(Node node1, Node node2) {
394
397
* @exception IllegalArgumentException when either node1 or node2 is null, or
395
398
* node1 or node2 do not belong to the cluster
396
399
*/
397
- public boolean isOnSameRack ( Node node1 , Node node2 ) {
400
+ public boolean isOnSameRack (Node node1 , Node node2 ) {
398
401
if (node1 == null || node2 == null ) {
399
402
return false ;
400
403
}
401
-
402
- netlock .readLock ().lock ();
403
- try {
404
- return isSameParents (node1 , node2 );
405
- } finally {
406
- netlock .readLock ().unlock ();
407
- }
404
+
405
+ return isSameParents (node1 , node2 );
408
406
}
409
407
410
408
/**
@@ -438,11 +436,14 @@ protected boolean isSameParents(Node node1, Node node2) {
438
436
return node1 .getParent ()==node2 .getParent ();
439
437
}
440
438
441
- private static final Random r = new Random ();
442
-
443
439
@ VisibleForTesting
444
440
void setRandomSeed (long seed ) {
445
- r .setSeed (seed );
441
+ RANDOM_REF .set (new Random (seed ));
442
+ }
443
+
444
+ Random getRandom () {
445
+ Random random = RANDOM_REF .get ();
446
+ return (random == null ) ? ThreadLocalRandom .current () : random ;
446
447
}
447
448
448
449
/**
@@ -561,6 +562,7 @@ private Node chooseRandom(final InnerNode parentNode,
561
562
totalInScopeNodes , availableNodes );
562
563
return null ;
563
564
}
565
+ Random r = getRandom ();
564
566
if (excludedNodes == null || excludedNodes .isEmpty ()) {
565
567
// if there are no excludedNodes, randomly choose a node
566
568
final int index = r .nextInt (totalInScopeNodes );
@@ -876,7 +878,7 @@ public void sortByDistance(Node reader, Node[] nodes, int activeLen) {
876
878
* This method is called if the reader is a datanode,
877
879
* so nonDataNodeReader flag is set to false.
878
880
*/
879
- sortByDistance (reader , nodes , activeLen , list -> Collections . shuffle ( list ) );
881
+ sortByDistance (reader , nodes , activeLen , null );
880
882
}
881
883
882
884
/**
@@ -919,8 +921,7 @@ public void sortByDistanceUsingNetworkLocation(Node reader, Node[] nodes,
919
921
* This method is called if the reader is not a datanode,
920
922
* so nonDataNodeReader flag is set to true.
921
923
*/
922
- sortByDistanceUsingNetworkLocation (reader , nodes , activeLen ,
923
- list -> Collections .shuffle (list ));
924
+ sortByDistanceUsingNetworkLocation (reader , nodes , activeLen , null );
924
925
}
925
926
926
927
/**
@@ -958,38 +959,28 @@ private <T extends Node> void sortByDistance(Node reader, T[] nodes,
958
959
int activeLen , Consumer <List <T >> secondarySort ,
959
960
boolean nonDataNodeReader ) {
960
961
/** Sort weights for the nodes array */
961
- int [] weights = new int [activeLen ];
962
- for (int i =0 ; i <activeLen ; i ++) {
963
- if (nonDataNodeReader ) {
964
- weights [i ] = getWeightUsingNetworkLocation (reader , nodes [i ]);
962
+ TreeMap <Integer , List <T >> weightedNodeTree =
963
+ new TreeMap <>();
964
+ int nWeight ;
965
+ for (int i = 0 ; i < activeLen ; i ++) {
966
+ if (nonDataNodeReader ) {
967
+ nWeight = getWeightUsingNetworkLocation (reader , nodes [i ]);
965
968
} else {
966
- weights [i ] = getWeight (reader , nodes [i ]);
967
- }
968
- }
969
- // Add weight/node pairs to a TreeMap to sort
970
- TreeMap <Integer , List <T >> tree = new TreeMap <>();
971
- for (int i =0 ; i <activeLen ; i ++) {
972
- int weight = weights [i ];
973
- T node = nodes [i ];
974
- List <T > list = tree .get (weight );
975
- if (list == null ) {
976
- list = Lists .newArrayListWithExpectedSize (1 );
977
- tree .put (weight , list );
969
+ nWeight = getWeight (reader , nodes [i ]);
978
970
}
979
- list .add (node );
971
+ weightedNodeTree .computeIfAbsent (
972
+ nWeight , k -> new ArrayList <>(1 )).add (nodes [i ]);
980
973
}
981
- // Sort nodes which have the same weight using secondarySort.
982
974
int idx = 0 ;
983
- for (List <T > list : tree .values ()) {
984
- if (list != null ) {
985
- Collections .shuffle (list , r );
986
- if (secondarySort != null ) {
987
- secondarySort .accept (list );
988
- }
989
- for (T n : list ) {
990
- nodes [idx ] = n ;
991
- idx ++;
992
- }
975
+ // Sort nodes which have the same weight using secondarySort.
976
+ for (List <T > nodesList : weightedNodeTree .values ()) {
977
+ Collections .shuffle (nodesList , getRandom ());
978
+ if (secondarySort != null ) {
979
+ // a secondary sort breaks the tie between nodes.
980
+ secondarySort .accept (nodesList );
981
+ }
982
+ for (T n : nodesList ) {
983
+ nodes [idx ++] = n ;
993
984
}
994
985
}
995
986
Preconditions .checkState (idx == activeLen ,
0 commit comments