Search in sources :

Example 26 with Inode

use of alluxio.master.file.meta.Inode in project alluxio by Alluxio.

the class FileSystemMaster method freeAndJournal.

/**
   * Implements free operation.
   * <p>
   * This may write to the journal as free operation may change the pinned state of inodes.
   *
   * @param inodePath inode of the path to free
   * @param options options to free
   * @param journalContext the journal context
   * @throws FileDoesNotExistException if the file does not exist
   * @throws AccessControlException if permission checking fails
   * @throws InvalidPathException if the given path is invalid
   * @throws UnexpectedAlluxioException if the file or directory can not be freed
   */
private void freeAndJournal(LockedInodePath inodePath, FreeOptions options, JournalContext journalContext) throws FileDoesNotExistException, UnexpectedAlluxioException, AccessControlException, InvalidPathException {
    Inode<?> inode = inodePath.getInode();
    if (inode.isDirectory() && !options.isRecursive() && ((InodeDirectory) inode).getNumberOfChildren() > 0) {
        // inode is nonempty, and we don't free a nonempty directory unless recursive is true
        throw new UnexpectedAlluxioException(ExceptionMessage.CANNOT_FREE_NON_EMPTY_DIR.getMessage(mInodeTree.getPath(inode)));
    }
    long opTimeMs = System.currentTimeMillis();
    List<Inode<?>> freeInodes = new ArrayList<>();
    freeInodes.add(inode);
    try (InodeLockList lockList = mInodeTree.lockDescendants(inodePath, InodeTree.LockMode.WRITE)) {
        freeInodes.addAll(lockList.getInodes());
        TempInodePathForDescendant tempInodePath = new TempInodePathForDescendant(inodePath);
        // We go through each inode.
        for (int i = freeInodes.size() - 1; i >= 0; i--) {
            Inode<?> freeInode = freeInodes.get(i);
            if (freeInode.isFile()) {
                if (freeInode.getPersistenceState() != PersistenceState.PERSISTED) {
                    throw new UnexpectedAlluxioException(ExceptionMessage.CANNOT_FREE_NON_PERSISTED_FILE.getMessage(mInodeTree.getPath(freeInode)));
                }
                if (freeInode.isPinned()) {
                    if (!options.isForced()) {
                        throw new UnexpectedAlluxioException(ExceptionMessage.CANNOT_FREE_PINNED_FILE.getMessage(mInodeTree.getPath(freeInode)));
                    }
                    // the path to inode for getPath should already be locked.
                    tempInodePath.setDescendant(freeInode, mInodeTree.getPath(freeInode));
                    SetAttributeOptions setAttributeOptions = SetAttributeOptions.defaults().setRecursive(false).setPinned(false);
                    setAttributeInternal(tempInodePath, false, opTimeMs, setAttributeOptions);
                    journalSetAttribute(tempInodePath, opTimeMs, setAttributeOptions, journalContext);
                }
                // Remove corresponding blocks from workers.
                mBlockMaster.removeBlocks(((InodeFile) freeInode).getBlockIds(), false);
            }
        }
    }
    Metrics.FILES_FREED.inc(freeInodes.size());
}
Also used : SetAttributeOptions(alluxio.master.file.options.SetAttributeOptions) InodeDirectory(alluxio.master.file.meta.InodeDirectory) Inode(alluxio.master.file.meta.Inode) TempInodePathForDescendant(alluxio.master.file.meta.TempInodePathForDescendant) InodeLockList(alluxio.master.file.meta.InodeLockList) UnexpectedAlluxioException(alluxio.exception.UnexpectedAlluxioException) ArrayList(java.util.ArrayList)

Example 27 with Inode

use of alluxio.master.file.meta.Inode in project alluxio by Alluxio.

the class FileSystemMaster method renameInternal.

/**
   * Implements renaming.
   *
   * @param srcInodePath the path of the rename source
   * @param dstInodePath the path to the rename destination
   * @param replayed whether the operation is a result of replaying the journal
   * @param options method options
   * @throws FileDoesNotExistException if a non-existent file is encountered
   * @throws InvalidPathException if an invalid path is encountered
   * @throws IOException if an I/O error is encountered
   */
private void renameInternal(LockedInodePath srcInodePath, LockedInodePath dstInodePath, boolean replayed, RenameOptions options) throws FileDoesNotExistException, InvalidPathException, IOException {
    // Rename logic:
    // 1. Change the source inode name to the destination name.
    // 2. Insert the source inode into the destination parent.
    // 3. Do UFS operations if necessary.
    // 4. Remove the source inode (reverting the name) from the source parent.
    // 5. Set the last modification times for both source and destination parent inodes.
    Inode<?> srcInode = srcInodePath.getInode();
    AlluxioURI srcPath = srcInodePath.getUri();
    AlluxioURI dstPath = dstInodePath.getUri();
    InodeDirectory srcParentInode = srcInodePath.getParentInodeDirectory();
    InodeDirectory dstParentInode = dstInodePath.getParentInodeDirectory();
    String srcName = srcPath.getName();
    String dstName = dstPath.getName();
    LOG.debug("Renaming {} to {}", srcPath, dstPath);
    // 1. Change the source inode name to the destination name.
    srcInode.setName(dstName);
    srcInode.setParentId(dstParentInode.getId());
    // 2. Insert the source inode into the destination parent.
    if (!dstParentInode.addChild(srcInode)) {
        // On failure, revert changes and throw exception.
        srcInode.setName(srcName);
        srcInode.setParentId(srcParentInode.getId());
        throw new InvalidPathException("Destination path: " + dstPath + " already exists.");
    }
    // If the source file is persisted, rename it in the UFS.
    try {
        if (!replayed && srcInode.isPersisted()) {
            MountTable.Resolution resolution = mMountTable.resolve(srcPath);
            String ufsSrcPath = resolution.getUri().toString();
            UnderFileSystem ufs = resolution.getUfs();
            String ufsDstUri = mMountTable.resolve(dstPath).getUri().toString();
            // Create ancestor directories from top to the bottom. We cannot use recursive create
            // parents here because the permission for the ancestors can be different.
            List<Inode<?>> dstInodeList = dstInodePath.getInodeList();
            Stack<Pair<String, MkdirsOptions>> ufsDirsToMakeWithOptions = new Stack<>();
            AlluxioURI curUfsDirPath = new AlluxioURI(ufsDstUri).getParent();
            // The dst inode does not exist yet, so the last inode in the list is the existing parent.
            for (int i = dstInodeList.size() - 1; i >= 0; i--) {
                if (ufs.isDirectory(curUfsDirPath.toString())) {
                    break;
                }
                Inode<?> curInode = dstInodeList.get(i);
                MkdirsOptions mkdirsOptions = MkdirsOptions.defaults().setCreateParent(false).setOwner(curInode.getOwner()).setGroup(curInode.getGroup()).setMode(new Mode(curInode.getMode()));
                ufsDirsToMakeWithOptions.push(new Pair<>(curUfsDirPath.toString(), mkdirsOptions));
                curUfsDirPath = curUfsDirPath.getParent();
            }
            while (!ufsDirsToMakeWithOptions.empty()) {
                Pair<String, MkdirsOptions> ufsDirAndPerm = ufsDirsToMakeWithOptions.pop();
                if (!ufs.mkdirs(ufsDirAndPerm.getFirst(), ufsDirAndPerm.getSecond())) {
                    throw new IOException(ExceptionMessage.FAILED_UFS_CREATE.getMessage(ufsDirAndPerm.getFirst()));
                }
            }
            boolean success;
            if (srcInode.isFile()) {
                success = ufs.renameFile(ufsSrcPath, ufsDstUri);
            } else {
                success = ufs.renameDirectory(ufsSrcPath, ufsDstUri);
            }
            if (!success) {
                throw new IOException(ExceptionMessage.FAILED_UFS_RENAME.getMessage(ufsSrcPath, ufsDstUri));
            }
        }
    } catch (Exception e) {
        // On failure, revert changes and throw exception.
        if (!dstParentInode.removeChild(dstName)) {
            LOG.error("Failed to revert rename changes. Alluxio metadata may be inconsistent.");
        }
        srcInode.setName(srcName);
        srcInode.setParentId(srcParentInode.getId());
        throw e;
    }
    // TODO(jiri): A crash between now and the time the rename operation is journaled will result in
    // an inconsistency between Alluxio and UFS.
    // 4. Remove the source inode (reverting the name) from the source parent. The name must be
    // reverted or removeChild will not be able to find the appropriate child entry since it is
    // keyed on the original name.
    srcInode.setName(srcName);
    if (!srcParentInode.removeChild(srcInode)) {
        // This should never happen.
        LOG.error("Failed to rename {} to {} in Alluxio. Alluxio and under storage may be " + "inconsistent.", srcPath, dstPath);
        srcInode.setName(dstName);
        if (!dstParentInode.removeChild(dstName)) {
            LOG.error("Failed to revert changes when renaming {} to {}. Alluxio metadata may be " + "inconsistent.", srcPath, dstPath);
        }
        srcInode.setName(srcName);
        srcInode.setParentId(srcParentInode.getId());
        throw new IOException("Failed to remove source path " + srcPath + " from parent");
    }
    srcInode.setName(dstName);
    // 5. Set the last modification times for both source and destination parent inodes.
    // Note this step relies on setLastModificationTimeMs being thread safe to guarantee the
    // correct behavior when multiple files are being renamed within a directory.
    dstParentInode.setLastModificationTimeMs(options.getOperationTimeMs());
    srcParentInode.setLastModificationTimeMs(options.getOperationTimeMs());
    Metrics.PATHS_RENAMED.inc();
}
Also used : MkdirsOptions(alluxio.underfs.options.MkdirsOptions) Mode(alluxio.security.authorization.Mode) IOException(java.io.IOException) MountTable(alluxio.master.file.meta.MountTable) InvalidPathException(alluxio.exception.InvalidPathException) AlluxioException(alluxio.exception.AlluxioException) BlockInfoException(alluxio.exception.BlockInfoException) FileAlreadyExistsException(alluxio.exception.FileAlreadyExistsException) IOException(java.io.IOException) InvalidPathException(alluxio.exception.InvalidPathException) AccessControlException(alluxio.exception.AccessControlException) InvalidFileSizeException(alluxio.exception.InvalidFileSizeException) FileDoesNotExistException(alluxio.exception.FileDoesNotExistException) FileAlreadyCompletedException(alluxio.exception.FileAlreadyCompletedException) DirectoryNotEmptyException(alluxio.exception.DirectoryNotEmptyException) UnexpectedAlluxioException(alluxio.exception.UnexpectedAlluxioException) Stack(java.util.Stack) InodeDirectory(alluxio.master.file.meta.InodeDirectory) Inode(alluxio.master.file.meta.Inode) UnderFileSystem(alluxio.underfs.UnderFileSystem) AlluxioURI(alluxio.AlluxioURI) InodePathPair(alluxio.master.file.meta.InodePathPair) Pair(alluxio.collections.Pair)

Example 28 with Inode

use of alluxio.master.file.meta.Inode in project alluxio by Alluxio.

the class FileSystemMaster method deleteInternal.

/**
   * Implements file deletion.
   *
   * @param inodePath the file {@link LockedInodePath}
   * @param replayed whether the operation is a result of replaying the journal
   * @param opTimeMs the time of the operation
   * @param deleteOptions the method optitions
   * @throws FileDoesNotExistException if a non-existent file is encountered
   * @throws IOException if an I/O error is encountered
   * @throws InvalidPathException if the specified path is the root
   * @throws DirectoryNotEmptyException if recursive is false and the file is a nonempty directory
   */
private void deleteInternal(LockedInodePath inodePath, boolean replayed, long opTimeMs, DeleteOptions deleteOptions) throws FileDoesNotExistException, IOException, DirectoryNotEmptyException, InvalidPathException {
    // journaled will result in an inconsistency between Alluxio and UFS.
    if (!inodePath.fullPathExists()) {
        return;
    }
    Inode<?> inode = inodePath.getInode();
    if (inode == null) {
        return;
    }
    boolean recursive = deleteOptions.isRecursive();
    boolean alluxioOnly = deleteOptions.isAlluxioOnly();
    if (inode.isDirectory() && !recursive && ((InodeDirectory) inode).getNumberOfChildren() > 0) {
        // true
        throw new DirectoryNotEmptyException(ExceptionMessage.DELETE_NONEMPTY_DIRECTORY_NONRECURSIVE, inode.getName());
    }
    if (mInodeTree.isRootId(inode.getId())) {
        // The root cannot be deleted.
        throw new InvalidPathException(ExceptionMessage.DELETE_ROOT_DIRECTORY.getMessage());
    }
    List<Inode<?>> delInodes = new ArrayList<>();
    delInodes.add(inode);
    try (InodeLockList lockList = mInodeTree.lockDescendants(inodePath, InodeTree.LockMode.WRITE)) {
        delInodes.addAll(lockList.getInodes());
        TempInodePathForDescendant tempInodePath = new TempInodePathForDescendant(inodePath);
        // file, we deal with the checkpoints and blocks as well.
        for (int i = delInodes.size() - 1; i >= 0; i--) {
            Inode<?> delInode = delInodes.get(i);
            // the path to delInode for getPath should already be locked.
            AlluxioURI alluxioUriToDel = mInodeTree.getPath(delInode);
            tempInodePath.setDescendant(delInode, alluxioUriToDel);
            // Currently, it will result in an inconsistency between Alluxio and UFS.
            if (!replayed && delInode.isPersisted()) {
                try {
                    // TODO(calvin): Add tests (ALLUXIO-1831)
                    if (mMountTable.isMountPoint(alluxioUriToDel)) {
                        unmountInternal(alluxioUriToDel);
                    } else {
                        // Delete the file in the under file system.
                        MountTable.Resolution resolution = mMountTable.resolve(alluxioUriToDel);
                        String ufsUri = resolution.getUri().toString();
                        UnderFileSystem ufs = resolution.getUfs();
                        boolean failedToDelete = false;
                        if (!alluxioOnly) {
                            if (delInode.isFile()) {
                                if (!ufs.deleteFile(ufsUri)) {
                                    failedToDelete = ufs.isFile(ufsUri);
                                    if (!failedToDelete) {
                                        LOG.warn("The file to delete does not exist in ufs: {}", ufsUri);
                                    }
                                }
                            } else {
                                if (!ufs.deleteDirectory(ufsUri, alluxio.underfs.options.DeleteOptions.defaults().setRecursive(true))) {
                                    failedToDelete = ufs.isDirectory(ufsUri);
                                    if (!failedToDelete) {
                                        LOG.warn("The directory to delete does not exist in ufs: {}", ufsUri);
                                    }
                                }
                            }
                            if (failedToDelete) {
                                LOG.error("Failed to delete {} from the under filesystem", ufsUri);
                                throw new IOException(ExceptionMessage.DELETE_FAILED_UFS.getMessage(ufsUri));
                            }
                        }
                    }
                } catch (InvalidPathException e) {
                    LOG.warn(e.getMessage());
                }
            }
            if (delInode.isFile()) {
                // Remove corresponding blocks from workers and delete metadata in master.
                mBlockMaster.removeBlocks(((InodeFile) delInode).getBlockIds(), true);
            }
            mInodeTree.deleteInode(tempInodePath, opTimeMs);
        }
    }
    Metrics.PATHS_DELETED.inc(delInodes.size());
}
Also used : InodeLockList(alluxio.master.file.meta.InodeLockList) ArrayList(java.util.ArrayList) DirectoryNotEmptyException(alluxio.exception.DirectoryNotEmptyException) IOException(java.io.IOException) MountTable(alluxio.master.file.meta.MountTable) InvalidPathException(alluxio.exception.InvalidPathException) InodeDirectory(alluxio.master.file.meta.InodeDirectory) Inode(alluxio.master.file.meta.Inode) TempInodePathForDescendant(alluxio.master.file.meta.TempInodePathForDescendant) UnderFileSystem(alluxio.underfs.UnderFileSystem) AlluxioURI(alluxio.AlluxioURI)

Example 29 with Inode

use of alluxio.master.file.meta.Inode in project alluxio by Alluxio.

the class PermissionCheckerTest method createAndSetPermission.

/**
 * Helper function to create a path and set the permission to what specified in option.
 *
 * @param path path to construct the {@link AlluxioURI} from
 * @param context method context for creating a file
 */
private static void createAndSetPermission(String path, CreateFileContext context) throws Exception {
    try (LockedInodePath inodePath = sTree.lockInodePath(new AlluxioURI(path), LockPattern.WRITE_EDGE)) {
        List<Inode> result = sTree.createPath(RpcContext.NOOP, inodePath, context);
        MutableInode<?> inode = sInodeStore.getMutable(result.get(result.size() - 1).getId()).get();
        inode.setOwner(context.getOwner()).setGroup(context.getGroup()).setMode(context.getMode().toShort());
        sInodeStore.writeInode(inode);
    }
}
Also used : LockedInodePath(alluxio.master.file.meta.LockedInodePath) MutableInode(alluxio.master.file.meta.MutableInode) Inode(alluxio.master.file.meta.Inode) AlluxioURI(alluxio.AlluxioURI)

Example 30 with Inode

use of alluxio.master.file.meta.Inode in project alluxio by Alluxio.

the class CachingInodeStoreMockedBackingStoreTest method cacheGet.

@Test
public void cacheGet() {
    Inode testInode = Inode.wrap(TEST_INODE_DIR);
    for (int i = 0; i < CACHE_SIZE / 2; i++) {
        assertEquals(testInode, mStore.get(TEST_INODE_ID).get());
    }
    verifyNoBackingStoreReads();
}
Also used : Inode(alluxio.master.file.meta.Inode) Test(org.junit.Test)

Aggregations

Inode (alluxio.master.file.meta.Inode)42 AlluxioURI (alluxio.AlluxioURI)19 LockedInodePath (alluxio.master.file.meta.LockedInodePath)15 MountTable (alluxio.master.file.meta.MountTable)15 FileDoesNotExistException (alluxio.exception.FileDoesNotExistException)14 UnderFileSystem (alluxio.underfs.UnderFileSystem)13 ArrayList (java.util.ArrayList)13 AccessControlException (alluxio.exception.AccessControlException)12 InvalidPathException (alluxio.exception.InvalidPathException)12 InodeDirectory (alluxio.master.file.meta.InodeDirectory)11 IOException (java.io.IOException)11 UfsStatus (alluxio.underfs.UfsStatus)9 InodeFile (alluxio.master.file.meta.InodeFile)8 Fingerprint (alluxio.underfs.Fingerprint)8 BlockInfoException (alluxio.exception.BlockInfoException)7 DirectoryNotEmptyException (alluxio.exception.DirectoryNotEmptyException)6 FileAlreadyExistsException (alluxio.exception.FileAlreadyExistsException)6 UnexpectedAlluxioException (alluxio.exception.UnexpectedAlluxioException)6 FileAlreadyCompletedException (alluxio.exception.FileAlreadyCompletedException)5 InvalidFileSizeException (alluxio.exception.InvalidFileSizeException)5