com.splout.db.dnode.DNode.java Source code

Java tutorial

Introduction

Here is the source code for com.splout.db.dnode.DNode.java

Source

package com.splout.db.dnode;

/*
 * #%L
 * Splout SQL Server
 * %%
 * Copyright (C) 2012 Datasalt Systems S.L.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import com.splout.db.common.SploutConfiguration;
import com.splout.db.thrift.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.TException;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TNonblockingServerTransport;

import java.net.BindException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.Executors;

/**
 * The Thrift skeleton for the DNode service. This class only implements the
 * Thrift logic.
 * <p/>
 * The DNode's own business logic is packed into {@link DNodeHandler} which is
 * an implementation of {@link IDNodeHandler}. In this way, we can use the DNode
 * in unit tests by using Mock implementations of {@link IDNodeHandler}.
 */
public class DNode implements DNodeService.Iface {

    private final static Log log = LogFactory.getLog(DNode.class);

    private IDNodeHandler handler;
    private TServer server;
    private Thread servingThread;
    private SploutConfiguration config;
    private TCPStreamer streamer;

    public DNode(SploutConfiguration config, IDNodeHandler handler) {
        this.handler = handler;
        this.config = config;
    }

    /**
     * Returns the address (host:port) of this DNode.
     */
    public String getAddress() {
        return config.getString(DNodeProperties.HOST) + ":" + config.getInt(DNodeProperties.PORT);
    }

    /**
     * Initialize the DNode service - the important thing here is to instantiate a
     * multi-threaded Thrift server. Everything is based on the given
     * {@link SploutConfiguration} by constructor.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void init() throws Exception {
        DNodeService.Processor processor = new DNodeService.Processor(this);
        TNonblockingServerTransport serverTransport = null;

        boolean init = false;
        int retries = 0;
        int thriftPort;

        do {
            thriftPort = config.getInt(DNodeProperties.PORT);
            try {
                serverTransport = new TNonblockingServerSocket(thriftPort);
                init = true;
            } catch (org.apache.thrift.transport.TTransportException e) {
                if (!config.getBoolean(DNodeProperties.PORT_AUTOINCREMENT)) {
                    throw e;
                }
                config.setProperty(DNodeProperties.PORT, thriftPort + 1);
                retries++;
            }
        } while (!init && retries < 100);

        handler.init(config);

        THsHaServer.Args args = new THsHaServer.Args(serverTransport);
        args.executorService(Executors.newFixedThreadPool(config.getInt(DNodeProperties.SERVING_THREADS)));
        args.processor(processor);

        server = new THsHaServer(args);
        // We instantiate a long-living serving thread that will use the Thrift
        // server.
        servingThread = new Thread("Serving Thread") {
            public void run() {
                try {
                    server.serve();
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }
        };
        servingThread.start();
        log.info("Thrift server started on port: " + thriftPort);

        if (handler instanceof DNodeHandler && !config.getBoolean(DNodeProperties.STREAMING_API_DISABLE)) {
            // Instantiate a TCP server for serving streaming data if not disabled by config
            // Follow also the same incrementing port approach if specified so by config
            init = false;
            retries = 0;
            do {
                streamer = new TCPStreamer();
                int tcpPort = config.getInteger(DNodeProperties.STREAMING_PORT, 8888);
                try {
                    streamer.start(config, (DNodeHandler) handler);
                    log.info("TCP streamer server started on port: " + streamer.getTcpPort());
                    init = true;
                } catch (BindException e) {
                    if (!config.getBoolean(DNodeProperties.PORT_AUTOINCREMENT)) {
                        throw e;
                    }
                    config.setProperty(DNodeProperties.STREAMING_PORT, tcpPort + 1);
                    retries++;
                }
            } while (!init && retries < 100);
        }
        handler.giveGreenLigth();
    }

    // ---- The following methods are a facade for {@link IDNodeHandler} ---- //

    @Override
    public String sqlQuery(String tablespace, long version, int partition, String query)
            throws DNodeException, TException {
        return handler.sqlQuery(tablespace, version, partition, query);
    }

    @Override
    public String deploy(List<DeployAction> deployActions, long version) throws DNodeException, TException {
        return handler.deploy(deployActions, version);
    }

    @Override
    public String rollback(List<RollbackAction> rollbackActions, String distributedBarrier)
            throws DNodeException, TException {
        return handler.rollback(rollbackActions, distributedBarrier);
    }

    @Override
    public String status() throws DNodeException, TException {
        return handler.status();
    }

    @Override
    public String abortDeploy(long version) throws DNodeException, TException {
        return handler.abortDeploy(version);
    }

    @Override
    public String deleteOldVersions(List<TablespaceVersion> versions) throws DNodeException, TException {
        return handler.deleteOldVersions(versions);
    }

    @Override
    public String testCommand(String command) throws DNodeException, TException {
        return handler.testCommand(command);
    }

    @Override
    public ByteBuffer binarySqlQuery(String tablespace, long version, int partition, String query)
            throws DNodeException, TException {
        return handler.binarySqlQuery(tablespace, version, partition, query);
    }

    public void stop() throws Exception {
        if (streamer != null) {
            streamer.stop();
        }
        server.stop();
        handler.stop();
        servingThread.join();
    }

    public static void main(String[] args) throws Exception {
        SploutConfiguration config;
        if (args.length == 1) {
            // config root
            config = SploutConfiguration.get(args[0]);
        } else {
            config = SploutConfiguration.get();
        }
        final DNode dnode = new DNode(config, new DNodeHandler());
        // Add shutdown hook
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                try {
                    log.info("Shutdown hook called - trying to gently stop DNode ...");
                    dnode.stop();
                } catch (Throwable e) {
                    log.error("Error in ShutdownHook", e);
                }
            }
        });
        dnode.init();
    }
}