Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * JBoss, Home of Professional Open Source.
    * Copyright 2012 Red Hat, Inc., and individual contributors
    * as indicated by the @author tags.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.tomcat.util.net;
  
  import static org.jboss.web.CoyoteMessages.MESSAGES;
  
  import java.util.HashMap;
  
APR endpoint, providing the following services:
  • Socket acceptor thread
  • Socket poller thread
  • Sendfile thread
  • Simple Worker thread pool, with possible use of executors

Author(s):
Mladen Turk
Remy Maucherat
  
  public class AprEndpoint {
  
  
      // ----------------------------------------------------------------- Fields
  

    
Available workers.
  
      protected WorkerStack workers = null;


    
Running state of the endpoint.
  
      protected volatile boolean running = false;


    
Will be set to true whenever the endpoint is paused.
  
      protected volatile boolean paused = false;


    
Track the initialization state of the endpoint.
  
      protected boolean initialized = false;


    
Current worker threads busy count.
  
      protected int curThreadsBusy = 0;


    
Current worker threads count.
  
      protected int curThreads = 0;


    
Sequence number used to generate thread names.
  
     protected int sequence = 0;


    
Root APR memory pool.
 
     protected long rootPool = 0;


    
Server socket "pointer".
 
     protected long serverSock = 0;


    
APR memory pool for the server socket.
 
     protected long serverSockPool = 0;


    
SSL context.
 
     protected long sslContext = 0;
 
     
     // ------------------------------------------------------------- Properties
 

    
External Executor based thread pool.
 
     protected Executor executor = null;
     public void setExecutor(Executor executor) { this. = executor; }
     public Executor getExecutor() { return ; }


    
Maximum amount of worker threads.
 
     protected int maxThreads = (.....) ? 32 : ((. == -1) ? 32 * Runtime.getRuntime().availableProcessors() : .);
     public void setMaxThreads(int maxThreads) { this. = maxThreads; }
     public int getMaxThreads() { return ; }


    
Priority of the acceptor and poller threads.
 
     protected int threadPriority = .;
     public void setThreadPriority(int threadPriority) { this. = threadPriority; }
     public int getThreadPriority() { return ; }


    
Size of the socket poller.
 
     protected int pollerSize = -1;
     public void setPollerSize(int pollerSize) { this. = pollerSize; }
     public int getPollerSize() { return ; }


    
Size of the sendfile (= concurrent files which can be served).
 
     protected int sendfileSize = -1;
     public void setSendfileSize(int sendfileSize) { this. = sendfileSize; }
     public int getSendfileSize() { return ; }


    
Server socket port.
 
     protected int port;
     public int getPort() { return ; }
     public void setPort(int port ) { this.=port; }


    
Address for the server socket.
 
     protected InetAddress address;
     public InetAddress getAddress() { return ; }
     public void setAddress(InetAddress address) { this. = address; }


    
Handling of accepted sockets.
 
     protected Handler handler = null;
     public void setHandler(Handler handler ) { this. = handler; }
     public Handler getHandler() { return ; }


    
Allows the server developer to specify the backlog that should be used for server sockets. By default, this value is 100.
 
     protected int backlog = 100;
     public void setBacklog(int backlog) { if (backlog > 0) this. = backlog; }
     public int getBacklog() { return ; }


    
Socket TCP no delay.
 
     protected boolean tcpNoDelay = false;
     public boolean getTcpNoDelay() { return ; }
     public void setTcpNoDelay(boolean tcpNoDelay) { this. = tcpNoDelay; }


    
Socket linger.
 
     protected int soLinger = 100;
     public int getSoLinger() { return ; }
     public void setSoLinger(int soLinger) { this. = soLinger; }


    
Socket timeout.
 
     protected int soTimeout = -1;
     public int getSoTimeout() { return ; }
     public void setSoTimeout(int soTimeout) { this. = soTimeout; }


    
Defer accept.
 
     protected boolean deferAccept = true;
     public void setDeferAccept(boolean deferAccept) { this. = deferAccept; }
     public boolean getDeferAccept() { return ; }


    
Receive buffer.
 
     protected int soReceiveBuffer = .;
     public int getSoReceiveBuffer() { return ; }
     public void setSoReceiveBuffer(int soReceiveBuffer) { this. = soReceiveBuffer; }


    
Send buffer.
 
     protected int soSendBuffer = .;
     public int getSoSendBuffer() { return ; }
     public void setSoSendBuffer(int soSendBuffer) { this. = soSendBuffer; }


    
Keep-Alive timeout.
 
     protected int keepAliveTimeout = -1;
     public int getKeepAliveTimeout() { return ; }
     public void setKeepAliveTimeout(int keepAliveTimeout) { this. = keepAliveTimeout; }


    
Poll interval, in microseconds. The smaller the value, the more CPU the poller will use, but the more responsive to activity it will be.
 
     protected int pollTime = 2000;
     public int getPollTime() { return ; }
     public void setPollTime(int pollTime) { if (pollTime > 0) { this. = pollTime; } }


    
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 boolean daemon = true;
     public void setDaemon(boolean b) {  = b; }
     public boolean getDaemon() { return ; }


    
Name of the thread pool, which will be used for naming child threads.
 
     protected String name = "TP";
     public void setName(String name) { this. = name; }
     public String getName() { return ; }


    
Use sendfile for sending static files.
 
     protected boolean useSendfile = .;
     public void setUseSendfile(boolean useSendfile) { this. = useSendfile; }
     public boolean getUseSendfile() { return ; }


    
The socket poller.
 
     protected Poller poller = null;
     public Poller getPoller() {
         return ;
     }


    
The socket poller used for event support.
 
     protected Poller eventPoller = null;
     public Poller getEventPoller() {
         return ;
     }


    
The static file sender.
 
     protected Sendfile sendfile = null;
     public Sendfile getSendfile() {
         return ;
     }


    
The server address.
 
     protected long serverAddress = 0;
    
    
    
The server address family.
 
     protected int serverAddressFamily = 0;
    
    
    
Reverse connection. In this proxied mode, the endpoint will not use a server socket, but will connect itself to the front end server.
 
     protected boolean reverseConnection = false;
     public boolean isReverseConnection() { return ; }
     public void setReverseConnection(boolean reverseConnection) { this. = reverseConnection; }
    
List of socket counters.
 
     class ListSock {
        int count;
        int port;
     }
     protected ListSock[] listsock = null;


    
SSL engine.
 
     protected boolean SSLEnabled = false;
     public boolean isSSLEnabled() { return ; }
     public void setSSLEnabled(boolean SSLEnabled) { this. = SSLEnabled; }


    
SSL protocols.
 
     protected String SSLProtocol = "all";
     public String getSSLProtocol() { return ; }
     public void setSSLProtocol(String SSLProtocol) { this. = SSLProtocol; }


    
SSL password (if a cert is encrypted, and no password has been provided, a callback will ask for a password).
 
     protected String SSLPassword = null;
     public String getSSLPassword() { return ; }
     public void setSSLPassword(String SSLPassword) { this. = SSLPassword; }


    
SSL cipher suite.
 
     protected String SSLCipherSuite = "ALL";
     public String getSSLCipherSuite() { return ; }
     public void setSSLCipherSuite(String SSLCipherSuite) { this. = SSLCipherSuite; }


    
SSL certificate file.
 
     protected String SSLCertificateFile = null;
     public String getSSLCertificateFile() { return ; }
     public void setSSLCertificateFile(String SSLCertificateFile) { this. = SSLCertificateFile; }


    
SSL certificate key file.
 
     protected String SSLCertificateKeyFile = null;
     public String getSSLCertificateKeyFile() { return ; }
     public void setSSLCertificateKeyFile(String SSLCertificateKeyFile) { this. = SSLCertificateKeyFile; }


    
SSL certificate chain file.
 
     protected String SSLCertificateChainFile = null;
     public String getSSLCertificateChainFile() { return ; }
     public void setSSLCertificateChainFile(String SSLCertificateChainFile) { this. = SSLCertificateChainFile; }


    
SSL CA certificate path.
 
     protected String SSLCACertificatePath = null;
     public String getSSLCACertificatePath() { return ; }
     public void setSSLCACertificatePath(String SSLCACertificatePath) { this. = SSLCACertificatePath; }


    
SSL CA certificate file.
 
     protected String SSLCACertificateFile = null;
     public String getSSLCACertificateFile() { return ; }
     public void setSSLCACertificateFile(String SSLCACertificateFile) { this. = SSLCACertificateFile; }


    
SSL CA revocation path.
 
     protected String SSLCARevocationPath = null;
     public String getSSLCARevocationPath() { return ; }
     public void setSSLCARevocationPath(String SSLCARevocationPath) { this. = SSLCARevocationPath; }


    
SSL CA revocation file.
 
     protected String SSLCARevocationFile = null;
     public String getSSLCARevocationFile() { return ; }
     public void setSSLCARevocationFile(String SSLCARevocationFile) { this. = SSLCARevocationFile; }


    
SSL verify client.
 
     protected String SSLVerifyClient = "none";
     public String getSSLVerifyClient() { return ; }
     public void setSSLVerifyClient(String SSLVerifyClient) { this. = SSLVerifyClient; }


    
SSL verify depth.
 
     protected int SSLVerifyDepth = 10;
     public int getSSLVerifyDepth() { return ; }
     public void setSSLVerifyDepth(int SSLVerifyDepth) { this. = SSLVerifyDepth; }


    
SSL allow insecure renegotiation for the the client that does not support the secure renegotiation.
 
     protected boolean SSLInsecureRenegotiation = false;
     public void setSSLInsecureRenegotiation(boolean SSLInsecureRenegotiation) { this. = SSLInsecureRenegotiation; }
     public boolean getSSLInsecureRenegotiation() { return ; }
 
     // --------------------------------------------------------- Public Methods
 

    
Number of keepalive sockets.
 
     public int getKeepAliveCount() {
         if ( == null) {
             return 0;
         } else {
             return .getConnectionCount();
         }
     }


    
Number of sendfile sockets.
 
     public int getSendfileCount() {
         if ( == null) {
             return 0;
         } else {
             return .getSendfileCount();
         }
     }


    
Return the amount of threads that are managed by the pool.

Returns:
the amount of threads that are managed by the pool
 
     public int getCurrentThreadCount() {
         return ;
     }


    
Return the amount of threads currently busy.

Returns:
the amount of threads currently busy
 
     public int getCurrentThreadsBusy() {
         return ;
     }


    
Return the state of the endpoint.

Returns:
true if the endpoint is running, false otherwise
 
     public boolean isRunning() {
         return ;
     }


    
Return the state of the endpoint.

Returns:
true if the endpoint is paused, false otherwise
 
     public boolean isPaused() {
         return ;
     }
 
 
     // ----------------------------------------------- Public Lifecycle Methods
 

    
Initialize the endpoint.
 
     public void init()
         throws Exception {
 
         if ()
             return;
         
         // Create the root APR memory pool
          = Pool.create(0);
         // Create the pool for the server socket
          = Pool.create();
         // Create the APR address that will be bound
         String addressStr = null;
         if ( == null) {
             addressStr = null;
         } else {
             addressStr = .getHostAddress();
         }
         int family = .;
         if (.) {
             if (addressStr == null) {
                 if (!. && !. && !.)
                     family = .;
             } else if (addressStr.indexOf(':') >= 0) {
                 family = .;
             }
             if (!Boolean.getBoolean("java.net.preferIPv4Stack")) {
                 family = .;
                 if (addressStr != null && addressStr.indexOf(':') < 0) {
                     addressStr = "::ffff:" + addressStr;
                 }
             }
         }
 
         // Sendfile usage on systems which don't support it cause major problems
         if ( && !.) {
              = false;
         }
 
         long inetAddress = Address.info(addressStrfamily,
                 , 0, );
         
         if (!) {
             // Create the APR server socket
              = Socket.create(Address.getInfo(inetAddress)..,
                     .);
             if (.) {
                 Socket.optSet(., 1);
             }
             // Deal with the firewalls that tend to drop the inactive sockets
             Socket.optSet(., 1);
             // Bind the server socket
             int ret = Socket.bind(inetAddress);
             if (ret != 0) {
                 throw .socketBindFailed(ret, Error.strerror(ret));
             }
             // Start listening on the server socket
             ret = Socket.listen();
             if (ret != 0) {
                 throw .socketListenFailed(ret, Error.strerror(ret));
             }
             if (. || .) {
                 // On Windows set the reuseaddr flag after the bind/listen
                 Socket.optSet(., 1);
             }
 
             // Delay accepting of new connections until data is available
             // Only Linux kernels 2.4 + have that implemented
             // on other platforms this call is noop and will return APR_ENOTIMPL.
             if ( && (Socket.optSet(., 1) == .)) {
                  = false;
             }
         } else {
             /* Initialize the SockList */
              = new ListSock[10];
             for (int i=0; i<.i++) {
                 [i] = new ListSock();
                 [i]. =  + i;
                 [i]. = 0;
             }
              = inetAddress;
              = family;
              = false;
         }
 
         // Initialize SSL if needed
         if () {
 
             // SSL protocol
             int value = .;
             if ( == null || .length() == 0) {
                value = .;
             } else {
                String protocols = .replace(',''+');
                for (String protocol : protocols.split("\\+")) {
                    protocol = protocol.trim();
                    if ("SSLv2".equalsIgnoreCase(protocol)) {
                        value |= .;
                    } else if ("SSLv3".equalsIgnoreCase(protocol)) {
                        value |= .;
                    } else if ("TLSv1".equalsIgnoreCase(protocol)) {
                        value |= .;
                    } else if ("TLSv1.1".equalsIgnoreCase(protocol)) {
                        value |= .;
                    } else if ("TLSv1.2".equalsIgnoreCase(protocol)) {
                        value |= .;
                    } else if ("all".equalsIgnoreCase(protocol)) {
                        value |= .;
                    } else {
                        // Protocol not recognized, fail to start as it is safer than
                        // continuing with the default which might enable more than the
                        // is required
                        ..unsupportedProtocol(protocol);
                    }
                }
             }
 
             // Create SSL Context
              = SSLContext.make(value, () ? . : .);
             // SSL renegociation
             if () {
                 if (SSL.hasOp(.))
                     SSLContext.setOptions(.);
                 else {
                     // OpenSSL does not support unsafe legacy renegotiation.
                     ..noInsecureRengotiation(SSL.versionString());
                 }
             }
             // List the ciphers that the client is permitted to negotiate
             SSLContext.setCipherSuite();
             // Load Server key and certificate
             // Set certificate chain file
             SSLContext.setCertificateChainFile(false);
             // Support Client Certificates
             SSLContext.setCACertificate();
             // Set revocation
             SSLContext.setCARevocation();
             // Client certificate verification
             value = .;
             if ("optional".equalsIgnoreCase()) {
                 value = .;
             } else if ("require".equalsIgnoreCase()) {
                 value = .;
             } else if ("optionalNoCA".equalsIgnoreCase()) {
                 value = .;
             }
             SSLContext.setVerify(value);
             // For now, sendfile is not supported with SSL
              = false;
 
         }
         
          = true;
 
     }


    
Start the APR endpoint, creating acceptor, poller and sendfile threads.
 
     public void start()
         throws Exception {
         // Initialize socket if not done before
         if (!) {
             init();
         }
         if (!) {
              = true;
              = false;
 
             // Create worker collection
             if ( == null) {
                  = new WorkerStack();
             }
 
             // Start poller thread
              = new Poller(false);
             .init();
             Thread pollerThread = new Thread(getName() + "-Poller");
             pollerThread.setPriority();
             pollerThread.setDaemon(true);
             pollerThread.start();
 
             // Start event poller thread
              = new Poller(true);
             .init();
             Thread eventPollerThread = new Thread(getName() + "-EventPoller");
             eventPollerThread.setPriority();
             eventPollerThread.setDaemon(true);
             eventPollerThread.start();
 
             // Start sendfile thread
             if () {
                  = new Sendfile();
                 .init();
                 Thread sendfileThread = new Thread(getName() + "-Sendfile");
                 sendfileThread.setPriority();
                 sendfileThread.setDaemon(true);
                 sendfileThread.start();
             }
             
             // Start acceptor thread
             Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor");
             acceptorThread.setPriority();
             acceptorThread.setDaemon();
             acceptorThread.start();
 
         }
     }


    
Pause the endpoint, which will make it stop accepting new sockets.
 
     public void pause() {
         if ( && !) {
              = true;
             unlockAccept();
         }
     }


    
Resume the endpoint, which will make it start accepting new sockets again.
 
     public void resume() {
         if () {
              = false;
         }
     }


    
Stop the endpoint. This will cause all processing threads to stop.
 
     public void stop() {
         if () {
              = false;
             unlockAccept();
             .destroy();
              = null;
             .destroy();
              = null;
             if () {
                 .destroy();
                  = null;
             }
         }
     }


    
Deallocate APR memory pools, and close server socket.
 
     public void destroy() throws Exception {
         if () {
             stop();
         }
         Pool.destroy();
          = 0;
         // Close server socket
         Socket.close();
          = 0;
          = 0;
         // Close all APR memory pools and resources
         Pool.destroy();
          = 0;
          = false;
     }
 
 
     // ------------------------------------------------------ Protected Methods
 

    
Get a sequence number used for thread naming.
 
     protected int getSequence() {
         return ++;
     }
 
 
     protected void unlockAccept() {
         java.net.Socket s = null;
         InetSocketAddress saddr = null;
         try {
             // Need to create a connection to unlock the accept();
             if ( == null) {
                 saddr = new InetSocketAddress("localhost");
             } else {
                 saddr = new InetSocketAddress();
             }
             s = new java.net.Socket();
             s.setSoLinger(true, 0);
             s.connect(saddr, 2000);
             // If deferAccept is enabled, send at least one byte
             if () {
                 s.getOutputStream().write(" ".getBytes());
                 s.getOutputStream().flush();
             }
         } catch (Exception e) {
             // Ignore
         } finally {
             if (s != null) {
                 try {
                     s.close();
                 } catch (Exception e) {
                     // Ignore
                 }
             }
         }
     }


    
Process the specified connection.
 
     protected boolean setSocketOptions(long socket) {
         // Process the connection
         int step = 1;
         try {
 
             // 1: Set socket options: timeout, linger, etc
             if ( >= 0)
                 Socket.optSet(socket.);
             if ()
                 Socket.optSet(socket., ( ? 1 : 0));
             if ( > 0)
                 Socket.timeoutSet(socket * 1000);
             if ( > 0)
                 Socket.optSet(socket.);
             if ( > 0)
                 Socket.optSet(socket.);
 
             // 2: SSL handshake
             step = 2;
             if ( != 0) {
                 SSLSocket.attach(socket);
                 if (SSLSocket.handshake(socket) != 0) {
                     ..handshakeFailed(SSL.getLastError());
                     return false;
                 }
             }
 
         } catch (Throwable t) {
             if (step == 2) {
                 ..handshakeFailed(t);
             } else {
                 ..unexpectedError(t);
             }
             // Tell to close the socket
             return false;
         }
         return true;
     }


    
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.
 
     protected Worker createWorkerThread() {
 
         synchronized () {
             if (.size() > 0) {
                 ++;
                 return (.pop());
             }
             if (( > 0) && ( < )) {
                 ++;
                 if ( == ) {
                     ..maxThreadsReached();
                 }
                 return (newWorkerThread());
             } else {
                 if ( < 0) {
                     ++;
                     return (newWorkerThread());
                 } else {
                     return (null);
                 }
             }
         }
 
     }


    
Create and return a new processor suitable for processing HTTP requests and returning the corresponding responses.
 
     protected Worker newWorkerThread() {
 
         Worker workerThread = new Worker();
         workerThread.start();
         return (workerThread);
 
     }


    
Recycle the specified Processor so that it can be used again.

Parameters:
workerThread The processor to be recycled
 
     protected void recycleWorkerThread(Worker workerThread) {
         synchronized () {
             .push(workerThread);
             --;
             .notify();
         }
     }

    
    
Return a new worker thread, and block while to worker is available.
 
     protected Worker getWorkerThread() {
         // Allocate a new worker thread
         Worker workerThread = createWorkerThread();
                 || .....) {
             while (workerThread == null) {
                 try {
                     synchronized () {
                         .wait();
                     }
                 } catch (InterruptedException e) {
                     // Ignore
                 }
                 workerThread = createWorkerThread();
             }
         }
         return workerThread;
     }


    
Allocate a new poller of the specified size.
 
     protected long allocatePoller(int sizelong poolint timeout) {
         try {
             return Poll.create(sizepool, 0, (timeout > 0) ? (timeout * 1000) : -1);
         } catch (Error e) {
             if (Status.APR_STATUS_IS_EINVAL(e.getError())) {
                 ..limitedPollerSize(size);
                 return 0;
             } else {
                 ..errorCreatingPoller(e);
                 return -1;
             }
         }
     }

    
    
Process given socket.
 
     protected boolean processSocketWithOptions(long socket) {
         try {
            if ( == null) {
                Worker worker = getWorkerThread();
                if (worker != null) {
                    worker.assignWithOptions(socket);
                } else {
                    return false;
                }
            } else {
                .execute(new SocketWithOptionsProcessor(socket));
            }
        } catch (Throwable t) {
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            return false;
        }
        return true;
    }
    

    
Process given socket.
    protected boolean processSocket(long socket) {
        try {
            if ( == null) {
                Worker worker = getWorkerThread();
                if (worker != null) {
                    worker.assign(socket);
                } else {
                    return false;
                }
            } else {
                .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
            return false;
        }
        return true;
    }
    

    
Process given socket for an event.
    protected boolean processSocket(long socketSocketStatus status) {
        try {
            if ( == null) {
                Worker worker = getWorkerThread();
                if (worker != null) {
                    worker.assign(socketstatus);
                } else {
                    return false;
                }
            } else {
                .execute(new SocketEventProcessor(socketstatus));
            }
        } catch (Throwable t) {
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            return false;
        }
        return true;
    }
    
    // --------------------------------------------------- Acceptor Inner Class


    
Server socket acceptor thread.
    protected class Acceptor implements Runnable {


        
The background thread that listens for incoming TCP/IP connections and hands them off to an appropriate processor.
        public void run() {
            // Loop until we receive a shutdown command
            while () {
                // Loop if endpoint is paused
                while ( && ) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }
                if (!) {
                    break;
                }
                if () {
                    if (.getConnectionCount() < ( / 5)) {
                        /* Sort the ListSock (by count) */
                        boolean go = true;
                        while (go) {
                            go = false;
                            for (int i=0; i<. -1; i++) {
                                ListSock current;
                                if ([i+1].<[i].) {
                                    go = false;
                                    current = [i+1];
                                    [i+1] = [i];
                                    [i] = current;
                                }
                            }
                        }
                        // Create maxThreads / 5 sockets
                        int nsock =  / 5;
                        if (nsock>.)
                            nsock = .;
                        String addressStr = .getHostAddress();
                        for (int i=0; i < nsocki++) {
                            try {
                                long socket = Socket.create(.,
                                        .);
                                long inetAddress = Address.info(addressStr,
                                        [i]., 0, );
                                if (Socket.connect(socketinetAddress) != 0) {
                                    Socket.destroy(socket);
                                    continue// try next one.
                                }
                                // Hand this socket off to an appropriate processor
                                if (!processSocketWithOptions(socket)) {
                                    // Close socket and pool right away
                                    Socket.destroy(socket);
                                } else {
                                    [i].++;
                                }
                                // Don't immediately create another socket
                                try {
                                    Thread.sleep(1);
                                } catch (InterruptedException e) {
                                    // Ignore
                                }
                            } catch (Throwable t) {
                                ..errorAcceptingSocket(t);
                            }
                        }
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                } else {
                
                    try {
                        // Accept the next incoming connection from the server socket
                        long socket = Socket.accept();
                        // Hand this socket off to an appropriate processor
                        if (!processSocketWithOptions(socket)) {
                            // Close socket and pool right away
                            Socket.destroy(socket);
                        }
                    } catch (Throwable t) {
                        if () {
                            if (t instanceof Error) {
                                Error e = (Errort;
                                if (e.getError() == 233) {
                                    // Not an error on HP-UX so log as a warning
                                    // so it can be filtered out on that platform
                                    // See bug 50273
                                    ..warnAcceptingSocket(t);
                                } else {
                                    ..errorAcceptingSocket(t);
                                }
                            } else {
                                ..errorAcceptingSocket(t);
                            }
                        }
                    }
                }
                // The processor will recycle itself when it finishes
            }
        }
        
    }
    // ------------------------------------------------- SocketInfo Inner Class


    
Socket list class, used to avoid using a possibly large amount of objects with very little actual use.
    public static class SocketInfo {
        public static final int READ = 1;
        public static final int WRITE = 2;
        public static final int RESUME = 4;
        public static final int WAKEUP = 8;
        public long socket;
        public int timeout;
        public int flags;
        public boolean read() {
            return ( & ) == ;
        }
        public boolean write() {
            return ( & ) == ;
        }
        public boolean resume() {
            return ( & ) == ;
        }
        public boolean wakeup() {
            return ( & ) == ;
        }
        public static int merge(int flag1int flag2) {
            return ((flag1 & ) | (flag2 & ))
                | ((flag1 & ) | (flag2 & )) 
                | ((flag1 & ) | (flag2 & )) 
                | ((flag1 & ) & (flag2 & ));
        }
    }
    
    
    // --------------------------------------------- SocketTimeouts Inner Class


    
Socket list class, used to avoid using a possibly large amount of objects with very little actual use.
    public class SocketTimeouts {
        protected int size;
        protected long[] sockets;
        protected long[] timeouts;
        protected int pos = 0;
        public SocketTimeouts(int size) {
            this. = 0;
             = new long[size];
             = new long[size];
        }
        public void add(long socketlong timeout) {
            [] = socket;
            [] = timeout;
            ++;
        }
        
        public boolean remove(long socket) {
            for (int i = 0; i < i++) {
                if ([i] == socket) {
                    [i] = [ - 1];
                    [i] = [ - 1];
                    --;
                    return true;
                }
            }
            return false;
        }
        
        public long check(long date) {
            while ( < ) {
                if (date >= []) {
                    long result = [];
                    [] = [ - 1];
                    [] = [ - 1];
                    --;
                    return result;
                }
                ++;
            }
             = 0;
            return 0;
        }
        
    }
    
    
    // ------------------------------------------------- SocketList Inner Class


    
Socket list class, used to avoid using a possibly large amount of objects with very little actual use.
    public class SocketList {
        protected int size;
        protected int pos;
        protected long[] sockets;
        protected int[] timeouts;
        protected int[] flags;
        
        protected SocketInfo info = new SocketInfo();
        
        public SocketList(int size) {
            this. = 0;
             = 0;
             = new long[size];
             = new int[size];
             = new int[size];
        }
        
        public int size() {
            return this.;
        }