diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java index 74ee6936652..bf284a8a9d5 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java @@ -582,7 +582,7 @@ public class HFileArchiver { public boolean moveAndClose(Path dest) throws IOException { this.close(); Path p = this.getPath(); - return fs.rename(p, dest); + return FSUtils.renameAndSetModifyTime(fs, p, dest); } /** diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java index f96bf506235..5d3fd1ec5a8 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java @@ -701,7 +701,7 @@ class FSHLog implements HLog, Syncable { i.preLogArchive(p, newPath); } } - if (!this.fs.rename(p, newPath)) { + if (!FSUtils.renameAndSetModifyTime(this.fs, p, newPath)) { throw new IOException("Unable to rename " + p + " to " + newPath); } // Tell our listeners that a log has been archived. @@ -754,7 +754,7 @@ class FSHLog implements HLog, Syncable { } } - if (!fs.rename(file.getPath(),p)) { + if (!FSUtils.renameAndSetModifyTime(fs, file.getPath(), p)) { throw new IOException("Unable to rename " + file.getPath() + " to " + p); } // Tell our listeners that a log was archived. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLogSplitter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLogSplitter.java index af27e9e587b..cc78143f44f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLogSplitter.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLogSplitter.java @@ -672,7 +672,7 @@ public class HLogSplitter { for (Path p : processedLogs) { Path newPath = FSHLog.getHLogArchivePath(oldLogDir, p); if (fs.exists(p)) { - if (!fs.rename(p, newPath)) { + if (!FSUtils.renameAndSetModifyTime(fs, p, newPath)) { LOG.warn("Unable to move " + p + " to " + newPath); } else { LOG.debug("Archived processed log " + p + " to " + newPath); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java index 8da23ad360b..f24a7b89cf3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java @@ -1641,4 +1641,12 @@ public abstract class FSUtils { } } } + + public static boolean renameAndSetModifyTime(final FileSystem fs, Path src, Path dest) + throws IOException { + if (!fs.rename(src, dest)) return false; + // set the modify time for TimeToLive Cleaner + fs.setTimes(dest, EnvironmentEdgeManager.currentTimeMillis(), -1); + return true; + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java index a333c8ec481..13347351620 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotEquals; import java.io.File; import java.io.IOException; @@ -287,4 +288,39 @@ public class TestFSUtils { } } + @Test + public void testRenameAndSetModifyTime() throws Exception { + HBaseTestingUtility htu = new HBaseTestingUtility(); + Configuration conf = htu.getConfiguration(); + + MiniDFSCluster cluster = htu.startMiniDFSCluster(1); + assertTrue(FSUtils.isHDFS(conf)); + + FileSystem fs = FileSystem.get(conf); + Path testDir = htu.getDataTestDir("testArchiveFile"); + + String file = UUID.randomUUID().toString(); + Path p = new Path(testDir, file); + + FSDataOutputStream out = fs.create(p); + out.close(); + assertTrue("The created file should be present", FSUtils.isExists(fs, p)); + + long expect = System.currentTimeMillis() + 1000; + assertNotEquals(expect, fs.getFileStatus(p).getModificationTime()); + + ManualEnvironmentEdge mockEnv = new ManualEnvironmentEdge(); + mockEnv.setValue(expect); + EnvironmentEdgeManager.injectEdge(mockEnv); + + String dstFile = UUID.randomUUID().toString(); + Path dst = new Path(testDir , dstFile); + + assertTrue(FSUtils.renameAndSetModifyTime(fs, p, dst)); + assertFalse("The moved file should not be present", FSUtils.isExists(fs, p)); + assertTrue("The dst file should be present", FSUtils.isExists(fs, dst)); + + assertEquals(expect, fs.getFileStatus(dst).getModificationTime()); + cluster.shutdown(); + } }