Skip to content

Commit 2326123

Browse files
committed
HDFS-15359. EC: Allow closing a file with committed blocks. Contributed by Ayush Saxena.
1 parent 8abff51 commit 2326123

File tree

4 files changed

+69
-11
lines changed

4 files changed

+69
-11
lines changed

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,12 +1158,19 @@ public boolean commitOrCompleteLastBlock(BlockCollection bc,
11581158
/**
11591159
* If IBR is not sent from expected locations yet, add the datanodes to
11601160
* pendingReconstruction in order to keep RedundancyMonitor from scheduling
1161-
* the block.
1161+
* the block. In case of erasure coding blocks, adds only in case there
1162+
* isn't any missing node.
11621163
*/
11631164
public void addExpectedReplicasToPending(BlockInfo blk) {
1164-
if (!blk.isStriped()) {
1165-
DatanodeStorageInfo[] expectedStorages =
1166-
blk.getUnderConstructionFeature().getExpectedStorageLocations();
1165+
boolean addForStriped = false;
1166+
DatanodeStorageInfo[] expectedStorages =
1167+
blk.getUnderConstructionFeature().getExpectedStorageLocations();
1168+
if (blk.isStriped()) {
1169+
BlockInfoStriped blkStriped = (BlockInfoStriped) blk;
1170+
addForStriped =
1171+
blkStriped.getRealTotalBlockNum() == expectedStorages.length;
1172+
}
1173+
if (!blk.isStriped() || addForStriped) {
11671174
if (expectedStorages.length - blk.numNodes() > 0) {
11681175
ArrayList<DatanodeStorageInfo> pendingNodes = new ArrayList<>();
11691176
for (DatanodeStorageInfo storage : expectedStorages) {

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/INodeFile.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,17 +374,27 @@ static String checkBlockComplete(BlockInfo[] blocks, int i,
374374
if (state == BlockUCState.COMPLETE) {
375375
return null;
376376
}
377-
if (b.isStriped() || i < blocks.length - numCommittedAllowed) {
377+
if (i < blocks.length - numCommittedAllowed) {
378378
return b + " is " + state + " but not COMPLETE";
379379
}
380380
if (state != BlockUCState.COMMITTED) {
381381
return b + " is " + state + " but neither COMPLETE nor COMMITTED";
382382
}
383-
final int numExpectedLocations
384-
= b.getUnderConstructionFeature().getNumExpectedLocations();
385-
if (numExpectedLocations <= minReplication) {
386-
return b + " is " + state + " but numExpectedLocations = "
387-
+ numExpectedLocations + " <= minReplication = " + minReplication;
383+
384+
if (b.isStriped()) {
385+
BlockInfoStriped blkStriped = (BlockInfoStriped) b;
386+
if (b.getUnderConstructionFeature().getNumExpectedLocations()
387+
!= blkStriped.getRealTotalBlockNum()) {
388+
return b + " is a striped block in " + state + " with less then "
389+
+ "required number of blocks.";
390+
}
391+
} else {
392+
final int numExpectedLocations =
393+
b.getUnderConstructionFeature().getNumExpectedLocations();
394+
if (numExpectedLocations <= minReplication) {
395+
return b + " is " + state + " but numExpectedLocations = "
396+
+ numExpectedLocations + " <= minReplication = " + minReplication;
397+
}
388398
}
389399
return null;
390400
}

hadoop-hdfs-project/hadoop-hdfs/src/main/resources/hdfs-default.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4903,7 +4903,9 @@
49034903
<description>
49044904
Normally a file can only be closed with all its blocks are committed.
49054905
When this value is set to a positive integer N, a file can be closed
4906-
when N blocks are committed and the rest complete.
4906+
when N blocks are committed and the rest complete. In case of Erasure Coded
4907+
blocks, the committed block shall be allowed only when the block group is
4908+
complete. i.e no missing/lost block in the blockgroup.
49074909
</description>
49084910
</property>
49094911

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDistributedFileSystem.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.hadoop.hdfs;
2020

2121
import static org.apache.hadoop.fs.CommonConfigurationKeys.FS_CLIENT_TOPOLOGY_RESOLUTION_ENABLED;
22+
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_FILE_CLOSE_NUM_COMMITTED_ALLOWED_KEY;
2223
import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.DFS_CLIENT_CONTEXT;
2324
import static org.junit.Assert.assertEquals;
2425
import static org.junit.Assert.assertFalse;
@@ -100,6 +101,7 @@
100101
import org.apache.hadoop.hdfs.protocol.OpenFileEntry;
101102
import org.apache.hadoop.hdfs.protocol.OpenFilesIterator;
102103
import org.apache.hadoop.hdfs.server.datanode.DataNode;
104+
import org.apache.hadoop.hdfs.server.datanode.DataNodeTestUtils;
103105
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsDatasetSpi;
104106
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
105107
import org.apache.hadoop.hdfs.server.namenode.ErasureCodingPolicyManager;
@@ -2105,4 +2107,41 @@ public void testGetECTopologyResultForPolicies() throws Exception {
21052107
assertFalse(result.isSupported());
21062108
}
21072109
}
2110+
2111+
@Test
2112+
public void testECCloseCommittedBlock() throws Exception {
2113+
HdfsConfiguration conf = new HdfsConfiguration();
2114+
conf.setInt(DFS_NAMENODE_FILE_CLOSE_NUM_COMMITTED_ALLOWED_KEY, 1);
2115+
try (MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf)
2116+
.numDataNodes(3).build()) {
2117+
cluster.waitActive();
2118+
final DistributedFileSystem dfs = cluster.getFileSystem();
2119+
Path dir = new Path("/dir");
2120+
dfs.mkdirs(dir);
2121+
dfs.enableErasureCodingPolicy("XOR-2-1-1024k");
2122+
dfs.setErasureCodingPolicy(dir, "XOR-2-1-1024k");
2123+
2124+
try (FSDataOutputStream str = dfs.create(new Path("/dir/file"));) {
2125+
for (int i = 0; i < 1024 * 1024 * 4; i++) {
2126+
str.write(i);
2127+
}
2128+
DataNodeTestUtils.pauseIBR(cluster.getDataNodes().get(0));
2129+
DataNodeTestUtils.pauseIBR(cluster.getDataNodes().get(1));
2130+
}
2131+
DataNodeTestUtils.resumeIBR(cluster.getDataNodes().get(0));
2132+
DataNodeTestUtils.resumeIBR(cluster.getDataNodes().get(1));
2133+
2134+
// Check if the blockgroup isn't complete then file close shouldn't be
2135+
// success with block in committed state.
2136+
cluster.getDataNodes().get(0).shutdown();
2137+
FSDataOutputStream str = dfs.create(new Path("/dir/file1"));
2138+
2139+
for (int i = 0; i < 1024 * 1024 * 4; i++) {
2140+
str.write(i);
2141+
}
2142+
DataNodeTestUtils.pauseIBR(cluster.getDataNodes().get(1));
2143+
DataNodeTestUtils.pauseIBR(cluster.getDataNodes().get(2));
2144+
LambdaTestUtils.intercept(IOException.class, "", () -> str.close());
2145+
}
2146+
}
21082147
}

0 commit comments

Comments
 (0)