Skip to content

Commit bcef4ee

Browse files
authored
HDFS-17913. Dead DataNode in Host2NodesMap can break block location sorting (#8462)
1 parent 215a1ed commit bcef4ee

2 files changed

Lines changed: 54 additions & 0 deletions

File tree

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,9 @@ private void sortLocatedBlock(final LocatedBlock lb, String targetHost,
637637
// here we should get node but not datanode only .
638638
boolean nonDatanodeReader = false;
639639
Node client = getDatanodeByHost(targetHost);
640+
if (client != null && client.getParent() == null) {
641+
client = null;
642+
}
640643
if (client == null) {
641644
nonDatanodeReader = true;
642645
List<String> hosts = new ArrayList<>(1);

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestDatanodeManager.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,57 @@ public void testGetBlockLocationConsiderLoad()
667667
assertEquals(locs[0].getIpAddr(), sortedLocs2[4].getIpAddr());
668668
}
669669

670+
@Test
671+
public void testGetBlockLocationWithDeadDatanodeReader()
672+
throws IOException, URISyntaxException {
673+
Configuration conf = new Configuration();
674+
conf.setBoolean(
675+
DFSConfigKeys.DFS_NAMENODE_READ_CONSIDERLOAD_KEY, true);
676+
conf.setBoolean(
677+
DFSConfigKeys.DFS_NAMENODE_AVOID_STALE_DATANODE_FOR_READ_KEY, true);
678+
conf.setLong(DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_KEY, 0);
679+
conf.setInt(
680+
DFSConfigKeys.DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_KEY, 0);
681+
FSNamesystem fsn = Mockito.mock(FSNamesystem.class);
682+
Mockito.when(fsn.hasWriteLock()).thenReturn(true);
683+
Mockito.when(fsn.hasWriteLock(RwLockMode.BM)).thenReturn(true);
684+
URL shellScript = getClass().getResource(
685+
"/" + Shell.appendScriptExtension("topology-script"));
686+
Path resourcePath = Paths.get(shellScript.toURI());
687+
FileUtil.setExecutable(resourcePath.toFile(), true);
688+
conf.set(DFSConfigKeys.NET_TOPOLOGY_SCRIPT_FILE_NAME_KEY,
689+
resourcePath.toString());
690+
DatanodeManager dm = mockDatanodeManager(fsn, conf);
691+
692+
int totalDNs = 5;
693+
DatanodeInfo[] locs = new DatanodeInfo[totalDNs];
694+
for (int i = 0; i < totalDNs; i++) {
695+
String uuid = "UUID-" + i;
696+
String ip = "IP-" + i / 2 + "-" + i;
697+
DatanodeRegistration dr = Mockito.mock(DatanodeRegistration.class);
698+
Mockito.when(dr.getDatanodeUuid()).thenReturn(uuid);
699+
Mockito.when(dr.getIpAddr()).thenReturn(ip);
700+
dm.registerDatanode(dr);
701+
locs[i] = dm.getDatanode(uuid);
702+
locs[i].setXceiverCount(i);
703+
}
704+
705+
locs[3].setLastUpdateMonotonic(0);
706+
dm.removeDeadDatanode(locs[3], true);
707+
assertThat(locs[3].getParent()).isNull();
708+
assertThat(dm.getDatanodeByHost(locs[3].getIpAddr())).isSameAs(locs[3]);
709+
710+
ExtendedBlock b = new ExtendedBlock("somePoolID", 1234);
711+
LocatedBlock block = new LocatedBlock(b,
712+
new DatanodeInfo[] {locs[1], locs[2], locs[4]});
713+
List<LocatedBlock> blocks = new ArrayList<>();
714+
blocks.add(block);
715+
716+
dm.sortLocatedBlocks(locs[3].getIpAddr(), blocks);
717+
DatanodeInfo[] sortedLocs = block.getLocations();
718+
assertEquals(locs[2].getIpAddr(), sortedLocs[0].getIpAddr());
719+
}
720+
670721
@Test
671722
public void testGetBlockLocationConsiderLoadWithNodesOfSameDistance()
672723
throws IOException, URISyntaxException {

0 commit comments

Comments
 (0)