You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by aa...@apache.org on 2022/04/07 08:30:03 UTC
[hadoop] branch trunk updated: HADOOP-18188. Support touch command for directory (#4135)
This is an automated email from the ASF dual-hosted git repository.
aajisaka pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/trunk by this push:
new f70935522b0 HADOOP-18188. Support touch command for directory (#4135)
f70935522b0 is described below
commit f70935522b0fd771dedb9604b92397135fd0c8ad
Author: Viraj Jasani <vj...@apache.org>
AuthorDate: Thu Apr 7 13:59:45 2022 +0530
HADOOP-18188. Support touch command for directory (#4135)
Signed-off-by: Akira Ajisaka <aa...@apache.org>
---
.../org/apache/hadoop/fs/shell/TouchCommands.java | 3 -
.../org/apache/hadoop/fs/TestFsShellTouch.java | 72 +++++++
.../org/apache/hadoop/hdfs/TestDFSShellTouch.java | 239 +++++++++++++++++++++
3 files changed, 311 insertions(+), 3 deletions(-)
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/TouchCommands.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/TouchCommands.java
index 902eada98db..457cd86ab70 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/TouchCommands.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/TouchCommands.java
@@ -147,9 +147,6 @@ public class TouchCommands extends FsCommand {
@Override
protected void processPath(PathData item) throws IOException {
- if (item.stat.isDirectory()) {
- throw new PathIsDirectoryException(item.toString());
- }
touch(item);
}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShellTouch.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShellTouch.java
index 49bbd5af04f..c2bd5b2133d 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShellTouch.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShellTouch.java
@@ -200,6 +200,78 @@ public class TestFsShellTouch {
FileStatus fileStatus = lfs.getFileStatus(newFile);
assertThat(fileStatus.getAccessTime()).isEqualTo(dateObj.getTime());
assertThat(fileStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ lfs.delete(newFile, true);
+ assertThat(lfs.exists(newFile)).isFalse();
+
+ }
+
+ @Test
+ public void testTouchDir() throws Exception {
+ String strTime;
+ final String newFileName = "dir3/newFile3";
+ Date dateObj;
+ final Path newFile = new Path(newFileName);
+ FileStatus fstatus;
+ Path dirPath = new Path("dir3");
+ lfs.delete(dirPath, true);
+ lfs.mkdirs(dirPath);
+ lfs.delete(newFile, true);
+ assertThat(lfs.exists(newFile)).isFalse();
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-t", strTime, newFileName)).as(
+ "Expected successful touch on a new file with a specified timestamp").isEqualTo(0);
+ FileStatus newStatus = lfs.getFileStatus(newFile);
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ Thread.sleep(500);
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-m", "-a", "-t", strTime, "dir3")).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+
+ newStatus = lfs.getFileStatus(dirPath);
+ // Verify if both modification and access times are recorded correctly
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ fstatus = lfs.getFileStatus(dirPath);
+ Thread.sleep(500);
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-m", "-t", strTime, "dir3")).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+
+ newStatus = lfs.getFileStatus(dirPath);
+ // Verify if modification time is recorded correctly (and access time
+ // remains unchanged).
+ assertThat(newStatus.getAccessTime()).isEqualTo(fstatus.getAccessTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ fstatus = lfs.getFileStatus(dirPath);
+ Thread.sleep(500);
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-a", "-t", strTime, "dir3")).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+
+ newStatus = lfs.getFileStatus(dirPath);
+ // Verify if access time is recorded correctly (and modification time
+ // remains unchanged).
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(fstatus.getModificationTime());
+
+ lfs.delete(newFile, true);
+ lfs.delete(dirPath, true);
+ assertThat(lfs.exists(newFile)).isFalse();
+ assertThat(lfs.exists(dirPath)).isFalse();
}
private String formatTimestamp(long timeInMillis) {
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShellTouch.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShellTouch.java
new file mode 100644
index 00000000000..d0334cbf427
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShellTouch.java
@@ -0,0 +1,239 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hdfs;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.Date;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FsShell;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.shell.TouchCommands;
+import org.apache.hadoop.test.GenericTestUtils;
+import org.apache.hadoop.util.StringUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests to perform Touch operations on DFS.
+ */
+public class TestDFSShellTouch {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TestDFSShellTouch.class);
+
+ private static MiniDFSCluster miniCluster;
+ private static DistributedFileSystem dfs;
+ private static FsShell shell;
+
+ @BeforeClass
+ public static void setup() throws IOException {
+ final Configuration conf = new Configuration();
+ conf.set(MiniDFSCluster.HDFS_MINIDFS_BASEDIR,
+ GenericTestUtils.getTestDir("TestDFSShellTouch").getAbsolutePath());
+
+ miniCluster = new MiniDFSCluster.Builder(conf).numDataNodes(2).build();
+ miniCluster.waitActive();
+ dfs = miniCluster.getFileSystem();
+ shell = new FsShell(dfs.getConf());
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if (miniCluster != null) {
+ miniCluster.shutdown(true, true);
+ }
+ }
+
+ @Test
+ public void testTouch() throws Exception {
+ final String newFileName = "newFile1";
+ final Path newFile = new Path(newFileName);
+ dfs.delete(newFile, true);
+ assertThat(dfs.exists(newFile)).isFalse();
+ dfs.create(newFile);
+ assertThat(dfs.exists(newFile)).isTrue();
+
+ String strTime = formatTimestamp(System.currentTimeMillis());
+ Date dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-t", strTime, newFileName)).as(
+ "Expected successful touch on a new file" + " with a specified timestamp").isEqualTo(0);
+ FileStatus newStatus = dfs.getFileStatus(newFile);
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ FileStatus fileStatus = dfs.getFileStatus(newFile);
+ Thread.sleep(500);
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-a", "-t", strTime, newFileName)).as(
+ "Expected successful touch with a specified access time").isEqualTo(0);
+ newStatus = dfs.getFileStatus(newFile);
+ // Verify if access time is recorded correctly (and modification time
+ // remains unchanged).
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(fileStatus.getModificationTime());
+
+ fileStatus = dfs.getFileStatus(newFile);
+ Thread.sleep(500);
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-m", "-t", strTime, newFileName)).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+ // Verify if modification time is recorded correctly (and access time
+ // remains unchanged).
+ newStatus = dfs.getFileStatus(newFile);
+ assertThat(newStatus.getAccessTime()).isEqualTo(fileStatus.getAccessTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-t", strTime, newFileName)).as(
+ "Expected successful touch with a specified timestamp").isEqualTo(0);
+
+ // Verify if both modification and access times are recorded correctly
+ newStatus = dfs.getFileStatus(newFile);
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-a", "-m", "-t", strTime, newFileName)).as(
+ "Expected successful touch with a specified timestamp").isEqualTo(0);
+
+ // Verify if both modification and access times are recorded correctly
+ newStatus = dfs.getFileStatus(newFile);
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ assertThat(shellRun("-touch", "-t", newFileName)).as(
+ "Expected failed touch with a missing timestamp").isNotEqualTo(0);
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+ assertThat(shellRun("-touch", "-c", "-t", strTime, newFileName)).as(
+ "Expected successful touch on a non-existent file with -c option").isEqualTo(0);
+ fileStatus = dfs.getFileStatus(newFile);
+ assertThat(fileStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(fileStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ dfs.delete(newFile, true);
+ assertThat(dfs.exists(newFile)).isFalse();
+
+ }
+
+ @Test
+ public void testTouchDirs() throws IOException, ParseException, InterruptedException {
+ final String newFileName = "dir2/newFile2";
+ final Path newFile = new Path(newFileName);
+ FileStatus newStatus;
+ FileStatus fileStatus;
+ String strTime;
+ Date dateObj;
+ Path dirPath = new Path("dir2");
+ dfs.mkdirs(dirPath);
+ dfs.delete(newFile, true);
+ assertThat(dfs.exists(newFile)).isFalse();
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-t", strTime, newFileName)).as(
+ "Expected successful touch on a new file with a specified timestamp").isEqualTo(0);
+ newStatus = dfs.getFileStatus(newFile);
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ Thread.sleep(500);
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-m", "-a", "-t", strTime, "dir2")).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+
+ newStatus = dfs.getFileStatus(dirPath);
+ // Verify if both modification and access times are recorded correctly
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ fileStatus = dfs.getFileStatus(dirPath);
+ Thread.sleep(500);
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-m", "-t", strTime, "dir2")).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+
+ newStatus = dfs.getFileStatus(dirPath);
+ // Verify if modification time is recorded correctly (and access time
+ // remains unchanged).
+ assertThat(newStatus.getAccessTime()).isEqualTo(fileStatus.getAccessTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(dateObj.getTime());
+
+ fileStatus = dfs.getFileStatus(dirPath);
+ Thread.sleep(500);
+
+ strTime = formatTimestamp(System.currentTimeMillis());
+ dateObj = parseTimestamp(strTime);
+
+ assertThat(shellRun("-touch", "-a", "-t", strTime, "dir2")).as(
+ "Expected successful touch with a specified modification time").isEqualTo(0);
+
+ newStatus = dfs.getFileStatus(dirPath);
+ // Verify if access time is recorded correctly (and modification time
+ // remains unchanged).
+ assertThat(newStatus.getAccessTime()).isEqualTo(dateObj.getTime());
+ assertThat(newStatus.getModificationTime()).isEqualTo(fileStatus.getModificationTime());
+
+ dfs.delete(newFile, true);
+ dfs.delete(dirPath, true);
+ assertThat(dfs.exists(newFile)).isFalse();
+ assertThat(dfs.exists(dirPath)).isFalse();
+ }
+
+ private int shellRun(String... args) {
+ int exitCode = shell.run(args);
+ LOG.info("exit " + exitCode + " - " + StringUtils.join(" ", args));
+ return exitCode;
+ }
+
+ private String formatTimestamp(long timeInMillis) {
+ return (new TouchCommands.Touch()).getDateFormat().format(new Date(timeInMillis));
+ }
+
+ private Date parseTimestamp(String tstamp) throws ParseException {
+ return (new TouchCommands.Touch()).getDateFormat().parse(tstamp);
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org