use of org.voltdb.exceptions.SerializableException in project voltdb by VoltDB.
the class SysprocFragmentTask method processFragmentTask.
// Extracted the sysproc portion of ExecutionSite processFragmentTask(), then
// modified to work in the new world
public FragmentResponseMessage processFragmentTask(SiteProcedureConnection siteConnection) {
final FragmentResponseMessage currentFragResponse = new FragmentResponseMessage(m_fragmentMsg, m_initiator.getHSId());
currentFragResponse.setStatus(FragmentResponseMessage.SUCCESS, null);
for (int frag = 0; frag < m_fragmentMsg.getFragmentCount(); frag++) {
final long fragmentId = VoltSystemProcedure.hashToFragId(m_fragmentMsg.getPlanHash(frag));
// equivalent to dep.depId:
// final int outputDepId = m_fragmentMsg.getOutputDepId(frag);
final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.SPSITE);
if (traceLog != null) {
traceLog.add(() -> VoltTrace.beginDuration("runfragmenttask", "txnId", TxnEgo.txnIdToString(getTxnId()), "partition", Integer.toString(siteConnection.getCorrespondingPartitionId()), "fragmentId", String.valueOf(fragmentId)));
}
ParameterSet params = m_fragmentMsg.getParameterSetForFragment(frag);
try {
// run the overloaded sysproc planfragment. pass an empty dependency
// set since remote (non-aggregator) fragments don't receive dependencies.
final DependencyPair dep = siteConnection.executeSysProcPlanFragment(m_txnState, m_inputDeps, fragmentId, params);
// @Shutdown returns null, handle it here
if (dep != null) {
currentFragResponse.addDependency(dep);
}
} catch (final EEException e) {
hostLog.l7dlog(Level.TRACE, LogKeys.host_ExecutionSite_ExceptionExecutingPF.name(), new Object[] { Encoder.hexEncode(m_fragmentMsg.getFragmentPlan(frag)) }, e);
currentFragResponse.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, e);
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(m_fragmentMsg.getOutputDepId(0), m_rawDummyResult, 0, m_rawDummyResult.length));
}
break;
} catch (final SQLException e) {
hostLog.l7dlog(Level.TRACE, LogKeys.host_ExecutionSite_ExceptionExecutingPF.name(), new Object[] { Encoder.hexEncode(m_fragmentMsg.getFragmentPlan(frag)) }, e);
currentFragResponse.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, e);
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(m_fragmentMsg.getOutputDepId(0), m_rawDummyResult, 0, m_rawDummyResult.length));
}
break;
} catch (final SpecifiedException e) {
// Note that with SpecifiedException, the error code here might get changed before
// the client/user sees it. It really just needs to indicate failure.
//
// Key point here vs the next catch block for VAE is to not wrap the subclass of
// SerializableException here to preserve it during the serialization.
//
currentFragResponse.setStatus(FragmentResponseMessage.USER_ERROR, e);
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(m_fragmentMsg.getOutputDepId(0), m_rawDummyResult, 0, m_rawDummyResult.length));
}
} catch (final VoltAbortException e) {
currentFragResponse.setStatus(FragmentResponseMessage.USER_ERROR, new SerializableException(CoreUtils.throwableToString(e)));
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(m_fragmentMsg.getOutputDepId(0), m_rawDummyResult, 0, m_rawDummyResult.length));
}
break;
}
if (traceLog != null) {
traceLog.add(VoltTrace::endDuration);
}
}
return currentFragResponse;
}
use of org.voltdb.exceptions.SerializableException in project voltdb by VoltDB.
the class StreamSnapshotAckReceiver method run.
@Override
public void run() {
rejoinLog.trace("Starting ack receiver thread");
try {
while (true) {
rejoinLog.trace("Blocking on receiving mailbox");
// Wait for 10 minutes
VoltMessage msg = m_mb.recvBlocking(10 * 60 * 1000);
if (msg == null) {
rejoinLog.warn("No stream snapshot ack message was received in the past 10 minutes" + " or the thread was interrupted (expected eofs: " + m_expectedEOFs.get() + ")");
continue;
}
// TestMidRejoinDeath ignores acks to trigger the watchdog
if (StreamSnapshotDataTarget.m_rejoinDeathTestMode && (m_msgFactory.getAckTargetId(msg) == 1)) {
continue;
}
SerializableException se = m_msgFactory.getException(msg);
if (se != null) {
m_lastException = se;
rejoinLog.error("Received exception in ack receiver", se);
return;
}
AckCallback ackCallback = m_callbacks.get(m_msgFactory.getAckTargetId(msg));
if (ackCallback == null) {
rejoinLog.error("Unknown target ID " + m_msgFactory.getAckTargetId(msg) + " in stream snapshot ack message");
} else if (m_msgFactory.getAckBlockIndex(msg) != -1) {
ackCallback.receiveAck(m_msgFactory.getAckBlockIndex(msg));
}
if (m_msgFactory.isAckEOS(msg)) {
// messages are received before terminating the thread.
if (m_expectedEOFs.decrementAndGet() == 0) {
return;
}
}
}
} catch (Exception e) {
m_lastException = e;
rejoinLog.error("Error reading a message from a recovery stream", e);
} finally {
rejoinLog.trace("Ack receiver thread exiting");
}
}
use of org.voltdb.exceptions.SerializableException in project voltdb by VoltDB.
the class ProcedureRunner method coreCall.
@SuppressWarnings("finally")
private ClientResponseImpl coreCall(Object... paramListIn) {
// verify per-txn state has been reset
assert (m_statusCode == ClientResponse.SUCCESS);
assert (m_statusString == null);
assert (m_appStatusCode == ClientResponse.UNINITIALIZED_APP_STATUS_CODE);
assert (m_appStatusString == null);
assert (m_cachedRNG == null);
// reset batch context info
m_batchIndex = -1;
// reset the beginning big batch undo token
m_spBigBatchBeginToken = -1;
// set procedure name in the site/ee
m_site.setProcedureName(m_procedureName);
// use local var to avoid warnings about reassigning method argument
Object[] paramList = paramListIn;
// reset the hash of results for a new call
if (m_systemProcedureContext != null) {
m_determinismHash.reset(m_systemProcedureContext.getCatalogVersion());
} else {
m_determinismHash.reset(0);
}
ClientResponseImpl retval = null;
// assert no sql is queued
assert (m_batch.size() == 0);
try {
VoltTable[] results = null;
// inject sysproc execution context as the first parameter.
if (isSystemProcedure()) {
final Object[] combinedParams = new Object[paramList.length + 1];
combinedParams[0] = m_systemProcedureContext;
for (int i = 0; i < paramList.length; ++i) {
combinedParams[i + 1] = paramList[i];
}
// swap the lists.
paramList = combinedParams;
}
if (paramList.length != m_paramTypes.length) {
String msg = "PROCEDURE " + m_procedureName + " EXPECTS " + String.valueOf(m_paramTypes.length) + " PARAMS, BUT RECEIVED " + String.valueOf(paramList.length);
m_statusCode = ClientResponse.GRACEFUL_FAILURE;
return getErrorResponse(m_statusCode, m_appStatusCode, m_appStatusString, msg, null);
}
for (int i = 0; i < m_paramTypes.length; i++) {
try {
paramList[i] = ParameterConverter.tryToMakeCompatible(m_paramTypes[i], paramList[i]);
// check the result type in an assert
assert (ParameterConverter.verifyParameterConversion(paramList[i], m_paramTypes[i]));
} catch (Exception e) {
String msg = "PROCEDURE " + m_procedureName + " TYPE ERROR FOR PARAMETER " + i + ": " + e.toString();
m_statusCode = ClientResponse.GRACEFUL_FAILURE;
return getErrorResponse(m_statusCode, m_appStatusCode, m_appStatusString, msg, null);
}
}
// run a regular java class
if (m_hasJava) {
try {
if (HOST_TRACE_ENABLED) {
log.trace("invoking... procMethod=" + m_procMethod.getName() + ", class=" + m_procMethod.getDeclaringClass().getName());
}
try {
Object rawResult = m_procMethod.invoke(m_procedure, paramList);
results = ParameterConverter.getResultsFromRawResults(m_procedureName, rawResult);
} catch (IllegalAccessException e) {
// If reflection fails, invoke the same error handling that other exceptions do
throw new InvocationTargetException(e);
}
log.trace("invoked");
} catch (InvocationTargetException itex) {
//itex.printStackTrace();
Throwable ex = itex.getCause();
if (CoreUtils.isStoredProcThrowableFatalToServer(ex)) {
// the condition as best as it can (usually a crashLocalVoltDB).
try {
m_statsCollector.endProcedure(false, true, m_perCallStats);
} finally {
// Ensure that ex is always re-thrown even if endProcedure throws an exception.
throw (Error) ex;
}
}
retval = getErrorResponse(m_procedureName, m_isReadOnly, getBatchTimeout(), m_appStatusCode, m_appStatusString, getNonVoltDBBackendIfExists(), ex);
}
} else // single statement only work
// (this could be made faster, but with less code re-use)
{
assert (m_catProc.getStatements().size() == 1);
try {
m_cachedSingleStmt.params = getCleanParams(m_cachedSingleStmt.stmt, false, paramList);
if (getNonVoltDBBackendIfExists() != null) {
// Backend handling, such as HSQL or PostgreSQL
VoltTable table = getNonVoltDBBackendIfExists().runSQLWithSubstitutions(m_cachedSingleStmt.stmt, m_cachedSingleStmt.params, m_cachedSingleStmt.stmt.statementParamTypes);
table.convertToHeapBuffer();
results = new VoltTable[] { table };
} else {
m_batch.add(m_cachedSingleStmt);
results = voltExecuteSQL(true);
results = convertTablesToHeapBuffers(results);
}
} catch (SerializableException ex) {
retval = getErrorResponse(m_procedureName, m_isReadOnly, getBatchTimeout(), m_appStatusCode, m_appStatusString, getNonVoltDBBackendIfExists(), ex);
}
}
// don't leave empty handed
if (results == null) {
results = new VoltTable[0];
} else if (results.length > Short.MAX_VALUE) {
String statusString = "Stored procedure returns too much data. Exceeded maximum number of VoltTables: " + Short.MAX_VALUE;
retval = new ClientResponseImpl(ClientResponse.GRACEFUL_FAILURE, ClientResponse.GRACEFUL_FAILURE, statusString, new VoltTable[0], statusString);
}
if (retval == null) {
retval = new ClientResponseImpl(m_statusCode, m_appStatusCode, m_appStatusString, results, m_statusString);
}
// Even when the transaction fails, the computed hashes are valuable for diagnostic purpose,
// so always return the hashes.
int[] hashes = m_determinismHash.get();
retval.setHashes(hashes);
} finally {
// finally at the call(..) scope to ensure params can be
// garbage collected and that the queue will be empty for
// the next call
m_batch.clear();
// reset other per-txn state
m_txnState = null;
m_statusCode = ClientResponse.SUCCESS;
m_statusString = null;
m_appStatusCode = ClientResponse.UNINITIALIZED_APP_STATUS_CODE;
m_appStatusString = null;
m_cachedRNG = null;
m_cachedSingleStmt.params = null;
m_cachedSingleStmt.expectation = null;
m_seenFinalBatch = false;
m_site.setProcedureName(null);
}
return retval;
}
use of org.voltdb.exceptions.SerializableException in project voltdb by VoltDB.
the class ProcedureRunner method getErrorResponse.
/**
*
* @param e
* @return A ClientResponse containing error information
*/
public static ClientResponseImpl getErrorResponse(String procedureName, boolean readOnly, int individualTimeout, byte appStatus, String appStatusString, NonVoltDBBackend nonVoltDBBackend, Throwable eIn) {
// use local var to avoid warnings about reassigning method argument
Throwable e = eIn;
boolean expected_failure = true;
boolean hideStackTrace = false;
StackTraceElement[] stack = e.getStackTrace();
ArrayList<StackTraceElement> matches = new ArrayList<StackTraceElement>();
for (StackTraceElement ste : stack) {
if (isProcedureStackTraceElement(procedureName, ste)) {
matches.add(ste);
}
}
byte status = ClientResponse.UNEXPECTED_FAILURE;
StringBuilder msg = new StringBuilder();
if (e.getClass() == VoltAbortException.class) {
status = ClientResponse.USER_ABORT;
msg.append("USER ABORT\n");
} else if (e.getClass() == org.voltdb.exceptions.ConstraintFailureException.class) {
status = ClientResponse.GRACEFUL_FAILURE;
msg.append("CONSTRAINT VIOLATION\n");
} else if (e.getClass() == org.voltdb.exceptions.SQLException.class) {
status = ClientResponse.GRACEFUL_FAILURE;
msg.append("SQL ERROR\n");
} else // or by a timeout in the middle of executing.
if (e.getClass() == org.voltdb.exceptions.InterruptException.class) {
status = ClientResponse.GRACEFUL_FAILURE;
msg.append("Transaction Interrupted\n");
} else if (e.getClass() == org.voltdb.ExpectedProcedureException.class) {
String backendType = "HSQL";
if (nonVoltDBBackend instanceof PostgreSQLBackend) {
backendType = "PostgreSQL";
}
msg.append(backendType);
msg.append("-BACKEND ERROR\n");
if (e.getCause() != null) {
e = e.getCause();
}
} else if (e.getClass() == org.voltdb.exceptions.TransactionRestartException.class) {
status = ClientResponse.TXN_RESTART;
msg.append("TRANSACTION RESTART\n");
} else // SpecifiedException means the dev wants control over status and message
if (e.getClass() == SpecifiedException.class) {
SpecifiedException se = (SpecifiedException) e;
status = se.getStatus();
expected_failure = true;
hideStackTrace = true;
} else {
msg.append("UNEXPECTED FAILURE:\n");
expected_failure = false;
}
// ensure the message is returned if we're not going to hit the verbose condition below
if (expected_failure || hideStackTrace) {
msg.append(" ").append(e.getMessage());
if (e instanceof org.voltdb.exceptions.InterruptException && readOnly) {
int originalTimeout = VoltDB.instance().getConfig().getQueryTimeout();
if (BatchTimeoutOverrideType.isUserSetTimeout(individualTimeout)) {
msg.append(" query-specific timeout period.");
msg.append(" The query-specific timeout is currently " + individualTimeout / 1000.0 + " seconds.");
} else {
msg.append(" default query timeout period.");
}
if (originalTimeout > 0) {
msg.append(" The default query timeout is currently " + originalTimeout / 1000.0 + " seconds and can be changed in the systemsettings section of the deployment file.");
} else if (originalTimeout == 0) {
msg.append(" The default query timeout is currently set to no timeout and can be changed in the systemsettings section of the deployment file.");
}
}
}
// known and not helpful to the user.
if (!hideStackTrace) {
// Otherwise, generate more output for debuggability
if (expected_failure) {
for (StackTraceElement ste : matches) {
msg.append("\n at ");
msg.append(ste.getClassName()).append(".").append(ste.getMethodName());
msg.append("(").append(ste.getFileName()).append(":");
msg.append(ste.getLineNumber()).append(")");
}
} else {
Writer result = new StringWriter();
PrintWriter pw = new PrintWriter(result);
e.printStackTrace(pw);
msg.append(" ").append(result.toString());
}
}
return getErrorResponse(status, appStatus, appStatusString, msg.toString(), e instanceof SerializableException ? (SerializableException) e : null);
}
use of org.voltdb.exceptions.SerializableException in project voltdb by VoltDB.
the class ProcedureRunnerNT method coreCall.
/**
* Core Synchronous call to NT procedure run(..) method.
* @return ClientResponseImpl non-null if done and null if there is an
* async task still running.
*/
private ClientResponseImpl coreCall(Object... paramListIn) {
VoltTable[] results = null;
// use local var to avoid warnings about reassigning method argument
Object[] paramList = paramListIn;
try {
if ((m_paramTypes.length > 0) && (m_paramTypes[0] == ParameterSet.class)) {
assert (m_paramTypes.length == 1);
paramList = new Object[] { ParameterSet.fromArrayNoCopy(paramListIn) };
}
if (paramList.length != m_paramTypes.length) {
String msg = "PROCEDURE " + m_procedureName + " EXPECTS " + String.valueOf(m_paramTypes.length) + " PARAMS, BUT RECEIVED " + String.valueOf(paramList.length);
m_statusCode = ClientResponse.GRACEFUL_FAILURE;
return ProcedureRunner.getErrorResponse(m_statusCode, m_appStatusCode, m_appStatusString, msg, null);
}
for (int i = 0; i < m_paramTypes.length; i++) {
try {
paramList[i] = ParameterConverter.tryToMakeCompatible(m_paramTypes[i], paramList[i]);
// check the result type in an assert
assert (ParameterConverter.verifyParameterConversion(paramList[i], m_paramTypes[i]));
} catch (Exception e) {
String msg = "PROCEDURE " + m_procedureName + " TYPE ERROR FOR PARAMETER " + i + ": " + e.toString();
m_statusCode = ClientResponse.GRACEFUL_FAILURE;
return ProcedureRunner.getErrorResponse(m_statusCode, m_appStatusCode, m_appStatusString, msg, null);
}
}
try {
m_procedure.m_runner = this;
Object rawResult = m_procMethod.invoke(m_procedure, paramList);
if (rawResult instanceof CompletableFuture<?>) {
final CompletableFuture<?> fut = (CompletableFuture<?>) rawResult;
fut.thenRun(() -> {
//
// Happy path. No exceptions thrown. Procedure work is complete.
//
Object innerRawResult = null;
ClientResponseImpl response = null;
try {
innerRawResult = fut.get();
} catch (InterruptedException | ExecutionException e) {
assert (false);
// this is a bad place to be, but it's hard to know if it's crash bad...
innerRawResult = new ClientResponseImpl(ClientResponseImpl.UNEXPECTED_FAILURE, new VoltTable[0], "Future returned from NTProc " + m_procedureName + " failed to complete.", m_clientHandle);
}
if (innerRawResult instanceof ClientResponseImpl) {
response = (ClientResponseImpl) innerRawResult;
} else {
try {
VoltTable[] r = ParameterConverter.getResultsFromRawResults(m_procedureName, innerRawResult);
response = responseFromTableArray(r);
} catch (Exception e) {
// this is a bad place to be, but it's hard to know if it's crash bad...
response = new ClientResponseImpl(ClientResponseImpl.GRACEFUL_FAILURE, new VoltTable[0], "Type " + innerRawResult.getClass().getName() + " returned from NTProc \"" + m_procedureName + "\" was not an acceptible VoltDB return type.", m_clientHandle);
}
}
completeCall(response);
}).exceptionally(e -> {
SerializableException se = null;
if (e instanceof SerializableException) {
se = (SerializableException) e;
}
String msg = "PROCEDURE " + m_procedureName + " THREW EXCEPTION: ";
if (se != null)
msg += se.getMessage();
else
msg += e.toString();
m_statusCode = ClientResponse.GRACEFUL_FAILURE;
completeCall(ProcedureRunner.getErrorResponse(m_statusCode, m_appStatusCode, m_appStatusString, msg, se));
return null;
});
return null;
}
results = ParameterConverter.getResultsFromRawResults(m_procedureName, rawResult);
} catch (IllegalAccessException e) {
// If reflection fails, invoke the same error handling that other exceptions do
throw new InvocationTargetException(e);
}
} catch (InvocationTargetException itex) {
//itex.printStackTrace();
Throwable ex = itex.getCause();
if (CoreUtils.isStoredProcThrowableFatalToServer(ex)) {
// the condition as best as it can (usually a crashLocalVoltDB).
throw (Error) ex;
}
return ProcedureRunner.getErrorResponse(m_procedureName, true, 0, m_appStatusCode, m_appStatusString, null, ex);
}
return responseFromTableArray(results);
}
Aggregations