/* * 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.client.file; import alluxio.AlluxioURI; import alluxio.annotation.PublicApi; import alluxio.client.file.options.CreateDirectoryOptions; import alluxio.client.file.options.CreateFileOptions; import alluxio.client.file.options.DeleteOptions; import alluxio.client.file.options.ExistsOptions; import alluxio.client.file.options.FreeOptions; import alluxio.client.file.options.GetStatusOptions; import alluxio.client.file.options.InStreamOptions; import alluxio.client.file.options.ListStatusOptions; import alluxio.client.file.options.LoadMetadataOptions; import alluxio.client.file.options.MountOptions; import alluxio.client.file.options.OpenFileOptions; import alluxio.client.file.options.OutStreamOptions; import alluxio.client.file.options.RenameOptions; import alluxio.client.file.options.SetAttributeOptions; import alluxio.client.file.options.UnmountOptions; import alluxio.exception.AlluxioException; import alluxio.exception.DirectoryNotEmptyException; import alluxio.exception.ExceptionMessage; import alluxio.exception.FileAlreadyExistsException; import alluxio.exception.FileDoesNotExistException; import alluxio.exception.InvalidPathException; import alluxio.exception.status.AlluxioStatusException; import alluxio.exception.status.AlreadyExistsException; import alluxio.exception.status.FailedPreconditionException; import alluxio.exception.status.InvalidArgumentException; import alluxio.exception.status.NotFoundException; import alluxio.exception.status.UnavailableException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.List; import javax.annotation.concurrent.ThreadSafe; /** * Default implementation of the {@link FileSystem} interface. Developers can extend this class * instead of implementing the interface. This implementation reads and writes data through * {@link FileInStream} and {@link FileOutStream}. This class is thread safe. */ @PublicApi @ThreadSafe public class BaseFileSystem implements FileSystem { private static final Logger LOG = LoggerFactory.getLogger(BaseFileSystem.class); protected final FileSystemContext mFileSystemContext; /** * @param context file system context * @return a {@link BaseFileSystem} */ public static BaseFileSystem get(FileSystemContext context) { return new BaseFileSystem(context); } /** * Constructs a new base file system. * * @param context file system context */ protected BaseFileSystem(FileSystemContext context) { mFileSystemContext = context; } @Override public void createDirectory(AlluxioURI path) throws FileAlreadyExistsException, InvalidPathException, IOException, AlluxioException { createDirectory(path, CreateDirectoryOptions.defaults()); } @Override public void createDirectory(AlluxioURI path, CreateDirectoryOptions options) throws FileAlreadyExistsException, InvalidPathException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { masterClient.createDirectory(path, options); LOG.debug("Created directory {}, options: {}", path.getPath(), options); } catch (AlreadyExistsException e) { throw new FileAlreadyExistsException(e.getMessage()); } catch (InvalidArgumentException e) { throw new InvalidPathException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public FileOutStream createFile(AlluxioURI path) throws FileAlreadyExistsException, InvalidPathException, IOException, AlluxioException { return createFile(path, CreateFileOptions.defaults()); } @Override public FileOutStream createFile(AlluxioURI path, CreateFileOptions options) throws FileAlreadyExistsException, InvalidPathException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); URIStatus status; try { masterClient.createFile(path, options); status = masterClient.getStatus(path); LOG.debug("Created file {}, options: {}", path.getPath(), options); } catch (AlreadyExistsException e) { throw new FileAlreadyExistsException(e.getMessage()); } catch (InvalidArgumentException e) { throw new InvalidPathException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } OutStreamOptions outStreamOptions = options.toOutStreamOptions(); outStreamOptions.setUfsPath(status.getUfsPath()); outStreamOptions.setMountId(status.getMountId()); return new FileOutStream(path, outStreamOptions, mFileSystemContext); } @Override public void delete(AlluxioURI path) throws DirectoryNotEmptyException, FileDoesNotExistException, IOException, AlluxioException { delete(path, DeleteOptions.defaults()); } @Override public void delete(AlluxioURI path, DeleteOptions options) throws DirectoryNotEmptyException, FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { masterClient.delete(path, options); LOG.debug("Deleted {}, options: {}", path.getPath(), options); } catch (FailedPreconditionException e) { // A little sketchy, but this should be the only case that throws FailedPrecondition. throw new DirectoryNotEmptyException(e.getMessage()); } catch (NotFoundException e) { throw new FileDoesNotExistException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public boolean exists(AlluxioURI path) throws InvalidPathException, IOException, AlluxioException { return exists(path, ExistsOptions.defaults()); } @Override public boolean exists(AlluxioURI path, ExistsOptions options) throws InvalidPathException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { // TODO(calvin): Make this more efficient masterClient.getStatus(path); return true; } catch (NotFoundException e) { return false; } catch (InvalidArgumentException e) { // The server will throw this when a prefix of the path is a file. // TODO(andrew): Change the server so that a prefix being a file means the path does not exist return false; } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public void free(AlluxioURI path) throws FileDoesNotExistException, IOException, AlluxioException { free(path, FreeOptions.defaults()); } @Override public void free(AlluxioURI path, FreeOptions options) throws FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { masterClient.free(path, options); LOG.debug("Freed {}, options: {}", path.getPath(), options); } catch (NotFoundException e) { throw new FileDoesNotExistException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public URIStatus getStatus(AlluxioURI path) throws FileDoesNotExistException, IOException, AlluxioException { return getStatus(path, GetStatusOptions.defaults()); } @Override public URIStatus getStatus(AlluxioURI path, GetStatusOptions options) throws FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { return masterClient.getStatus(path); } catch (NotFoundException e) { throw new FileDoesNotExistException(ExceptionMessage.PATH_DOES_NOT_EXIST.getMessage(path)); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public List<URIStatus> listStatus(AlluxioURI path) throws FileDoesNotExistException, IOException, AlluxioException { return listStatus(path, ListStatusOptions.defaults()); } @Override public List<URIStatus> listStatus(AlluxioURI path, ListStatusOptions options) throws FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); // TODO(calvin): Fix the exception handling in the master try { return masterClient.listStatus(path, options); } catch (NotFoundException e) { throw new FileDoesNotExistException(ExceptionMessage.PATH_DOES_NOT_EXIST.getMessage(path)); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } /** * {@inheritDoc} * * @deprecated since version 1.1 and will be removed in version 2.0 */ @Deprecated @Override public void loadMetadata(AlluxioURI path) throws FileDoesNotExistException, IOException, AlluxioException { loadMetadata(path, LoadMetadataOptions.defaults()); } /** * {@inheritDoc} * * @deprecated since version 1.1 and will be removed in version 2.0 */ @Deprecated @Override public void loadMetadata(AlluxioURI path, LoadMetadataOptions options) throws FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { masterClient.loadMetadata(path, options); LOG.debug("Loaded metadata {}, options: {}", path.getPath(), options); } catch (NotFoundException e) { throw new FileDoesNotExistException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public void mount(AlluxioURI alluxioPath, AlluxioURI ufsPath) throws IOException, AlluxioException { mount(alluxioPath, ufsPath, MountOptions.defaults()); } @Override public void mount(AlluxioURI alluxioPath, AlluxioURI ufsPath, MountOptions options) throws IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { // TODO(calvin): Make this fail on the master side masterClient.mount(alluxioPath, ufsPath, options); LOG.info("Mount " + ufsPath.toString() + " to " + alluxioPath.getPath()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public FileInStream openFile(AlluxioURI path) throws FileDoesNotExistException, IOException, AlluxioException { return openFile(path, OpenFileOptions.defaults()); } @Override public FileInStream openFile(AlluxioURI path, OpenFileOptions options) throws FileDoesNotExistException, IOException, AlluxioException { URIStatus status = getStatus(path); if (status.isFolder()) { throw new FileDoesNotExistException( ExceptionMessage.CANNOT_READ_DIRECTORY.getMessage(status.getName())); } InStreamOptions inStreamOptions = options.toInStreamOptions(); return FileInStream.create(status, inStreamOptions, mFileSystemContext); } @Override public void rename(AlluxioURI src, AlluxioURI dst) throws FileDoesNotExistException, IOException, AlluxioException { rename(src, dst, RenameOptions.defaults()); } @Override public void rename(AlluxioURI src, AlluxioURI dst, RenameOptions options) throws FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { // TODO(calvin): Update this code on the master side. masterClient.rename(src, dst); LOG.debug("Renamed {} to {}, options: {}", src.getPath(), dst.getPath(), options); } catch (NotFoundException e) { throw new FileDoesNotExistException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public void setAttribute(AlluxioURI path) throws FileDoesNotExistException, IOException, AlluxioException { setAttribute(path, SetAttributeOptions.defaults()); } @Override public void setAttribute(AlluxioURI path, SetAttributeOptions options) throws FileDoesNotExistException, IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { masterClient.setAttribute(path, options); LOG.debug("Set attributes for {}, options: {}", path.getPath(), options); } catch (NotFoundException e) { throw new FileDoesNotExistException(e.getMessage()); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } @Override public void unmount(AlluxioURI path) throws IOException, AlluxioException { unmount(path, UnmountOptions.defaults()); } @Override public void unmount(AlluxioURI path, UnmountOptions options) throws IOException, AlluxioException { FileSystemMasterClient masterClient = mFileSystemContext.acquireMasterClient(); try { masterClient.unmount(path); LOG.debug("Unmounted {}, options: {}", path.getPath(), options); } catch (UnavailableException e) { throw e; } catch (AlluxioStatusException e) { throw e.toAlluxioException(); } finally { mFileSystemContext.releaseMasterClient(masterClient); } } }