Skip to content

Commit

Permalink
[NO ISSUE][RT] Best-effort serialization of ErrorCode enum values
Browse files Browse the repository at this point in the history
Change-Id: Ia8ffec3961f20db9355ec6b309a5b6fd99921da9
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10683
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <mblow@apache.org>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
  • Loading branch information
mblow committed Mar 25, 2021
1 parent 30f2a14 commit 30d8fcb
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 36 deletions.
Expand Up @@ -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;
Expand All @@ -35,6 +29,7 @@
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;
Expand Down Expand Up @@ -65,6 +60,7 @@
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;
Expand All @@ -86,7 +82,8 @@
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;
Expand Down Expand Up @@ -419,6 +416,38 @@ protected void executeStatement(IServletRequest request, IRequestReference reque
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) {
Expand All @@ -430,30 +459,17 @@ protected void handleExecuteStatementException(Throwable t, RequestExecutionStat
+ 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,
Expand Down
Expand Up @@ -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;

Expand All @@ -28,15 +31,15 @@
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;
private final int errorCode;
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;
Expand Down Expand Up @@ -134,4 +137,12 @@ public String getMessage() {
}
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);
}
}
Expand Up @@ -25,15 +25,15 @@
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) {
Expand Down Expand Up @@ -166,7 +166,11 @@ public Optional<IError> getError() {
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);
}
}
Expand Up @@ -45,9 +45,14 @@ 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();
Expand Down Expand Up @@ -85,4 +90,16 @@ static boolean matches(Throwable th, IError candidate) {
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();
}
}
Expand Up @@ -21,11 +21,14 @@

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;
Expand Down Expand Up @@ -140,4 +143,22 @@ public static String[] defineMessageEnumOrdinalMap(IError[] values, String resou
}
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();
}
}
}

0 comments on commit 30d8fcb

Please sign in to comment.