HDFS-5443. Delete 0-sized block when deleting an under-construction file that is included in snapshot. Contributed by Jing Zhao.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1539754 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
16c6755554
commit
9964a94386
@ -498,6 +498,9 @@ Release 2.3.0 - UNRELEASED
|
||||
HDFS-5427. Not able to read deleted files from snapshot directly under
|
||||
snapshottable dir after checkpoint and NN restart. (Vinay via jing9)
|
||||
|
||||
HDFS-5443. Delete 0-sized block when deleting an under-construction file that
|
||||
is included in snapshot. (jing9)
|
||||
|
||||
Release 2.2.1 - UNRELEASED
|
||||
|
||||
INCOMPATIBLE CHANGES
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.fs.permission.PermissionStatus;
|
||||
@ -30,6 +31,7 @@
|
||||
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor;
|
||||
import org.apache.hadoop.hdfs.server.blockmanagement.MutableBlockCollection;
|
||||
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState;
|
||||
import org.apache.hadoop.hdfs.server.namenode.Quota.Counts;
|
||||
import org.apache.hadoop.hdfs.server.namenode.snapshot.INodeFileUnderConstructionWithSnapshot;
|
||||
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
|
||||
|
||||
@ -130,6 +132,39 @@ protected INodeFile toINodeFile(long mtime) {
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Quota.Counts cleanSubtree(final Snapshot snapshot, Snapshot prior,
|
||||
final BlocksMapUpdateInfo collectedBlocks,
|
||||
final List<INode> removedINodes, final boolean countDiffChange)
|
||||
throws QuotaExceededException {
|
||||
if (snapshot == null && prior != null) {
|
||||
cleanZeroSizeBlock(collectedBlocks);
|
||||
return Counts.newInstance();
|
||||
} else {
|
||||
return super.cleanSubtree(snapshot, prior, collectedBlocks,
|
||||
removedINodes, countDiffChange);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When deleting a file in the current fs directory, and the file is contained
|
||||
* in a snapshot, we should delete the last block if it's under construction
|
||||
* and its size is 0.
|
||||
*/
|
||||
private void cleanZeroSizeBlock(final BlocksMapUpdateInfo collectedBlocks) {
|
||||
final BlockInfo[] blocks = getBlocks();
|
||||
if (blocks != null && blocks.length > 0
|
||||
&& blocks[blocks.length - 1] instanceof BlockInfoUnderConstruction) {
|
||||
BlockInfoUnderConstruction lastUC =
|
||||
(BlockInfoUnderConstruction) blocks[blocks.length - 1];
|
||||
if (lastUC.getNumBytes() == 0) {
|
||||
// this is a 0-sized block. do not need check its UC state here
|
||||
collectedBlocks.addDeleteBlock(lastUC);
|
||||
removeLastBlock(lastUC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public INodeFileUnderConstruction recordModification(final Snapshot latest,
|
||||
final INodeMap inodeMap) throws QuotaExceededException {
|
||||
@ -157,7 +192,7 @@ protected void assertAllBlocksComplete() {
|
||||
* Remove a block from the block list. This block should be
|
||||
* the last one on the list.
|
||||
*/
|
||||
boolean removeLastBlock(Block oldblock) throws IOException {
|
||||
boolean removeLastBlock(Block oldblock) {
|
||||
final BlockInfo[] blocks = getBlocks();
|
||||
if (blocks == null || blocks.length == 0) {
|
||||
return false;
|
||||
|
@ -32,6 +32,7 @@
|
||||
import org.apache.hadoop.hdfs.DFSTestUtil;
|
||||
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
|
||||
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
|
||||
import org.apache.hadoop.hdfs.server.blockmanagement.BlockManager;
|
||||
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
||||
@ -274,4 +275,76 @@ public void testReadRenamedSnapshotFileWithCheckpoint() throws Exception {
|
||||
"s2/bar");
|
||||
DFSTestUtil.readFile(hdfs, new Path(bar2SnapshotPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we delete 0-sized block when deleting an INodeFileUCWithSnapshot
|
||||
*/
|
||||
@Test
|
||||
public void testDeletionWithZeroSizeBlock() throws Exception {
|
||||
final Path foo = new Path("/foo");
|
||||
final Path bar = new Path(foo, "bar");
|
||||
DFSTestUtil.createFile(hdfs, bar, BLOCKSIZE, REPLICATION, 0L);
|
||||
|
||||
SnapshotTestHelper.createSnapshot(hdfs, foo, "s0");
|
||||
hdfs.append(bar);
|
||||
|
||||
INodeFile barNode = fsdir.getINode4Write(bar.toString()).asFile();
|
||||
BlockInfo[] blks = barNode.getBlocks();
|
||||
assertEquals(1, blks.length);
|
||||
assertEquals(BLOCKSIZE, blks[0].getNumBytes());
|
||||
ExtendedBlock previous = new ExtendedBlock(fsn.getBlockPoolId(), blks[0]);
|
||||
cluster.getNameNodeRpc()
|
||||
.addBlock(bar.toString(), hdfs.getClient().getClientName(), previous,
|
||||
null, barNode.getId(), null);
|
||||
|
||||
SnapshotTestHelper.createSnapshot(hdfs, foo, "s1");
|
||||
|
||||
barNode = fsdir.getINode4Write(bar.toString()).asFile();
|
||||
blks = barNode.getBlocks();
|
||||
assertEquals(2, blks.length);
|
||||
assertEquals(BLOCKSIZE, blks[0].getNumBytes());
|
||||
assertEquals(0, blks[1].getNumBytes());
|
||||
|
||||
hdfs.delete(bar, true);
|
||||
final Path sbar = SnapshotTestHelper.getSnapshotPath(foo, "s1",
|
||||
bar.getName());
|
||||
barNode = fsdir.getINode(sbar.toString()).asFile();
|
||||
blks = barNode.getBlocks();
|
||||
assertEquals(1, blks.length);
|
||||
assertEquals(BLOCKSIZE, blks[0].getNumBytes());
|
||||
}
|
||||
|
||||
/** Make sure we delete 0-sized block when deleting an INodeFileUC */
|
||||
@Test
|
||||
public void testDeletionWithZeroSizeBlock2() throws Exception {
|
||||
final Path foo = new Path("/foo");
|
||||
final Path subDir = new Path(foo, "sub");
|
||||
final Path bar = new Path(subDir, "bar");
|
||||
DFSTestUtil.createFile(hdfs, bar, BLOCKSIZE, REPLICATION, 0L);
|
||||
|
||||
hdfs.append(bar);
|
||||
|
||||
INodeFile barNode = fsdir.getINode4Write(bar.toString()).asFile();
|
||||
BlockInfo[] blks = barNode.getBlocks();
|
||||
assertEquals(1, blks.length);
|
||||
ExtendedBlock previous = new ExtendedBlock(fsn.getBlockPoolId(), blks[0]);
|
||||
cluster.getNameNodeRpc()
|
||||
.addBlock(bar.toString(), hdfs.getClient().getClientName(), previous,
|
||||
null, barNode.getId(), null);
|
||||
|
||||
SnapshotTestHelper.createSnapshot(hdfs, foo, "s1");
|
||||
|
||||
barNode = fsdir.getINode4Write(bar.toString()).asFile();
|
||||
blks = barNode.getBlocks();
|
||||
assertEquals(2, blks.length);
|
||||
assertEquals(BLOCKSIZE, blks[0].getNumBytes());
|
||||
assertEquals(0, blks[1].getNumBytes());
|
||||
|
||||
hdfs.delete(subDir, true);
|
||||
final Path sbar = SnapshotTestHelper.getSnapshotPath(foo, "s1", "sub/bar");
|
||||
barNode = fsdir.getINode(sbar.toString()).asFile();
|
||||
blks = barNode.getBlocks();
|
||||
assertEquals(1, blks.length);
|
||||
assertEquals(BLOCKSIZE, blks[0].getNumBytes());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user