org.kaaproject.kaa.server.control.service.ControlServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kaaproject.kaa.server.control.service.ControlServiceImpl.java

Source

/*
 * Copyright 2014 CyberVision, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.kaaproject.kaa.server.control.service;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;
import org.kaaproject.kaa.server.common.thrift.gen.control.ControlThriftService;
import org.kaaproject.kaa.server.control.service.loadmgmt.LoadDistributionService;
import org.kaaproject.kaa.server.control.service.zk.ControlZkService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * The Class ControlServiceImpl.
 */
@Service
public class ControlServiceImpl implements ControlService {

    /** The Constant logger. */
    private static final Logger LOG = LoggerFactory.getLogger(ControlServiceImpl.class);

    /** The thrift host. */
    @Value("#{properties[thrift_host]}")
    private String host;

    /** The thrift port. */
    @Value("#{properties[thrift_port]}")
    private int port;

    /** The Thrift server. */
    private TServer server;

    /** The Thrift server executor service. */
    private ExecutorService executorService;

    /** The control service thrift interface. */
    @Autowired
    private ControlThriftService.Iface controlService;

    /** The control zookeeper service. */
    @Autowired
    private ControlZkService controlZkService;

    /** Dynamic Load Distribution Service */
    @Autowired
    private LoadDistributionService loadMgmtService;
    /** The control service is started. */
    private boolean serviceStarted = false;

    /*
     * (non-Javadoc)
     *
     * @see org.kaaproject.kaa.server.control.service.ControlService#start()
     */
    @Override
    public void start() {
        if (!serviceStarted) {

            final CountDownLatch thriftStartupLatch = new CountDownLatch(1);
            final CountDownLatch thriftShutdownLatch = new CountDownLatch(1);

            startThrift(thriftStartupLatch, thriftShutdownLatch);

            try {
                thriftStartupLatch.await();
            } catch (InterruptedException e) {
                LOG.error("Interrupted while waiting for thrift to start...", e);
            }

            serviceStarted = true;
            controlZkService.start();
            loadMgmtService.setZkService(controlZkService);
            loadMgmtService.start();

            LOG.info("Control Server Started.");

            try {
                thriftShutdownLatch.await();
            } catch (InterruptedException e) {
                LOG.error("Interrupted while waiting for thrift to stop...", e);
            }

        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.kaaproject.kaa.server.control.service.ControlService#stop()
     */
    @Override
    public void stop() {
        if (serviceStarted) {
            serviceStarted = false;
            loadMgmtService.shutdown();
            controlZkService.stop();
            server.stop();
        }
    }

    /**
     * Start thrift.
     *
     * @param thriftShutdownLatch
     * @param thriftStartupLatch
     */
    private void startThrift(final CountDownLatch thriftStartupLatch, final CountDownLatch thriftShutdownLatch) {

        Runnable thriftRunnable = new Runnable() {

            @Override
            public void run() {

                LOG.info("Initializing Thrift Service for Control Server....");
                LOG.info("host: " + host);
                LOG.info("port: " + port);

                try {
                    ControlThriftService.Processor<ControlThriftService.Iface> processor = new ControlThriftService.Processor<ControlThriftService.Iface>(
                            controlService);
                    TServerTransport serverTransport = createServerSocket();
                    server = createServer(serverTransport, processor);

                    LOG.info("Thrift Control Server Started.");

                    thriftStartupLatch.countDown();

                    server.serve();

                    if (executorService != null && !executorService.isTerminated()) {
                        for (TSocketWrapper socket : new ArrayList<>(openedSockets)) {
                            if (socket.getSocket() != null && !socket.getSocket().isClosed()) {
                                socket.close();
                            }
                        }
                        LOG.info("Terminating executor service.");
                        executorService.shutdownNow();
                    }

                    LOG.info("Thrift Control Server Stopped.");

                    thriftShutdownLatch.countDown();

                } catch (TTransportException e) {
                    LOG.error("TTransportException", e);
                } finally {
                    if (thriftStartupLatch.getCount() > 0) {
                        thriftStartupLatch.countDown();
                    }
                    if (thriftShutdownLatch.getCount() > 0) {
                        LOG.info("Thrift Control Server Stopped.");
                        thriftShutdownLatch.countDown();
                    }
                }
            }
        };

        new Thread(thriftRunnable).start();
    }

    /**
     * Creates the server socket.
     *
     * @return the t server transport
     * @throws TTransportException
     *             the t transport exception
     */
    public TServerTransport createServerSocket() throws TTransportException {
        return new TServerSocket(new InetSocketAddress(host, port)) {
            @Override
            protected TSocket acceptImpl() throws TTransportException {
                ServerSocket serverSocket = getServerSocket();
                if (serverSocket == null) {
                    throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket.");
                }
                try {
                    Socket result = serverSocket.accept();
                    TSocketWrapper result2 = new TSocketWrapper(result);
                    result2.setTimeout(0);
                    openedSockets.add(result2);
                    return result2;
                } catch (IOException iox) {
                    throw new TTransportException(iox);
                }
            }
        };
    }

    private final Set<TSocketWrapper> openedSockets = new HashSet<TSocketWrapper>();

    class TSocketWrapper extends TSocket {
        public TSocketWrapper(Socket socket) throws TTransportException {
            super(socket);
        }

        @Override
        public void close() {
            super.close();
            openedSockets.remove(this);
        }
    }

    /**
     * Creates the server.
     *
     * @param serverTransport
     *            the server transport
     * @param processor
     *            the processor
     * @return the t server
     */
    public TServer createServer(TServerTransport serverTransport,
            ControlThriftService.Processor<ControlThriftService.Iface> processor) {
        TThreadPoolServer.Args args = new Args(serverTransport).processor(processor);
        args.stopTimeoutVal = 3;
        args.stopTimeoutUnit = TimeUnit.SECONDS;

        SynchronousQueue<Runnable> executorQueue = // NOSONAR
                new SynchronousQueue<Runnable>();
        executorService = new ThreadPoolExecutor(args.minWorkerThreads, args.maxWorkerThreads, 60, TimeUnit.SECONDS,
                executorQueue);
        args.executorService = executorService;
        return new TThreadPoolServer(args);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.kaaproject.kaa.server.control.service.ControlService#started()
     */
    @Override
    public boolean started() {
        return serviceStarted;
    }
}