package edu.brown.hstore.callbacks;
import org.apache.log4j.Logger;
import com.google.protobuf.RpcCallback;
import edu.brown.hstore.HStoreSite;
import edu.brown.hstore.Hstoreservice;
import edu.brown.hstore.Hstoreservice.SendDataResponse;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.hstore.Hstoreservice.TransactionInitResponse;
import edu.brown.hstore.txns.MapReduceTransaction;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
/**
* This is callback is used on the remote side of a TransactionMapRequest
* so that the network-outbound callback is not invoked until all of the partitions
* at this HStoreSite is finished with the Map phase.
* @author pavlo
*/
public class SendDataWrapperCallback extends BlockingRpcCallback<SendDataResponse, Integer> {
private static final Logger LOG = Logger.getLogger(SendDataWrapperCallback.class);
private static final LoggerBoolean debug = new LoggerBoolean();
private static final LoggerBoolean trace = new LoggerBoolean();
static {
LoggerUtil.attachObserver(LOG, debug, trace);
}
private SendDataResponse.Builder builder = null;
private MapReduceTransaction ts = null;
public SendDataResponse.Builder getBuilder() {
return builder;
}
public SendDataWrapperCallback(HStoreSite hstore_site) {
super(hstore_site, false);
}
public void init(MapReduceTransaction ts, RpcCallback<SendDataResponse> orig_callback) {
assert(this.isInitialized() == false) :
String.format("Trying to initialize %s twice! [origTs=%s, newTs=%s]",
this.getClass().getSimpleName(), this.ts, ts);
if (debug.val)
LOG.debug("Starting new " + this.getClass().getSimpleName() + " for " + ts);
this.ts = ts;
this.builder = SendDataResponse.newBuilder()
.setTransactionId(ts.getTransactionId().longValue())
.setStatus(Hstoreservice.Status.OK);
super.init(ts.getTransactionId(), hstore_site.getLocalPartitionIds().size(), orig_callback);
}
@Override
protected void abortCallback(Status status) {
if (debug.val)
LOG.debug(String.format("Txn #%d - Aborting %s with status %s",
this.getTransactionId(), this.getClass().getSimpleName(), status));
this.builder.setStatus(status);
this.unblockCallback();
}
@Override
protected void finishImpl() {
this.builder = null;
this.ts = null;
}
@Override
public boolean isInitialized() {
return ( this.ts != null && this.builder != null && super.isInitialized());
}
@Override
protected synchronized int runImpl(Integer partition) {
assert(this.ts != null) :
String.format("Missing MapReduceTransaction handle for txn #%d", this.ts.getTransactionId());
return 1;
}
@Override
protected void unblockCallback() {
if (debug.val) {
LOG.debug(String.format("Txn #%d - Sending %s to %s with status %s",
this.getTransactionId(),
TransactionInitResponse.class.getSimpleName(),
this.getOrigCallback().getClass().getSimpleName(),
this.builder.getStatus()));
}
assert(this.getOrigCallback() != null) :
String.format("The original callback for txn #%d is null!", this.getTransactionId());
this.getOrigCallback().run(this.builder.build());
}
}