Search in sources :

Example 1 with SwiftOperationFailedException

use of org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException in project hadoop by apache.

the class SwiftNativeFileSystem method create.

/**
   * @param permission Currently ignored.
   */
@Override
public FSDataOutputStream create(Path file, FsPermission permission, boolean overwrite, int bufferSize, short replication, long blockSize, Progressable progress) throws IOException {
    LOG.debug("SwiftFileSystem.create");
    FileStatus fileStatus = null;
    Path absolutePath = makeAbsolute(file);
    try {
        fileStatus = getFileStatus(absolutePath);
    } catch (FileNotFoundException e) {
    //the file isn't there.
    }
    if (fileStatus != null) {
        //no need to bother creating any parent entries
        if (fileStatus.isDirectory()) {
            /*    we can't throw an exception here as there is no easy way to distinguish
     a file from the dir

        throw new SwiftPathExistsException("Cannot create a file over a directory:"
                                           + file);
 */
            if (LOG.isDebugEnabled()) {
                LOG.debug("Overwriting either an empty file or a directory");
            }
        }
        if (overwrite) {
            //overwrite set -> delete the object.
            store.delete(absolutePath, true);
        } else {
            throw new FileAlreadyExistsException("Path exists: " + file);
        }
    } else {
        // destination does not exist -trigger creation of the parent
        Path parent = file.getParent();
        if (parent != null) {
            if (!mkdirs(parent)) {
                throw new SwiftOperationFailedException("Mkdirs failed to create " + parent);
            }
        }
    }
    SwiftNativeOutputStream out = createSwiftOutputStream(file);
    return new FSDataOutputStream(out, statistics);
}
Also used : Path(org.apache.hadoop.fs.Path) SwiftObjectPath(org.apache.hadoop.fs.swift.util.SwiftObjectPath) SwiftOperationFailedException(org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException) FileAlreadyExistsException(org.apache.hadoop.fs.FileAlreadyExistsException) FileStatus(org.apache.hadoop.fs.FileStatus) FileNotFoundException(java.io.FileNotFoundException) FSDataOutputStream(org.apache.hadoop.fs.FSDataOutputStream)

Example 2 with SwiftOperationFailedException

use of org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException in project hadoop by apache.

the class SwiftNativeFileSystemStore method rename.

/**
   * Rename through copy-and-delete. this is a consequence of the
   * Swift filesystem using the path as the hash
   * into the Distributed Hash Table, "the ring" of filenames.
   * <p>
   * Because of the nature of the operation, it is not atomic.
   *
   * @param src source file/dir
   * @param dst destination
   * @throws IOException                   IO failure
   * @throws SwiftOperationFailedException if the rename failed
   * @throws FileNotFoundException         if the source directory is missing, or
   *                                       the parent directory of the destination
   */
public void rename(Path src, Path dst) throws FileNotFoundException, SwiftOperationFailedException, IOException {
    if (LOG.isDebugEnabled()) {
        LOG.debug("mv " + src + " " + dst);
    }
    boolean renamingOnToSelf = src.equals(dst);
    SwiftObjectPath srcObject = toObjectPath(src);
    SwiftObjectPath destObject = toObjectPath(dst);
    if (SwiftUtils.isRootDir(srcObject)) {
        throw new SwiftOperationFailedException("cannot rename root dir");
    }
    final SwiftFileStatus srcMetadata;
    srcMetadata = getObjectMetadata(src);
    SwiftFileStatus dstMetadata;
    try {
        dstMetadata = getObjectMetadata(dst);
    } catch (FileNotFoundException e) {
        //destination does not exist.
        LOG.debug("Destination does not exist");
        dstMetadata = null;
    }
    //check to see if the destination parent directory exists
    Path srcParent = src.getParent();
    Path dstParent = dst.getParent();
    //directory is root, in which case it must also exist
    if (dstParent != null && !dstParent.equals(srcParent)) {
        try {
            getObjectMetadata(dstParent);
        } catch (FileNotFoundException e) {
            //destination parent doesn't exist; bail out
            LOG.debug("destination parent directory " + dstParent + " doesn't exist");
            throw e;
        }
    }
    boolean destExists = dstMetadata != null;
    boolean destIsDir = destExists && SwiftUtils.isDirectory(dstMetadata);
    //calculate the destination
    SwiftObjectPath destPath;
    //enum the child entries and everything underneath
    List<FileStatus> childStats = listDirectory(srcObject, true, true);
    boolean srcIsFile = !srcMetadata.isDir();
    if (srcIsFile) {
        // #3 dest does not exist: use dest as name
        if (destExists) {
            if (destIsDir) {
                //outcome #2 -move to subdir of dest
                destPath = toObjectPath(new Path(dst, src.getName()));
            } else {
                //outcome #1 dest it's a file: fail if different
                if (!renamingOnToSelf) {
                    throw new FileAlreadyExistsException("cannot rename a file over one that already exists");
                } else {
                    //is mv self self where self is a file. this becomes a no-op
                    LOG.debug("Renaming file onto self: no-op => success");
                    return;
                }
            }
        } else {
            //outcome #3 -new entry
            destPath = toObjectPath(dst);
        }
        int childCount = childStats.size();
        // ->
        if (childCount == 0) {
            copyThenDeleteObject(srcObject, destPath);
        } else {
            //do the copy
            SwiftUtils.debug(LOG, "Source file appears to be partitioned." + " copying file and deleting children");
            copyObject(srcObject, destPath);
            for (FileStatus stat : childStats) {
                SwiftUtils.debug(LOG, "Deleting partitioned file %s ", stat);
                deleteObject(stat.getPath());
            }
            swiftRestClient.delete(srcObject);
        }
    } else {
        if (destExists && !destIsDir) {
            // #1 destination is a file: fail
            throw new FileAlreadyExistsException("the source is a directory, but not the destination");
        }
        Path targetPath;
        if (destExists) {
            // #2 destination is a directory: create a new dir under that one
            targetPath = new Path(dst, src.getName());
        } else {
            // #3 destination doesn't exist: create a new dir with that name
            targetPath = dst;
        }
        SwiftObjectPath targetObjectPath = toObjectPath(targetPath);
        //final check for any recursive operations
        if (srcObject.isEqualToOrParentOf(targetObjectPath)) {
            //you can't rename a directory onto itself
            throw new SwiftOperationFailedException("cannot move a directory under itself");
        }
        LOG.info("mv  " + srcObject + " " + targetPath);
        logDirectory("Directory to copy ", srcObject, childStats);
        // iterative copy of everything under the directory.
        // by listing all children this can be done iteratively
        // rather than recursively -everything in this list is either a file
        // or a 0-byte-len file pretending to be a directory.
        String srcURI = src.toUri().toString();
        int prefixStripCount = srcURI.length() + 1;
        for (FileStatus fileStatus : childStats) {
            Path copySourcePath = fileStatus.getPath();
            String copySourceURI = copySourcePath.toUri().toString();
            String copyDestSubPath = copySourceURI.substring(prefixStripCount);
            Path copyDestPath = new Path(targetPath, copyDestSubPath);
            if (LOG.isTraceEnabled()) {
                //trace to debug some low-level rename path problems; retained
                //in case they ever come back.
                LOG.trace("srcURI=" + srcURI + "; copySourceURI=" + copySourceURI + "; copyDestSubPath=" + copyDestSubPath + "; copyDestPath=" + copyDestPath);
            }
            SwiftObjectPath copyDestination = toObjectPath(copyDestPath);
            try {
                copyThenDeleteObject(toObjectPath(copySourcePath), copyDestination);
            } catch (FileNotFoundException e) {
                LOG.info("Skipping rename of " + copySourcePath);
            }
            //add a throttle delay
            throttle();
        }
        //now rename self. If missing, create the dest directory and warn
        if (!SwiftUtils.isRootDir(srcObject)) {
            try {
                copyThenDeleteObject(srcObject, targetObjectPath);
            } catch (FileNotFoundException e) {
                //create the destination directory
                LOG.warn("Source directory deleted during rename", e);
                innerCreateDirectory(destObject);
            }
        }
    }
}
Also used : SwiftOperationFailedException(org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException) Path(org.apache.hadoop.fs.Path) SwiftObjectPath(org.apache.hadoop.fs.swift.util.SwiftObjectPath) FileAlreadyExistsException(org.apache.hadoop.fs.FileAlreadyExistsException) FileStatus(org.apache.hadoop.fs.FileStatus) FileNotFoundException(java.io.FileNotFoundException) SwiftObjectPath(org.apache.hadoop.fs.swift.util.SwiftObjectPath)

Example 3 with SwiftOperationFailedException

use of org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException in project hadoop by apache.

the class SwiftNativeFileSystemStore method extractUris.

/**
   * extracts URIs from json
   * @param json json to parse
   * @param path path (used in exceptions)
   * @return URIs
   * @throws SwiftOperationFailedException on any problem parsing the JSON
   */
public static List<URI> extractUris(String json, Path path) throws SwiftOperationFailedException {
    final Matcher matcher = URI_PATTERN.matcher(json);
    final List<URI> result = new ArrayList<URI>();
    while (matcher.find()) {
        final String s = matcher.group();
        final String uri = s.substring(1, s.length() - 1);
        try {
            URI createdUri = URI.create(uri);
            result.add(createdUri);
        } catch (IllegalArgumentException e) {
            //to an exception with useful text
            throw new SwiftOperationFailedException(String.format("could not convert \"%s\" into a URI." + " source: %s " + " first JSON: %s", uri, path, json.substring(0, 256)));
        }
    }
    return result;
}
Also used : SwiftOperationFailedException(org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) URI(java.net.URI)

Example 4 with SwiftOperationFailedException

use of org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException in project hadoop by apache.

the class SwiftNativeFileSystemStore method delete.

/**
   * Delete the entire tree. This is an internal one with slightly different
   * behavior: if an entry is missing, a {@link FileNotFoundException} is
   * raised. This lets the caller distinguish a file not found with
   * other reasons for failure, so handles race conditions in recursive
   * directory deletes better.
   * <p>
   * The problem being addressed is: caller A requests a recursive directory
   * of directory /dir ; caller B requests a delete of a file /dir/file,
   * between caller A enumerating the files contents, and requesting a delete
   * of /dir/file. We want to recognise the special case
   * "directed file is no longer there" and not convert that into a failure
   *
   * @param absolutePath  the path to delete.
   * @param recursive if path is a directory and set to
   *                  true, the directory is deleted else throws an exception if the
   *                  directory is not empty
   *                  case of a file the recursive can be set to either true or false.
   * @return true if the object was deleted
   * @throws IOException           IO problems
   * @throws FileNotFoundException if a file/dir being deleted is not there -
   *                               this includes entries below the specified path, (if the path is a dir
   *                               and recursive is true)
   */
public boolean delete(Path absolutePath, boolean recursive) throws IOException {
    Path swiftPath = getCorrectSwiftPath(absolutePath);
    SwiftUtils.debug(LOG, "Deleting path '%s' recursive=%b", absolutePath, recursive);
    boolean askForNewest = true;
    SwiftFileStatus fileStatus = getObjectMetadata(swiftPath, askForNewest);
    //ask for the file/dir status, but don't demand the newest, as we
    //don't mind if the directory has changed
    //list all entries under this directory.
    //this will throw FileNotFoundException if the file isn't there
    FileStatus[] statuses = listSubPaths(absolutePath, true, askForNewest);
    if (statuses == null) {
        //the directory went away during the non-atomic stages of the operation.
        // Return false as it was not this thread doing the deletion.
        SwiftUtils.debug(LOG, "Path '%s' has no status -it has 'gone away'", absolutePath, recursive);
        return false;
    }
    int filecount = statuses.length;
    SwiftUtils.debug(LOG, "Path '%s' %d status entries'", absolutePath, filecount);
    if (filecount == 0) {
        //it's an empty directory or a path
        rmdir(absolutePath);
        return true;
    }
    if (LOG.isDebugEnabled()) {
        SwiftUtils.debug(LOG, "%s", SwiftUtils.fileStatsToString(statuses, "\n"));
    }
    if (filecount == 1 && swiftPath.equals(statuses[0].getPath())) {
        // 1 entry => simple file and it is the target
        //simple file: delete it
        SwiftUtils.debug(LOG, "Deleting simple file %s", absolutePath);
        deleteObject(absolutePath);
        return true;
    }
    // like a partitioned file (len > 0 && has children)
    if (!fileStatus.isDir()) {
        LOG.debug("Multiple child entries but entry has data: assume partitioned");
    } else if (!recursive) {
        //if there are children, unless this is a recursive operation, fail immediately
        throw new SwiftOperationFailedException("Directory " + fileStatus + " is not empty: " + SwiftUtils.fileStatsToString(statuses, "; "));
    }
    //delete the entries. including ourselves.
    for (FileStatus entryStatus : statuses) {
        Path entryPath = entryStatus.getPath();
        try {
            boolean deleted = deleteObject(entryPath);
            if (!deleted) {
                SwiftUtils.debug(LOG, "Failed to delete entry '%s'; continuing", entryPath);
            }
        } catch (FileNotFoundException e) {
            //the path went away -race conditions.
            //do not fail, as the outcome is still OK.
            SwiftUtils.debug(LOG, "Path '%s' is no longer present; continuing", entryPath);
        }
        throttle();
    }
    //now delete self
    SwiftUtils.debug(LOG, "Deleting base entry %s", absolutePath);
    deleteObject(absolutePath);
    return true;
}
Also used : Path(org.apache.hadoop.fs.Path) SwiftObjectPath(org.apache.hadoop.fs.swift.util.SwiftObjectPath) SwiftOperationFailedException(org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException) FileStatus(org.apache.hadoop.fs.FileStatus) FileNotFoundException(java.io.FileNotFoundException)

Example 5 with SwiftOperationFailedException

use of org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException in project hadoop by apache.

the class TestSwiftFileSystemRename method testMoveDirUnderParent.

@Test(timeout = SWIFT_TEST_TIMEOUT)
public void testMoveDirUnderParent() throws Throwable {
    if (!renameSupported()) {
        return;
    }
    Path testdir = path("test/dir");
    fs.mkdirs(testdir);
    Path parent = testdir.getParent();
    //the outcome here is ambiguous, so is not checked
    try {
        fs.rename(testdir, parent);
    } catch (SwiftOperationFailedException e) {
    // allowed
    }
    assertExists("Source directory has been deleted ", testdir);
}
Also used : Path(org.apache.hadoop.fs.Path) SwiftOperationFailedException(org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException) Test(org.junit.Test)

Aggregations

SwiftOperationFailedException (org.apache.hadoop.fs.swift.exceptions.SwiftOperationFailedException)5 Path (org.apache.hadoop.fs.Path)4 FileNotFoundException (java.io.FileNotFoundException)3 FileStatus (org.apache.hadoop.fs.FileStatus)3 SwiftObjectPath (org.apache.hadoop.fs.swift.util.SwiftObjectPath)3 FileAlreadyExistsException (org.apache.hadoop.fs.FileAlreadyExistsException)2 URI (java.net.URI)1 ArrayList (java.util.ArrayList)1 Matcher (java.util.regex.Matcher)1 FSDataOutputStream (org.apache.hadoop.fs.FSDataOutputStream)1 Test (org.junit.Test)1