diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 346050c2aca..d10dd292a26 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -839,6 +839,9 @@ Release 2.7.0 - UNRELEASED HDFS-6833. DirectoryScanner should not register a deleting block with memory of DataNode. (Shinichi Yamashita via szetszwo) + HDFS-7926. NameNode implementation of ClientProtocol.truncate(..) is not + idempotent (Tsz Wo Nicholas Sze via brandonli) + BREAKDOWN OF HDFS-7584 SUBTASKS AND RELATED JIRAS HDFS-7720. Quota by Storage Type API, tools and ClientNameNode diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfoContiguousUnderConstruction.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfoContiguousUnderConstruction.java index 91b76ccb0e2..ae809a5e919 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfoContiguousUnderConstruction.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfoContiguousUnderConstruction.java @@ -383,6 +383,7 @@ public class BlockInfoContiguousUnderConstruction extends BlockInfoContiguous { private void appendUCParts(StringBuilder sb) { sb.append("{UCState=").append(blockUCState) + .append(", truncateBlock=" + truncateBlock) .append(", primaryNodeIndex=").append(primaryNodeIndex) .append(", replicas=["); if (replicas != null) { diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java index 81d2b887df2..d49088597a4 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java @@ -2021,6 +2021,21 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean, throw new UnsupportedOperationException( "Cannot truncate lazy persist file " + src); } + + // Check if the file is already being truncated with the same length + final BlockInfoContiguous last = file.getLastBlock(); + if (last != null && last.getBlockUCState() == BlockUCState.UNDER_RECOVERY) { + final Block truncateBlock + = ((BlockInfoContiguousUnderConstruction)last).getTruncateBlock(); + if (truncateBlock != null) { + final long truncateLength = file.computeFileSize(false, false) + + truncateBlock.getNumBytes(); + if (newLength == truncateLength) { + return false; + } + } + } + // Opening an existing file for truncate. May need lease recovery. recoverLeaseInternal(RecoverLeaseOp.TRUNCATE_FILE, iip, src, clientName, clientMachine, false); diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFileTruncate.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFileTruncate.java index b69d3456be0..260d8bbb496 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFileTruncate.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFileTruncate.java @@ -166,6 +166,8 @@ public class TestFileTruncate { LOG.info("newLength=" + newLength + ", isReady=" + isReady); assertEquals("File must be closed for truncating at the block boundary", isReady, newLength % BLOCK_SIZE == 0); + assertEquals("Truncate is not idempotent", + isReady, fs.truncate(p, newLength)); if (!isReady) { checkBlockRecovery(p); }