Package edu.brown.hstore.handlers

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

package edu.brown.hstore.handlers;

import org.apache.log4j.Logger;
import org.voltdb.CatalogContext;

import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcController;

import edu.brown.hstore.HStoreCoordinator;
import edu.brown.hstore.HStoreSite;
import edu.brown.hstore.HStoreThreadManager;
import edu.brown.hstore.Hstoreservice.HStoreService;
import edu.brown.hstore.conf.HStoreConf;
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;

/**
* AbstractTransactionHandler is a wrapper around the invocation methods for some action
* There is a local and remote method to send a message to the necessary HStoreSites
* for a transaction. The sendMessages() method is the main entry point that the
* HStoreCoordinator's convenience methods will use.
* @param <T> The message that we will send out on the network
* @param <U> The expected message that we will need to get back as a response
*/
public abstract class AbstractTransactionHandler<T extends GeneratedMessage, U extends GeneratedMessage> {
    private static final Logger LOG = Logger.getLogger(AbstractTransactionHandler.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    private static final LoggerBoolean trace = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug, trace);
    }
   
    protected final HStoreSite hstore_site;
    protected final HStoreConf hstore_conf;
    protected final HStoreCoordinator coordinator;
    protected final HStoreService handler;
    protected final CatalogContext catalogContext;
   
    /** The total number of sites in the cluster */
    protected final int num_sites;
   
    /** The site id where this handler is running at */
    protected final int local_site_id;
   
    public AbstractTransactionHandler(HStoreSite hstore_site, HStoreCoordinator hstore_coord) {
        this.hstore_site = hstore_site;
        this.hstore_conf = hstore_site.getHStoreConf();
        this.catalogContext = hstore_site.getCatalogContext();
        this.coordinator = hstore_coord;
        this.handler = this.coordinator.getHandler();
        this.num_sites = this.catalogContext.numberOfSites;
        this.local_site_id = hstore_site.getSiteId();
    }
   
    /**
     * Send a copy of a single message request to the partitions given as input
     * If a partition is managed by the local HStoreSite, then we will invoke
     * the sendLocal() method. If it is on a remote HStoreSite, then we will
     * invoke sendRemote().
     * @param ts
     * @param request
     * @param callback
     * @param partitions
     */
    public void sendMessages(LocalTransaction ts, T request, RpcCallback<U> callback, PartitionSet partitions) {
        // If this flag is true, then we'll invoke the local method
        // We want to do this *after* we send out all the messages to the remote sites
        // so that we don't have to wait as long for the responses to come back over the network
        boolean send_local = false;
        boolean site_sent[] = new boolean[this.num_sites];
       
        if (debug.val)
            LOG.debug(String.format("Sending %s to %d partitions for %s",
                                    request.getClass().getSimpleName(),  partitions.size(), ts));
       
        for (int partition : partitions.values()) {
            int dest_site_id = this.catalogContext.getSiteIdForPartitionId(partition);

            // Skip this HStoreSite if we're already sent it a message
            if (site_sent[dest_site_id]) continue;
           
            if (trace.val)
                LOG.trace(String.format("Sending %s message to %s for %s",
                          request.getClass().getSimpleName(),
                          HStoreThreadManager.formatSiteName(dest_site_id), ts));
           
            // Local Partition
            if (this.local_site_id == dest_site_id) {
                send_local = true;
            }
            // Remote Partition
            else {
                HStoreService channel = this.coordinator.getChannel(dest_site_id);
                assert(channel != null) : "Invalid partition id '" + partition + "'";
                ProtoRpcController controller = this.getProtoRpcController(ts, dest_site_id);
                assert(controller != null) : "Invalid " + request.getClass().getSimpleName() + " ProtoRpcController for site #" + dest_site_id;
                this.sendRemote(channel, controller, request, callback);
            }
            site_sent[dest_site_id] = true;
        } // FOR
        // Optimization: We'll invoke sendLocal() after we have sent out
        // all of the messages to remote sites
        if (send_local) this.sendLocal(ts.getTransactionId(), request, partitions, callback);
    }
   
    /**
     * The processing method that is invoked if the outgoing message needs
     * to be sent to a partition that is on the same machine as where this
     * handler is executing.
     * @param txn_id
     * @param request
     * @param partitions
     * @param callback
     */
    public abstract void sendLocal(Long txn_id, T request, PartitionSet partitions, RpcCallback<U> callback);
   
    /**
     * The processing method that is invoked if the outgoing message needs
     * to be sent to a partition that is *not* managed by the same HStoreSite
     * as where this handler is executing. This is non-blocking and does not
     * wait for the callback to be executed in response to the remote side.
     * @param channel
     * @param controller
     * @param request
     * @param callback
     */
    public abstract void sendRemote(HStoreService channel, ProtoRpcController controller, T request, RpcCallback<U> callback);
   
    /**
     * This is the method that is invoked on the remote HStoreSite for each incoming
     * message request. This will then determine whether the message should be queued up
     * for execution in a different thread, or whether it should invoke remoteHandler()
     * right away.
     * @param controller
     * @param request
     * @param callback
     */
    public abstract void remoteQueue(RpcController controller, T request, RpcCallback<U> callback);
   
    /**
     * The remoteHandler is the code that executes on the remote node to process
     * the request for a transaction that is executing on a different node.
     * @param controller
     * @param request
     * @param callback
     */
    public abstract void remoteHandler(RpcController controller, T request, RpcCallback<U> callback);
   
    /**
     * Return a cached ProtoRpcController handler from the LocalTransaction object
     * @param ts
     * @param site_id
     * @return
     */
    protected abstract ProtoRpcController getProtoRpcController(LocalTransaction ts, int site_id);
}
TOP

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

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.