package edu.brown.hstore.handlers;
import org.apache.log4j.Logger;
import org.voltdb.utils.EstTime;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcController;
import edu.brown.hstore.HStoreCoordinator;
import edu.brown.hstore.HStoreSite;
import edu.brown.hstore.Hstoreservice.HStoreService;
import edu.brown.hstore.Hstoreservice.TransactionMapRequest;
import edu.brown.hstore.Hstoreservice.TransactionMapResponse;
import edu.brown.hstore.txns.LocalTransaction;
import edu.brown.hstore.txns.MapReduceTransaction;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.protorpc.ProtoRpcController;
import edu.brown.utils.PartitionSet;
public class TransactionMapHandler extends AbstractTransactionHandler<TransactionMapRequest, TransactionMapResponse> {
private static final Logger LOG = Logger.getLogger(TransactionMapHandler.class);
private static final LoggerBoolean debug = new LoggerBoolean();
private static final LoggerBoolean trace = new LoggerBoolean();
static {
LoggerUtil.attachObserver(LOG, debug, trace);
}
//final Dispatcher<Object[]> MapDispatcher;
public TransactionMapHandler(HStoreSite hstore_site, HStoreCoordinator hstore_coord) {
super(hstore_site, hstore_coord);
}
@Override
public void sendLocal(Long txn_id, TransactionMapRequest request, PartitionSet partitions, RpcCallback<TransactionMapResponse> callback) {
// This is for MapReduce Transaction, the local task is still passed to the remoteHandler to be invoked the TransactionStart
// as the a LocalTransaction. This LocalTransaction in this partition is the base partition for MR transaction.
if (debug.val) LOG.debug("Send to remoteHandler from sendLocal");
this.remoteHandler(null, request, callback);
}
@Override
public void sendRemote(HStoreService channel, ProtoRpcController controller, TransactionMapRequest request, RpcCallback<TransactionMapResponse> callback) {
channel.transactionMap(controller, request, callback);
}
@Override
public void remoteQueue(RpcController controller, TransactionMapRequest request,
RpcCallback<TransactionMapResponse> callback) {
this.remoteHandler(controller, request, callback);
}
@Override
public void remoteHandler(RpcController controller,
TransactionMapRequest request,
RpcCallback<TransactionMapResponse> callback) {
assert(request.hasTransactionId()) :
"Got " + request.getClass().getSimpleName() + " without a txn id!";
Long txn_id = Long.valueOf(request.getTransactionId());
if (debug.val)
LOG.debug(String.format("Got %s for txn #%d",
request.getClass().getSimpleName(), txn_id));
// The mr_ts handle will be null if this HStoreSite is not where the
// base partition for the original MRTransaction
MapReduceTransaction mr_ts = hstore_site.getTransaction(txn_id);
if (mr_ts == null) {
mr_ts = hstore_site.getTransactionInitializer()
.createMapReduceTransaction(txn_id,
EstTime.currentTimeMillis(),
request.getClientHandle(),
request.getBasePartition(),
request.getProcedureId(),
request.getParams().asReadOnlyByteBuffer());
}
assert(mr_ts.isMapPhase());
mr_ts.initTransactionMapWrapperCallback(callback);
/*
* Here we would like to start MapReduce Transaction on the remote partition except the base partition of it.
* This is to avoid the double invoke for remote task.
* */
for (int partition : hstore_site.getLocalPartitionIds()) {
if (partition != mr_ts.getBasePartition()) {
LocalTransaction ts = mr_ts.getLocalTransaction(partition);
hstore_site.transactionStart(ts);
}
} // FOR
}
@Override
protected ProtoRpcController getProtoRpcController(LocalTransaction ts, int site_id) {
return ts.getTransactionWorkController(site_id);
}
}