From b2d186d865a878ecfdb25a6b53f9b3275b9a693c Mon Sep 17 00:00:00 2001 From: Aaron Myers Date: Wed, 29 Aug 2012 01:19:07 +0000 Subject: [PATCH] HDFS-3864. NN does not update internal file mtime for OP_CLOSE when reading from the edit log. Contributed by Aaron T. Myers. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1378413 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 3 ++ .../hdfs/server/namenode/FSEditLogLoader.java | 4 +- .../org/apache/hadoop/hdfs/TestModTime.java | 43 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 55956076e5..248c133967 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -693,6 +693,9 @@ Branch-2 ( Unreleased changes ) HDFS-3849. When re-loading the FSImage, we should clear the existing genStamp and leases. (Colin Patrick McCabe via atm) + HDFS-3864. NN does not update internal file mtime for OP_CLOSE when reading + from the edit log. (atm) + BREAKDOWN OF HDFS-3042 SUBTASKS HDFS-2185. HDFS portion of ZK-based FailoverController (todd) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java index 78b28a9588..5a874fc136 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java @@ -302,7 +302,9 @@ private void applyEditLogOp(FSEditLogOp op, FSDirectory fsDir, addCloseOp.path); } - // Update in-memory data structures + // Update the salient file attributes. + oldFile.setAccessTime(addCloseOp.atime); + oldFile.setModificationTimeForce(addCloseOp.mtime); updateBlocks(fsDir, addCloseOp, oldFile); // Now close the file diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestModTime.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestModTime.java index f30de965fc..e5ef1acfec 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestModTime.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestModTime.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.io.OutputStream; import java.net.InetSocketAddress; import java.util.Random; @@ -32,12 +33,14 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.protocol.DatanodeInfo; import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType; +import org.apache.hadoop.util.ThreadUtil; import org.junit.Test; /** * This class tests the decommissioning of nodes. */ public class TestModTime { + static final long seed = 0xDEADBEEFL; static final int blockSize = 8192; static final int fileSize = 16384; @@ -186,6 +189,46 @@ public void testModTime() throws IOException { cluster.shutdown(); } } + + /** + * Regression test for HDFS-3864 - NN does not update internal file mtime for + * OP_CLOSE when reading from the edit log. + */ + @Test + public void testModTimePersistsAfterRestart() throws IOException { + final long sleepTime = 10; // 10 milliseconds + MiniDFSCluster cluster = null; + FileSystem fs = null; + Configuration conf = new HdfsConfiguration(); + try { + cluster = new MiniDFSCluster.Builder(conf).build(); + fs = cluster.getFileSystem(); + Path testPath = new Path("/test"); + + // Open a file, and get its initial modification time. + OutputStream out = fs.create(testPath); + long initialModTime = fs.getFileStatus(testPath).getModificationTime(); + assertTrue(initialModTime > 0); + + // Wait and then close the file. Ensure that the mod time goes up. + ThreadUtil.sleepAtLeastIgnoreInterrupts(sleepTime); + out.close(); + long modTimeAfterClose = fs.getFileStatus(testPath).getModificationTime(); + assertTrue(modTimeAfterClose >= initialModTime + sleepTime); + + // Restart the NN, and make sure that the later mod time is still used. + cluster.restartNameNode(); + long modTimeAfterRestart = fs.getFileStatus(testPath).getModificationTime(); + assertEquals(modTimeAfterClose, modTimeAfterRestart); + } finally { + if (fs != null) { + fs.close(); + } + if (cluster != null) { + cluster.shutdown(); + } + } + } public static void main(String[] args) throws Exception { new TestModTime().testModTime();