LOG.debug(String.format("2PC:FINISH Txn #%d [status=%s, partitions=%s]",
txn_id, status, partitions));
// If we don't have a AbstractTransaction handle, then we know that we never did anything
// for this transaction and we can just ignore this finish request.
AbstractTransaction ts = this.inflight_txns.get(txn_id);
if (ts == null) {
if (debug.val)
LOG.warn(String.format("No transaction information exists for #%d." +
"Ignoring finish request", txn_id));
return;
}
// Set the status in case something goes awry and we just want
// to check whether this transaction is suppose to be aborted.
// XXX: Why is this needed?
ts.setStatus(status);
// We only need to do this for distributed transactions, because all single-partition
// transactions will commit/abort immediately
if (ts.isPredictSinglePartition() == false) {
// PartitionCountingCallback<AbstractTransaction> callback = null;
for (int partition : this.local_partitions.values()) {
if (partitions.contains(partition) == false) continue;
// 2013-01-11
// We can check to see whether the txn was ever released at the partition.
// If it wasn't then we know that we don't need to queue a finish message
// This is to allow the PartitionExecutor to spend more time processing other
// more useful stuff.
// if (ts.isMarkedReleased(partition)) {
if (trace.val)
LOG.trace(String.format("%s - Queuing transaction to get finished on partition %d",
ts, partition));
try {
this.executors[partition].queueFinish(ts, status);
} catch (Throwable ex) {
LOG.error(String.format("Unexpected error when trying to finish %s\nHashCode: %d / Status: %s / Partitions: %s",
ts, ts.hashCode(), status, partitions));
throw new RuntimeException(ex);
}
// }
// else {
// if (callback == null) callback = ts.getFinishCallback();