package edu.brown.hstore.estimators;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
import org.voltdb.CatalogContext;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Statement;
import edu.brown.hashing.AbstractHasher;
import edu.brown.hstore.HStoreConstants;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.hstore.conf.HStoreConf;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.utils.PartitionEstimator;
import edu.brown.utils.PartitionSet;
import edu.brown.utils.StringUtil;
/**
* An Estimator is the runtime piece that we use to keep track of where the
* transaction is in its execution workflow. This allows us to make predictions about
* what kind of things we expect the txn to do in the future
* @author pavlo
* @param <S> An EstimationState for the txn
* @param <E> The current Estimation generated for the txn
*/
public abstract class TransactionEstimator {
private static final Logger LOG = Logger.getLogger(TransactionEstimator.class);
private static final LoggerBoolean debug = new LoggerBoolean();
private static final LoggerBoolean trace = new LoggerBoolean();
static {
LoggerUtil.attachObserver(LOG, debug, trace);
}
protected final HStoreConf hstore_conf;
protected final PartitionEstimator p_estimator;
protected final CatalogContext catalogContext;
protected final AbstractHasher hasher;
protected final int num_partitions;
protected final AtomicInteger txn_count = new AtomicInteger(0);
public TransactionEstimator(PartitionEstimator p_estimator) {
this.hstore_conf = HStoreConf.singleton();
this.p_estimator = p_estimator;
this.catalogContext = p_estimator.getCatalogContext();
this.hasher = p_estimator.getHasher();
this.num_partitions = this.catalogContext.numberOfPartitions;
if (debug.val)
LOG.debug("Initialized fixed transaction estimator -> " + this.getClass().getSimpleName());
}
public CatalogContext getCatalogContext() {
return this.catalogContext;
}
public PartitionEstimator getPartitionEstimator() {
return this.p_estimator;
}
/**
* Sets up the beginning of a transaction. Returns an estimate of where this
* transaction will go.
* @param txn_id
* @param catalog_proc
* @param BASE_PARTITION
* @return an estimate for the transaction's future
*/
public final <T extends EstimatorState> T startTransaction(Long txn_id, Procedure catalog_proc, Object args[]) {
int base_partition = HStoreConstants.NULL_PARTITION_ID;
try {
base_partition = this.p_estimator.getBasePartition(catalog_proc, args);
assert(base_partition != HStoreConstants.NULL_PARTITION_ID);
} catch (Throwable ex) {
throw new RuntimeException(String.format("Failed to calculate base partition for <%s, %s>", catalog_proc.getName(), Arrays.toString(args)), ex);
}
return (this.startTransaction(txn_id, base_partition, catalog_proc, args));
}
/**
* Sets up the beginning of a transaction. Returns an estimate of where this
* transaction will go.
* @param txn_id
* @param base_partition
* @param catalog_proc
* @param args
* @return
*/
public final <T extends EstimatorState> T startTransaction(Long txn_id, int base_partition, Procedure catalog_proc, Object args[]) {
if (debug.val) LOG.debug(String.format("Checking %s input parameters: %s",
catalog_proc.getName(),
StringUtil.toString(args, true, true)));
T state = this.startTransactionImpl(txn_id, base_partition, catalog_proc, args);
if (state != null) this.txn_count.incrementAndGet();
return (state);
}
/**
* Implementation for starting a opening up a new transaction in the estimator
* @param txn_id
* @param base_partition
* @param catalog_proc
* @param args
* @return
*/
protected abstract <T extends EstimatorState> T startTransactionImpl(Long txn_id, int base_partition, Procedure catalog_proc, Object args[]);
/**
* Takes a series of queries and executes them in order given the partition
* information. Provides an estimate of where the transaction might go next.
* @param state
* @param catalog_stmts
* @param partitions
* @return
*/
public abstract <T extends Estimate> T executeQueries(EstimatorState state, Statement catalog_stmts[], PartitionSet partitions[]);
/**
* The transaction with provided txn_id is finished
* @param txn_id finished transaction
*/
public void commit(EstimatorState state) {
this.completeTransaction(state, Status.OK);
}
/**
* The transaction with provided txn_id has aborted
* @param txn_id
*/
public void abort(EstimatorState state, Status status) {
this.completeTransaction(state, status);
}
/**
* Mark a transaction as finished execution
* @param txn_id
* @param vtype
*/
protected abstract void completeTransaction(EstimatorState state, Status status);
/**
* Return the EstimatorState and have it destroyed.
* <B>Note:</B> The EstimateState will be invalidated when this method is called.
* @param state
*/
public abstract void destroyEstimatorState(EstimatorState state);
}