view src/org/eclipse/jetty/server/nio/SelectChannelConnector.java @ 953:7db4a488fc82

simplify SelectorManager
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 12 Oct 2016 22:16:36 -0600
parents 669769bcdf5c
children a021c4c9c244
line wrap: on
line source

//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.server.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.server.AsyncHttpConnection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;

/* ------------------------------------------------------------------------------- */
/**
 * Selecting NIO connector.
 * <p>
 * This connector uses efficient NIO buffers with a non blocking threading model. Direct NIO buffers
 * are used and threads are only allocated to connections with requests. Synchronization is used to
 * simulate blocking for the servlet API, and any unflushed content at the end of request handling
 * is written asynchronously.
 * </p>
 * <p>
 * This connector is best used when there are a many connections that have idle periods.
 * </p>
 *
 * @org.apache.xbean.XBean element="nioConnector" description="Creates an NIO based socket connector"
 */
public class SelectChannelConnector extends Connector
{
	private final SelectorManager _manager = new ConnectorSelectorManager();

	public SelectChannelConnector(Server server,int port)
	{
		super(server,port);
		_manager.setMaxIdleTime(getMaxIdleTime());
		addBean(_manager,true);
		setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4));
	}
	
	@Override
	public final void accept() throws IOException
	{
		ServerSocketChannel server = _acceptChannel;

		if (server!=null && server.isOpen() && _manager.isStarted())
		{
			final SocketChannel channel = server.accept();
			channel.configureBlocking(false);
			Socket socket = channel.socket();
			configure(socket);
			this.server.threadPool.execute(new Runnable(){public void run(){
				_manager.register(channel);
			}});
		}
	}

	@Override
	public void customize(EndPoint endpoint, Request request) throws IOException
	{
		request.setTimeStamp(System.currentTimeMillis());
		endpoint.setMaxIdleTime(_maxIdleTime);
		super.customize(endpoint, request);
	}

	@Override
	public void persist(EndPoint endpoint) throws IOException
	{
		AsyncEndPoint aEndp = ((AsyncEndPoint)endpoint);
		aEndp.setCheckForIdle(true);
		super.persist(endpoint);
	}

	@Override
	protected synchronized void doStart() throws Exception
	{
		_manager.setSelectSets(getAcceptors());
//		_manager.setMaxIdleTime(getMaxIdleTime());
		_manager.setLowResourcesConnections(0);

		if (_acceptChannel == null)
		{
			// Create a new server socket
			_acceptChannel = ServerSocketChannel.open();
			// Set to blocking mode
			_acceptChannel.configureBlocking(true);

			// Bind the server socket to the local host and port
			_acceptChannel.socket().setReuseAddress(true);
			InetSocketAddress addr = getHost()==null?new InetSocketAddress(port):new InetSocketAddress(getHost(),port);
			_acceptChannel.bind(addr);
			if( _acceptChannel.socket().getLocalPort() != port)
				throw new IOException("Server channel not bound");
		}

		super.doStart();
	}

	protected AsyncConnection newConnection(SocketChannel channel,AsyncEndPoint endpoint)
	{
		return new AsyncHttpConnection(SelectChannelConnector.this,endpoint,server);
	}


	private final class ConnectorSelectorManager extends SelectorManager
	{
		@Override
		public void execute(Runnable task)
		{
			server.threadPool.execute(task);
		}

		@Override
		public AsyncConnection newConnection(SocketChannel channel,SelectChannelEndPoint endpoint, Object attachment)
		{
			return SelectChannelConnector.this.newConnection(channel,endpoint);
		}
	}
}