Skip to content

Commit 1b40cf5

Browse files
committed
addressing short data blocks
1 parent 8a4daad commit 1b40cf5

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,9 @@ BlockReconstructionWork scheduleReconstruction(BlockInfo block,
21662166
// skip if source datanodes for reconstructing ec block are not enough
21672167
if (block.isStriped()) {
21682168
BlockInfoStriped stripedBlock = (BlockInfoStriped) block;
2169-
if (stripedBlock.getDataBlockNum() > srcNodes.length) {
2169+
int cellsNum = (int) ((stripedBlock.getNumBytes() - 1) / stripedBlock.getCellSize() + 1);
2170+
int minRequiredSources = Math.min(cellsNum, stripedBlock.getDataBlockNum());
2171+
if (minRequiredSources > srcNodes.length) {
21702172
LOG.debug("Block {} cannot be reconstructed due to shortage of source datanodes ", block);
21712173
return null;
21722174
}

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

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,12 @@ public void testSkipReconstructionWithManyBusyNodes() {
858858
// RS-3-2 EC policy
859859
ErasureCodingPolicy ecPolicy =
860860
SystemErasureCodingPolicies.getPolicies().get(1);
861-
// striped blockInfo
861+
862+
// striped blockInfo: 3 data blocks + 2 parity blocks
862863
Block aBlock = new Block(blockId, ecPolicy.getCellSize() * ecPolicy.getNumDataUnits(), 0);
863864
BlockInfoStriped aBlockInfoStriped = new BlockInfoStriped(aBlock, ecPolicy);
864-
// ec storageInfo
865+
866+
// create 4 storageInfo, which means 1 block is missing
865867
DatanodeStorageInfo ds1 = DFSTestUtil.createDatanodeStorageInfo(
866868
"storage1", "1.1.1.1", "rack1", "host1");
867869
DatanodeStorageInfo ds2 = DFSTestUtil.createDatanodeStorageInfo(
@@ -884,7 +886,7 @@ public void testSkipReconstructionWithManyBusyNodes() {
884886
BlockReconstructionWork work = bm.scheduleReconstruction(aBlockInfoStriped, 3);
885887
assertNotNull(work);
886888

887-
// simulate the 3 nodes reach maxReplicationStreams
889+
// simulate the 2 nodes reach maxReplicationStreams
888890
for(int i = 0; i < bm.maxReplicationStreams; i++){
889891
ds3.getDatanodeDescriptor().incrementPendingReplicationWithoutTargets();
890892
ds4.getDatanodeDescriptor().incrementPendingReplicationWithoutTargets();
@@ -895,6 +897,56 @@ public void testSkipReconstructionWithManyBusyNodes() {
895897
assertNull(work);
896898
}
897899

900+
@Test
901+
public void testSkipReconstructionWithManyBusyNodes2() {
902+
long blockId = -9223372036854775776L; // real ec block id
903+
// RS-3-2 EC policy
904+
ErasureCodingPolicy ecPolicy =
905+
SystemErasureCodingPolicies.getPolicies().get(1);
906+
907+
// striped blockInfo: 2 data blocks + 2 paritys
908+
Block aBlock = new Block(blockId, ecPolicy.getCellSize() * (ecPolicy.getNumDataUnits() - 1), 0);
909+
BlockInfoStriped aBlockInfoStriped = new BlockInfoStriped(aBlock, ecPolicy);
910+
911+
// create 3 storageInfo, which means 1 block is missing
912+
DatanodeStorageInfo ds1 = DFSTestUtil.createDatanodeStorageInfo(
913+
"storage1", "1.1.1.1", "rack1", "host1");
914+
DatanodeStorageInfo ds2 = DFSTestUtil.createDatanodeStorageInfo(
915+
"storage2", "2.2.2.2", "rack2", "host2");
916+
DatanodeStorageInfo ds3 = DFSTestUtil.createDatanodeStorageInfo(
917+
"storage3", "3.3.3.3", "rack3", "host3");
918+
919+
// link block with storage
920+
aBlockInfoStriped.addStorage(ds1, aBlock);
921+
aBlockInfoStriped.addStorage(ds2, new Block(blockId + 1, 0, 0));
922+
aBlockInfoStriped.addStorage(ds3, new Block(blockId + 2, 0, 0));
923+
924+
addEcBlockToBM(blockId, ecPolicy);
925+
aBlockInfoStriped.setBlockCollectionId(mockINodeId);
926+
927+
// reconstruction should be scheduled
928+
BlockReconstructionWork work = bm.scheduleReconstruction(aBlockInfoStriped, 3);
929+
assertNotNull(work);
930+
931+
// simulate the 1 node reaches maxReplicationStreams
932+
for(int i = 0; i < bm.maxReplicationStreams; i++){
933+
ds2.getDatanodeDescriptor().incrementPendingReplicationWithoutTargets();
934+
}
935+
936+
// reconstruction should still be scheduled since there are 2 source nodes to create 2 blocks
937+
work = bm.scheduleReconstruction(aBlockInfoStriped, 3);
938+
assertNotNull(work);
939+
940+
// simulate the 1 more node reaches maxReplicationStreams
941+
for(int i = 0; i < bm.maxReplicationStreams; i++){
942+
ds3.getDatanodeDescriptor().incrementPendingReplicationWithoutTargets();
943+
}
944+
945+
// reconstruction should be skipped since the number of non-busy nodes are not enough
946+
work = bm.scheduleReconstruction(aBlockInfoStriped, 3);
947+
assertNull(work);
948+
}
949+
898950
@Test
899951
public void testFavorDecomUntilHardLimit() throws Exception {
900952
bm.maxReplicationStreams = 0;

0 commit comments

Comments
 (0)