RpcCallback<ClientResponseImpl> client_callback) {
final int procId = catalog_proc.getId();
boolean predict_abortable = (hstore_conf.site.exec_no_undo_logging_all == false);
boolean predict_readOnly = this.isReadOnly[procId];
PartitionSet predict_partitions = null;
EstimatorState t_state = null;
// Setup TransactionProfiler
if (hstore_conf.site.txn_profiling) {
this.setupTransactionProfiler(ts, this.isSysProc[procId]);
}
// -------------------------------
// SYSTEM PROCEDURES
// -------------------------------
if (this.isSysProc[procId]) {
// Sysprocs can be either all partitions or single-partitioned
// TODO: It would be nice if the client could pass us a hint when loading the tables
// It would be just for the loading, and not regular transactions
if (catalog_proc.getSinglepartition() && catalog_proc.getEverysite() == false) {
predict_partitions = catalogContext.getPartitionSetSingleton(base_partition);
} else {
predict_partitions = catalogContext.getAllPartitionIds();
}
}
// -------------------------------
// MAPREDUCE TRANSACTIONS
// -------------------------------
else if (this.isMapReduce[procId]) {
// MapReduceTransactions always need all partitions
if (debug.val)
LOG.debug(String.format("New request is for MapReduce %s, so it has to be " +
"multi-partitioned [clientHandle=%d]",
catalog_proc.getName(), ts.getClientHandle()));
predict_partitions = catalogContext.getAllPartitionIds();
}
// -------------------------------
// VOLTDB @PROCINFO
// -------------------------------
else if (hstore_conf.site.exec_voltdb_procinfo) {
if (debug.val)
LOG.debug(String.format("Using the catalog information to determine whether the %s transaction " +
"is single-partitioned [clientHandle=%d, singleP=%s]",
catalog_proc.getName(), ts.getClientHandle(), catalog_proc.getSinglepartition()));
if (catalog_proc.getSinglepartition()) {
predict_partitions = catalogContext.getPartitionSetSingleton(base_partition);
} else {
predict_partitions = catalogContext.getAllPartitionIds();
}
}
// -------------------------------
// FORCE DISTRIBUTED
// -------------------------------
else if (hstore_conf.site.exec_force_allpartitions) {
predict_partitions = catalogContext.getAllPartitionIds();
}
// -------------------------------
// TRANSACTION ESTIMATORS
// -------------------------------
else if (hstore_conf.site.markov_enable || hstore_conf.site.markov_fixed) {
// Grab the TransactionEstimator for the destination partition and figure out whether
// this mofo is likely to be single-partition or not. Anything that we can't estimate
// will just have to be multi-partitioned. This includes sysprocs
TransactionEstimator t_estimator = this.t_estimators[base_partition];
if (t_estimator == null) {
t_estimator = this.hstore_site.getPartitionExecutor(base_partition).getTransactionEstimator();
this.t_estimators[base_partition] = t_estimator;
}
try {
if (hstore_conf.site.txn_profiling && ts.profiler != null) ts.profiler.startInitEstimation();
if (t_estimator != null) {
if (debug.val)
LOG.debug(String.format("%s - Using %s to populate txn properties [clientHandle=%d]",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
t_estimator.getClass().getSimpleName(), client_handle));
t_state = t_estimator.startTransaction(txn_id, base_partition, catalog_proc, params.toArray());
}
// If there is no EstimatorState, then there is nothing we can do
// It has to be executed as multi-partitioned
if (t_state == null) {
if (debug.val) {
LOG.debug(String.format("%s - No %s was returned. Using default estimate.",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
EstimatorState.class.getSimpleName()));
}
}
// We have a EstimatorState handle, so let's see what it says...
else {
if (trace.val)
LOG.trace("\n" + StringBoxUtil.box(t_state.toString()));
Estimate t_estimate = t_state.getInitialEstimate();
// Bah! We didn't get back a Estimation for some reason...
if (t_estimate == null) {
if (debug.val)
LOG.debug(String.format("%s - No %s handle was return. Using default estimate.",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
Estimate.class.getSimpleName()));
}
// Invalid Estimation. Stick with defaults
else if (t_estimate.isValid() == false) {
if (debug.val)
LOG.debug(String.format("%s - %s is marked as invalid. Using default estimate.\n%s",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
t_estimate.getClass().getSimpleName(), t_estimate));
}
// Use Estimation to determine things
else {
if (debug.val) {
LOG.debug(String.format("%s - Using %s to determine if txn is single-partitioned",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
t_estimate.getClass().getSimpleName()));
LOG.trace(String.format("%s %s:\n%s",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
t_estimate.getClass().getSimpleName(), t_estimate));
}
predict_partitions = t_estimate.getTouchedPartitions(this.thresholds);
predict_readOnly = t_estimate.isReadOnlyAllPartitions(this.thresholds);
predict_abortable = (predict_partitions.size() == 1 ||
predict_readOnly == false ||
t_estimate.isAbortable(this.thresholds));
// Check whether the TransactionEstimator *really* thinks that we should
// give it updates about this txn. If the flag is false, then we'll
// check whether the updates are enabled in the HStoreConf parameters
if (t_state.shouldAllowUpdates() == false) {
if (predict_partitions.size() == 1) {
if (hstore_conf.site.markov_singlep_updates == false) t_state.disableUpdates();
}
else if (hstore_conf.site.markov_dtxn_updates == false) {
t_state.disableUpdates();
}
}
if (debug.val && predict_partitions.isEmpty()) {
LOG.warn(String.format("%s - Unexpected empty predicted %s from %s [updatesEnabled=%s]\n%s",
TransactionUtil.formatTxnName(catalog_proc, txn_id),
PartitionSet.class.getSimpleName(),
t_estimator.getClass().getSimpleName(),
t_state.isUpdatesEnabled(), t_estimate));
ts.setAllowEarlyPrepare(false);
// System.err.println("WROTE MARKOVGRAPH: " + ((MarkovEstimatorState)t_state).dumpMarkovGraph());
// System.err.flush();
// HStore.crashDB();
}