Package edu.brown.hstore.handlers

Source Code of edu.brown.hstore.handlers.TransactionInitHandler

package edu.brown.hstore.handlers;

import org.apache.log4j.Logger;
import org.voltdb.ParameterSet;
import org.voltdb.exceptions.ServerFaultException;
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.HStoreService;
import edu.brown.hstore.Hstoreservice.TransactionInitRequest;
import edu.brown.hstore.Hstoreservice.TransactionInitResponse;
import edu.brown.hstore.Hstoreservice.WorkFragment;
import edu.brown.hstore.callbacks.RemoteInitQueueCallback;
import edu.brown.hstore.dispatchers.AbstractDispatcher;
import edu.brown.hstore.txns.AbstractTransaction;
import edu.brown.hstore.txns.LocalTransaction;
import edu.brown.hstore.txns.RemoteTransaction;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.protorpc.ProtoRpcController;
import edu.brown.utils.PartitionSet;

/**
* Add the given transaction id to this site's queue manager with all of the partitions that
* it needs to lock. This is only for distributed transactions.
* The callback will be invoked once the transaction has acquired all of the locks for the
* partitions provided, or aborted if the transaction is unable to lock those partitions.
* @author pavlo
*/
public class TransactionInitHandler extends AbstractTransactionHandler<TransactionInitRequest, TransactionInitResponse> {
    private static final Logger LOG = Logger.getLogger(TransactionInitHandler.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    private static final LoggerBoolean trace = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug, trace);
    }
   
    private final AbstractDispatcher<Object[]> initDispatcher;
   
    public TransactionInitHandler(HStoreSite hstore_site, HStoreCoordinator hstore_coord, AbstractDispatcher<Object[]> initDispatcher) {
        super(hstore_site, hstore_coord);
        this.initDispatcher = initDispatcher;
    }
   
    @Override
    public void sendLocal(Long txn_id, TransactionInitRequest request, PartitionSet partitions, RpcCallback<TransactionInitResponse> callback) {
        this.remoteQueue(null, request, callback);
    }
    @Override
    public void sendRemote(HStoreService channel, ProtoRpcController controller, TransactionInitRequest request, RpcCallback<TransactionInitResponse> callback) {
        channel.transactionInit(controller, request, callback);
    }
    @Override
    public void remoteQueue(RpcController controller, TransactionInitRequest request,
            RpcCallback<TransactionInitResponse> callback) {
        if (initDispatcher != null) {
            if (debug.val) LOG.debug("Queuing request for txn #" + request.getTransactionId());
            Object o[] = { controller, request, callback };
            initDispatcher.queue(o);
        } else {
            this.remoteHandler(controller, request, callback);
        }
    }
    @Override
    public void remoteHandler(RpcController controller, TransactionInitRequest request, RpcCallback<TransactionInitResponse> callback) {
        assert(request.hasTransactionId()) : "Got " + request.getClass().getSimpleName() + " without a txn id!";
        Long txn_id = request.getTransactionId();
        if (debug.val)
            LOG.debug(String.format("Got %s for txn #%d", request.getClass().getSimpleName(), txn_id));
       
        AbstractTransaction ts = this.hstore_site.getTransaction(txn_id);
        assert(ts == null || ts instanceof LocalTransaction) :
            String.format("Got init request for remote txn #%d but we already have one [%s]",
                          txn_id, ts);

        // This allocation is unnecessary if we're on the same site
        PartitionSet partitions = null;
        if (ts instanceof LocalTransaction) {
            partitions = ((LocalTransaction)ts).getPredictTouchedPartitions();
        } else {
           
            // We first need all of the partitions so that we know
            // what it's actually going to touch
            // The init callback obviously only needs to have the
            // partitions that are local at this site.
            partitions = new PartitionSet(request.getPartitionsList());

            ParameterSet procParams = null;
            if (request.hasProcParams()) {
                FastDeserializer fds = new FastDeserializer(request.getProcParams().asReadOnlyByteBuffer());
                try {
                    procParams = fds.readObject(ParameterSet.class);
                } catch (Exception ex) {
                    String msg = String.format("Failed to deserialize procedure ParameterSet for txn #%d from %s",
                                               txn_id, request.getClass().getSimpleName());
                    throw new ServerFaultException(msg, ex, txn_id);
                }
            }
           
            // If we don't have a handle, we need to make one so that we can stick in the
            // things that we need to keep track of at this site. At this point we know that we're on
            // a remote site from the txn's base partition
            ts = this.hstore_site.getTransactionInitializer()
                                 .createRemoteTransaction(txn_id,
                                                          partitions,
                                                          procParams,
                                                          request.getBasePartition(),
                                                          request.getProcedureId());
           
            // Make sure that we initialize the RemoteTransactionInitCallback too!
            RemoteInitQueueCallback initCallback = ts.getInitCallback();
            initCallback.init((RemoteTransaction)ts, partitions, callback);
        }
       
        // If (request.getPrefetchFragmentsCount() > 0), then we need to
        // make a RemoteTransaction handle for ourselves so that we can keep track of
        // our state when prefetching queries.
        if (request.getPrefetchFragmentsCount() > 0) {
            // Stick the prefetch information into the transaction
            if (debug.val) {
                PartitionSet prefetchPartitions = new PartitionSet();
                for (WorkFragment fragment : request.getPrefetchFragmentsList())
                    prefetchPartitions.add(fragment.getPartitionId());
                LOG.debug(String.format("%s - Attaching %d prefetch %s at partitions %s",
                          ts, request.getPrefetchFragmentsCount(),
                          WorkFragment.class.getSimpleName(), prefetchPartitions));
            }
//            for (int i = 0; i < request.getPrefetchParamsCount(); i++) {
//                LOG.info(String.format("%s - XXX INBOUND PREFETCH RAW [%02d]: %s",
//                         ts, i,
//                         StringUtil.md5sum(request.getPrefetchParams(i).asReadOnlyByteBuffer())));
//            }
           
            ts.initializePrefetch();
            ts.attachPrefetchQueries(request.getPrefetchFragmentsList(),
                                     request.getPrefetchParamsList());
        }

        // We don't need to send back a response right here.
        // The init callback will wait until it has results from all of the partitions
        // the tasks were sent to and then send back everything in a single response message
        this.hstore_site.transactionInit(ts);
    }
    @Override
    protected ProtoRpcController getProtoRpcController(LocalTransaction ts, int site_id) {
        return ts.getTransactionInitController(site_id);
    }
}
TOP

Related Classes of edu.brown.hstore.handlers.TransactionInitHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.