Long txn_id = Long.valueOf(request.getTransactionId());
if (debug.val)
LOG.debug(String.format("Got %s for txn #%d [partitionFragments=%d]",
request.getClass().getSimpleName(), txn_id, request.getFragmentsCount()));
RemoteTransaction ts = hstore_site.getTransaction(txn_id);
assert(ts != null);
assert(txn_id.equals(ts.getTransactionId())) :
String.format("Mismatched %s - Expected[%d] != Actual[%s]", ts, txn_id, ts.getTransactionId());
// Deserialize embedded ParameterSets and store it in the RemoteTransaction handle
// This way we only do it once per HStoreSite. This will also force us to avoid having
// to do it for local work
ParameterSet parameterSets[] = new ParameterSet[request.getParamsCount()]; // TODO: Cache!
for (int i = 0; i < parameterSets.length; i++) {
ByteString paramData = request.getParams(i);
if (paramData != null && paramData.isEmpty() == false) {
final FastDeserializer fds = new FastDeserializer(paramData.asReadOnlyByteBuffer());
if (trace.val)
LOG.trace(String.format("Txn #%d paramData[%d] => %s",
txn_id, i, fds.buffer()));
try {
parameterSets[i] = fds.readObject(ParameterSet.class);
} catch (Exception ex) {
String msg = String.format("Failed to deserialize ParameterSet[%d] for txn #%d TransactionRequest", i, txn_id);
throw new ServerFaultException(msg, ex, txn_id);
}
// LOG.info("PARAMETER[" + i + "]: " + parameterSets[i]);
} else {
parameterSets[i] = ParameterSet.EMPTY;
}
} // FOR
ts.attachParameterSets(parameterSets);
// Deserialize attached VoltTable input dependencies
FastDeserializer fds = null;
VoltTable vt = null;
for (int i = 0, cnt = request.getAttachedDataCount(); i < cnt; i++) {
int input_dep_id = request.getAttachedDepId(i);
ByteString data = request.getAttachedData(i);
if (data.isEmpty()) {
String msg = String.format("%s input dependency %d is empty", ts, input_dep_id);
LOG.warn(msg + "\n" + request);
throw new ServerFaultException(msg, txn_id);
}
if (fds == null) fds = new FastDeserializer(data.asReadOnlyByteBuffer());
else fds.setBuffer(data.asReadOnlyByteBuffer());
vt = null;
try {
vt = fds.readObject(VoltTable.class);
} catch (Exception ex) {
String msg = String.format("Failed to deserialize VoltTable[%d] for txn #%d", input_dep_id, txn_id);
throw new ServerFaultException(msg, ex, txn_id);
}
assert(vt != null);
ts.attachInputDependency(input_dep_id, vt);
} // FOR
// This is work from a transaction executing at another node
// Any other message can just be sent along to the ExecutionSite without sending
// back anything right away. The ExecutionSite will use our wrapped callback handle
// to send back whatever response it needs to, but we won't actually send it
// until we get back results from all of the partitions
// TODO: The base information of a set of FragmentTaskMessages should be moved into
// the message wrapper (e.g., base partition, client handle)
boolean first = true;
int fragmentCount = request.getFragmentsCount();
PartitionSet partitions = null;
if (fragmentCount == 1) {
WorkFragment work = CollectionUtil.first(request.getFragmentsList());
partitions = this.catalogContext.getPartitionSetSingleton(work.getPartitionId());
}
else {
partitions = new PartitionSet();
for (WorkFragment work : request.getFragmentsList()) {
partitions.add(work.getPartitionId());
} // FOR
}
for (WorkFragment work : request.getFragmentsList()) {
// Always initialize the TransactionWorkCallback for the first callback
if (first) {
RemoteWorkCallback work_callback = ts.getWorkCallback();
if (work_callback.isInitialized()) work_callback.finish(); // HACK
work_callback.init(ts, partitions, callback);
if (debug.val)
LOG.debug(String.format("Initializing %s for %s",
work_callback.getClass().getSimpleName(), ts));