/* * 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.exception.status; import alluxio.exception.AccessControlException; import alluxio.exception.AlluxioException; import alluxio.exception.BlockAlreadyExistsException; import alluxio.exception.BlockDoesNotExistException; import alluxio.exception.BlockInfoException; import alluxio.exception.ConnectionFailedException; import alluxio.exception.DependencyDoesNotExistException; import alluxio.exception.DirectoryNotEmptyException; import alluxio.exception.FailedToCheckpointException; import alluxio.exception.FileAlreadyCompletedException; import alluxio.exception.FileAlreadyExistsException; import alluxio.exception.FileDoesNotExistException; import alluxio.exception.InvalidFileSizeException; import alluxio.exception.InvalidPathException; import alluxio.exception.InvalidWorkerStateException; import alluxio.exception.LineageDeletionException; import alluxio.exception.LineageDoesNotExistException; import alluxio.exception.NoWorkerException; import alluxio.exception.UfsBlockAccessTokenUnavailableException; import alluxio.exception.WorkerOutOfSpaceException; import alluxio.thrift.AlluxioTException; import com.google.common.base.Preconditions; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.nio.channels.ClosedChannelException; import java.nio.file.attribute.UserPrincipalNotFoundException; /** * An exception thrown by Alluxio. {@link #getStatus()} can be used to determine the represented * class of error. */ public class AlluxioStatusException extends IOException { private static final long serialVersionUID = -7422144873058169662L; private final Status mStatus; /** * @param status the status code for this exception * @param message the exception message */ public AlluxioStatusException(Status status, String message) { super(message); mStatus = status; } /** * @param status the status code for this exception * @param cause the cause of the exception */ public AlluxioStatusException(Status status, Throwable cause) { super(cause.getMessage(), cause); mStatus = status; } /** * @param status the status code for this exception * @param message the exception message * @param cause the cause of the exception */ public AlluxioStatusException(Status status, String message, Throwable cause) { super(message, cause); mStatus = status; } /** * @return the status code for this exception */ public Status getStatus() { return mStatus; } /** * @return the Thrift representation of this exception */ public AlluxioTException toThrift() { return new AlluxioTException(getMessage(), Status.toThrift(mStatus)); } /** * @return a specific {@link AlluxioException} corresponding to this exception if there is one; * otherwise return a generic {@link AlluxioException} */ public AlluxioException toAlluxioException() { switch (mStatus) { // Fall throughs are intentional. case PERMISSION_DENIED: case UNAUTHENTICATED: return new AccessControlException(getMessage(), this); case ABORTED: case ALREADY_EXISTS: case CANCELED: case DATA_LOSS: case DEADLINE_EXCEEDED: case FAILED_PRECONDITION: case INTERNAL: case INVALID_ARGUMENT: case NOT_FOUND: case OUT_OF_RANGE: case RESOURCE_EXHAUSTED: case UNAVAILABLE: case UNIMPLEMENTED: case UNKNOWN: default: return new AlluxioException(getMessage(), this); } } /** * Converts an Alluxio exception from Thrift representation to native representation. * * @param e the Thrift exception * @return the native Alluxio exception */ public static AlluxioStatusException fromThrift(AlluxioTException e) { return from(Status.fromThrift(e.getStatus()), e.getMessage()); } /** * Converts an Alluxio exception from status and message representation to native representation. * The status must not be null or {@link Status#OK}. * * @param status the status * @param m the message * @return an {@link AlluxioStatusException} for the given status and message */ public static AlluxioStatusException from(Status status, String m) { Preconditions.checkNotNull(status, "status"); Preconditions.checkArgument(status != Status.OK, "OK is not an error status"); switch (status) { case CANCELED: return new CanceledException(m); case INVALID_ARGUMENT: return new InvalidArgumentException(m); case DEADLINE_EXCEEDED: return new DeadlineExceededException(m); case NOT_FOUND: return new NotFoundException(m); case ALREADY_EXISTS: return new AlreadyExistsException(m); case PERMISSION_DENIED: return new PermissionDeniedException(m); case UNAUTHENTICATED: return new UnauthenticatedException(m); case RESOURCE_EXHAUSTED: return new ResourceExhaustedException(m); case FAILED_PRECONDITION: return new FailedPreconditionException(m); case ABORTED: return new AbortedException(m); case OUT_OF_RANGE: return new OutOfRangeException(m); case UNIMPLEMENTED: return new UnimplementedException(m); case INTERNAL: return new InternalException(m); case UNAVAILABLE: return new UnavailableException(m); case DATA_LOSS: return new DataLossException(m); default: return new UnknownException(m); } } /** * Converts checked throwables to Alluxio status exceptions. Unchecked throwables should not be * passed to this method. Use Throwables.propagateIfPossible before passing a Throwable to this * method. * * @param throwable a throwable * @return the converted {@link AlluxioStatusException} */ public static AlluxioStatusException fromCheckedException(Throwable throwable) { try { throw throwable; } catch (IOException e) { return fromIOException(e); } catch (AlluxioException e) { return fromAlluxioException(e); } catch (InterruptedException e) { return new CanceledException(e); } catch (RuntimeException e) { throw new IllegalStateException("Expected a checked exception but got " + e); } catch (Exception e) { return new UnknownException(e); } catch (Throwable t) { throw new IllegalStateException("Expected a checked exception but got " + t); } } /** * Converts an arbitrary throwable to an Alluxio status exception. This method should be used with * caution because it could potentially convert an unchecked exception (indicating a bug) to a * checked Alluxio status exception. * * @param t a throwable * @return the converted {@link AlluxioStatusException} */ public static AlluxioStatusException fromThrowable(Throwable t) { if (t instanceof Error || t instanceof RuntimeException) { return new InternalException(t); } return fromCheckedException(t); } /** * Converts checked Alluxio exceptions to Alluxio status exceptions. * * @param ae the Alluxio exception to convert * @return the converted {@link AlluxioStatusException} */ public static AlluxioStatusException fromAlluxioException(AlluxioException ae) { try { throw ae; } catch (AccessControlException e) { return new PermissionDeniedException(e); } catch (BlockAlreadyExistsException | FileAlreadyCompletedException | FileAlreadyExistsException e) { return new AlreadyExistsException(e); } catch (BlockDoesNotExistException | FileDoesNotExistException | LineageDoesNotExistException e) { return new NotFoundException(e); } catch (BlockInfoException | InvalidFileSizeException | InvalidPathException e) { return new InvalidArgumentException(e); } catch (ConnectionFailedException | FailedToCheckpointException | NoWorkerException | UfsBlockAccessTokenUnavailableException e) { return new UnavailableException(e); } catch (DependencyDoesNotExistException | DirectoryNotEmptyException | InvalidWorkerStateException | LineageDeletionException e) { return new FailedPreconditionException(e); } catch (WorkerOutOfSpaceException e) { return new ResourceExhaustedException(e); } catch (AlluxioException e) { return new UnknownException(e); } } /** * Converts an IOException to a corresponding status exception. Unless special cased, IOExceptions * are converted to {@link UnavailableException}. * * @param ioe the IO exception to convert * @return the corresponding status exception */ public static AlluxioStatusException fromIOException(IOException ioe) { try { throw ioe; } catch (FileNotFoundException e) { return new NotFoundException(e); } catch (MalformedURLException e) { return new InvalidArgumentException(e); } catch (UserPrincipalNotFoundException e) { return new UnauthenticatedException(e); } catch (ClosedChannelException e) { return new FailedPreconditionException(e); } catch (AlluxioStatusException e) { return e; } catch (IOException e) { return new UnavailableException(e); } } }