Skip to content

Commit 4bd873b

Browse files
authored
HDFS-17044. Set size of non-exist block to NO_ACK when process FBR or IBR to avoid useless report from DataNode. (#5735). Contributed by Haiyang Hu.
Signed-off-by: He Xiaoqiao <hexiaoqiao@apache.org>
1 parent 8a52990 commit 4bd873b

3 files changed

Lines changed: 89 additions & 2 deletions

File tree

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,8 +3295,11 @@ private BlockInfo processReportedBlock(
32953295
BlockInfo storedBlock = getStoredBlock(block);
32963296
if(storedBlock == null) {
32973297
// If blocksMap does not contain reported block id,
3298-
// the replica should be removed from the data-node.
3299-
toInvalidate.add(new Block(block));
3298+
// The replica should be removed from Datanode, and set NumBytes to BlockCommand.No_ACK to
3299+
// avoid useless report to NameNode from Datanode when complete to process it.
3300+
Block invalidateBlock = new Block(block);
3301+
invalidateBlock.setNumBytes(BlockCommand.NO_ACK);
3302+
toInvalidate.add(invalidateBlock);
33003303
return null;
33013304
}
33023305
BlockUCState ucState = storedBlock.getBlockUCState();

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeMetrics.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ public void incrBlocksRemoved(int delta) {
346346
blocksRemoved.incr(delta);
347347
}
348348

349+
public long getBlocksRemoved() {
350+
return blocksRemoved.value();
351+
}
352+
349353
public void incrBytesWritten(int delta) {
350354
bytesWritten.incr(delta);
351355
}

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

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
import java.util.concurrent.atomic.AtomicBoolean;
118118

119119
import static org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState.UNDER_CONSTRUCTION;
120+
import static org.apache.hadoop.test.MetricsAsserts.getLongCounter;
120121
import static org.apache.hadoop.test.MetricsAsserts.getMetrics;
121122
import static org.junit.Assert.assertEquals;
122123
import static org.junit.Assert.assertFalse;
@@ -2121,4 +2122,83 @@ public void testBlockReportAfterDataNodeRestart() throws Exception {
21212122
assertEquals(2, locs[0].getHosts().length);
21222123
}
21232124
}
2125+
2126+
/**
2127+
* Test processing toInvalidate in block reported, if the block not exists need
2128+
* to set the numBytes of the block to NO_ACK,
2129+
* the DataNode processing will not report incremental blocks.
2130+
*/
2131+
@Test(timeout = 360000)
2132+
public void testBlockReportSetNoAckBlockToInvalidate() throws Exception {
2133+
Configuration conf = new HdfsConfiguration();
2134+
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_KEY, 500);
2135+
conf.setInt(DFSConfigKeys.DFS_NAMENODE_REDUNDANCY_INTERVAL_SECONDS_KEY, 10);
2136+
conf.setLong(DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_KEY, 1L);
2137+
try (MiniDFSCluster cluster =
2138+
new MiniDFSCluster.Builder(conf).numDataNodes(1).build()) {
2139+
cluster.waitActive();
2140+
BlockManager blockManager = cluster.getNamesystem().getBlockManager();
2141+
DistributedFileSystem fs = cluster.getFileSystem();
2142+
// Write file.
2143+
Path file = new Path("/test");
2144+
DFSTestUtil.createFile(fs, file, 10240L, (short)1, 0L);
2145+
DFSTestUtil.waitReplication(fs, file, (short) 1);
2146+
LocatedBlock lb = DFSTestUtil.getAllBlocks(fs, file).get(0);
2147+
DatanodeInfo[] loc = lb.getLocations();
2148+
assertEquals(1, loc.length);
2149+
List<DataNode> datanodes = cluster.getDataNodes();
2150+
assertEquals(1, datanodes.size());
2151+
DataNode datanode = datanodes.get(0);
2152+
assertEquals(datanode.getDatanodeUuid(), loc[0].getDatanodeUuid());
2153+
2154+
MetricsRecordBuilder rb = getMetrics(datanode.getMetrics().name());
2155+
// Check the IncrementalBlockReportsNumOps of DataNode, it will be 0.
2156+
assertEquals(1, getLongCounter("IncrementalBlockReportsNumOps", rb));
2157+
2158+
// Delete file and remove block.
2159+
fs.delete(file, false);
2160+
2161+
// Wait for the processing of the marked deleted block to complete.
2162+
BlockManagerTestUtil.waitForMarkedDeleteQueueIsEmpty(blockManager);
2163+
assertNull(blockManager.getStoredBlock(lb.getBlock().getLocalBlock()));
2164+
2165+
// Expire heartbeat on the NameNode,and datanode to be marked dead.
2166+
datanode.setHeartbeatsDisabledForTests(true);
2167+
cluster.setDataNodeDead(datanode.getDatanodeId());
2168+
assertFalse(blockManager.containsInvalidateBlock(loc[0], lb.getBlock().getLocalBlock()));
2169+
2170+
// Wait for re-registration and heartbeat.
2171+
datanode.setHeartbeatsDisabledForTests(false);
2172+
final DatanodeDescriptor dn1Desc = cluster.getNamesystem(0)
2173+
.getBlockManager().getDatanodeManager()
2174+
.getDatanode(datanode.getDatanodeId());
2175+
GenericTestUtils.waitFor(
2176+
() -> dn1Desc.isAlive() && dn1Desc.isHeartbeatedSinceRegistration(),
2177+
100, 5000);
2178+
2179+
// Trigger BlockReports and block is not exists,
2180+
// it will add invalidateBlocks and set block numBytes be NO_ACK.
2181+
cluster.triggerBlockReports();
2182+
GenericTestUtils.waitFor(
2183+
() -> blockManager.containsInvalidateBlock(loc[0], lb.getBlock().getLocalBlock()),
2184+
100, 1000);
2185+
2186+
// Trigger schedule blocks for deletion at datanode.
2187+
int workCount = blockManager.computeInvalidateWork(1);
2188+
assertEquals(1, workCount);
2189+
assertFalse(blockManager.containsInvalidateBlock(loc[0], lb.getBlock().getLocalBlock()));
2190+
2191+
// Wait for the blocksRemoved value in DataNode to be 1.
2192+
GenericTestUtils.waitFor(
2193+
() -> datanode.getMetrics().getBlocksRemoved() == 1,
2194+
100, 5000);
2195+
2196+
// Trigger immediate deletion report at datanode.
2197+
cluster.triggerDeletionReports();
2198+
2199+
// Delete block numBytes be NO_ACK and will not deletion block report,
2200+
// so check the IncrementalBlockReportsNumOps of DataNode still 1.
2201+
assertEquals(1, getLongCounter("IncrementalBlockReportsNumOps", rb));
2202+
}
2203+
}
21242204
}

0 commit comments

Comments
 (0)