/*
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/
package alluxio.worker.file;
import alluxio.AlluxioURI;
import alluxio.client.file.FileSystem;
import alluxio.client.file.URIStatus;
import alluxio.collections.Pair;
import alluxio.exception.AlluxioException;
import alluxio.exception.ExceptionMessage;
import alluxio.security.authorization.Mode;
import alluxio.underfs.UnderFileSystem;
import alluxio.underfs.options.MkdirsOptions;
import java.io.IOException;
import java.util.Stack;
import javax.annotation.concurrent.ThreadSafe;
/**
* Utility functions for working with {@link alluxio.underfs.UnderFileSystem}.
*/
@ThreadSafe
public final class UnderFileSystemUtils {
/**
* Creates parent directories for path with correct permissions if required.
*
* @param alluxioPath Alluxio path
* @param ufsPath path in the under file system
* @param fs file system master client
* @param ufs the under file system
*/
public static void prepareFilePath(AlluxioURI alluxioPath, String ufsPath, FileSystem fs,
UnderFileSystem ufs) throws AlluxioException, IOException {
AlluxioURI dstPath = new AlluxioURI(ufsPath);
String parentPath = dstPath.getParent().getPath();
// creates the parent folder if it does not exist
if (!ufs.isDirectory(parentPath)) {
// Create ancestor directories from top to the bottom. We cannot use recursive create parents
// here because the permission for the ancestors can be different.
Stack<Pair<String, MkdirsOptions>> ufsDirsToMakeWithOptions = new Stack<>();
AlluxioURI curAlluxioPath = alluxioPath.getParent();
AlluxioURI curUfsPath = dstPath.getParent();
// Stop at Alluxio mount point because the mapped directory in UFS may not exist.
while (curUfsPath != null && !ufs.isDirectory(curUfsPath.toString())
&& curAlluxioPath != null) {
URIStatus curDirStatus = fs.getStatus(curAlluxioPath);
if (curDirStatus.isMountPoint()) {
throw new IOException(ExceptionMessage.UFS_PATH_DOES_NOT_EXIST.getMessage(curUfsPath));
}
ufsDirsToMakeWithOptions.push(new Pair<>(curUfsPath.toString(),
MkdirsOptions.defaults().setCreateParent(false).setOwner(curDirStatus.getOwner())
.setGroup(curDirStatus.getGroup())
.setMode(new Mode((short) curDirStatus.getMode()))));
curAlluxioPath = curAlluxioPath.getParent();
curUfsPath = curUfsPath.getParent();
}
while (!ufsDirsToMakeWithOptions.empty()) {
Pair<String, MkdirsOptions> ufsDirAndPerm = ufsDirsToMakeWithOptions.pop();
// UFS mkdirs might fail if the directory is already created. If so, skip the mkdirs
// and assume the directory is already prepared, regardless of permission matching.
if (!ufs.mkdirs(ufsDirAndPerm.getFirst(), ufsDirAndPerm.getSecond())
&& !ufs.isDirectory(ufsDirAndPerm.getFirst())) {
throw new IOException("Failed to create dir: " + ufsDirAndPerm.getFirst());
}
}
}
}
private UnderFileSystemUtils() {} // prevent instantiation
}