HADOOP-13701. AbstractContractRootDirectoryTest can fail when handling delete "/". Contributed by Genmao Yu

This commit is contained in:
Kai Zheng 2016-10-08 17:35:59 +06:00
parent a57bba470b
commit c31b5e61b1

View File

@ -33,6 +33,7 @@
import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.PathIOException;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable; import org.apache.hadoop.util.Progressable;
@ -53,6 +54,7 @@ public class AliyunOSSFileSystem extends FileSystem {
private static final Logger LOG = private static final Logger LOG =
LoggerFactory.getLogger(AliyunOSSFileSystem.class); LoggerFactory.getLogger(AliyunOSSFileSystem.class);
private URI uri; private URI uri;
private String bucket;
private Path workingDir; private Path workingDir;
private AliyunOSSFileSystemStore store; private AliyunOSSFileSystemStore store;
private int maxKeys; private int maxKeys;
@ -124,11 +126,20 @@ public boolean delete(Path path, boolean recursive) throws IOException {
private boolean innerDelete(FileStatus status, boolean recursive) private boolean innerDelete(FileStatus status, boolean recursive)
throws IOException { throws IOException {
Path f = status.getPath(); Path f = status.getPath();
String p = f.toUri().getPath();
FileStatus[] statuses;
// indicating root directory "/".
if (p.equals("/")) {
statuses = listStatus(status.getPath());
boolean isEmptyDir = statuses.length <= 0;
return rejectRootDirectoryDelete(isEmptyDir, recursive);
}
String key = pathToKey(f); String key = pathToKey(f);
if (status.isDirectory()) { if (status.isDirectory()) {
if (!recursive) { if (!recursive) {
FileStatus[] statuses = listStatus(status.getPath());
// Check whether it is an empty directory or not // Check whether it is an empty directory or not
statuses = listStatus(status.getPath());
if (statuses.length > 0) { if (statuses.length > 0) {
throw new IOException("Cannot remove directory " + f + throw new IOException("Cannot remove directory " + f +
": It is not empty!"); ": It is not empty!");
@ -148,6 +159,31 @@ private boolean innerDelete(FileStatus status, boolean recursive)
return true; return true;
} }
/**
* Implements the specific logic to reject root directory deletion.
* The caller must return the result of this call, rather than
* attempt to continue with the delete operation: deleting root
* directories is never allowed. This method simply implements
* the policy of when to return an exit code versus raise an exception.
* @param isEmptyDir empty directory or not
* @param recursive recursive flag from command
* @return a return code for the operation
* @throws PathIOException if the operation was explicitly rejected.
*/
private boolean rejectRootDirectoryDelete(boolean isEmptyDir,
boolean recursive) throws IOException {
LOG.info("oss delete the {} root directory of {}", bucket, recursive);
if (isEmptyDir) {
return true;
}
if (recursive) {
return false;
} else {
// reject
throw new PathIOException(bucket, "Cannot delete root path");
}
}
private void createFakeDirectoryIfNecessary(Path f) throws IOException { private void createFakeDirectoryIfNecessary(Path f) throws IOException {
String key = pathToKey(f); String key = pathToKey(f);
if (StringUtils.isNotEmpty(key) && !exists(f)) { if (StringUtils.isNotEmpty(key) && !exists(f)) {
@ -226,6 +262,7 @@ public String getCanonicalServiceName() {
public void initialize(URI name, Configuration conf) throws IOException { public void initialize(URI name, Configuration conf) throws IOException {
super.initialize(name, conf); super.initialize(name, conf);
bucket = name.getHost();
uri = java.net.URI.create(name.getScheme() + "://" + name.getAuthority()); uri = java.net.URI.create(name.getScheme() + "://" + name.getAuthority());
workingDir = new Path("/user", workingDir = new Path("/user",
System.getProperty("user.name")).makeQualified(uri, null); System.getProperty("user.name")).makeQualified(uri, null);