This is an automated email from the ASF dual-hosted git repository. mblow pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit 30d8fcbe3475aa4b1e1c6a742ac071d0b8f9bc38 Author: Michael Blow <[email protected]> AuthorDate: Wed Mar 24 15:08:51 2021 -0400 [NO ISSUE][RT] Best-effort serialization of ErrorCode enum values Change-Id: Ia8ffec3961f20db9355ec6b309a5b6fd99921da9 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10683 Integration-Tests: Jenkins <[email protected]> Reviewed-by: Michael Blow <[email protected]> Reviewed-by: Murtadha Hubail <[email protected]> Tested-by: Jenkins <[email protected]> --- .../api/http/server/QueryServiceServlet.java | 74 +++++++++++++--------- .../common/exceptions/AlgebricksException.java | 15 ++++- .../hyracks/api/exceptions/HyracksException.java | 12 ++-- .../api/exceptions/IFormattedException.java | 19 +++++- .../apache/hyracks/api/util/ErrorMessageUtil.java | 21 ++++++ 5 files changed, 105 insertions(+), 36 deletions(-) diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java index fcc6993..5153ebb 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java @@ -18,13 +18,7 @@ */ package org.apache.asterix.api.http.server; -import static org.apache.asterix.common.exceptions.ErrorCode.INVALID_REQ_JSON_VAL; -import static org.apache.asterix.common.exceptions.ErrorCode.INVALID_REQ_PARAM_VAL; import static org.apache.asterix.common.exceptions.ErrorCode.NO_STATEMENT_PROVIDED; -import static org.apache.asterix.common.exceptions.ErrorCode.REJECT_BAD_CLUSTER_STATE; -import static org.apache.asterix.common.exceptions.ErrorCode.REJECT_NODE_UNREGISTERED; -import static org.apache.asterix.common.exceptions.ErrorCode.REQUEST_TIMEOUT; -import static org.apache.hyracks.api.exceptions.ErrorCode.JOB_REQUIREMENTS_EXCEED_CAPACITY; import java.io.IOException; import java.io.PrintWriter; @@ -35,6 +29,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; @@ -65,6 +60,7 @@ import org.apache.asterix.common.api.IRequestReference; import org.apache.asterix.common.context.IStorageComponentProvider; import org.apache.asterix.common.dataflow.ICcApplicationContext; import org.apache.asterix.common.exceptions.CompilationException; +import org.apache.asterix.common.exceptions.ErrorCode; import org.apache.asterix.common.exceptions.RuntimeDataException; import org.apache.asterix.compiler.provider.ILangCompilationProvider; import org.apache.asterix.lang.common.base.IParser; @@ -86,7 +82,8 @@ import org.apache.asterix.translator.SessionOutput; import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.api.application.IServiceContext; import org.apache.hyracks.api.exceptions.HyracksDataException; -import org.apache.hyracks.api.exceptions.HyracksException; +import org.apache.hyracks.api.exceptions.IError; +import org.apache.hyracks.api.exceptions.IFormattedException; import org.apache.hyracks.api.exceptions.Warning; import org.apache.hyracks.api.result.IResultSet; import org.apache.hyracks.control.common.controllers.CCConfig; @@ -419,6 +416,38 @@ public class QueryServiceServlet extends AbstractQueryApiServlet { buildResponseResults(responsePrinter, sessionOutput, translator.getExecutionPlans(), warnings); } + protected boolean handleIFormattedException(IError error, IFormattedException ex, + RequestExecutionState executionState, QueryServiceRequestParameters param) { + if (error instanceof ErrorCode) { + switch ((ErrorCode) error) { + case INVALID_REQ_PARAM_VAL: + case INVALID_REQ_JSON_VAL: + case NO_STATEMENT_PROVIDED: + executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.BAD_REQUEST); + return true; + case REQUEST_TIMEOUT: + LOGGER.info(() -> "handleException: request execution timed out: " + + LogRedactionUtil.userData(param.toString())); + executionState.setStatus(ResultStatus.TIMEOUT, HttpResponseStatus.OK); + return true; + case REJECT_NODE_UNREGISTERED: + case REJECT_BAD_CLUSTER_STATE: + LOGGER.warn(() -> "handleException: " + ex.getMessage() + ": " + + LogRedactionUtil.userData(param.toString())); + executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.SERVICE_UNAVAILABLE); + default: + // fall-through + } + } else if (error instanceof org.apache.hyracks.api.exceptions.ErrorCode) { + switch ((org.apache.hyracks.api.exceptions.ErrorCode) error) { + case JOB_REQUIREMENTS_EXCEED_CAPACITY: + executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.BAD_REQUEST); + return true; + } + } + return false; + } + protected void handleExecuteStatementException(Throwable t, RequestExecutionState executionState, QueryServiceRequestParameters param) { if (t instanceof org.apache.asterix.lang.sqlpp.parser.TokenMgrError || t instanceof AlgebricksException) { @@ -430,30 +459,17 @@ public class QueryServiceServlet extends AbstractQueryApiServlet { + LogRedactionUtil.statement(param.toString())); } executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.BAD_REQUEST); - } else if (t instanceof HyracksException) { - HyracksException he = (HyracksException) t; - // TODO(mblow): reconsolidate - if (he.matchesAny(INVALID_REQ_PARAM_VAL, INVALID_REQ_JSON_VAL, NO_STATEMENT_PROVIDED, - JOB_REQUIREMENTS_EXCEED_CAPACITY)) { - executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.BAD_REQUEST); - } else if (he.matches(REQUEST_TIMEOUT)) { - LOGGER.info(() -> "handleException: request execution timed out: " - + LogRedactionUtil.userData(param.toString())); - executionState.setStatus(ResultStatus.TIMEOUT, HttpResponseStatus.OK); - } else if (he.matchesAny(REJECT_BAD_CLUSTER_STATE, REJECT_NODE_UNREGISTERED)) { - LOGGER.warn(() -> "handleException: " + he.getMessage() + ": " - + LogRedactionUtil.userData(param.toString())); - executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.SERVICE_UNAVAILABLE); - } else { - LOGGER.warn(() -> "handleException: unexpected exception " + he.getMessage() + ": " - + LogRedactionUtil.userData(param.toString()), he); - executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.INTERNAL_SERVER_ERROR); + return; + } else if (t instanceof IFormattedException) { + IFormattedException formattedEx = (IFormattedException) t; + Optional<IError> maybeError = formattedEx.getError(); + if (maybeError.isPresent() + && handleIFormattedException(maybeError.get(), (IFormattedException) t, executionState, param)) { + return; } - } else { - LOGGER.warn(() -> "handleException: unexpected exception: " + LogRedactionUtil.userData(param.toString()), - t); - executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.INTERNAL_SERVER_ERROR); } + LOGGER.warn(() -> "handleException: unexpected exception: " + LogRedactionUtil.userData(param.toString()), t); + executionState.setStatus(ResultStatus.FATAL, HttpResponseStatus.INTERNAL_SERVER_ERROR); } private void setSessionConfig(SessionOutput sessionOutput, QueryServiceRequestParameters param, diff --git a/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java b/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java index f00161c..4b8179c 100644 --- a/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java +++ b/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java @@ -18,6 +18,9 @@ */ package org.apache.hyracks.algebricks.common.exceptions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Optional; @@ -28,7 +31,7 @@ import org.apache.hyracks.api.exceptions.SourceLocation; import org.apache.hyracks.api.util.ErrorMessageUtil; public class AlgebricksException extends Exception implements IFormattedException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; public static final int UNKNOWN = 0; private final String component; @@ -36,7 +39,7 @@ public class AlgebricksException extends Exception implements IFormattedExceptio private final Serializable[] params; private final String nodeId; private final SourceLocation sourceLoc; - protected final transient IError error; + protected transient IError error; @SuppressWarnings("squid:S1165") // exception class not final private transient volatile String msgCache; @@ -134,4 +137,12 @@ public class AlgebricksException extends Exception implements IFormattedExceptio } return msgCache; } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + ErrorMessageUtil.writeObjectWithError(error, out); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + error = ErrorMessageUtil.readObjectWithError(in).orElse(null); + } } diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/HyracksException.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/HyracksException.java index d6085f6..0769e18 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/HyracksException.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/HyracksException.java @@ -25,15 +25,15 @@ import java.util.Optional; import org.apache.hyracks.api.util.ErrorMessageUtil; public class HyracksException extends IOException implements IFormattedException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; public static final int UNKNOWN = 0; private final String component; private final int errorCode; private final Serializable[] params; private final String nodeId; - protected transient final IError error; private SourceLocation sourceLoc; + protected transient IError error; private transient volatile String msgCache; public static HyracksException create(Throwable cause) { @@ -166,7 +166,11 @@ public class HyracksException extends IOException implements IFormattedException return Optional.ofNullable(error); } - public boolean matches(ErrorCode errorCode) { - return component.equals(errorCode.component()) && getErrorCode() == errorCode.intValue(); + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + ErrorMessageUtil.writeObjectWithError(error, out); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + error = ErrorMessageUtil.readObjectWithError(in).orElse(null); } } diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IFormattedException.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IFormattedException.java index 1f814b4..33b3995 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IFormattedException.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IFormattedException.java @@ -46,8 +46,13 @@ public interface IFormattedException { String getMessage(); /** + * See {@link Throwable#getSuppressed()} + */ + Throwable[] getSuppressed(); + + /** * If available, returns the {@link IError} associated with this exception - * @return the error instance, othewise {@link Optional#empty()} + * @return the error instance, otherwise {@link Optional#empty()} * @since 0.3.5.1 */ Optional<IError> getError(); @@ -85,4 +90,16 @@ public interface IFormattedException { static boolean matchesAny(Throwable th, IError candidate, IError... otherCandidates) { return th instanceof IFormattedException && ((IFormattedException) th).matchesAny(candidate, otherCandidates); } + + /** + * If the supplied {@link Throwable} is an instance of {@link IFormattedException}, return the {@link IError} + * associated with this exception if available + * + * @return the error instance, otherwise {@link Optional#empty()} + * @since 0.3.5.1 + */ + static Optional<IError> getError(Throwable throwable) { + return throwable instanceof IFormattedException ? ((IFormattedException) throwable).getError() + : Optional.empty(); + } } diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java index a7372ae..6479c8d 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java @@ -21,11 +21,14 @@ package org.apache.hyracks.api.util; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Arrays; import java.util.Formatter; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.Properties; import org.apache.hyracks.api.exceptions.IError; @@ -140,4 +143,22 @@ public class ErrorMessageUtil { } return enumMessages; } + + public static void writeObjectWithError(IError error, ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeObject(error); + } + + public static Optional<IError> readObjectWithError(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + try { + return Optional.ofNullable((IError) in.readObject()); + } catch (IllegalArgumentException e) { + // this is expected in case of error codes not available in this version; return null + LOGGER.debug("unable to deserialize error object due to {}, the error reference will be empty", + String.valueOf(e)); + return Optional.empty(); + } + } }
