Skip to content

Commit cbc7b6b

Browse files
committed
HDFS-8831. Trash Support for deletion in HDFS encryption zone. Contributed by Xiaoyu Yao.
1 parent 0ac8fb4 commit cbc7b6b

File tree

11 files changed

+368
-93
lines changed

11 files changed

+368
-93
lines changed

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ public abstract class FileSystem extends Configured implements Closeable {
105105
*/
106106
public static final int SHUTDOWN_HOOK_PRIORITY = 10;
107107

108+
public static final String TRASH_PREFIX = ".Trash";
109+
108110
/** FileSystem cache */
109111
static final Cache CACHE = new Cache();
110112

@@ -2663,6 +2665,53 @@ public Collection<? extends BlockStoragePolicySpi> getAllStoragePolicies()
26632665
+ " doesn't support getAllStoragePolicies");
26642666
}
26652667

2668+
/**
2669+
* Get the root directory of Trash for current user when the path specified
2670+
* is deleted.
2671+
*
2672+
* @param path the trash root of the path to be determined.
2673+
* @return the default implementation returns "/user/$USER/.Trash".
2674+
* @throws IOException
2675+
*/
2676+
public Path getTrashRoot(Path path) throws IOException {
2677+
return this.makeQualified(new Path(getHomeDirectory().toUri().getPath(),
2678+
TRASH_PREFIX));
2679+
}
2680+
2681+
/**
2682+
* Get all the trash roots for current user or all users.
2683+
*
2684+
* @param allUsers return trash roots for all users if true.
2685+
* @return all the trash root directories.
2686+
* Default FileSystem returns .Trash under users' home directories if
2687+
* /user/$USER/.Trash exists.
2688+
* @throws IOException
2689+
*/
2690+
public Collection<FileStatus> getTrashRoots(boolean allUsers)
2691+
throws IOException {
2692+
Path userHome = new Path(getHomeDirectory().toUri().getPath());
2693+
List<FileStatus> ret = new ArrayList<FileStatus>();
2694+
if (!allUsers) {
2695+
Path userTrash = new Path(userHome, TRASH_PREFIX);
2696+
if (exists(userTrash)) {
2697+
ret.add(getFileStatus(userTrash));
2698+
}
2699+
} else {
2700+
Path homeParent = userHome.getParent();
2701+
if (exists(homeParent)) {
2702+
FileStatus[] candidates = listStatus(homeParent);
2703+
for (FileStatus candidate : candidates) {
2704+
Path userTrash = new Path(candidate.getPath(), TRASH_PREFIX);
2705+
if (exists(userTrash)) {
2706+
candidate.setPath(userTrash);
2707+
ret.add(candidate);
2708+
}
2709+
}
2710+
}
2711+
}
2712+
return ret;
2713+
}
2714+
26662715
// making it volatile to be able to do a double checked locking
26672716
private volatile static boolean FILE_SYSTEMS_LOADED = false;
26682717

@@ -3183,7 +3232,7 @@ public void incrementWriteOps(int count) {
31833232
* For each StatisticsData object, we will call accept on the visitor.
31843233
* Finally, at the end, we will call aggregate to get the final total.
31853234
*
3186-
* @param The visitor to use.
3235+
* @param visitor to use.
31873236
* @return The total.
31883237
*/
31893238
private synchronized <T> T visitAll(StatisticsAggregator<T> visitor) {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,4 +643,15 @@ public Collection<? extends BlockStoragePolicySpi> getAllStoragePolicies()
643643
throws IOException {
644644
return fs.getAllStoragePolicies();
645645
}
646+
647+
@Override
648+
public Path getTrashRoot(Path path) throws IOException {
649+
return fs.getTrashRoot(path);
650+
}
651+
652+
@Override
653+
public Collection<FileStatus> getTrashRoots(boolean allUsers)
654+
throws IOException {
655+
return fs.getTrashRoots(allUsers);
656+
}
646657
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ public Path getCurrentTrashDir() throws IOException {
121121
return getTrash().getCurrentTrashDir();
122122
}
123123

124+
/**
125+
* Returns the current trash location for the path specified
126+
* @param path to be deleted
127+
* @return path to the trash
128+
* @throws IOException
129+
*/
130+
public Path getCurrentTrashDir(Path path) throws IOException {
131+
return getTrash().getCurrentTrashDir(path);
132+
}
133+
124134
protected String getUsagePrefix() {
125135
return usagePrefix;
126136
}
@@ -129,7 +139,7 @@ protected String getUsagePrefix() {
129139
// that access commandFactory
130140

131141
/**
132-
* Display help for commands with their short usage and long description
142+
* Display help for commands with their short usage and long description.
133143
*/
134144
protected class Usage extends FsCommand {
135145
public static final String NAME = "usage";

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public Trash(Configuration conf) throws IOException {
5454
*/
5555
public Trash(FileSystem fs, Configuration conf) throws IOException {
5656
super(conf);
57-
trashPolicy = TrashPolicy.getInstance(conf, fs, fs.getHomeDirectory());
57+
trashPolicy = TrashPolicy.getInstance(conf, fs);
5858
}
5959

6060
/**
@@ -92,11 +92,7 @@ public static boolean moveToAppropriateTrash(FileSystem fs, Path p,
9292
throw new IOException("Failed to get server trash configuration", e);
9393
}
9494
Trash trash = new Trash(fullyResolvedFs, conf);
95-
boolean success = trash.moveToTrash(fullyResolvedPath);
96-
if (success) {
97-
LOG.info("Moved: '" + p + "' to trash at: " + trash.getCurrentTrashDir());
98-
}
99-
return success;
95+
return trash.moveToTrash(fullyResolvedPath);
10096
}
10197

10298
/**
@@ -124,7 +120,7 @@ public void expunge() throws IOException {
124120
}
125121

126122
/** get the current working directory */
127-
Path getCurrentTrashDir() {
123+
Path getCurrentTrashDir() throws IOException {
128124
return trashPolicy.getCurrentTrashDir();
129125
}
130126

@@ -139,4 +135,8 @@ TrashPolicy getTrashPolicy() {
139135
public Runnable getEmptier() throws IOException {
140136
return trashPolicy.getEmptier();
141137
}
138+
139+
public Path getCurrentTrashDir(Path path) throws IOException {
140+
return trashPolicy.getCurrentTrashDir(path);
141+
}
142142
}

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

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,27 @@ public abstract class TrashPolicy extends Configured {
3838

3939
/**
4040
* Used to setup the trash policy. Must be implemented by all TrashPolicy
41-
* implementations
41+
* implementations.
4242
* @param conf the configuration to be used
4343
* @param fs the filesystem to be used
4444
* @param home the home directory
4545
*/
4646
public abstract void initialize(Configuration conf, FileSystem fs, Path home);
4747

4848
/**
49-
* Returns whether the Trash Policy is enabled for this filesystem
49+
* Used to setup the trash policy. Must be implemented by all TrashPolicy
50+
* implementations. Different from initialize(conf, fs, home), this one does
51+
* not assume trash always under /user/$USER due to HDFS encryption zone.
52+
* @param conf the configuration to be used
53+
* @param fs the filesystem to be used
54+
* @throws IOException
55+
*/
56+
public void initialize(Configuration conf, FileSystem fs) throws IOException{
57+
throw new UnsupportedOperationException();
58+
}
59+
60+
/**
61+
* Returns whether the Trash Policy is enabled for this filesystem.
5062
*/
5163
public abstract boolean isEnabled();
5264

@@ -68,8 +80,27 @@ public abstract class TrashPolicy extends Configured {
6880

6981
/**
7082
* Get the current working directory of the Trash Policy
83+
* This API does not work with files deleted from encryption zone when HDFS
84+
* data encryption at rest feature is enabled as rename file between
85+
* encryption zones or encryption zone and non-encryption zone is not allowed.
86+
*
87+
* The caller is recommend to use the new API
88+
* TrashPolicy#getCurrentTrashDir(Path path).
89+
* It returns the trash location correctly for the path specified no matter
90+
* the path is in encryption zone or not.
91+
*/
92+
public abstract Path getCurrentTrashDir() throws IOException;
93+
94+
/**
95+
* Get the current trash directory for path specified based on the Trash
96+
* Policy
97+
* @param path path to be deleted
98+
* @return current trash directory for the path to be deleted
99+
* @throws IOException
71100
*/
72-
public abstract Path getCurrentTrashDir();
101+
public Path getCurrentTrashDir(Path path) throws IOException {
102+
throw new UnsupportedOperationException();
103+
}
73104

74105
/**
75106
* Return a {@link Runnable} that periodically empties the trash of all
@@ -78,7 +109,7 @@ public abstract class TrashPolicy extends Configured {
78109
public abstract Runnable getEmptier() throws IOException;
79110

80111
/**
81-
* Get an instance of the configured TrashPolicy based on the value
112+
* Get an instance of the configured TrashPolicy based on the value
82113
* of the configuration parameter fs.trash.classname.
83114
*
84115
* @param conf the configuration to be used
@@ -93,4 +124,21 @@ public static TrashPolicy getInstance(Configuration conf, FileSystem fs, Path ho
93124
trash.initialize(conf, fs, home); // initialize TrashPolicy
94125
return trash;
95126
}
127+
128+
/**
129+
* Get an instance of the configured TrashPolicy based on the value
130+
* of the configuration parameter fs.trash.classname.
131+
*
132+
* @param conf the configuration to be used
133+
* @param fs the file system to be used
134+
* @return an instance of TrashPolicy
135+
*/
136+
public static TrashPolicy getInstance(Configuration conf, FileSystem fs)
137+
throws IOException {
138+
Class<? extends TrashPolicy> trashClass = conf.getClass(
139+
"fs.trash.classname", TrashPolicyDefault.class, TrashPolicy.class);
140+
TrashPolicy trash = ReflectionUtils.newInstance(trashClass, conf);
141+
trash.initialize(conf, fs); // initialize TrashPolicy
142+
return trash;
143+
}
96144
}

0 commit comments

Comments
 (0)