/** * Copyright 2013-2015 Seagate Technology LLC. * * This Source Code Form is subject to the terms of the Mozilla * Public License, v. 2.0. If a copy of the MPL was not * distributed with this file, You can obtain one at * https://mozilla.org/MP:/2.0/. * * This program is distributed in the hope that it will be useful, * but is provided AS-IS, WITHOUT ANY WARRANTY; including without * the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or * FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public * License for more details. * * See www.openkinetic.org for more project information */ package com.seagate.kinetic.simulator.io.provider.tcp; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import com.seagate.kinetic.simulator.io.provider.spi.MessageService; import com.seagate.kinetic.simulator.io.provider.spi.TransportProvider; /** * * TCP transport i/o service. * <p> * This instantiates Thread Pooling and network server socket service. * * @author James Hughes * @author chiaming Yang * */ public class TcpTransportProvider implements TransportProvider, Runnable { // my logger private final static Logger logger = Logger.getLogger(TcpTransportProvider.class .getName()); // wait termination time in seconds private static final int WAIT_TERMINATION_TIME = 7; // my master server private MessageService service = null; // server socket listening to client request private ServerSocket serverSocket = null; // thread pool service private ExecutorService pool = null; // I/O service thread (server socket) private Thread myThread = null; // my name private String myName = null; /** * constructor. * * @param simulatorEngine * master server * * @throws IOException * if unable to bind to a service port. */ public TcpTransportProvider() { } /** * init thread pool and server socket. * * @throws IOException * if unable to create a server socket. */ private void doInit() throws IOException { // my thread pool pool = Executors.newCachedThreadPool(new ServiceThreadFactory(service .getServiceConfiguration())); try { // create a new server socket serverSocket = new ServerSocket(service.getServiceConfiguration() .getPort()); // my own thread myThread = new Thread(this); // create my name myName = "IoService" + "-" + this.service.getServiceConfiguration().getPort() + "-main"; // set my thread name so that I can see it. myThread.setName(myName); // start the i/o service myThread.start(); } catch (IOException e) { close(); throw e; } } /** * server socket service */ @Override public void run() { logger.info("starting io service, port=" + this.service.getServiceConfiguration().getPort()); try { for (;;) { // accept socket request Socket socket = serverSocket.accept(); if (socket != null) { // handle socket request pool.execute(new IoHandler(socket, this)); } } } catch (java.net.SocketException e) { logger.log(Level.FINE, e.getMessage(), e); close(); } catch (IOException e) { logger.log(Level.SEVERE, e.getMessage(), e); close(); } finally { ; } } /** * Get thread pool service. * * @return my thread pool service */ public ExecutorService getPool() { return this.pool; } /** * Get master server service. * * @return master server service. */ public MessageService getMessageService() { return this.service; } /** * shutdown thread pool and server socket. */ @Override public void close() { ; } private void shutdownAndAwaitTermination() { pool.shutdown(); // Disable new tasks from being submitted try { // Wait a while for existing tasks to terminate if (!pool.awaitTermination(WAIT_TERMINATION_TIME, TimeUnit.SECONDS)) { pool.shutdownNow(); // Cancel currently executing tasks // Wait a while for tasks to respond to being cancelled if (!pool.awaitTermination(WAIT_TERMINATION_TIME, TimeUnit.SECONDS)) { logger.warning("Pool did not terminate"); } else { logger.info("pool shutdown, my name=" + this.myName); } } } catch (InterruptedException ie) { // (Re-)Cancel if current thread also interrupted pool.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } } /** * Get my name. * * @return my service name. */ public String getName() { return this.myName; } @Override public void init(MessageService messageService) { this.service = messageService; } @Override public void start() throws IOException { this.doInit(); } @Override public void stop() { try { logger.info("shutting down server ..."); shutdownAndAwaitTermination(); serverSocket.close(); logger.info("server shutdown properly, my name=" + this.myName); } catch (IOException e) { logger.log(Level.WARNING, e.getMessage(), e); } } }