From f9c6fd94711458b77ecf3fa425aad7fda5089376 Mon Sep 17 00:00:00 2001 From: John Zhuge Date: Mon, 27 Aug 2018 09:22:59 -0700 Subject: [PATCH] HADOOP-15633. fs.TrashPolicyDefault: Can't create trash directory. Contributed by Fei Hui. --- .../apache/hadoop/fs/TrashPolicyDefault.java | 14 +++++ .../java/org/apache/hadoop/fs/TestTrash.java | 54 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java index 265e967b01e..9c6a685c6ab 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java @@ -148,6 +148,20 @@ public class TrashPolicyDefault extends TrashPolicy { LOG.warn("Can't create(mkdir) trash directory: " + baseTrashPath); return false; } + } catch (FileAlreadyExistsException e) { + // find the path which is not a directory, and modify baseTrashPath + // & trashPath, then mkdirs + Path existsFilePath = baseTrashPath; + while (!fs.exists(existsFilePath)) { + existsFilePath = existsFilePath.getParent(); + } + baseTrashPath = new Path(baseTrashPath.toString().replace( + existsFilePath.toString(), existsFilePath.toString() + Time.now()) + ); + trashPath = new Path(baseTrashPath, trashPath.getName()); + // retry, ignore current failure + --i; + continue; } catch (IOException e) { LOG.warn("Can't create trash directory: " + baseTrashPath, e); cause = e; diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestTrash.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestTrash.java index fa2d21fb423..568821be280 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestTrash.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestTrash.java @@ -517,6 +517,60 @@ public class TestTrash { trashShell(FileSystem.getLocal(conf), TEST_DIR); } + @Test + public void testExistingFileTrash() throws IOException { + Configuration conf = new Configuration(); + conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class); + FileSystem fs = FileSystem.getLocal(conf); + conf.set("fs.defaultFS", fs.getUri().toString()); + conf.setLong(FS_TRASH_INTERVAL_KEY, 0); // disabled + assertFalse(new Trash(conf).isEnabled()); + + conf.setLong(FS_TRASH_INTERVAL_KEY, 10); // 10 minute + assertTrue(new Trash(conf).isEnabled()); + + FsShell shell = new FsShell(); + shell.setConf(conf); + + // First create a new directory with mkdirs + Path myPath = new Path(TEST_DIR, "test/mkdirs"); + mkdir(fs, myPath); + + // Second, create a file in that directory. + Path myFile = new Path(TEST_DIR, "test/mkdirs/myExistingFile"); + writeFile(fs, myFile, 10); + // First rm a file + mkdir(fs, myPath); + writeFile(fs, myFile, 10); + + String[] args1 = new String[2]; + args1[0] = "-rm"; + args1[1] = myFile.toString(); + int val1 = -1; + try { + val1 = shell.run(args1); + } catch (Exception e) { + System.err.println("Exception raised from Trash.run " + + e.getLocalizedMessage()); + } + assertTrue(val1 == 0); + + // Second rm a file which parent path is the same as above + mkdir(fs, myFile); + writeFile(fs, new Path(myFile, "mySubFile"), 10); + String[] args2 = new String[2]; + args2[0] = "-rm"; + args2[1] = new Path(myFile, "mySubFile").toString(); + int val2 = -1; + try { + val2 = shell.run(args2); + } catch (Exception e) { + System.err.println("Exception raised from Trash.run " + + e.getLocalizedMessage()); + } + assertTrue(val2 == 0); + } + @Test public void testNonDefaultFS() throws IOException { Configuration conf = new Configuration();