FileDocCategorySizeDatePackage
JIoEndpoint.javaAPI DocApache Tomcat 6.0.1422800Fri Jul 20 04:20:36 BST 2007org.apache.tomcat.util.net

JIoEndpoint

public class JIoEndpoint extends Object
Handle incoming TCP connections. This class implement a simple server model: one listener thread accepts on a socket and creates a new worker thread for each incoming connection. More advanced Endpoints will reuse the threads, use queues, etc.
author
James Duncan Davidson
author
Jason Hunter
author
James Todd
author
Costin Manolache
author
Gal Shachor
author
Yoav Shapira
author
Remy Maucherat

Fields Summary
protected static org.apache.juli.logging.Log
log
protected org.apache.tomcat.util.res.StringManager
sm
public static final String
CIPHER_SUITE_KEY
The Request attribute key for the cipher suite.
public static final String
KEY_SIZE_KEY
The Request attribute key for the key size.
public static final String
CERTIFICATE_KEY
The Request attribute key for the client certificate chain.
public static final String
SESSION_ID_KEY
The Request attribute key for the session id. This one is a Tomcat extension to the Servlet spec.
protected WorkerStack
workers
Available workers.
protected volatile boolean
running
Running state of the endpoint.
protected volatile boolean
paused
Will be set to true whenever the endpoint is paused.
protected boolean
initialized
Track the initialization state of the endpoint.
protected int
curThreadsBusy
Current worker threads busy count.
protected int
curThreads
Current worker threads count.
protected int
sequence
Sequence number used to generate thread names.
protected ServerSocket
serverSocket
Associated server socket.
protected int
acceptorThreadCount
Acceptor thread count.
protected Executor
executor
External Executor based thread pool.
protected int
maxThreads
Maximum amount of worker threads.
protected int
threadPriority
Priority of the acceptor and poller threads.
protected int
port
Server socket port.
protected InetAddress
address
Address for the server socket.
protected Handler
handler
Handling of accepted sockets.
protected int
backlog
Allows the server developer to specify the backlog that should be used for server sockets. By default, this value is 100.
protected boolean
tcpNoDelay
Socket TCP no delay.
protected int
soLinger
Socket linger.
protected int
soTimeout
Socket timeout.
protected boolean
daemon
The default is true - the created threads will be in daemon mode. If set to false, the control thread will not be daemon - and will keep the process alive.
protected String
name
Name of the thread pool, which will be used for naming child threads.
protected ServerSocketFactory
serverSocketFactory
Server socket factory.
Constructors Summary
Methods Summary
protected org.apache.tomcat.util.net.JIoEndpoint$WorkercreateWorkerThread()
Create (or allocate) and return an available processor for use in processing a specific HTTP request, if possible. If the maximum allowed processors have already been created and are in use, return null instead.


        synchronized (workers) {
            if (workers.size() > 0) {
                curThreadsBusy++;
                return workers.pop();
            }
            if ((maxThreads > 0) && (curThreads < maxThreads)) {
                curThreadsBusy++;
                return (newWorkerThread());
            } else {
                if (maxThreads < 0) {
                    curThreadsBusy++;
                    return (newWorkerThread());
                } else {
                    return (null);
                }
            }
        }

    
public voiddestroy()
Deallocate APR memory pools, and close server socket.

        if (running) {
            stop();
        }
        if (serverSocket != null) {
            try {
                if (serverSocket != null)
                    serverSocket.close();
            } catch (Exception e) {
                log.error(sm.getString("endpoint.err.close"), e);
            }
            serverSocket = null;
        }
        initialized = false ;
    
public intgetAcceptorThreadCount()

 return acceptorThreadCount; 
public java.net.InetAddressgetAddress()

 return address; 
public intgetBacklog()

 return backlog; 
public intgetCurrentThreadCount()

        return curThreads;
    
public intgetCurrentThreadsBusy()

        return workers!=null?curThreads - workers.size():0;
    
public booleangetDaemon()

 return daemon; 
public java.util.concurrent.ExecutorgetExecutor()

 return executor; 
public org.apache.tomcat.util.net.JIoEndpoint$HandlergetHandler()

 return handler; 
public intgetMaxThreads()

 return maxThreads; 
public java.lang.StringgetName()

 return name; 
public intgetPort()

 return port; 
public ServerSocketFactorygetServerSocketFactory()

 return serverSocketFactory; 
public intgetSoLinger()

        return soLinger; 
public intgetSoTimeout()

        return soTimeout; 
public booleangetTcpNoDelay()

        return tcpNoDelay; 
public intgetThreadPriority()

 return threadPriority; 
protected org.apache.tomcat.util.net.JIoEndpoint$WorkergetWorkerThread()
Return a new worker thread, and block while to worker is available.

        // Allocate a new worker thread
        Worker workerThread = createWorkerThread();
        while (workerThread == null) {
            try {
                synchronized (workers) {
                    workers.wait();
                }
            } catch (InterruptedException e) {
                // Ignore
            }
            workerThread = createWorkerThread();
        }
        return workerThread;
    
public voidinit()


        if (initialized)
            return;
        
        // Initialize thread count defaults for acceptor
        if (acceptorThreadCount == 0) {
            acceptorThreadCount = 1;
        }
        if (serverSocketFactory == null) {
            serverSocketFactory = ServerSocketFactory.getDefault();
        }
        if (serverSocket == null) {
            try {
                if (address == null) {
                    serverSocket = serverSocketFactory.createSocket(port, backlog);
                } else {
                    serverSocket = serverSocketFactory.createSocket(port, backlog, address);
                }
            } catch (BindException be) {
                throw new BindException(be.getMessage() + ":" + port);
            }
        }
        //if( serverTimeout >= 0 )
        //    serverSocket.setSoTimeout( serverTimeout );
        
        initialized = true;
        
    
public booleanisPaused()

        return paused;
    
public booleanisRunning()

        return running;
    
protected org.apache.tomcat.util.net.JIoEndpoint$WorkernewWorkerThread()
Create and return a new processor suitable for processing HTTP requests and returning the corresponding responses.


        Worker workerThread = new Worker();
        workerThread.start();
        return (workerThread);

    
public voidpause()

        if (running && !paused) {
            paused = true;
            unlockAccept();
        }
    
protected booleanprocessSocket(java.net.Socket socket)
Process given socket.

        try {
            if (executor == null) {
                getWorkerThread().assign(socket);
            } else {
                executor.execute(new SocketProcessor(socket));
            }
        } catch (Throwable t) {
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            log.error(sm.getString("endpoint.process.fail"), t);
            return false;
        }
        return true;
    
protected voidrecycleWorkerThread(org.apache.tomcat.util.net.JIoEndpoint$Worker workerThread)
Recycle the specified Processor so that it can be used again.

param
workerThread The processor to be recycled

        synchronized (workers) {
            workers.push(workerThread);
            curThreadsBusy--;
            workers.notify();
        }
    
public voidresume()

        if (running) {
            paused = false;
        }
    
public voidsetAcceptorThreadCount(int acceptorThreadCount)

         this.acceptorThreadCount = acceptorThreadCount; 
public voidsetAddress(java.net.InetAddress address)

 this.address = address; 
public voidsetBacklog(int backlog)

         if (backlog > 0) this.backlog = backlog; 
public voidsetDaemon(boolean b)

         daemon = b; 
public voidsetExecutor(java.util.concurrent.Executor executor)

         this.executor = executor; 
public voidsetHandler(org.apache.tomcat.util.net.JIoEndpoint$Handler handler)

          this.handler = handler; 
public voidsetMaxThreads(int maxThreads)

         this.maxThreads = maxThreads; 
public voidsetName(java.lang.String name)

         this.name = name; 
public voidsetPort(int port)

 this.port=port; 
public voidsetServerSocketFactory(ServerSocketFactory factory)

         this.serverSocketFactory = factory; 
public voidsetSoLinger(int soLinger)

 this.soLinger = soLinger; 
public voidsetSoTimeout(int soTimeout)

 this.soTimeout = soTimeout; 
protected booleansetSocketOptions(java.net.Socket socket)
Set the options for the current socket.

        // Process the connection
        int step = 1;
        try {

            // 1: Set socket options: timeout, linger, etc
            if (soLinger >= 0) { 
                socket.setSoLinger(true, soLinger);
            }
            if (tcpNoDelay) {
                socket.setTcpNoDelay(tcpNoDelay);
            }
            if (soTimeout > 0) {
                socket.setSoTimeout(soTimeout);
            }

            // 2: SSL handshake
            step = 2;
            serverSocketFactory.handshake(socket);

        } catch (Throwable t) {
            if (log.isDebugEnabled()) {
                if (step == 2) {
                    log.debug(sm.getString("endpoint.err.handshake"), t);
                } else {
                    log.debug(sm.getString("endpoint.err.unexpected"), t);
                }
            }
            // Tell to close the socket
            return false;
        }
        return true;
    
public voidsetTcpNoDelay(boolean tcpNoDelay)

 this.tcpNoDelay = tcpNoDelay; 
public voidsetThreadPriority(int threadPriority)

         this.threadPriority = threadPriority; 
public voidstart()

        // Initialize socket if not done before
        if (!initialized) {
            init();
        }
        if (!running) {
            running = true;
            paused = false;

            // Create worker collection
            if (executor == null) {
                workers = new WorkerStack(maxThreads);
            }

            // Start acceptor threads
            for (int i = 0; i < acceptorThreadCount; i++) {
                Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
                acceptorThread.setPriority(threadPriority);
                acceptorThread.setDaemon(daemon);
                acceptorThread.start();
            }
        }
    
public voidstop()

        if (running) {
            running = false;
            unlockAccept();
        }
    
protected voidunlockAccept()
Unlock the accept by using a local connection.

        Socket s = null;
        try {
            // Need to create a connection to unlock the accept();
            if (address == null) {
                s = new Socket("127.0.0.1", port);
            } else {
                s = new Socket(address, port);
                    // setting soLinger to a small value will help shutdown the
                    // connection quicker
                s.setSoLinger(true, 0);
            }
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
            }
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (Exception e) {
                    // Ignore
                }
            }
        }