Skip to content

Commit b955951

Browse files
HADOOP-18801. Delete path directly when it can not be parsed in trash. (#5744). Contributed by farmmamba.
Signed-off-by: Ayush Saxena <ayushsaxena@apache.org> Signed-off-by: He Xiaoqiao <hexiaoqiao@apache.org>
1 parent 8dd9c87 commit b955951

File tree

4 files changed

+83
-2
lines changed

4 files changed

+83
-2
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,15 @@ public class CommonConfigurationKeysPublic {
214214
public static final String FS_TRASH_INTERVAL_KEY = "fs.trash.interval";
215215
/** Default value for FS_TRASH_INTERVAL_KEY */
216216
public static final long FS_TRASH_INTERVAL_DEFAULT = 0;
217+
/**
218+
* @see
219+
* <a href="{@docRoot}/../hadoop-project-dist/hadoop-common/core-default.xml">
220+
* core-default.xml</a>
221+
*/
222+
public static final String FS_TRASH_CLEAN_TRASHROOT_ENABLE_KEY =
223+
"fs.trash.clean.trashroot.enable";
224+
/** Default value for FS_TRASH_CLEAN_TRASHROOT_ENABLE_KEY. */
225+
public static final boolean FS_TRASH_CLEAN_TRASHROOT_ENABLE_DEFAULT = false;
217226
/**
218227
* @see
219228
* <a href="{@docRoot}/../hadoop-project-dist/hadoop-common/core-default.xml">

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_CHECKPOINT_INTERVAL_DEFAULT;
2121
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_CHECKPOINT_INTERVAL_KEY;
22+
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_CLEAN_TRASHROOT_ENABLE_DEFAULT;
23+
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_CLEAN_TRASHROOT_ENABLE_KEY;
2224
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_DEFAULT;
2325
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY;
2426

@@ -70,6 +72,8 @@ public class TrashPolicyDefault extends TrashPolicy {
7072

7173
private long emptierInterval;
7274

75+
private boolean cleanNonCheckpointUnderTrashRoot;
76+
7377
public TrashPolicyDefault() { }
7478

7579
private TrashPolicyDefault(FileSystem fs, Configuration conf)
@@ -90,6 +94,8 @@ public void initialize(Configuration conf, FileSystem fs, Path home) {
9094
this.emptierInterval = (long)(conf.getFloat(
9195
FS_TRASH_CHECKPOINT_INTERVAL_KEY, FS_TRASH_CHECKPOINT_INTERVAL_DEFAULT)
9296
* MSECS_PER_MINUTE);
97+
this.cleanNonCheckpointUnderTrashRoot = conf.getBoolean(
98+
FS_TRASH_CLEAN_TRASHROOT_ENABLE_KEY, FS_TRASH_CLEAN_TRASHROOT_ENABLE_DEFAULT);
9399
}
94100

95101
@Override
@@ -101,6 +107,8 @@ public void initialize(Configuration conf, FileSystem fs) {
101107
this.emptierInterval = (long)(conf.getFloat(
102108
FS_TRASH_CHECKPOINT_INTERVAL_KEY, FS_TRASH_CHECKPOINT_INTERVAL_DEFAULT)
103109
* MSECS_PER_MINUTE);
110+
this.cleanNonCheckpointUnderTrashRoot = conf.getBoolean(
111+
FS_TRASH_CLEAN_TRASHROOT_ENABLE_KEY, FS_TRASH_CLEAN_TRASHROOT_ENABLE_DEFAULT);
104112
if (deletionInterval < 0) {
105113
LOG.warn("Invalid value {} for deletion interval,"
106114
+ " deletion interaval can not be negative."
@@ -374,8 +382,14 @@ private void deleteCheckpoint(Path trashRoot, boolean deleteImmediately)
374382
try {
375383
time = getTimeFromCheckpoint(name);
376384
} catch (ParseException e) {
377-
LOG.warn("Unexpected item in trash: "+dir+". Ignoring.");
378-
continue;
385+
if (cleanNonCheckpointUnderTrashRoot) {
386+
fs.delete(path, true);
387+
LOG.warn("Unexpected item in trash: " + dir + ". Deleting.");
388+
continue;
389+
} else {
390+
LOG.warn("Unexpected item in trash: " + dir + ". Ignoring.");
391+
continue;
392+
}
379393
}
380394

381395
if (((now - deletionInterval) > time) || deleteImmediately) {

hadoop-common-project/hadoop-common/src/main/resources/core-default.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,14 @@
974974
</description>
975975
</property>
976976

977+
<property>
978+
<name>fs.trash.clean.trashroot.enable</name>
979+
<value>false</value>
980+
<description>Whether clean some directories and files
981+
in Trash home which are not under checkpoint directory.
982+
</description>
983+
</property>
984+
977985
<property>
978986
<name>fs.protected.directories</name>
979987
<value></value>

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestTrash.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.Random;
3333
import java.util.Set;
3434
import java.util.concurrent.atomic.AtomicInteger;
35+
import java.util.function.Supplier;
3536

3637
import org.junit.After;
3738
import org.junit.Before;
@@ -786,6 +787,55 @@ public void testTrashEmptier() throws Exception {
786787
emptierThread.join();
787788
}
788789

790+
/**
791+
* Test trash emptier can delete non-checkpoint dir or not.
792+
* @throws Exception
793+
*/
794+
@Test()
795+
public void testTrashEmptierCleanDirNotInCheckpointDir() throws Exception {
796+
Configuration conf = new Configuration();
797+
// Trash with 12 second deletes and 6 seconds checkpoints.
798+
conf.set(FS_TRASH_INTERVAL_KEY, "0.2"); // 12 seconds
799+
conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class);
800+
conf.set(FS_TRASH_CHECKPOINT_INTERVAL_KEY, "0.1"); // 6 seconds
801+
conf.setBoolean(FS_TRASH_CLEAN_TRASHROOT_ENABLE_KEY, true);
802+
FileSystem fs = FileSystem.getLocal(conf);
803+
conf.set("fs.default.name", fs.getUri().toString());
804+
805+
Trash trash = new Trash(conf);
806+
807+
// Start Emptier in background.
808+
Runnable emptier = trash.getEmptier();
809+
Thread emptierThread = new Thread(emptier);
810+
emptierThread.start();
811+
812+
FsShell shell = new FsShell();
813+
shell.setConf(conf);
814+
shell.init();
815+
816+
// Make sure the .Trash dir existed.
817+
mkdir(fs, shell.getCurrentTrashDir());
818+
assertTrue(fs.exists(shell.getCurrentTrashDir()));
819+
// Create a directory under .Trash directly.
820+
Path myPath = new Path(shell.getCurrentTrashDir().getParent(), "test_dirs");
821+
mkdir(fs, myPath);
822+
assertTrue(fs.exists(myPath));
823+
824+
GenericTestUtils.waitFor(new Supplier<Boolean>() {
825+
@Override
826+
public Boolean get() {
827+
try {
828+
return !fs.exists(myPath);
829+
} catch (IOException e) {
830+
// Do nothing.
831+
}
832+
return false;
833+
}
834+
}, 6000, 60000);
835+
emptierThread.interrupt();
836+
emptierThread.join();
837+
}
838+
789839
@After
790840
public void tearDown() throws IOException {
791841
File trashDir = new File(TEST_DIR.toUri().getPath());

0 commit comments

Comments
 (0)