geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From xiam...@apache.org
Subject svn commit: r1214761 [6/10] - in /geronimo/external/trunk/tomcat-parent-6.0.35: catalina-ha/src/main/java/org/apache/catalina/ha/ catalina-ha/src/main/java/org/apache/catalina/ha/authenticator/ catalina-ha/src/main/java/org/apache/catalina/ha/deploy/ c...
Date Thu, 15 Dec 2011 13:55:35 GMT
Added: geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/JIoEndpoint.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1214761&view=auto
==============================================================================
--- geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/JIoEndpoint.java (added)
+++ geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/JIoEndpoint.java Thu Dec 15 13:55:25 2011
@@ -0,0 +1,880 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 java.io.IOException;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.Executor;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * 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
+ */
+public class JIoEndpoint {
+
+
+    // -------------------------------------------------------------- Constants
+
+
+    protected static Log log = LogFactory.getLog(JIoEndpoint.class);
+
+    protected StringManager sm = 
+        StringManager.getManager("org.apache.tomcat.util.net.res");
+
+
+    /**
+     * The Request attribute key for the cipher suite.
+     */
+    public static final String CIPHER_SUITE_KEY = "javax.servlet.request.cipher_suite";
+
+    /**
+     * The Request attribute key for the key size.
+     */
+    public static final String KEY_SIZE_KEY = "javax.servlet.request.key_size";
+
+    /**
+     * The Request attribute key for the client certificate chain.
+     */
+    public static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate";
+
+    /**
+     * The Request attribute key for the session id.
+     * This one is a Tomcat extension to the Servlet spec.
+     */
+    public static final String SESSION_ID_KEY = "javax.servlet.request.ssl_session";
+
+
+    // ----------------------------------------------------------------- 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;
+
+
+    /**
+     * Associated server socket.
+     */
+    protected ServerSocket serverSocket = null;
+
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * Acceptor thread count.
+     */
+    protected int acceptorThreadCount = 0;
+    public void setAcceptorThreadCount(int acceptorThreadCount) { this.acceptorThreadCount = acceptorThreadCount; }
+    public int getAcceptorThreadCount() { return acceptorThreadCount; }
+
+
+    /**
+     * External Executor based thread pool.
+     */
+    protected Executor executor = null;
+    public void setExecutor(Executor executor) { this.executor = executor; }
+    public Executor getExecutor() { return executor; }
+
+
+    /**
+     * Maximum amount of worker threads.
+     */
+    protected int maxThreads = 200;
+    public void setMaxThreads(int maxThreads) {
+        this.maxThreads = maxThreads;
+        if (running) {
+            synchronized(workers) {
+                workers.resize(maxThreads);
+            }
+        }
+    }
+    public int getMaxThreads() {
+        if (executor != null) {
+            return -1;
+        } else {
+            return maxThreads;
+        }
+    }
+
+
+    /**
+     * Priority of the acceptor and poller threads.
+     */
+    protected int threadPriority = Thread.NORM_PRIORITY;
+    public void setThreadPriority(int threadPriority) { this.threadPriority = threadPriority; }
+    public int getThreadPriority() { return threadPriority; }
+
+    
+    /**
+     * Server socket port.
+     */
+    protected int port;
+    public int getPort() { return port; }
+    public void setPort(int port ) { this.port=port; }
+
+
+    /**
+     * Address for the server socket.
+     */
+    protected InetAddress address;
+    public InetAddress getAddress() { return address; }
+    public void setAddress(InetAddress address) { this.address = address; }
+
+
+    /**
+     * Handling of accepted sockets.
+     */
+    protected Handler handler = null;
+    public void setHandler(Handler handler ) { this.handler = handler; }
+    public Handler getHandler() { return handler; }
+
+
+    /**
+     * 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 = backlog; }
+    public int getBacklog() { return backlog; }
+
+
+    /**
+     * Socket TCP no delay.
+     */
+    protected boolean tcpNoDelay = false;
+    public boolean getTcpNoDelay() { return tcpNoDelay; }
+    public void setTcpNoDelay(boolean tcpNoDelay) { this.tcpNoDelay = tcpNoDelay; }
+
+
+    /**
+     * Socket linger.
+     */
+    protected int soLinger = 100;
+    public int getSoLinger() { return soLinger; }
+    public void setSoLinger(int soLinger) { this.soLinger = soLinger; }
+
+
+    /**
+     * Socket timeout.
+     */
+    protected int soTimeout = -1;
+    public int getSoTimeout() { return soTimeout; }
+    public void setSoTimeout(int soTimeout) { this.soTimeout = soTimeout; }
+
+
+    /**
+     * 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) { daemon = b; }
+    public boolean getDaemon() { return daemon; }
+
+
+    /**
+     * Name of the thread pool, which will be used for naming child threads.
+     */
+    protected String name = "TP";
+    public void setName(String name) { this.name = name; }
+    public String getName() { return name; }
+
+
+    /**
+     * Server socket factory.
+     */
+    protected ServerSocketFactory serverSocketFactory = null;
+    public void setServerSocketFactory(ServerSocketFactory factory) { this.serverSocketFactory = factory; }
+    public ServerSocketFactory getServerSocketFactory() { return serverSocketFactory; }
+
+
+    /**
+     * Unlock timeout.
+     */
+    protected int unlockTimeout = 250;
+    public int getUnlockTimeout() { return unlockTimeout; }
+    public void setUnlockTimeout(int unlockTimeout) {
+        this.unlockTimeout = unlockTimeout;
+    }
+
+    
+    public boolean isRunning() {
+        return running;
+    }
+    
+    public boolean isPaused() {
+        return paused;
+    }
+    
+    /**
+     * Return the amount of threads that are managed by the pool.
+     *
+     * @return the amount of threads that are managed by the pool
+     */
+    public int getCurrentThreadCount() {
+        if (executor!=null) {
+            return -1;
+        } else {
+            return curThreads;
+        }
+    }
+
+    /**
+     * Return the amount of threads that are in use 
+     *
+     * @return the amount of threads that are in use
+     */
+    public int getCurrentThreadsBusy() {
+        if (executor!=null) {
+            return -1;
+        } else {
+            return workers!=null?curThreads - workers.size():0;
+        }
+    }
+    
+
+    // ------------------------------------------------ Handler Inner Interface
+
+
+    /**
+     * Bare bones interface used for socket processing. Per thread data is to be
+     * stored in the ThreadWithAttributes extra folders, or alternately in
+     * thread local fields.
+     */
+    public interface Handler {
+        public boolean process(Socket socket);
+    }
+
+
+    // --------------------------------------------------- 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 (running) {
+
+                // Loop if endpoint is paused
+                while (paused) {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        // Ignore
+                    }
+                }
+
+                // Accept the next incoming connection from the server socket
+                try {
+                    Socket socket = serverSocketFactory.acceptSocket(serverSocket);
+                    serverSocketFactory.initSocket(socket);
+                    // Hand this socket off to an appropriate processor
+                    if (!processSocket(socket)) {
+                        // Close socket right away
+                        try {
+                            socket.close();
+                        } catch (IOException e) {
+                            // Ignore
+                        }
+                    }
+                }catch ( IOException x ) {
+                    if ( running ) log.error(sm.getString("endpoint.accept.fail"), x);
+                } catch (Throwable t) {
+                    log.error(sm.getString("endpoint.accept.fail"), t);
+                }
+
+                // The processor will recycle itself when it finishes
+
+            }
+
+        }
+
+    }
+
+
+    // ------------------------------------------- SocketProcessor Inner Class
+
+
+    /**
+     * This class is the equivalent of the Worker, but will simply use in an
+     * external Executor thread pool.
+     */
+    protected class SocketProcessor implements Runnable {
+        
+        protected Socket socket = null;
+        
+        public SocketProcessor(Socket socket) {
+            this.socket = socket;
+        }
+
+        public void run() {
+
+            // Process the request from this socket
+            if (!setSocketOptions(socket) || !handler.process(socket)) {
+                // Close socket
+                try {
+                    socket.close();
+                } catch (IOException e) {
+                }
+            }
+
+            // Finish up this request
+            socket = null;
+
+        }
+        
+    }
+    
+    
+    // ----------------------------------------------------- Worker Inner Class
+
+
+    protected class Worker implements Runnable {
+
+        protected Thread thread = null;
+        protected boolean available = false;
+        protected Socket socket = null;
+
+        
+        /**
+         * Process an incoming TCP/IP connection on the specified socket.  Any
+         * exception that occurs during processing must be logged and swallowed.
+         * <b>NOTE</b>:  This method is called from our Connector's thread.  We
+         * must assign it to our own thread so that multiple simultaneous
+         * requests can be handled.
+         *
+         * @param socket TCP socket to process
+         */
+        synchronized void assign(Socket socket) {
+
+            // Wait for the Processor to get the previous Socket
+            while (available) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                }
+            }
+
+            // Store the newly available Socket and notify our thread
+            this.socket = socket;
+            available = true;
+            notifyAll();
+
+        }
+
+        
+        /**
+         * Await a newly assigned Socket from our Connector, or <code>null</code>
+         * if we are supposed to shut down.
+         */
+        private synchronized Socket await() {
+
+            // Wait for the Connector to provide a new Socket
+            while (!available) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                }
+            }
+
+            // Notify the Connector that we have received this Socket
+            Socket socket = this.socket;
+            available = false;
+            notifyAll();
+
+            return (socket);
+
+        }
+
+
+
+        /**
+         * The background thread that listens for incoming TCP/IP connections and
+         * hands them off to an appropriate processor.
+         */
+        public void run() {
+
+            // Process requests until we receive a shutdown signal
+            while (running) {
+
+                // Wait for the next socket to be assigned
+                Socket socket = await();
+                if (socket == null)
+                    continue;
+
+                // Process the request from this socket
+                if (!setSocketOptions(socket) || !handler.process(socket)) {
+                    // Close socket
+                    try {
+                        socket.close();
+                    } catch (IOException e) {
+                    }
+                }
+
+                // Finish up this request
+                socket = null;
+                recycleWorkerThread(this);
+
+            }
+
+        }
+
+
+        /**
+         * Start the background processing thread.
+         */
+        public void start() {
+            thread = new Thread(this);
+            thread.setName(getName() + "-" + (++curThreads));
+            thread.setDaemon(true);
+            thread.start();
+        }
+
+
+    }
+
+
+    // -------------------- Public methods --------------------
+
+    public void init()
+        throws Exception {
+
+        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 orig) {
+                String msg;
+                if (address == null)
+                    msg = orig.getMessage() + " <null>:" + port;
+                else
+                    msg = orig.getMessage() + " " +
+                            address.toString() + ":" + port;
+                BindException be = new BindException(msg);
+                be.initCause(orig);
+                throw be;
+            }
+        }
+        //if( serverTimeout >= 0 )
+        //    serverSocket.setSoTimeout( serverTimeout );
+        
+        initialized = true;
+        
+    }
+    
+    public void start()
+        throws Exception {
+        // 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 void pause() {
+        if (running && !paused) {
+            paused = true;
+            unlockAccept();
+        }
+    }
+
+    public void resume() {
+        if (running) {
+            paused = false;
+        }
+    }
+
+    public void stop() {
+        if (running) {
+            running = false;
+            unlockAccept();
+        }
+    }
+
+    /**
+     * Deallocate APR memory pools, and close server socket.
+     */
+    public void destroy() throws Exception {
+        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 ;
+    }
+
+    
+    /**
+     * Unlock the accept by using a local connection.
+     */
+    protected void unlockAccept() {
+        Socket s = null;
+        InetSocketAddress saddr = null;
+        try {
+            // Need to create a connection to unlock the accept();
+            if (address == null) {
+                saddr = new InetSocketAddress("localhost", port);
+            } else {
+                saddr = new InetSocketAddress(address,port);
+            }
+            s = new java.net.Socket();
+            s.setSoTimeout(soTimeout);
+            s.setSoLinger(true ,0);
+            if (log.isDebugEnabled()) {
+                log.debug("About to unlock socket for: " + saddr);
+            }
+            s.connect(saddr, unlockTimeout);
+            if (log.isDebugEnabled()) {
+                log.debug("Socket unlock completed for:"+saddr);
+            } 
+        } 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
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Set the options for the current socket.
+     */
+    protected boolean setSocketOptions(Socket 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;
+    }
+
+    
+    /**
+     * 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
+     * <code>null</code> instead.
+     */
+    protected Worker createWorkerThread() {
+
+        synchronized (workers) {
+            if (workers.size() > 0) {
+                curThreadsBusy++;
+                return workers.pop();
+            }
+            if ((maxThreads > 0) && (curThreads < maxThreads)) {
+                curThreadsBusy++;
+                if (curThreadsBusy == maxThreads) {
+                    log.info(sm.getString("endpoint.info.maxThreads",
+                            Integer.toString(maxThreads), address,
+                            Integer.toString(port)));
+                }
+                return (newWorkerThread());
+            } else {
+                if (maxThreads < 0) {
+                    curThreadsBusy++;
+                    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);
+
+    }
+
+
+    /**
+     * Return a new worker thread, and block while to worker is available.
+     */
+    protected Worker getWorkerThread() {
+        // Allocate a new worker thread
+        synchronized (workers) {
+            Worker workerThread;
+            while ((workerThread = createWorkerThread()) == null) {
+                try {
+                    workers.wait();
+                } catch (InterruptedException e) {
+                    // Ignore
+                }
+            }
+            return workerThread;
+        }
+    }
+
+
+    /**
+     * Recycle the specified Processor so that it can be used again.
+     *
+     * @param workerThread The processor to be recycled
+     */
+    protected void recycleWorkerThread(Worker workerThread) {
+        synchronized (workers) {
+            workers.push(workerThread);
+            curThreadsBusy--;
+            workers.notify();
+        }
+    }
+
+
+    /**
+     * Process given socket.
+     */
+    protected boolean processSocket(Socket 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;
+    }
+    
+
+    // ------------------------------------------------- WorkerStack Inner Class
+
+
+    public class WorkerStack {
+        
+        protected Worker[] workers = null;
+        protected int end = 0;
+        
+        public WorkerStack(int size) {
+            workers = new Worker[size];
+        }
+        
+        /** 
+         * Put the object into the queue. If the queue is full (for example if
+         * the queue has been reduced in size) the object will be dropped.
+         * 
+         * @param   object  the object to be appended to the queue (first
+         *                  element).
+         */
+        public void push(Worker worker) {
+            if (end < workers.length) {
+                workers[end++] = worker;
+            } else {
+                curThreads--;
+            }
+        }
+        
+        /**
+         * Get the first object out of the queue. Return null if the queue
+         * is empty. 
+         */
+        public Worker pop() {
+            if (end > 0) {
+                return workers[--end];
+            }
+            return null;
+        }
+        
+        /**
+         * Get the first object out of the queue, Return null if the queue
+         * is empty.
+         */
+        public Worker peek() {
+            return workers[end];
+        }
+        
+        /**
+         * Is the queue empty?
+         */
+        public boolean isEmpty() {
+            return (end == 0);
+        }
+        
+        /**
+         * How many elements are there in this queue?
+         */
+        public int size() {
+            return (end);
+        }
+        
+        /**
+         * Resize the queue. If there are too many objects in the queue for the
+         * new size, drop the excess.
+         * 
+         * @param newSize
+         */
+        public void resize(int newSize) {
+            Worker[] newWorkers = new Worker[newSize];
+            int len = workers.length;
+            if (newSize < len) {
+                len = newSize;
+            }
+            System.arraycopy(workers, 0, newWorkers, 0, len);
+            workers = newWorkers;
+        }
+    }
+
+}

Added: geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/LeaderFollowerWorkerThread.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/LeaderFollowerWorkerThread.java?rev=1214761&view=auto
==============================================================================
--- geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/LeaderFollowerWorkerThread.java (added)
+++ geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/LeaderFollowerWorkerThread.java Thu Dec 15 13:55:25 2011
@@ -0,0 +1,87 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 java.net.Socket;
+import org.apache.tomcat.util.threads.ThreadPoolRunnable;
+
+/*
+ * I switched the threading model here.
+ *
+ * We used to have a "listener" thread and a "connection"
+ * thread, this results in code simplicity but also a needless
+ * thread switch.
+ *
+ * Instead I am now using a pool of threads, all the threads are
+ * simmetric in their execution and no thread switch is needed.
+ */
+class LeaderFollowerWorkerThread implements ThreadPoolRunnable {
+    /* This is not a normal Runnable - it gets attached to an existing
+       thread, runs and when run() ends - the thread keeps running.
+
+       It's better to keep the name ThreadPoolRunnable - avoid confusion.
+       We also want to use per/thread data and avoid sync wherever possible.
+    */
+    PoolTcpEndpoint endpoint;
+    
+    public LeaderFollowerWorkerThread(PoolTcpEndpoint endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    public Object[] getInitData() {
+        // no synchronization overhead, but 2 array access 
+        Object obj[]=new Object[2];
+        obj[1]= endpoint.getConnectionHandler().init();
+        obj[0]=new TcpConnection();
+        return obj;
+    }
+    
+    public void runIt(Object perThrData[]) {
+
+        // Create per-thread cache
+        if (endpoint.isRunning()) {
+
+            // Loop if endpoint is paused
+            while (endpoint.isPaused()) {
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    // Ignore
+                }
+            }
+
+            // Accept a new connection
+            Socket s = null;
+            try {
+                s = endpoint.acceptSocket();
+            } finally {
+                // Continue accepting on another thread...
+                if (endpoint.isRunning()) {
+                    endpoint.tp.runIt(this);
+                }
+            }
+
+            // Process the connection
+            if (null != s) {
+                endpoint.processSocket(s, (TcpConnection) perThrData[0], (Object[]) perThrData[1]);
+            }
+
+        }
+    }
+    
+}

Added: geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/MasterSlaveWorkerThread.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/MasterSlaveWorkerThread.java?rev=1214761&view=auto
==============================================================================
--- geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/MasterSlaveWorkerThread.java (added)
+++ geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/MasterSlaveWorkerThread.java Thu Dec 15 13:55:25 2011
@@ -0,0 +1,151 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 java.net.Socket;
+
+import org.apache.tomcat.util.threads.ThreadWithAttributes;
+
+/**
+ * Regular master slave thread pool. Slave threads will wait for work.
+ */
+class MasterSlaveWorkerThread implements Runnable {
+
+    protected PoolTcpEndpoint endpoint;
+    protected String threadName;
+    protected boolean stopped = false;
+    private Object threadSync = new Object();
+    private Thread thread = null;
+    private boolean available = false;
+    private Socket socket = null;
+    private TcpConnection con = new TcpConnection();
+    private Object[] threadData = null;
+
+    
+    public MasterSlaveWorkerThread(PoolTcpEndpoint endpoint, String threadName) {
+        this.endpoint = endpoint;
+        this.threadName = threadName;
+    }
+
+
+    /**
+     * Process an incoming TCP/IP connection on the specified socket.  Any
+     * exception that occurs during processing must be logged and swallowed.
+     * <b>NOTE</b>:  This method is called from our Connector's thread.  We
+     * must assign it to our own thread so that multiple simultaneous
+     * requests can be handled.
+     *
+     * @param socket TCP socket to process
+     */
+    synchronized void assign(Socket socket) {
+
+        // Wait for the Processor to get the previous Socket
+        while (available) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+            }
+        }
+
+        // Store the newly available Socket and notify our thread
+        this.socket = socket;
+        available = true;
+        notifyAll();
+
+    }
+
+    
+    /**
+     * Await a newly assigned Socket from our Connector, or <code>null</code>
+     * if we are supposed to shut down.
+     */
+    private synchronized Socket await() {
+
+        // Wait for the Connector to provide a new Socket
+        while (!available) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+            }
+        }
+
+        // Notify the Connector that we have received this Socket
+        Socket socket = this.socket;
+        available = false;
+        notifyAll();
+
+        return (socket);
+
+    }
+
+
+
+    /**
+     * The background thread that listens for incoming TCP/IP connections and
+     * hands them off to an appropriate processor.
+     */
+    public void run() {
+
+        // Process requests until we receive a shutdown signal
+        while (!stopped) {
+
+            // Wait for the next socket to be assigned
+            Socket socket = await();
+            if (socket == null)
+                continue;
+
+            // Process the request from this socket
+            endpoint.processSocket(socket, con, threadData);
+
+            // Finish up this request
+            endpoint.recycleWorkerThread(this);
+
+        }
+
+        // Tell threadStop() we have shut ourselves down successfully
+        synchronized (threadSync) {
+            threadSync.notifyAll();
+        }
+
+    }
+
+
+    /**
+     * Start the background processing thread.
+     */
+    public void start() {
+        threadData = endpoint.getConnectionHandler().init();
+        thread = new ThreadWithAttributes(null, this);
+        thread.setName(threadName);
+        thread.setDaemon(true);
+        thread.start();
+    }
+
+
+    /**
+     * Stop the background processing thread.
+     */
+    public void stop() {
+        stopped = true;
+        assign(null);
+        thread = null;
+        threadData = null;
+    }
+
+
+}

Added: geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioBlockingSelector.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioBlockingSelector.java?rev=1214761&view=auto
==============================================================================
--- geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioBlockingSelector.java (added)
+++ geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioBlockingSelector.java Thu Dec 15 13:55:25 2011
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.io.EOFException;
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.nio.ByteBuffer;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.MutableInteger;
+import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class NioBlockingSelector {
+    
+    protected static Log log = LogFactory.getLog(NioBlockingSelector.class);
+    
+    private static int threadCounter = 0;
+    
+    protected Selector sharedSelector;
+    
+    protected BlockPoller poller;
+    public NioBlockingSelector() {
+        
+    }
+    
+    public void open(Selector selector) {
+        sharedSelector = selector;
+        poller = new BlockPoller();
+        poller.selector = sharedSelector;
+        poller.setDaemon(true);
+        poller.setName("NioBlockingSelector.BlockPoller-"+(++threadCounter));
+        poller.start();
+    }
+    
+    public void close() {
+        if (poller!=null) {
+            poller.disable();
+            poller.interrupt();
+            poller = null;
+        }
+    }
+
+    /**
+     * Performs a blocking write using the bytebuffer for data to be written
+     * If the <code>selector</code> parameter is null, then it will perform a busy write that could
+     * take up a lot of CPU cycles.
+     * @param buf ByteBuffer - the buffer containing the data, we will write as long as <code>(buf.hasRemaining()==true)</code>
+     * @param socket SocketChannel - the socket to write data to
+     * @param writeTimeout long - the timeout for this write operation in milliseconds, -1 means no timeout
+     * @return int - returns the number of bytes written
+     * @throws EOFException if write returns -1
+     * @throws SocketTimeoutException if the write times out
+     * @throws IOException if an IO Exception occurs in the underlying socket logic
+     */
+    public int write(ByteBuffer buf, NioChannel socket, long writeTimeout,MutableInteger lastWrite) throws IOException {
+        SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
+        if ( key == null ) throw new IOException("Key no longer registered");
+        KeyReference reference = new KeyReference();
+        KeyAttachment att = (KeyAttachment) key.attachment();
+        int written = 0;
+        boolean timedout = false;
+        int keycount = 1; //assume we can write
+        long time = System.currentTimeMillis(); //start the timeout timer
+        try {
+            while ( (!timedout) && buf.hasRemaining()) {
+                if (keycount > 0) { //only write if we were registered for a write
+                    int cnt = socket.write(buf); //write the data
+                    lastWrite.set(cnt);
+                    if (cnt == -1)
+                        throw new EOFException();
+                    written += cnt;
+                    if (cnt > 0) {
+                        time = System.currentTimeMillis(); //reset our timeout timer
+                        continue; //we successfully wrote, try again without a selector
+                    }
+                }
+                try {
+                    if ( att.getWriteLatch()==null || att.getWriteLatch().getCount()==0) att.startWriteLatch(1);
+                    poller.add(att,SelectionKey.OP_WRITE,reference);
+                    att.awaitWriteLatch(writeTimeout,TimeUnit.MILLISECONDS);
+                }catch (InterruptedException ignore) {
+                    Thread.interrupted();
+                }
+                if ( att.getWriteLatch()!=null && att.getWriteLatch().getCount()> 0) {
+                    //we got interrupted, but we haven't received notification from the poller.
+                    keycount = 0;
+                }else {
+                    //latch countdown has happened
+                    keycount = 1;
+                    att.resetWriteLatch();
+                }
+
+                if (writeTimeout > 0 && (keycount == 0))
+                    timedout = (System.currentTimeMillis() - time) >= writeTimeout;
+            } //while
+            if (timedout) 
+                throw new SocketTimeoutException();
+        } finally {
+            poller.remove(att,SelectionKey.OP_WRITE);
+            if (timedout && reference.key!=null) {
+                poller.cancelKey(reference.key);
+            }
+            reference.key = null;
+        }
+        return written;
+    }
+
+    /**
+     * Performs a blocking read using the bytebuffer for data to be read
+     * If the <code>selector</code> parameter is null, then it will perform a busy read that could
+     * take up a lot of CPU cycles.
+     * @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
+     * @param socket SocketChannel - the socket to write data to
+     * @param selector Selector - the selector to use for blocking, if null then a busy read will be initiated
+     * @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
+     * @return int - returns the number of bytes read
+     * @throws EOFException if read returns -1
+     * @throws SocketTimeoutException if the read times out
+     * @throws IOException if an IO Exception occurs in the underlying socket logic
+     */
+    public int read(ByteBuffer buf, NioChannel socket, long readTimeout) throws IOException {
+        SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
+        if ( key == null ) throw new IOException("Key no longer registered");
+        KeyReference reference = new KeyReference();
+        KeyAttachment att = (KeyAttachment) key.attachment();
+        int read = 0;
+        boolean timedout = false;
+        int keycount = 1; //assume we can write
+        long time = System.currentTimeMillis(); //start the timeout timer
+        try {
+            while ( (!timedout) && read == 0) {
+                if (keycount > 0) { //only read if we were registered for a read
+                    int cnt = socket.read(buf);
+                    if (cnt == -1)
+                        throw new EOFException();
+                    read += cnt;
+                    if (cnt > 0)
+                        break;
+                }
+                try {
+                    if ( att.getReadLatch()==null || att.getReadLatch().getCount()==0) att.startReadLatch(1);
+                    poller.add(att,SelectionKey.OP_READ, reference);
+                    att.awaitReadLatch(readTimeout,TimeUnit.MILLISECONDS);
+                }catch (InterruptedException ignore) {
+                    Thread.interrupted();
+                }
+                if ( att.getReadLatch()!=null && att.getReadLatch().getCount()> 0) {
+                    //we got interrupted, but we haven't received notification from the poller.
+                    keycount = 0;
+                }else {
+                    //latch countdown has happened
+                    keycount = 1;
+                    att.resetReadLatch();
+                }
+                if (readTimeout > 0 && (keycount == 0))
+                    timedout = (System.currentTimeMillis() - time) >= readTimeout;
+            } //while
+            if (timedout)
+                throw new SocketTimeoutException();
+        } finally {
+            poller.remove(att,SelectionKey.OP_READ);
+            if (timedout && reference.key!=null) {
+                poller.cancelKey(reference.key);
+            }
+            reference.key = null;
+        }
+        return read;
+    }
+
+    
+    protected class BlockPoller extends Thread {
+        protected boolean run = true;
+        protected Selector selector = null;
+        protected ConcurrentLinkedQueue<Runnable> events = new ConcurrentLinkedQueue<Runnable>();
+        public void disable() { run = false; selector.wakeup();}
+        protected AtomicInteger wakeupCounter = new AtomicInteger(0);
+        public void cancelKey(final SelectionKey key) {
+            Runnable r = new Runnable() {
+                public void run() {
+                    key.cancel();
+                }
+            };
+            events.offer(r);
+            wakeup();
+        }
+
+        public void wakeup() {
+            if (wakeupCounter.addAndGet(1)==0) selector.wakeup();
+        }
+
+        public void cancel(SelectionKey sk, KeyAttachment key, int ops){
+            if (sk!=null) {
+                sk.cancel();
+                sk.attach(null);
+                if (SelectionKey.OP_WRITE==(ops&SelectionKey.OP_WRITE)) countDown(key.getWriteLatch());
+                if (SelectionKey.OP_READ==(ops&SelectionKey.OP_READ))countDown(key.getReadLatch());
+            }
+        }
+        
+        public void add(final KeyAttachment key, final int ops, final KeyReference ref) {
+            Runnable r = new Runnable() {
+                public void run() {
+                    if ( key == null ) return;
+                    NioChannel nch = key.getChannel();
+                    if ( nch == null ) return;
+                    SocketChannel ch = nch.getIOChannel();
+                    if ( ch == null ) return;
+                    SelectionKey sk = ch.keyFor(selector);
+                    try {
+                        if (sk == null) {
+                            sk = ch.register(selector, ops, key);
+                            ref.key = sk;
+                        } else if (!sk.isValid()) {
+                            cancel(sk,key,ops);
+                        } else {
+                            sk.interestOps(sk.interestOps() | ops);
+                        }
+                    }catch (CancelledKeyException cx) {
+                        cancel(sk,key,ops);
+                    }catch (ClosedChannelException cx) {
+                        cancel(sk,key,ops);
+                    }
+                }
+            };
+            events.offer(r);
+            wakeup();
+        }
+        
+        public void remove(final KeyAttachment key, final int ops) {
+            Runnable r = new Runnable() {
+                public void run() {
+                    if ( key == null ) return;
+                    NioChannel nch = key.getChannel();
+                    if ( nch == null ) return;
+                    SocketChannel ch = nch.getIOChannel();
+                    if ( ch == null ) return;
+                    SelectionKey sk = ch.keyFor(selector);
+                    try {
+                        if (sk == null) {
+                            if (SelectionKey.OP_WRITE==(ops&SelectionKey.OP_WRITE)) countDown(key.getWriteLatch());
+                            if (SelectionKey.OP_READ==(ops&SelectionKey.OP_READ))countDown(key.getReadLatch());
+                        } else {
+                            if (sk.isValid()) {
+                            	sk.interestOps(sk.interestOps() & (~ops));
+                            	if (SelectionKey.OP_WRITE==(ops&SelectionKey.OP_WRITE)) countDown(key.getWriteLatch());
+                            	if (SelectionKey.OP_READ==(ops&SelectionKey.OP_READ))countDown(key.getReadLatch());
+                            	if (sk.interestOps()==0) {
+                            	    sk.cancel();
+                            	    sk.attach(null);
+                            	}
+                            }else {
+                                sk.cancel();
+                                sk.attach(null);
+                            }
+                        }
+                    }catch (CancelledKeyException cx) {
+                        if (sk!=null) {
+                            sk.cancel();
+                            sk.attach(null);
+                        }
+                    }
+                }
+            };
+            events.offer(r);
+            wakeup();
+        }
+
+
+        public boolean events() {
+            boolean result = false;
+            Runnable r = null;
+            result = (events.size() > 0);
+            while ( (r = events.poll()) != null ) {
+                r.run();
+                result = true;
+            }
+            return result;
+        }
+
+        public void run() {
+            while (run) {
+                try {
+                    events();
+                    int keyCount = 0;
+                    try {
+                        int i = wakeupCounter.get();
+                        if (i>0) 
+                            keyCount = selector.selectNow();
+                        else {
+                            wakeupCounter.set(-1);
+                            keyCount = selector.select(1000);
+                        }
+                        wakeupCounter.set(0);
+                        if (!run) break;
+                    }catch ( NullPointerException x ) {
+                        //sun bug 5076772 on windows JDK 1.5
+                        if (selector==null) throw x;
+                        if ( log.isDebugEnabled() ) log.debug("Possibly encountered sun bug 5076772 on windows JDK 1.5",x);
+                        continue;
+                    } catch ( CancelledKeyException x ) {
+                        //sun bug 5076772 on windows JDK 1.5
+                        if ( log.isDebugEnabled() ) log.debug("Possibly encountered sun bug 5076772 on windows JDK 1.5",x);
+                        continue;
+                    } catch (Throwable x) {
+                        log.error("",x);
+                        continue;
+                    }
+
+                    Iterator<SelectionKey> iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null;
+
+                    // Walk through the collection of ready keys and dispatch
+                    // any active event.
+                    while (run && iterator != null && iterator.hasNext()) {
+                        SelectionKey sk = iterator.next();
+                        KeyAttachment attachment = (KeyAttachment)sk.attachment();
+                        try {
+                            attachment.access();
+                            iterator.remove(); ;
+                            sk.interestOps(sk.interestOps() & (~sk.readyOps()));
+                            if ( sk.isReadable() ) {
+                                countDown(attachment.getReadLatch());
+                            }
+                            if (sk.isWritable()) {
+                                countDown(attachment.getWriteLatch());
+                            }
+                        }catch (CancelledKeyException ckx) {
+                            if (sk!=null) sk.cancel();
+                            countDown(attachment.getReadLatch());
+                            countDown(attachment.getWriteLatch());
+                        }
+                    }//while
+                }catch ( Throwable t ) {
+                    log.error("",t);
+                }
+            }
+            events.clear();
+            try {
+                selector.selectNow();//cancel all remaining keys
+            }catch( Exception ignore ) {
+                if (log.isDebugEnabled())log.debug("",ignore);
+            }
+            try {
+                selector.close();//Close the connector
+            }catch( Exception ignore ) {
+                if (log.isDebugEnabled())log.debug("",ignore);
+            }
+        }
+        
+        public void countDown(CountDownLatch latch) {
+            if ( latch == null ) return;
+            latch.countDown();
+        }
+    }
+    
+    public class KeyReference {
+        SelectionKey key = null;
+        
+        @Override
+        public void finalize() {
+            if (key!=null && key.isValid()) {
+                log.warn("Possible key leak, cancelling key in the finalizer.");
+                try {key.cancel();}catch (Exception ignore){}
+            }
+            key = null;
+        }
+    }
+
+}
\ No newline at end of file

Added: geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioChannel.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioChannel.java?rev=1214761&view=auto
==============================================================================
--- geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioChannel.java (added)
+++ geronimo/external/trunk/tomcat-parent-6.0.35/catalina/src/main/java/org/apache/tomcat/util/net/NioChannel.java Thu Dec 15 13:55:25 2011
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.SocketChannel;
+
+import org.apache.tomcat.util.net.NioEndpoint.Poller;
+import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
+import org.apache.tomcat.util.MutableInteger;
+
+/**
+ * 
+ * Base class for a SocketChannel wrapper used by the endpoint.
+ * This way, logic for a SSL socket channel remains the same as for
+ * a non SSL, making sure we don't need to code for any exception cases.
+ * 
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class NioChannel implements ByteChannel{
+
+    protected static ByteBuffer emptyBuf = ByteBuffer.allocate(0);
+
+    protected SocketChannel sc = null;
+
+    protected ApplicationBufferHandler bufHandler;
+
+    protected Poller poller;
+    
+    protected boolean sendFile = false;
+
+    public NioChannel(SocketChannel channel, ApplicationBufferHandler bufHandler) throws IOException {
+        this.sc = channel;
+        this.bufHandler = bufHandler;
+    }
+
+    public void reset() throws IOException {
+        bufHandler.getReadBuffer().clear();
+        bufHandler.getWriteBuffer().clear();
+        this.sendFile = false;
+    }
+    
+    public int getBufferSize() {
+        if ( bufHandler == null ) return 0;
+        int size = 0;
+        size += bufHandler.getReadBuffer()!=null?bufHandler.getReadBuffer().capacity():0;
+        size += bufHandler.getWriteBuffer()!=null?bufHandler.getWriteBuffer().capacity():0;
+        return size;
+    }
+
+    /**
+     * returns true if the network buffer has 
+     * been flushed out and is empty
+     * @return boolean
+     */
+    public boolean flush(boolean block, Selector s, long timeout,MutableInteger lastWrite) throws IOException {
+        if (lastWrite!=null) lastWrite.set(1);
+        return true; //no network buffer in the regular channel
+    }
+
+
+    /**
+     * Closes this channel.
+     *
+     * @throws IOException If an I/O error occurs
+     * @todo Implement this java.nio.channels.Channel method
+     */
+    public void close() throws IOException {
+        getIOChannel().socket().close();
+        getIOChannel().close();
+    }
+
+    public void close(boolean force) throws IOException {
+        if (isOpen() || force ) close();
+    }
+    /**
+     * Tells whether or not this channel is open.
+     *
+     * @return <tt>true</tt> if, and only if, this channel is open
+     * @todo Implement this java.nio.channels.Channel method
+     */
+    public boolean isOpen() {
+        return sc.isOpen();
+    }
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * @param src The buffer from which bytes are to be retrieved
+     * @return The number of bytes written, possibly zero
+     * @throws IOException If some other I/O error occurs
+     * @todo Implement this java.nio.channels.WritableByteChannel method
+     */
+    public int write(ByteBuffer src) throws IOException {
+        return sc.write(src);
+    }
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * @param dst The buffer into which bytes are to be transferred
+     * @return The number of bytes read, possibly zero, or <tt>-1</tt> if the channel has reached end-of-stream
+     * @throws IOException If some other I/O error occurs
+     * @todo Implement this java.nio.channels.ReadableByteChannel method
+     */
+    public int read(ByteBuffer dst) throws IOException {
+        return sc.read(dst);
+    }
+
+    public Object getAttachment(boolean remove) {
+        Poller pol = getPoller();
+        Selector sel = pol!=null?pol.getSelector():null;
+        SelectionKey key = sel!=null?getIOChannel().keyFor(sel):null;
+        Object att = key!=null?key.attachment():null;
+        if (key != null && att != null && remove ) key.attach(null);
+        return att;
+    }
+    /**
+     * getBufHandler
+     *
+     * @return ApplicationBufferHandler
+     * @todo Implement this org.apache.tomcat.util.net.SecureNioChannel method
+     */
+    public ApplicationBufferHandler getBufHandler() {
+        return bufHandler;
+    }
+
+    public Poller getPoller() {
+        return poller;
+    }
+    /**
+     * getIOChannel
+     *
+     * @return SocketChannel
+     * @todo Implement this org.apache.tomcat.util.net.SecureNioChannel method
+     */
+    public SocketChannel getIOChannel() {
+        return sc;
+    }
+
+    /**
+     * isClosing
+     *
+     * @return boolean
+     * @todo Implement this org.apache.tomcat.util.net.SecureNioChannel method
+     */
+    public boolean isClosing() {
+        return false;
+    }
+
+    /**
+     * isInitHandshakeComplete
+     *
+     * @return boolean
+     * @todo Implement this org.apache.tomcat.util.net.SecureNioChannel method
+     */
+    public boolean isInitHandshakeComplete() {
+        return true;
+    }
+
+    public int handshake(boolean read, boolean write) throws IOException {
+        return 0;
+    }
+
+    public void setPoller(Poller poller) {
+        this.poller = poller;
+    }
+
+    public void setIOChannel(SocketChannel IOChannel) {
+        this.sc = IOChannel;
+    }
+
+    public String toString() {
+        return super.toString()+":"+this.sc.toString();
+    }
+    
+    public int getOutboundRemaining() {
+        return 0;
+    }
+    
+    /**
+     * Return true if the buffer wrote data
+     * @return
+     * @throws IOException
+     */
+    public boolean flushOutbound() throws IOException {
+        return false;
+    }
+    
+    public boolean isSendFile() {
+        return sendFile;
+    }
+    
+    public void setSendFile(boolean s) {
+        this.sendFile = s;
+    }
+    
+
+}



Mime
View raw message