Skip to content

Commit 07da67e

Browse files
committed
HDFS-17052. Erasure coding reconstruction failed when num of storageType rack NOT enough
1 parent ba08f26 commit 07da67e

2 files changed

Lines changed: 75 additions & 3 deletions

File tree

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ private void chooseEvenlyFromRemainingRacks(Node writer,
170170
NotEnoughReplicasException lastException = e;
171171
int bestEffortMaxNodesPerRack = maxNodesPerRack;
172172
while (results.size() != totalReplicaExpected &&
173-
numResultsOflastChoose != results.size()) {
173+
bestEffortMaxNodesPerRack < totalReplicaExpected) {
174174
// Exclude the chosen nodes
175175
final Set<Node> newExcludeNodes = new HashSet<>();
176176
for (DatanodeStorageInfo resultStorage : results) {
@@ -192,11 +192,22 @@ private void chooseEvenlyFromRemainingRacks(Node writer,
192192
} finally {
193193
excludedNodes.addAll(newExcludeNodes);
194194
}
195+
// To improve performance, the maximum value of 'bestEffortMaxNodesPerRack'
196+
// is calculated only when it is not possible to select a node.
197+
if (numResultsOflastChoose == results.size()) {
198+
Map<String, Integer> nodesPerRack = new HashMap<>();
199+
for (DatanodeStorageInfo dsInfo : results) {
200+
String rackName = dsInfo.getDatanodeDescriptor().getNetworkLocation();
201+
nodesPerRack.merge(rackName, 1, Integer::sum);
202+
}
203+
bestEffortMaxNodesPerRack =
204+
Math.max(bestEffortMaxNodesPerRack, Collections.max(nodesPerRack.values()));
205+
}
195206
}
196207

197-
if (numResultsOflastChoose != totalReplicaExpected) {
208+
if (results.size() != totalReplicaExpected) {
198209
LOG.debug("Best effort placement failed: expecting {} replicas, only "
199-
+ "chose {}.", totalReplicaExpected, numResultsOflastChoose);
210+
+ "chose {}.", totalReplicaExpected, results.size());
200211
throw lastException;
201212
}
202213
}

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestReconstructStripedBlocks.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.apache.hadoop.conf.Configuration;
2121
import org.apache.hadoop.fs.Path;
22+
import org.apache.hadoop.fs.StorageType;
2223
import org.apache.hadoop.hdfs.DFSConfigKeys;
2324
import org.apache.hadoop.hdfs.DFSTestUtil;
2425
import org.apache.hadoop.hdfs.DistributedFileSystem;
@@ -52,6 +53,7 @@
5253
import org.slf4j.Logger;
5354
import org.slf4j.LoggerFactory;
5455

56+
import java.util.Arrays;
5557
import java.util.BitSet;
5658
import java.util.Iterator;
5759
import java.util.List;
@@ -515,4 +517,63 @@ public void testReconstrutionWithBusyBlock1() throws Exception {
515517
assertEquals(9, bm.countNodes(blockInfo).liveReplicas());
516518
}
517519

520+
@Test
521+
public void testReconstructionWithStorageTypeNotEnough() throws Exception {
522+
final HdfsConfiguration conf = new HdfsConfiguration();
523+
conf.setInt(DFSConfigKeys.DFS_NAMENODE_REDUNDANCY_INTERVAL_SECONDS_KEY, 1);
524+
525+
// Nine disk node eleven archive node.
526+
int numDn = groupSize * 2 + 2;
527+
StorageType[][] storageTypes = new StorageType[numDn][];
528+
Arrays.fill(storageTypes, 0, groupSize,
529+
new StorageType[]{StorageType.DISK, StorageType.DISK});
530+
Arrays.fill(storageTypes, groupSize, numDn,
531+
new StorageType[]{StorageType.ARCHIVE, StorageType.ARCHIVE});
532+
533+
// Nine disk racks and one archive rack.
534+
String[] racks = {
535+
"/rack1", "/rack2", "/rack3", "/rack4", "/rack5", "/rack6", "/rack7", "/rack8",
536+
"/rack9", "/rack0", "/rack0", "/rack0", "/rack0", "/rack0", "/rack0", "/rack0",
537+
"/rack0", "/rack0", "/rack0", "/rack0"};
538+
539+
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(numDn)
540+
.storageTypes(storageTypes)
541+
.racks(racks)
542+
.build();
543+
cluster.waitActive();
544+
DistributedFileSystem fs = cluster.getFileSystem();
545+
fs.enableErasureCodingPolicy(
546+
StripedFileTestUtil.getDefaultECPolicy().getName());
547+
548+
try {
549+
fs.mkdirs(dirPath);
550+
fs.setStoragePolicy(dirPath, "COLD");
551+
fs.setErasureCodingPolicy(dirPath,
552+
StripedFileTestUtil.getDefaultECPolicy().getName());
553+
DFSTestUtil.createFile(fs, filePath,
554+
cellSize * dataBlocks * 2, (short) 1, 0L);
555+
556+
// Stop one dn.
557+
LocatedBlocks blks = fs.getClient().getLocatedBlocks(filePath.toString(), 0);
558+
LocatedStripedBlock block = (LocatedStripedBlock) blks.getLastLocatedBlock();
559+
DatanodeInfo dnToStop = block.getLocations()[0];
560+
cluster.stopDataNode(dnToStop.getXferAddr());
561+
cluster.setDataNodeDead(dnToStop);
562+
563+
// Wait for reconstruction to happen.
564+
StripedFileTestUtil.waitForReconstructionFinished(filePath, fs, groupSize);
565+
blks = fs.getClient().getLocatedBlocks(filePath.toString(), 0);
566+
block = (LocatedStripedBlock) blks.getLastLocatedBlock();
567+
BitSet bitSet = new BitSet(groupSize);
568+
for (byte index : block.getBlockIndices()) {
569+
bitSet.set(index);
570+
}
571+
for (int i = 0; i < groupSize; i++) {
572+
Assert.assertTrue(bitSet.get(i));
573+
}
574+
} finally {
575+
cluster.shutdown();
576+
}
577+
}
578+
518579
}

0 commit comments

Comments
 (0)