Skip to content

Commit 91320b4

Browse files
committed
HDFS-14859. Prevent unnecessary evaluation of costly operation getNumLiveDataNodes when dfs.namenode.safemode.min.datanodes is not zero. Contributed by Srinivasu Majeti.
1 parent 7615945 commit 91320b4

File tree

2 files changed

+97
-5
lines changed

2 files changed

+97
-5
lines changed

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -572,12 +572,18 @@ private boolean areThresholdsMet() {
572572
assert namesystem.hasWriteLock();
573573
// Calculating the number of live datanodes is time-consuming
574574
// in large clusters. Skip it when datanodeThreshold is zero.
575-
int datanodeNum = 0;
576-
if (datanodeThreshold > 0) {
577-
datanodeNum = blockManager.getDatanodeManager().getNumLiveDataNodes();
578-
}
575+
// We need to evaluate getNumLiveDataNodes only when
576+
// (blockSafe >= blockThreshold) is true and hence moving evaluation
577+
// of datanodeNum conditional to isBlockThresholdMet as well
579578
synchronized (this) {
580-
return blockSafe >= blockThreshold && datanodeNum >= datanodeThreshold;
579+
boolean isBlockThresholdMet = (blockSafe >= blockThreshold);
580+
boolean isDatanodeThresholdMet = true;
581+
if (isBlockThresholdMet && datanodeThreshold > 0) {
582+
int datanodeNum = blockManager.getDatanodeManager().
583+
getNumLiveDataNodes();
584+
isDatanodeThresholdMet = (datanodeNum >= datanodeThreshold);
585+
}
586+
return isBlockThresholdMet && isDatanodeThresholdMet;
581587
}
582588
}
583589

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,87 @@ public void testDatanodeThreshodShouldBeMet() throws Exception {
377377
assertFalse(bmSafeMode.isInSafeMode());
378378
}
379379

380+
/**
381+
* Test block manager won't leave safe mode if datanode threshold is not met
382+
* only if datanodeThreshold is configured > 0.
383+
*/
384+
@Test(timeout = 30000)
385+
public void testDatanodeThreshodShouldBeMetOnlyIfConfigured()
386+
throws Exception {
387+
bmSafeMode.activate(BLOCK_TOTAL);
388+
389+
//Blocks received is set to threshold
390+
setBlockSafe(BLOCK_THRESHOLD);
391+
392+
//datanodeThreshold is configured to 1 but not all DNs registered .
393+
// Expecting safe mode .
394+
when(dn.getNumLiveDataNodes()).thenReturn(1);
395+
setDatanodeThreshold(1);
396+
bmSafeMode.checkSafeMode();
397+
assertTrue(bmSafeMode.isInSafeMode());
398+
399+
//datanodeThreshold is configured to 1 and all DNs registered .
400+
// Not expecting safe mode .
401+
when(dn.getNumLiveDataNodes()).thenReturn(DATANODE_NUM);
402+
setDatanodeThreshold(1);
403+
bmSafeMode.checkSafeMode();
404+
waitForExtensionPeriod();
405+
assertFalse(bmSafeMode.isInSafeMode());
406+
407+
//datanodeThreshold is configured to 0 but not all DNs registered .
408+
// Not Expecting safe mode .
409+
bmSafeMode.activate(BLOCK_TOTAL);
410+
setBlockSafe(BLOCK_THRESHOLD);
411+
when(dn.getNumLiveDataNodes()).thenReturn(1);
412+
setDatanodeThreshold(0);
413+
bmSafeMode.checkSafeMode();
414+
assertFalse(bmSafeMode.isInSafeMode());
415+
416+
//datanodeThreshold is configured to 0 and all DNs registered .
417+
// Not Expecting safe mode .
418+
bmSafeMode.activate(BLOCK_TOTAL);
419+
setBlockSafe(BLOCK_THRESHOLD);
420+
when(dn.getNumLiveDataNodes()).thenReturn(DATANODE_NUM);
421+
setDatanodeThreshold(0);
422+
bmSafeMode.checkSafeMode();
423+
assertFalse(bmSafeMode.isInSafeMode());
424+
425+
//Blocks received set to below threshold and all combinations
426+
//of datanodeThreshold should result in safe mode.
427+
428+
429+
//datanodeThreshold is configured to 1 but not all DNs registered .
430+
// Expecting safe mode .
431+
bmSafeMode.activate(BLOCK_TOTAL);
432+
setBlockSafe(BLOCK_THRESHOLD-1);
433+
setSafeModeStatus(BMSafeModeStatus.PENDING_THRESHOLD);
434+
when(dn.getNumLiveDataNodes()).thenReturn(1);
435+
setDatanodeThreshold(1);
436+
bmSafeMode.checkSafeMode();
437+
assertTrue(bmSafeMode.isInSafeMode());
438+
439+
//datanodeThreshold is configured to 1 and all DNs registered .
440+
// Expecting safe mode .
441+
when(dn.getNumLiveDataNodes()).thenReturn(DATANODE_NUM);
442+
setDatanodeThreshold(1);
443+
bmSafeMode.checkSafeMode();
444+
assertTrue(bmSafeMode.isInSafeMode());
445+
446+
//datanodeThreshold is configured to 0 but not all DNs registered .
447+
// Expecting safe mode .
448+
when(dn.getNumLiveDataNodes()).thenReturn(1);
449+
setDatanodeThreshold(0);
450+
bmSafeMode.checkSafeMode();
451+
assertTrue(bmSafeMode.isInSafeMode());
452+
453+
//datanodeThreshold is configured to 0 and all DNs registered .
454+
// Expecting safe mode .
455+
when(dn.getNumLiveDataNodes()).thenReturn(DATANODE_NUM);
456+
setDatanodeThreshold(0);
457+
bmSafeMode.checkSafeMode();
458+
assertTrue(bmSafeMode.isInSafeMode());
459+
}
460+
380461
/**
381462
* Test block manager won't leave safe mode if there are blocks with
382463
* generation stamp (GS) in future.
@@ -604,6 +685,11 @@ private void setBlockSafe(long blockSafe) {
604685
Whitebox.setInternalState(bmSafeMode, "blockSafe", blockSafe);
605686
}
606687

688+
private void setDatanodeThreshold(int dnSafeModeThreshold) {
689+
Whitebox.setInternalState(bmSafeMode, "datanodeThreshold",
690+
dnSafeModeThreshold);
691+
}
692+
607693
private long getblockSafe() {
608694
return (long)Whitebox.getInternalState(bmSafeMode, "blockSafe");
609695
}

0 commit comments

Comments
 (0)