package edu.brown.hstore.callbacks; import java.io.IOException; import org.apache.log4j.Logger; import org.voltdb.ClientResponseImpl; import org.voltdb.messaging.FastSerializer; import com.google.protobuf.ByteString; import com.google.protobuf.RpcCallback; import edu.brown.hstore.HStoreSite; import edu.brown.hstore.HStoreThreadManager; import edu.brown.hstore.Hstoreservice.TransactionRedirectResponse; import edu.brown.logging.LoggerUtil; import edu.brown.logging.LoggerUtil.LoggerBoolean; import edu.brown.pools.Poolable; /** * This callback is used by the receiving HStoreSite during a transaction redirect. * It must be given the TransactionRedirectResponse callback so that we know how * pass the ClientResponse back to the other HStoreSite, which will then send the * results back to the client * @author pavlo */ public class TransactionRedirectResponseCallback implements RpcCallback<ClientResponseImpl>, Poolable { private static final Logger LOG = Logger.getLogger(TransactionRedirectResponseCallback.class); private static final LoggerBoolean debug = new LoggerBoolean(); private static final LoggerBoolean trace = new LoggerBoolean(); static { LoggerUtil.attachObserver(LOG, debug, trace); } private HStoreSite hstore_site; private RpcCallback<TransactionRedirectResponse> orig_callback; /** Our local site id */ private int sourceSiteId = -1; /** The remote site id that we need to send the ClientResponse back to */ private int destSiteId = -1; /** * Default Constructor */ public TransactionRedirectResponseCallback(HStoreSite hstore_site) { this.hstore_site = hstore_site; } public void init(int source_id, int dest_id, RpcCallback<TransactionRedirectResponse> orig_callback) { this.orig_callback = orig_callback; this.sourceSiteId = source_id; this.destSiteId = dest_id; } @Override public boolean isInitialized() { return (this.orig_callback != null); } @Override public void finish() { this.orig_callback = null; this.sourceSiteId = -1; this.destSiteId = -1; } @Override public void run(ClientResponseImpl parameter) { if (debug.val) LOG.debug(String.format("Got ClientResponse callback for txn #%d! Sending back to %s", parameter.getTransactionId(), HStoreThreadManager.formatSiteName(this.destSiteId))); FastSerializer fs = new FastSerializer(); try { parameter.writeExternal(fs); } catch (IOException ex) { throw new RuntimeException(ex); } ByteString bs = ByteString.copyFrom(fs.getBuffer()); TransactionRedirectResponse response = TransactionRedirectResponse.newBuilder() .setSenderSite(this.sourceSiteId) .setOutput(bs) .build(); this.orig_callback.run(response); if (debug.val) LOG.debug(String.format("Sent back ClientResponse for txn #%d to %s [bytes=%d]", parameter.getTransactionId(), HStoreThreadManager.formatSiteName(this.destSiteId), bs.size())); // IMPORTANT: Since we're the only one that knows that we're finished (and actually even // cares), we need to be polite and clean-up after ourselves... // try { // this.finish(); // hstore_site.getObjectPools().CALLBACKS_TXN_REDIRECT_RESPONSE.returnObject(this); // } catch (Exception ex) { // throw new RuntimeException("Funky failure", ex); // } } }