org.xsocket.connection.Server Maven / Gradle / Ivy
/*
* Copyright (c) xlightweb.org, 2006 - 2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
* The latest copy of this software may be found on http://www.xsocket.org/
*/
package org.xsocket.connection;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import org.xsocket.DataConverter;
import org.xsocket.WorkerPool;
import org.xsocket.connection.IConnection.FlushMode;
/**
* Implementation of a server. For more information see
* {@link IServer}
*
* @author [email protected]
*/
public class Server implements IServer {
private static final Logger LOG = Logger.getLogger(Server.class.getName());
private static String implementationVersion = ConnectionUtils.getImplementationVersion();
private static String implementationDate;
protected static final int SIZE_WORKER_POOL = Integer.parseInt(System.getProperty("org.xsocket.connection.server.workerpoolSize", "100"));
protected static final int MIN_SIZE_WORKER_POOL = Integer.parseInt(System.getProperty("org.xsocket.connection.server.workerpoolMinSize", "0"));
protected static final int TASK_QUEUE_SIZE = Integer.parseInt(System.getProperty("org.xsocket.connection.server.taskqueuesize", Integer.toString(SIZE_WORKER_POOL)));
private FlushMode flushMode = IConnection.DEFAULT_FLUSH_MODE;
private boolean autoflush = IConnection.DEFAULT_AUTOFLUSH;
private Integer writeRate;
// is open flag
private final AtomicBoolean isOpen = new AtomicBoolean(false);
// name
private String name = "server";
// acceptor
private IoAcceptor acceptor;
// workerpool
private ExecutorService defaultWorkerPool;
private Executor workerpool;
//connection manager
private ConnectionManager connectionManager = new ConnectionManager();
private int maxConcurrentConnections = Integer.MAX_VALUE;
private boolean isMaxConnectionCheckAvtive = false;
// handler replace Listener
private final AtomicReference handlerReplaceListenerRef = new AtomicReference();
// app handler
private HandlerAdapter handlerAdapter = HandlerAdapter.newInstance(null);
// thresholds
private Integer maxReadBufferThreshold = null;
// timeouts
private long idleTimeoutMillis = IConnection.MAX_TIMEOUT_MILLIS;
private long connectionTimeoutMillis = IConnection.MAX_TIMEOUT_MILLIS;
// server listeners
private final ArrayList listeners = new ArrayList();
// local address
private String localHostname = "";
private int localPort = -1;
// start up message
private String startUpLogMessage = "xSocket " + implementationVersion;
// startup date
private long startUpTime = 0;
/**
* constructor
*
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws IOException If some other I/O error occurs
* @throws UnknownHostException if the local host cannot determined
*/
public Server(IHandler handler) throws UnknownHostException, IOException {
this(new InetSocketAddress(0), new HashMap(), handler, null, false, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws IOException If some other I/O error occurs
* @throws UnknownHostException if the local host cannot determined
*/
public Server(Map options, IHandler handler) throws UnknownHostException, IOException {
this(new InetSocketAddress(0), options, handler, null, false, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
*
* @param port the local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port, IHandler handler) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), new HashMap(), handler, null, false, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
*
* @param port the local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param minPoolsize the min workerpool size
* @param maxPoolsize the max workerpool size
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port, IHandler handler, int minPoolsize, int maxPoolsize) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), new HashMap(), handler, null, false, 0, minPoolsize, maxPoolsize, maxPoolsize);
}
/**
* constructor
*
*
* @param port the local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port, IHandler handler, int backlog) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), new HashMap(), handler, null, false, backlog, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param port the local port
* @param options the acceptor socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port, Map options, IHandler handler) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), options, handler, null, false, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param address the local address
* @param port the local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(InetAddress address, int port, IHandler handler) throws UnknownHostException, IOException {
this(address, port, new HashMap(), handler, null, false,0);
}
/**
* constructor
*
* @param ipAddress the local ip address
* @param port the local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(String ipAddress, int port, IHandler handler) throws UnknownHostException, IOException {
this(new InetSocketAddress(ipAddress, port), new HashMap(), handler, null, false, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
*
* @param ipAddress the local ip address
* @param port the local port
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(String ipAddress, int port, Map options, IHandler handler) throws UnknownHostException, IOException {
this(new InetSocketAddress(ipAddress, port), options, handler, null, false, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param port local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port, IHandler handler, SSLContext sslContext, boolean sslOn) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), new HashMap(), handler, sslContext, sslOn, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param port local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @param minPoolsize the min workerpool size
* @param maxPoolsize the max workerpool size
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port, IHandler handler, SSLContext sslContext, boolean sslOn, int minPoolsize, int maxPoolsize) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), new HashMap(), handler, sslContext, sslOn, 0, minPoolsize, maxPoolsize, maxPoolsize);
}
/**
* constructor
*
* @param port local port
* @param options the acceptor socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(int port,Map options, IHandler handler, SSLContext sslContext, boolean sslOn) throws UnknownHostException, IOException {
this(new InetSocketAddress(port), options, handler, sslContext, sslOn, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param ipAddress local ip address
* @param port local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(String ipAddress, int port, IHandler handler, SSLContext sslContext, boolean sslOn) throws UnknownHostException, IOException {
this(new InetSocketAddress(ipAddress, port), new HashMap(), handler, sslContext, sslOn, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param ipAddress local ip address
* @param port local port
* @param options the acceptor socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(String ipAddress, int port, Map options, IHandler handler, SSLContext sslContext, boolean sslOn) throws UnknownHostException, IOException {
this(new InetSocketAddress(ipAddress, port), options, handler, sslContext, sslOn, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param address local address
* @param port local port
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(InetAddress address, int port, IHandler handler, SSLContext sslContext, boolean sslOn) throws UnknownHostException, IOException {
this(new InetSocketAddress(address, port), new HashMap(), handler, sslContext, sslOn, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param address local address
* @param port local port
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(InetAddress address, int port, Map options, IHandler handler, SSLContext sslContext, boolean sslOn) throws UnknownHostException, IOException {
this(new InetSocketAddress(address, port), options, handler, sslContext, sslOn, 0, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param address local address
* @param port local port
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(InetAddress address, int port, Map options, IHandler handler, SSLContext sslContext, boolean sslOn, int backlog) throws UnknownHostException, IOException {
this(new InetSocketAddress(address, port), options, handler, sslContext, sslOn, backlog, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param address local address
* @param port local port
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
* @param minPoolsize The min workerpool size
* @param maxPoolsize The max workerpool size
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
public Server(InetAddress address, int port, Map options, IHandler handler, SSLContext sslContext, boolean sslOn, int backlog, int minPoolsize, int maxPoolsize) throws UnknownHostException, IOException {
this(new InetSocketAddress(address, port), options, handler, sslContext, sslOn, backlog, minPoolsize, maxPoolsize, maxPoolsize);
}
/**
* constructor
*
* @param address local address
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
protected Server(InetSocketAddress address, Map options, IHandler handler, SSLContext sslContext, boolean sslOn, int backlog) throws UnknownHostException, IOException {
this(address, options, handler, sslContext, sslOn, backlog, MIN_SIZE_WORKER_POOL, SIZE_WORKER_POOL, TASK_QUEUE_SIZE);
}
/**
* constructor
*
* @param address local address
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
* @param minPoolsize The min workerpool size
* @param maxPoolsize The max workerpool size
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
protected Server(InetSocketAddress address, Map options, IHandler handler, SSLContext sslContext, boolean sslOn, int backlog, int minPoolsize, int maxPoolsize) throws UnknownHostException, IOException {
this(address, options, handler, sslContext, sslOn, backlog, minPoolsize, maxPoolsize, maxPoolsize);
}
/**
* constructor
*
* @param address local address
* @param options the socket options
* @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
* @param sslOn true, is SSL should be activated
* @param sslContext the ssl context to use
* @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
* @param minPoolsize The min workerpool size
* @param maxPoolsize The max workerpool size
* @param taskqueueSize The taskqueue size
* @throws UnknownHostException if the local host cannot determined
* @throws IOException If some other I/O error occurs
*/
protected Server(InetSocketAddress address, Map options, IHandler handler, SSLContext sslContext, boolean sslOn, int backlog, int minPoolsize, int maxPoolsize, int taskqueueSize) throws UnknownHostException, IOException {
defaultWorkerPool = new WorkerPool(minPoolsize, maxPoolsize, taskqueueSize);
workerpool = defaultWorkerPool;
if (sslContext != null) {
acceptor = ConnectionUtils.getIoProvider().createAcceptor(new LifeCycleHandler(), address, backlog, options, sslContext, sslOn);
} else {
acceptor = ConnectionUtils.getIoProvider().createAcceptor(new LifeCycleHandler(), address, backlog, options);
}
localHostname = acceptor.getLocalAddress().getHostName();
localPort = acceptor.getLocalPort();
setHandler(handler);
}
/**
* set the handler
* @param handler the handler
*/
public void setHandler(IHandler handler) {
if (isOpen.get()) {
callCurrentHandlerOnDestroy();
}
IHandlerChangeListener changeListener = handlerReplaceListenerRef.get();
if (changeListener != null) {
IHandler oldHandler = handlerAdapter.getHandler();
changeListener.onHanderReplaced(oldHandler, handler);
}
handlerAdapter = HandlerAdapter.newInstance(handler);
// init app handler
initCurrentHandler();
}
private void initCurrentHandler() {
ConnectionUtils.injectServerField(this, handlerAdapter.getHandler());
handlerAdapter.onInit();
}
private void callCurrentHandlerOnDestroy() {
handlerAdapter.onDestroy();
}
/**
* the the server name. The server name will be used to print out the start log message.
*
* E.g.
*
* IServer cacheServer = new Server(port, new CacheHandler());
* ConnectionUtils.start(server);
* server.setServerName("CacheServer");
*
*
* // prints out
* // 01::52::42,756 10 INFO [Server$AcceptorCallback#onConnected] CacheServer listening on 172.25.34.33/172.25.34.33:9921 (xSocket 2.0)
*
*
* @param name the server name
*/
public final void setServerName(String name) {
this.name = name;
}
/**
* return the server name
*
* @return the server name
*/
public final String getServerName() {
return name;
}
/**
* {@inheritDoc}
*/
public String getStartUpLogMessage() {
return startUpLogMessage;
}
/**
* {@inheritDoc}
*/
public void setStartUpLogMessage(String message) {
this.startUpLogMessage = message;
}
/**
* {@inheritDoc}
*/
public void run() {
try {
if (getHandler() == null) {
LOG.warning("no handler has been set. Call setHandler-method to assign a handler");
}
startUpTime = System.currentTimeMillis();
ShutdownHookHandler shutdownHookHandler = new ShutdownHookHandler(this);
try {
// register shutdown hook handler
shutdownHookHandler.register();
// listening in a blocking way
acceptor.listen();
} finally {
// deregister shutdown hook handler
shutdownHookHandler.deregister();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static final class ShutdownHookHandler extends Thread {
private Runtime runtime;
private Server server;
public ShutdownHookHandler(Server server) {
this.server = server;
}
void register() {
runtime = Runtime.getRuntime();
runtime.addShutdownHook(this);
}
public void run() {
if (server != null) {
server.close();
}
}
void deregister() {
if (runtime != null) {
try {
runtime.removeShutdownHook(this);
} catch (Exception e) {
// eat and log exception
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("error occured by derigistering shutdwon hook " + e.toString());
}
}
runtime = null;
server = null;
}
}
}
/**
* starts the given server within a dedicated thread. This method blocks
* until the server is open. This method is equals to {@link ConnectionUtils#start(IServer)}
*
* @throws SocketTimeoutException is the timeout has been reached
*/
public void start() throws IOException {
ConnectionUtils.start(this);
}
/**
* {@inheritDoc}
*/
public final Object getOption(String name) throws IOException {
return acceptor.getOption(name);
}
public IHandler getHandler() {
return handlerAdapter.getHandler();
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public final Map getOptions() {
return acceptor.getOptions();
}
/**
* {@inheritDoc}
*/
public final void close() {
// is open?
if (isOpen.getAndSet(false)) {
// close connection manager
try {
connectionManager.close();
} catch (Throwable e) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("error occured by closing acceptor " + DataConverter.toString(e));
}
}
connectionManager = null;
// closing acceptor
try {
acceptor.close(); // closing of dispatcher will be initiated by acceptor
} catch (Throwable e) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("error occured by closing acceptor " + DataConverter.toString(e));
}
}
acceptor = null;
// notify listeners
try {
onClosed();
} catch (Throwable e) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("error occured by performing onClosed method " + DataConverter.toString(e));
}
}
// unset references
handlerAdapter = null;
}
}
protected void onClosed() throws IOException {
}
final IoAcceptor getAcceptor() {
return acceptor;
}
final long getConnectionManagerWatchDogPeriodMillis() {
return connectionManager.getWatchDogPeriodMillis();
}
final int getConnectionManagerWatchDogRuns() {
return connectionManager.getWatchDogRuns();
}
/**
* {@inheritDoc}
*/
public final void addListener(IServerListener listener) {
listeners.add(listener);
}
/**
* {@inheritDoc}
*/
public final boolean removeListener(IServerListener listener) {
boolean result = listeners.remove(listener);
return result;
}
/**
* {@inheritDoc}
*/
public final Executor getWorkerpool() {
return workerpool;
}
/**
* {@inheritDoc}
*/
public final void setWorkerpool(Executor executor) {
if (executor == null) {
throw new NullPointerException("executor has to be set");
}
if (isOpen.get()) {
LOG.warning("server is already running");
}
workerpool = executor;
if (defaultWorkerPool != null) {
defaultWorkerPool.shutdown();
defaultWorkerPool = null;
}
}
/**
* {@inheritDoc}
*/
public final boolean isOpen() {
return isOpen.get();
}
/**
* sets the max number of concurrent connections
*
* @param maxConcurrentConnections the max number of concurrent connections
*/
public final void setMaxConcurrentConnections(int maxConcurrentConnections) {
this.maxConcurrentConnections = maxConcurrentConnections;
if (maxConcurrentConnections == Integer.MAX_VALUE) {
isMaxConnectionCheckAvtive = false;
} else {
isMaxConnectionCheckAvtive = true;
}
}
/**
* set the max app read buffer threshold
*
* @param maxSize the max read buffer threshold
*/
public void setMaxReadBufferThreshold(int maxSize) {
this.maxReadBufferThreshold = maxSize;
}
/**
* returns the number of max concurrent connections
* @return the number of max concurrent connections
*/
int getMaxConcurrentConnections() {
return maxConcurrentConnections;
}
/**
* {@inheritDoc}
*/
public final int getLocalPort() {
return acceptor.getLocalPort();
}
/**
* {@inheritDoc}
*/
public final InetAddress getLocalAddress() {
return acceptor.getLocalAddress();
}
final int getNumberOfOpenConnections() {
return connectionManager.getSize();
}
final int getDispatcherPoolSize() {
return acceptor.getDispatcherSize();
}
final void setDispatcherPoolSize(int size) {
acceptor.setDispatcherSize(size);
}
final boolean getReceiveBufferIsDirect() {
return acceptor.getReceiveBufferIsDirect();
}
final void setReceiveBufferIsDirect(boolean isDirect) {
acceptor.setReceiveBufferIsDirect(isDirect);
}
final Integer getReceiveBufferPreallocatedMinSize() {
if (acceptor.isReceiveBufferPreallocationMode()) {
return acceptor.getReceiveBufferPreallocatedMinSize();
} else {
return null;
}
}
public Set getOpenConnections() {
HashSet cons = new HashSet();
if (connectionManager != null) {
for (INonBlockingConnection con: connectionManager.getConnections()) {
if (con.isOpen()) {
cons.add(con);
}
}
}
return cons;
}
final List getOpenConnectionInfos() {
List infos = new ArrayList();
for (NonBlockingConnection con : connectionManager.getConnections()) {
infos.add(con.toDetailedString());
}
return infos;
}
final int getNumberOfIdleTimeouts() {
return connectionManager.getNumberOfIdleTimeouts();
}
final int getNumberOfConnectionTimeouts() {
return connectionManager.getNumberOfConnectionTimeouts();
}
final Date getStartUPDate() {
return new Date(startUpTime);
}
/**
* {@inheritDoc}
*/
public final FlushMode getFlushmode() {
return flushMode;
}
/**
* {@inheritDoc}
*/
public final void setFlushmode(FlushMode flusmode) {
this.flushMode = flusmode;
}
/**
* {@inheritDoc}
*/
public final void setAutoflush(boolean autoflush) {
this.autoflush = autoflush;
}
/**
* {@inheritDoc}
*/
public final boolean getAutoflush() {
return autoflush;
}
/**
* {@inheritDoc}
*/
public final void setConnectionTimeoutMillis(long timeoutMillis) {
this.connectionTimeoutMillis = timeoutMillis;
}
/**
* {@inheritDoc}
*/
public void setWriteTransferRate(int bytesPerSecond) throws IOException {
if ((bytesPerSecond != INonBlockingConnection.UNLIMITED) && (flushMode != FlushMode.ASYNC)) {
LOG.warning("setWriteTransferRate is only supported for FlushMode ASYNC. Ignore update of the transfer rate");
return;
}
this.writeRate = bytesPerSecond;
}
// public void setReadTransferRate(int bytesPerSecond) throws IOException {
// this.readRate = bytesPerSecond;
// }
/**
* {@inheritDoc}
*/
public void setIdleTimeoutMillis(long timeoutMillis) {
this.idleTimeoutMillis = timeoutMillis;
}
/**
* {@inheritDoc}
*/
public final long getConnectionTimeoutMillis() {
return connectionTimeoutMillis;
}
/**
* {@inheritDoc}
*/
public final long getIdleTimeoutMillis() {
return idleTimeoutMillis;
}
private void blockAsLongAsMaxConnectionIsExceeded() {
// if max connection size reached -> sleep
while (isMaxConnectionCheckAvtive &&
isOpen.get() &&
(acceptor.getDispatcherPool().getRoughNumRegisteredHandles() >= maxConcurrentConnections) &&
(acceptor.getDispatcherPool().getNumRegisteredHandles() >= maxConcurrentConnections)) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
}
/**
* returns the implementation version
*
* @return the implementation version
*/
public String getImplementationVersion() {
return implementationVersion;
}
/**
* returns the implementation date
*
* @return the implementation date
*/
public String getImplementationDate() {
if (implementationDate == null) {
implementationDate = ConnectionUtils.getImplementationDate();
}
return implementationDate;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getServerName() + " on " + getLocalAddress().toString() + " Port " + getLocalPort());
sb.append("\r\nopen connections:");
for (NonBlockingConnection con : connectionManager.getConnections()) {
sb.append("\r\n " + con.toString());
}
return sb.toString();
}
private final class LifeCycleHandler implements IIoAcceptorCallback {
@SuppressWarnings("unchecked")
public void onConnected() {
isOpen.set(true);
// notify listeners
for (IServerListener listener : (ArrayList) listeners.clone()) {
listener.onInit();
}
// print out the startUp log message
if (acceptor.isSSLSupported()) {
if (acceptor.isSSLOn()) {
LOG.info(name + " listening on " + localHostname + ":" + localPort + " - SSL (" + startUpLogMessage + ")");
} else {
LOG.info(name + " listening on " + localHostname + ":" + localPort + " - activatable SSL (" + startUpLogMessage + ")");
}
} else {
LOG.info(name + " listening on " + localHostname + ":" + localPort + " (" + startUpLogMessage + ")");
}
}
@SuppressWarnings("unchecked")
public void onDisconnected() {
// perform handler callback
callCurrentHandlerOnDestroy();
// calling server listener
for (IServerListener listener : (ArrayList)listeners.clone()) {
try {
listener.onDestroy();
} catch (IOException ioe) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("exception occured by destroying " + listener + " " + ioe.toString());
}
}
}
listeners.clear();
// close default worker pool if exists
if (defaultWorkerPool != null) {
WorkerpoolCloser workerpoolCloser = new WorkerpoolCloser(Server.this);
workerpoolCloser.start();
}
// unset workerpool reference
workerpool = null;
// print log message
LOG.info("server (" + localHostname + ":" + localPort + ") has been shutdown");
}
public void onConnectionAccepted(IoChainableHandler ioHandler) throws IOException {
// create a new connection
NonBlockingConnection connection = new NonBlockingConnection(connectionManager, handlerAdapter.getConnectionInstance());
// set default flush properties
connection.setAutoflush(autoflush);
connection.setFlushmode(flushMode);
connection.setWorkerpool(workerpool);
// initialize the connection
connection.init(ioHandler);
// set timeouts (requires that connection is already initialized)
connection.setIdleTimeoutMillis(idleTimeoutMillis);
connection.setConnectionTimeoutMillis(connectionTimeoutMillis);
// set transfer rates
if (writeRate != null) {
connection.setWriteTransferRate(writeRate);
}
if (maxReadBufferThreshold != null) {
connection.setMaxReadBufferThreshold(maxReadBufferThreshold);
}
blockAsLongAsMaxConnectionIsExceeded();
}
}
private static final class WorkerpoolCloser extends Thread {
private Server server;
public WorkerpoolCloser(Server server) {
super("workerpoolCloser");
setDaemon(true);
this.server = server;
}
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
try {
server.defaultWorkerPool.shutdownNow();
} finally {
server.defaultWorkerPool = null;
server = null;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy