// -------------------------------
// Poll Lock Queue
// -------------------------------
LocalTransaction specTxn = null;
InternalMessage work = null;
// Check whether there is something we can speculatively execute right now
if (this.specExecIgnoreCurrent == false && this.lockQueue.approximateIsEmpty() == false) {
// if (trace.val)
// LOG.trace(String.format("Checking %s for something to do at partition %d while %s",
// this.specExecScheduler.getClass().getSimpleName(),
// this.partitionId,
// (this.currentDtxn != null ? "blocked on " + this.currentDtxn : "idle")));
assert(hstore_conf.site.specexec_enable) :
"Trying to schedule speculative txn even though it is disabled";
SpeculationType specType = this.calculateSpeculationType();
if (hstore_conf.site.exec_profiling) this.profiler.conflicts_time.start();
try {
specTxn = this.specExecScheduler.next(this.currentDtxn, specType);
} finally {
if (hstore_conf.site.exec_profiling) this.profiler.conflicts_time.stopIfStarted();
}
// Because we don't have fine-grained undo support, we are just going
// keep all of our speculative execution txn results around
if (specTxn != null) {
// TODO: What we really want to do is check to see whether we have anything
// in our work queue before we go ahead and fire off this txn
if (debug.val) {
if (this.work_queue.isEmpty() == false) {
LOG.warn(String.format("About to speculatively execute %s on partition %d but there " +
"are %d messages in the work queue\n%s",
specTxn, this.partitionId, this.work_queue.size(),
CollectionUtil.first(this.work_queue)));
}
LOG.debug(String.format("Utility Work found speculative txn to execute on " +
"partition %d [%s, specType=%s]",
this.partitionId, specTxn, specType));
// IMPORTANT: We need to make sure that we remove this transaction for the lock queue
// before we execute it so that we don't try to run it again.
// We have to do this now because otherwise we may get the same transaction again
assert(this.lockQueue.contains(specTxn.getTransactionId()) == false) :
String.format("Failed to remove speculative %s before executing", specTxn);
}
assert(specTxn.getBasePartition() == this.partitionId) :
String.format("Trying to speculatively execute %s at partition %d but its base partition is %d\n%s",
specTxn, this.partitionId, specTxn.getBasePartition(), specTxn.debug());
assert(specTxn.isMarkedControlCodeExecuted() == false) :
String.format("Trying to speculatively execute %s at partition %d but was already executed\n%s",
specTxn, this.partitionId, specTxn.getBasePartition(), specTxn.debug());
assert(specTxn.isSpeculative() == false) :
String.format("Trying to speculatively execute %s at partition %d but was already speculative\n%s",
specTxn, this.partitionId, specTxn.getBasePartition(), specTxn.debug());
// It's also important that we cancel this txn's init queue callback, otherwise
// it will never get cleaned up properly. This is necessary in order to support
// sending out client results *before* the dtxn finishes
specTxn.getInitCallback().cancel();
// Ok now that that's out of the way, let's run this baby...
specTxn.setSpeculative(specType);
if (hstore_conf.site.exec_profiling) profiler.specexec_time.start();
try {
this.executeTransaction(specTxn);
} finally {
if (hstore_conf.site.exec_profiling) profiler.specexec_time.stopIfStarted();