Arrays.toString(planFragmentIds),
Arrays.toString(parameterSets));
if (batchSize == 0) {
LOG.warn("No fragments to execute. Returning empty DependencySet");
return (new DependencySet(new int[0], HStoreConstants.EMPTY_RESULT));
}
if (this.trackingCache != null) {
this.trackingResetCacheEntry(txnId);
}
// serialize the param sets
fsForParameterSet.clear();
try {
for (int i = 0; i < batchSize; ++i) {
assert(parameterSets[i] != null) :
String.format("Null ParameterSet at offset %d for txn #%d\n" +
"PlanFragments:%s\nParameterSets:%s",
i, txnId,
Arrays.toString(planFragmentIds),
Arrays.toString(parameterSets));
parameterSets[i].writeExternal(fsForParameterSet);
if (trace.val)
LOG.trace(String.format("Batch Executing planfragment:%d, params=%s",
planFragmentIds[i], parameterSets[i]));
}
} catch (final IOException exception) {
throw new RuntimeException(exception); // can't happen
}
// Execute the plan, passing a raw pointer to the byte buffers for input and output
deserializer.clear();
final int errorCode = nativeExecuteQueryPlanFragmentsAndGetResults(this.pointer,
planFragmentIds, batchSize,
input_depIds,
output_depIds,
txnId, lastCommittedTxnId, undoToken);
checkErrorCode(errorCode);
// get a copy of the result buffers and make the tables use the copy
ByteBuffer fullBacking = deserializer.buffer();
try {
// read the complete size of the buffer used
fullBacking.getInt();
// check if anything was changed
m_dirty = (fullBacking.get() == 1 ? true : false);
// get a copy of the buffer
// Because this is a copy, that means we don't have to worry about the EE overwriting us
// Not sure of the implications for performance.
// deserializer.readBuffer(totalSize);
// At this point we don't know how many dependencies we expect to get back from our fragments.
// We're just going to assume that each PlanFragment generated one and only one output dependency
VoltTable results[] = new VoltTable[batchSize];
int dependencies[] = new int[batchSize];
int dep_ctr = 0;
for (int i = 0; i < batchSize; ++i) {
int numDependencies = fullBacking.getInt(); // number of dependencies for this frag
assert(numDependencies == 1) :
"Unexpected multiple output dependencies from PlanFragment #" + planFragmentIds[i];
// PAVLO: Since we can't pass the dependency ids using nativeExecuteQueryPlanFragmentsAndGetResults(),
// the results will come back without a dependency id. So we have to just assume
// that the frags were executed in the order that we passed to the EE and that we
// can just use the list of output_depIds that we have
for (int ii = 0; ii < numDependencies; ++ii) {
assert(dep_ctr < output_depIds.length) :
"Trying to get depId #" + dep_ctr + ": " + Arrays.toString(output_depIds);
fullBacking.getInt(); // IGNORE
int depid = output_depIds[dep_ctr];
assert(depid >= 0);
int tableSize = fullBacking.getInt();
assert(tableSize < 10000000);
byte tableBytes[] = new byte[tableSize];
fullBacking.get(tableBytes, 0, tableSize);
final ByteBuffer tableBacking = ByteBuffer.wrap(tableBytes);
// fullBacking.position(fullBacking.position() + tableSize);
results[dep_ctr] = PrivateVoltTableFactory.createVoltTableFromBuffer(tableBacking, true);
dependencies[dep_ctr] = depid;
if (debug.val) LOG.debug(String.format("%d - New output VoltTable for DependencyId %d [origTableSize=%d]\n%s",
txnId, depid, tableSize, results[dep_ctr].toString()));
dep_ctr++;
} // FOR
} // FOR
return (new DependencySet(dependencies, results));
} catch (Throwable ex) {
LOG.error("Failed to deserialze result table" + ex);
throw new EEException(ERRORCODE_WRONG_SERIALIZED_BYTES);
}
}