Package edu.brown.hstore.handlers

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

package edu.brown.hstore.handlers;

import org.apache.log4j.Logger;
import org.voltdb.ParameterSet;
import org.voltdb.VoltTable;
import org.voltdb.exceptions.ServerFaultException;
import org.voltdb.messaging.FastDeserializer;

import com.google.protobuf.ByteString;
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.TransactionWorkRequest;
import edu.brown.hstore.Hstoreservice.TransactionWorkResponse;
import edu.brown.hstore.Hstoreservice.WorkFragment;
import edu.brown.hstore.callbacks.RemoteWorkCallback;
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.CollectionUtil;
import edu.brown.utils.PartitionSet;

public class TransactionWorkHandler extends AbstractTransactionHandler<TransactionWorkRequest, TransactionWorkResponse> {
    private static final Logger LOG = Logger.getLogger(TransactionWorkHandler.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    private static final LoggerBoolean trace = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug, trace);
    }
   
    public TransactionWorkHandler(HStoreSite hstore_site, HStoreCoordinator hstore_coord) {
        super(hstore_site, hstore_coord);
    }
   
    @Override
    public void sendLocal(Long txn_id, TransactionWorkRequest request, PartitionSet partitions, RpcCallback<TransactionWorkResponse> callback) {
        // TODO
    }
    @Override
    public void sendRemote(HStoreService channel, ProtoRpcController controller, TransactionWorkRequest request, RpcCallback<TransactionWorkResponse> callback) {
        channel.transactionWork(controller, request, callback);
    }
    @Override
    public void remoteQueue(RpcController controller, TransactionWorkRequest request,
            RpcCallback<TransactionWorkResponse> callback) {
        if (debug.val)
            LOG.debug(String.format("Executing %s using remote handler for txn #%d",
                      request.getClass().getSimpleName(), request.getTransactionId()));
        this.remoteHandler(controller, request, callback);
    }
    @Override
    public void remoteHandler(RpcController controller, TransactionWorkRequest request,
            RpcCallback<TransactionWorkResponse> 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 [partitionFragments=%d]",
                      request.getClass().getSimpleName(), txn_id, request.getFragmentsCount()));
       
        RemoteTransaction ts = hstore_site.getTransaction(txn_id);
        assert(ts != null);
        assert(txn_id.equals(ts.getTransactionId())) :
            String.format("Mismatched %s - Expected[%d] != Actual[%s]", ts, txn_id, ts.getTransactionId());
       
        // Deserialize embedded ParameterSets and store it in the RemoteTransaction handle
        // This way we only do it once per HStoreSite. This will also force us to avoid having
        // to do it for local work
        ParameterSet parameterSets[] = new ParameterSet[request.getParamsCount()]; // TODO: Cache!
        for (int i = 0; i < parameterSets.length; i++) {
            ByteString paramData = request.getParams(i);
            if (paramData != null && paramData.isEmpty() == false) {
                final FastDeserializer fds = new FastDeserializer(paramData.asReadOnlyByteBuffer());
                if (trace.val)
                    LOG.trace(String.format("Txn #%d paramData[%d] => %s",
                              txn_id, i, fds.buffer()));
                try {
                    parameterSets[i] = fds.readObject(ParameterSet.class);
                } catch (Exception ex) {
                    String msg = String.format("Failed to deserialize ParameterSet[%d] for txn #%d TransactionRequest", i, txn_id);
                    throw new ServerFaultException(msg, ex, txn_id);
                }
                // LOG.info("PARAMETER[" + i + "]: " + parameterSets[i]);
            } else {
                parameterSets[i] = ParameterSet.EMPTY;
            }
        } // FOR
        ts.attachParameterSets(parameterSets);
       
        // Deserialize attached VoltTable input dependencies
        FastDeserializer fds = null;
        VoltTable vt = null;
        for (int i = 0, cnt = request.getAttachedDataCount(); i < cnt; i++) {
            int input_dep_id = request.getAttachedDepId(i);
            ByteString data = request.getAttachedData(i);
            if (data.isEmpty()) {
                String msg = String.format("%s input dependency %d is empty", ts, input_dep_id);
                LOG.warn(msg + "\n" + request);
                throw new ServerFaultException(msg, txn_id);
            }
           
            if (fds == null) fds = new FastDeserializer(data.asReadOnlyByteBuffer());
            else fds.setBuffer(data.asReadOnlyByteBuffer());

            vt = null;
            try {
                vt = fds.readObject(VoltTable.class);
            } catch (Exception ex) {
                String msg = String.format("Failed to deserialize VoltTable[%d] for txn #%d", input_dep_id, txn_id);
                throw new ServerFaultException(msg, ex, txn_id);
            }
            assert(vt != null);
            ts.attachInputDependency(input_dep_id, vt);
        } // FOR
       
        // This is work from a transaction executing at another node
        // Any other message can just be sent along to the ExecutionSite without sending
        // back anything right away. The ExecutionSite will use our wrapped callback handle
        // to send back whatever response it needs to, but we won't actually send it
        // until we get back results from all of the partitions
        // TODO: The base information of a set of FragmentTaskMessages should be moved into
        // the message wrapper (e.g., base partition, client handle)
        boolean first = true;
        int fragmentCount = request.getFragmentsCount();
        PartitionSet partitions = null;
        if (fragmentCount == 1) {
            WorkFragment work = CollectionUtil.first(request.getFragmentsList());
            partitions = this.catalogContext.getPartitionSetSingleton(work.getPartitionId());
        }
        else {
            partitions = new PartitionSet();
            for (WorkFragment work : request.getFragmentsList()) {
                partitions.add(work.getPartitionId());
            } // FOR
        }
       
        for (WorkFragment work : request.getFragmentsList()) {
            // Always initialize the TransactionWorkCallback for the first callback
            if (first) {
                RemoteWorkCallback work_callback = ts.getWorkCallback();
                if (work_callback.isInitialized()) work_callback.finish(); // HACK
                work_callback.init(ts, partitions, callback);
                if (debug.val)
                    LOG.debug(String.format("Initializing %s for %s",
                              work_callback.getClass().getSimpleName(), ts));
            }
           
            if (debug.val)
                LOG.debug(String.format("Invoking transactionWork for %s [first=%s]", ts, first));
            hstore_site.transactionWork(ts, work);
            first = false;
        } // FOR
       
        // We don't need to send back a response right here.
        // TransactionWorkCallback 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
       
    }
    @Override
    protected ProtoRpcController getProtoRpcController(LocalTransaction ts, int site_id) {
        return ts.getTransactionWorkController(site_id);
    }

}
TOP

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

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.