Mercurial Hosting > luan
diff src/org/eclipse/jetty/server/nio/SelectChannelConnector.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | e21ca9878a10 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/server/nio/SelectChannelConnector.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,334 @@ +// +// ======================================================================== +// 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.continuation.Continuation; +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.Request; +import org.eclipse.jetty.util.thread.ThreadPool; + +/* ------------------------------------------------------------------------------- */ +/** + * 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> + * <p> + * When used with {@link org.eclipse.jetty.continuation.Continuation}, threadless waits are supported. + * If a filter or servlet returns after calling {@link Continuation#suspend()} or when a + * runtime exception is thrown from a call to {@link Continuation#undispatch()}, Jetty will + * will not send a response to the client. Instead the thread is released and the Continuation is + * placed on the timer queue. If the Continuation timeout expires, or it's + * resume method is called, then the request is again allocated a thread and the request is retried. + * The limitation of this approach is that request content is not available on the retried request, + * thus if possible it should be read after the continuation or saved as a request attribute or as the + * associated object of the Continuation instance. + * </p> + * + * @org.apache.xbean.XBean element="nioConnector" description="Creates an NIO based socket connector" + */ +public class SelectChannelConnector extends AbstractNIOConnector +{ + protected ServerSocketChannel _acceptChannel; + private int _lowResourcesConnections; + private int _lowResourcesMaxIdleTime; + private int _localPort=-1; + + private final SelectorManager _manager = new ConnectorSelectorManager(); + + /* ------------------------------------------------------------------------------- */ + /** + * Constructor. + * + */ + public SelectChannelConnector() + { + _manager.setMaxIdleTime(getMaxIdleTime()); + addBean(_manager,true); + setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4)); + } + + @Override + public void setThreadPool(ThreadPool pool) + { + super.setThreadPool(pool); + // preserve start order + removeBean(_manager); + addBean(_manager,true); + } + + /* ------------------------------------------------------------ */ + @Override + public void accept(int acceptorID) throws IOException + { + ServerSocketChannel server; + synchronized(this) + { + server = _acceptChannel; + } + + if (server!=null && server.isOpen() && _manager.isStarted()) + { + SocketChannel channel = server.accept(); + channel.configureBlocking(false); + Socket socket = channel.socket(); + configure(socket); + _manager.register(channel); + } + } + + /* ------------------------------------------------------------ */ + public void close() throws IOException + { + synchronized(this) + { + if (_acceptChannel != null) + { + removeBean(_acceptChannel); + if (_acceptChannel.isOpen()) + _acceptChannel.close(); + } + _acceptChannel = null; + _localPort=-2; + } + } + + /* ------------------------------------------------------------------------------- */ + @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); + } + + /* ------------------------------------------------------------ */ + public SelectorManager getSelectorManager() + { + return _manager; + } + + /* ------------------------------------------------------------ */ + public synchronized Object getConnection() + { + return _acceptChannel; + } + + /* ------------------------------------------------------------------------------- */ + public int getLocalPort() + { + synchronized(this) + { + return _localPort; + } + } + + /* ------------------------------------------------------------ */ + public void open() throws IOException + { + synchronized(this) + { + 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(getReuseAddress()); + InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort()); + _acceptChannel.socket().bind(addr,getAcceptQueueSize()); + + _localPort=_acceptChannel.socket().getLocalPort(); + if (_localPort<=0) + throw new IOException("Server channel not bound"); + + addBean(_acceptChannel); + } + } + } + + /* ------------------------------------------------------------ */ + @Override + public void setMaxIdleTime(int maxIdleTime) + { + _manager.setMaxIdleTime(maxIdleTime); + super.setMaxIdleTime(maxIdleTime); + } + + /* ------------------------------------------------------------ */ + /** + * @return the lowResourcesConnections + */ + public int getLowResourcesConnections() + { + return _lowResourcesConnections; + } + + /* ------------------------------------------------------------ */ + /** + * Set the number of connections, which if exceeded places this manager in low resources state. + * This is not an exact measure as the connection count is averaged over the select sets. + * @param lowResourcesConnections the number of connections + * @see #setLowResourcesMaxIdleTime(int) + */ + public void setLowResourcesConnections(int lowResourcesConnections) + { + _lowResourcesConnections=lowResourcesConnections; + } + + /* ------------------------------------------------------------ */ + /** + * @return the lowResourcesMaxIdleTime + */ + @Override + public int getLowResourcesMaxIdleTime() + { + return _lowResourcesMaxIdleTime; + } + + /* ------------------------------------------------------------ */ + /** + * Set the period in ms that a connection is allowed to be idle when this there are more + * than {@link #getLowResourcesConnections()} connections. This allows the server to rapidly close idle connections + * in order to gracefully handle high load situations. + * @param lowResourcesMaxIdleTime the period in ms that a connection is allowed to be idle when resources are low. + * @see #setMaxIdleTime(int) + */ + @Override + public void setLowResourcesMaxIdleTime(int lowResourcesMaxIdleTime) + { + _lowResourcesMaxIdleTime=lowResourcesMaxIdleTime; + super.setLowResourcesMaxIdleTime(lowResourcesMaxIdleTime); + } + + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.server.AbstractConnector#doStart() + */ + @Override + protected void doStart() throws Exception + { + _manager.setSelectSets(getAcceptors()); + _manager.setMaxIdleTime(getMaxIdleTime()); + _manager.setLowResourcesConnections(getLowResourcesConnections()); + _manager.setLowResourcesMaxIdleTime(getLowResourcesMaxIdleTime()); + + super.doStart(); + } + + /* ------------------------------------------------------------ */ + protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException + { + SelectChannelEndPoint endp= new SelectChannelEndPoint(channel,selectSet,key, SelectChannelConnector.this._maxIdleTime); + endp.setConnection(selectSet.getManager().newConnection(channel,endp, key.attachment())); + return endp; + } + + /* ------------------------------------------------------------------------------- */ + protected void endPointClosed(SelectChannelEndPoint endpoint) + { + connectionClosed(endpoint.getConnection()); + } + + /* ------------------------------------------------------------------------------- */ + protected AsyncConnection newConnection(SocketChannel channel,final AsyncEndPoint endpoint) + { + return new AsyncHttpConnection(SelectChannelConnector.this,endpoint,getServer()); + } + + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + private final class ConnectorSelectorManager extends SelectorManager + { + @Override + public boolean dispatch(Runnable task) + { + ThreadPool pool=getThreadPool(); + if (pool==null) + pool=getServer().getThreadPool(); + return pool.dispatch(task); + } + + @Override + protected void endPointClosed(final SelectChannelEndPoint endpoint) + { + SelectChannelConnector.this.endPointClosed(endpoint); + } + + @Override + protected void endPointOpened(SelectChannelEndPoint endpoint) + { + // TODO handle max connections and low resources + connectionOpened(endpoint.getConnection()); + } + + @Override + protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection) + { + connectionUpgraded(oldConnection,endpoint.getConnection()); + } + + @Override + public AsyncConnection newConnection(SocketChannel channel,AsyncEndPoint endpoint, Object attachment) + { + return SelectChannelConnector.this.newConnection(channel,endpoint); + } + + @Override + protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey sKey) throws IOException + { + return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey); + } + } +}