use of org.voltdb.exceptions.SpecifiedException 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.SpecifiedException 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.SpecifiedException in project voltdb by VoltDB.
the class UpdateCore method checkForNonEmptyTables.
/**
* Use EE stats to get the row counts for all tables in this partition.
* Check the provided list of tables that need to be empty against actual
* row counts. If any of them aren't empty, stop the catalog update and
* return the pre-provided error message that corresponds to the non-empty
* tables.
*
* Each of the tablesThatMustBeEmpty strings represents a set of tables.
* This is is a sequence of names separated by plus signs (+). For example,
* "A+B+C" is the set {A, B, C}, and "A" is the singleton set {A}. In
* these sets, only one needs to be empty.
*
* @param tablesThatMustBeEmpty List of sets of table names that must include
* an empty table.
* @param reasonsForEmptyTables Error messages to return if that table isn't
* empty.
* @param context
*/
protected void checkForNonEmptyTables(String[] tablesThatMustBeEmpty, String[] reasonsForEmptyTables, SystemProcedureExecutionContext context) {
assert (tablesThatMustBeEmpty != null);
// no work to do if no tables need to be empty
if (tablesThatMustBeEmpty.length == 0) {
return;
}
assert (reasonsForEmptyTables != null);
assert (reasonsForEmptyTables.length == tablesThatMustBeEmpty.length);
// fetch the id of the tables that must be empty from the
// current catalog (not the new one).
CatalogMap<Table> tables = context.getDatabase().getTables();
List<List<String>> allTableSets = decodeTables(tablesThatMustBeEmpty);
Map<String, Boolean> allTables = collapseSets(allTableSets);
int[] tableIds = new int[allTables.size()];
int i = 0;
for (String tableName : allTables.keySet()) {
Table table = tables.get(tableName);
if (table == null) {
String msg = String.format("@UpdateCore was checking to see if table %s was empty, " + "presumably as part of a schema change, and it failed to find the table " + "in the current catalog context.", tableName);
throw new SpecifiedException(ClientResponse.UNEXPECTED_FAILURE, msg);
}
tableIds[i++] = table.getRelativeIndex();
}
// get the table stats for these tables from the EE
final VoltTable[] s1 = context.getSiteProcedureConnection().getStats(StatsSelector.TABLE, tableIds, false, getTransactionTime().getTime());
if ((s1 == null) || (s1.length == 0)) {
String tableNames = StringUtils.join(tablesThatMustBeEmpty, ", ");
String msg = String.format("@UpdateCore was checking to see if tables (%s) were empty ," + "presumably as part of a schema change, but failed to get the row counts " + "from the native storage engine.", tableNames);
throw new SpecifiedException(ClientResponse.UNEXPECTED_FAILURE, msg);
}
VoltTable stats = s1[0];
// find all empty tables and mark that they are empty.
while (stats.advanceRow()) {
long tupleCount = stats.getLong("TUPLE_COUNT");
String tableName = stats.getString("TABLE_NAME");
boolean isEmpty = true;
if (tupleCount > 0 && !"StreamedTable".equals(stats.getString("TABLE_TYPE"))) {
isEmpty = false;
}
allTables.put(tableName.toUpperCase(), isEmpty);
}
// Reexamine the sets of sets and see if any of them has
// one empty element. If not, then add the respective
// error message to the output message
String msg = "Unable to make requested schema change:\n";
boolean allOk = true;
for (int idx = 0; idx < allTableSets.size(); idx += 1) {
List<String> tableNames = allTableSets.get(idx);
boolean allNonEmpty = true;
for (String tableName : tableNames) {
Boolean oneEmpty = allTables.get(tableName);
if (oneEmpty != null && oneEmpty) {
allNonEmpty = false;
break;
}
}
if (allNonEmpty) {
String errMsg = reasonsForEmptyTables[idx];
msg += errMsg + "\n";
allOk = false;
}
}
if (!allOk) {
throw new SpecifiedException(ClientResponse.GRACEFUL_FAILURE, msg);
}
}
Aggregations