package edu.brown.hstore.handlers; import java.nio.ByteBuffer; import org.apache.log4j.Logger; import org.voltdb.VoltTable; import org.voltdb.messaging.FastDeserializer; 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; import edu.brown.hstore.Hstoreservice.HStoreService; import edu.brown.hstore.Hstoreservice.SendDataRequest; import edu.brown.hstore.Hstoreservice.SendDataResponse; import edu.brown.hstore.txns.AbstractTransaction; import edu.brown.hstore.txns.LocalTransaction; import edu.brown.logging.LoggerUtil; import edu.brown.logging.LoggerUtil.LoggerBoolean; import edu.brown.protorpc.ProtoRpcController; import edu.brown.utils.PartitionSet; import edu.brown.utils.StringUtil; public class SendDataHandler extends AbstractTransactionHandler<SendDataRequest, SendDataResponse> { private static final Logger LOG = Logger.getLogger(SendDataHandler.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 SendDataHandler(HStoreSite hstore_site, HStoreCoordinator hstore_coord) { super(hstore_site, hstore_coord); } @Override public void sendLocal(Long txn_id, SendDataRequest request, PartitionSet partitions, RpcCallback<SendDataResponse> callback) { // We should never be called because we never want to have serialize/deserialize data // within our own process assert(false): this.getClass().getSimpleName() + ".sendLocal should never be called!"; } @Override public void sendRemote(HStoreService channel, ProtoRpcController controller, SendDataRequest request, RpcCallback<SendDataResponse> callback) { channel.sendData(controller, request, callback); } @Override public void remoteQueue(RpcController controller, SendDataRequest request, RpcCallback<SendDataResponse> callback) { this.remoteHandler(controller, request, callback); } @Override public void remoteHandler(RpcController controller, SendDataRequest request, RpcCallback<SendDataResponse> callback) { assert(request.hasTransactionId()) : "Got Hstore." + request.getClass().getSimpleName() + " without a txn id!"; long txn_id = request.getTransactionId(); if (debug.val) LOG.debug("__FILE__:__LINE__ " + String.format("Got %s for txn #%d", request.getClass().getSimpleName(), txn_id)); AbstractTransaction ts = hstore_site.getTransaction(txn_id); assert(ts != null) : "Unexpected transaction #" + txn_id; SendDataResponse.Builder builder = SendDataResponse.newBuilder() .setTransactionId(txn_id) .setStatus(Hstoreservice.Status.OK) .setSenderSite(hstore_site.getSiteId()); for (int i = 0, cnt = request.getDataCount(); i < cnt; i++) { int partition = request.getDepId(i); assert(hstore_site.getLocalPartitionIds().contains(partition)); ByteBuffer data = request.getData(i).asReadOnlyByteBuffer(); assert(data != null); // Deserialize the VoltTable object for the given byte array VoltTable vt = null; try { vt = FastDeserializer.deserialize(data, VoltTable.class); } catch (Exception ex) { LOG.warn("Unexpected error when deserializing VoltTable", ex); } assert(vt != null); if (debug.val) { byte bytes[] = request.getData(i).toByteArray(); LOG.debug(String.format("Inbound data for Partition #%d: RowCount=%d / MD5=%s / Length=%d", partition, vt.getRowCount(),StringUtil.md5sum(bytes), bytes.length)); } if (debug.val) LOG.debug(String.format("<StoreTable from Partition %d to Partition:%d>\n %s",hstore_site.getSiteId() ,partition,vt)); Hstoreservice.Status status = ts.storeData(partition, vt); if (status != Hstoreservice.Status.OK) builder.setStatus(status); builder.addPartitions(partition); } // FOR callback.run(builder.build()); } @Override protected ProtoRpcController getProtoRpcController(LocalTransaction ts, int site_id) { return ts.getTransactionWorkController(site_id); } }