Skip to content

Commit d1c303a

Browse files
HDFS-14699. Erasure Coding: Storage not considered in live replica when replication streams hard limit reached to threshold. Contributed by Zhao Yi Ming.
1 parent f4f9f0f commit d1c303a

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,22 +2351,30 @@ DatanodeDescriptor[] chooseSourceDatanodes(BlockInfo block,
23512351
&& node.getNumberOfBlocksToBeReplicated() >= maxReplicationStreams) {
23522352
continue; // already reached replication limit
23532353
}
2354+
2355+
// for EC here need to make sure the numReplicas replicates state correct
2356+
// because in the scheduleReconstruction it need the numReplicas to check
2357+
// whether need to reconstruct the ec internal block
2358+
byte blockIndex = -1;
2359+
if (isStriped) {
2360+
blockIndex = ((BlockInfoStriped) block)
2361+
.getStorageBlockIndex(storage);
2362+
if (!bitSet.get(blockIndex)) {
2363+
bitSet.set(blockIndex);
2364+
} else if (state == StoredReplicaState.LIVE) {
2365+
numReplicas.subtract(StoredReplicaState.LIVE, 1);
2366+
numReplicas.add(StoredReplicaState.REDUNDANT, 1);
2367+
}
2368+
}
2369+
23542370
if (node.getNumberOfBlocksToBeReplicated() >= replicationStreamsHardLimit) {
23552371
continue;
23562372
}
23572373

23582374
if(isStriped || srcNodes.isEmpty()) {
23592375
srcNodes.add(node);
23602376
if (isStriped) {
2361-
byte blockIndex = ((BlockInfoStriped) block).
2362-
getStorageBlockIndex(storage);
23632377
liveBlockIndices.add(blockIndex);
2364-
if (!bitSet.get(blockIndex)) {
2365-
bitSet.set(blockIndex);
2366-
} else if (state == StoredReplicaState.LIVE) {
2367-
numReplicas.subtract(StoredReplicaState.LIVE, 1);
2368-
numReplicas.add(StoredReplicaState.REDUNDANT, 1);
2369-
}
23702378
}
23712379
continue;
23722380
}

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.hadoop.hdfs.protocol.BlockListAsLongs;
4141
import org.apache.hadoop.hdfs.protocol.BlockType;
4242
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
43+
import org.apache.hadoop.hdfs.protocol.ErasureCodingPolicy;
4344
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
4445
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
4546
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
@@ -67,6 +68,7 @@
6768
import org.apache.hadoop.hdfs.server.protocol.StorageReport;
6869
import org.apache.hadoop.io.EnumSetWritable;
6970
import org.apache.hadoop.io.IOUtils;
71+
import org.apache.hadoop.io.erasurecode.ECSchema;
7072
import org.apache.hadoop.ipc.RemoteException;
7173
import org.apache.hadoop.metrics2.MetricsRecordBuilder;
7274
import org.apache.hadoop.net.NetworkTopology;
@@ -685,6 +687,67 @@ public void testHighestPriReplSrcChosenDespiteMaxReplLimit() throws Exception {
685687
LowRedundancyBlocks.QUEUE_HIGHEST_PRIORITY).length);
686688
}
687689

690+
@Test
691+
public void testChooseSrcDatanodesWithDupEC() throws Exception {
692+
bm.maxReplicationStreams = 4;
693+
694+
long blockId = -9223372036854775776L; // real ec block id
695+
Block aBlock = new Block(blockId, 0, 0);
696+
// ec policy
697+
ECSchema rsSchema = new ECSchema("rs", 3, 2);
698+
String policyName = "RS-3-2-128k";
699+
int cellSize = 128 * 1024;
700+
ErasureCodingPolicy ecPolicy =
701+
new ErasureCodingPolicy(policyName, rsSchema, cellSize, (byte) -1);
702+
// striped blockInfo
703+
BlockInfoStriped aBlockInfoStriped = new BlockInfoStriped(aBlock, ecPolicy);
704+
// ec storageInfo
705+
DatanodeStorageInfo ds1 = DFSTestUtil.createDatanodeStorageInfo(
706+
"storage1", "1.1.1.1", "rack1", "host1");
707+
DatanodeStorageInfo ds2 = DFSTestUtil.createDatanodeStorageInfo(
708+
"storage2", "2.2.2.2", "rack2", "host2");
709+
DatanodeStorageInfo ds3 = DFSTestUtil.createDatanodeStorageInfo(
710+
"storage3", "3.3.3.3", "rack3", "host3");
711+
DatanodeStorageInfo ds4 = DFSTestUtil.createDatanodeStorageInfo(
712+
"storage4", "4.4.4.4", "rack4", "host4");
713+
DatanodeStorageInfo ds5 = DFSTestUtil.createDatanodeStorageInfo(
714+
"storage5", "5.5.5.5", "rack5", "host5");
715+
// link block with storage
716+
aBlockInfoStriped.addStorage(ds1, aBlock);
717+
aBlockInfoStriped.addStorage(ds2, new Block(blockId + 1, 0, 0));
718+
aBlockInfoStriped.addStorage(ds3, new Block(blockId + 2, 0, 0));
719+
// dup internal block
720+
aBlockInfoStriped.addStorage(ds4, new Block(blockId + 3, 0, 0));
721+
aBlockInfoStriped.addStorage(ds5, new Block(blockId + 3, 0, 0));
722+
// simulate the node 2 arrive maxReplicationStreams
723+
for(int i = 0; i < 4; i++){
724+
ds4.getDatanodeDescriptor().incrementPendingReplicationWithoutTargets();
725+
}
726+
727+
addEcBlockToBM(blockId, ecPolicy);
728+
List<DatanodeDescriptor> cntNodes = new LinkedList<DatanodeDescriptor>();
729+
List<DatanodeStorageInfo> liveNodes = new LinkedList<DatanodeStorageInfo>();
730+
NumberReplicas numReplicas = new NumberReplicas();
731+
List<Byte> liveBlockIndices = new ArrayList<>();
732+
733+
bm.chooseSourceDatanodes(
734+
aBlockInfoStriped,
735+
cntNodes,
736+
liveNodes,
737+
numReplicas, liveBlockIndices,
738+
LowRedundancyBlocks.QUEUE_HIGHEST_PRIORITY);
739+
740+
assertEquals("Choose the source node for reconstruction with one node reach"
741+
+ " the MAX maxReplicationStreams, the numReplicas still return the"
742+
+ " correct live replicas.", 4,
743+
numReplicas.liveReplicas());
744+
745+
assertEquals("Choose the source node for reconstruction with one node reach"
746+
+ " the MAX maxReplicationStreams, the numReplicas should return"
747+
+ " the correct redundant Internal Blocks.", 1,
748+
numReplicas.redundantInternalBlocks());
749+
}
750+
688751
@Test
689752
public void testFavorDecomUntilHardLimit() throws Exception {
690753
bm.maxReplicationStreams = 0;
@@ -979,6 +1042,17 @@ public void testUCBlockNotConsideredMissing() throws Exception {
9791042
bm.setInitializedReplQueues(false);
9801043
}
9811044

1045+
private BlockInfo addEcBlockToBM(long blkId, ErasureCodingPolicy ecPolicy) {
1046+
Block block = new Block(blkId);
1047+
BlockInfo blockInfo = new BlockInfoStriped(block, ecPolicy);
1048+
long inodeId = ++mockINodeId;
1049+
final INodeFile bc = TestINodeFile.createINodeFile(inodeId);
1050+
bm.blocksMap.addBlockCollection(blockInfo, bc);
1051+
blockInfo.setBlockCollectionId(inodeId);
1052+
doReturn(bc).when(fsn).getBlockCollection(inodeId);
1053+
return blockInfo;
1054+
}
1055+
9821056
private BlockInfo addBlockToBM(long blkId) {
9831057
Block block = new Block(blkId);
9841058
BlockInfo blockInfo = new BlockInfoContiguous(block, (short) 3);

0 commit comments

Comments
 (0)