Author: fhanik
Date: Wed Oct 25 15:11:10 2006
New Revision: 467787

URL: http://svn.apache.org/viewvc?view=rev&rev=467787
Log:
Documented socket properties
Added in the ability to cache bytebuffers based on number of channels or number 
of bytes
Added in nonGC poller events to lower CPU usage during high traffic 

Modified:
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java

Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java?view=diff&rev=467787&r1=467786&r2=467787
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java Wed 
Oct 25 15:11:10 2006
@@ -55,6 +55,14 @@
         bufHandler.getReadBuffer().clear();
         bufHandler.getWriteBuffer().clear();
     }
+    
+    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 

Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?view=diff&rev=467787&r1=467786&r2=467787
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed 
Oct 25 15:11:10 2006
@@ -47,6 +47,7 @@
 import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * NIO tailored thread pool, providing the following services:
@@ -150,6 +151,8 @@
 
 
     protected ConcurrentLinkedQueue<NioChannel> nioChannels = new 
ConcurrentLinkedQueue<NioChannel>() {
+        protected AtomicInteger size = new AtomicInteger(0);
+        protected AtomicInteger bytes = new AtomicInteger(0);
         public boolean offer(NioChannel socket) {
             Poller pol = socket.getPoller();
             Selector sel = pol!=null?pol.getSelector():null;
@@ -157,13 +160,32 @@
             KeyAttachment att = key!=null?(KeyAttachment)key.attachment():null;
             if ( att!=null ) att.reset();
             if ( key!=null ) key.attach(null);
+            boolean offer = 
socketProperties.getBufferPool()==-1?true:size.get()<socketProperties.getBufferPool();
+            offer = offer && 
(socketProperties.getBufferPoolSize()==-1?true:(bytes.get()+socket.getBufferSize())<socketProperties.getBufferPoolSize());
             //avoid over growing our cache or add after we have stopped
-            if ( running && (!paused) && (size() < 
socketProperties.getDirectBufferPool()) ) return super.offer(socket);
+            if ( running && (!paused) && (offer) ) {
+                boolean result = super.offer(socket);
+                if ( result ) {
+                    size.incrementAndGet();
+                    bytes.addAndGet(socket.getBufferSize());
+                }
+                return result;
+            }
             else return false;
         }
         
         public NioChannel poll() {
-            return super.poll();
+            NioChannel result = super.poll();
+            if ( result != null ) {
+                size.decrementAndGet();
+                bytes.addAndGet(-result.getBufferSize());
+            }
+            return result;
+        }
+        
+        public void clear() {
+            super.clear();
+            size.set(0);
         }
     };
 
@@ -940,16 +962,62 @@
     }
 
 
-    // ----------------------------------------------------- Poller Inner Class
-
+    // ----------------------------------------------------- Poller Inner 
Classes
 
     /**
+     * 
+     * PollerEvent, cacheable object for poller events to avoid GC
+     */
+    public class PollerEvent implements Runnable {
+        protected NioChannel socket;
+        protected int interestOps;
+        public PollerEvent(NioChannel ch, int intOps) {
+            reset(ch, intOps);
+        }
+    
+        public void reset(NioChannel ch, int intOps) {
+            socket = ch;
+            interestOps = intOps;
+        }
+    
+        public void reset() {
+            reset(null, 0);
+        }
+    
+        public void run() {
+            final SelectionKey key = 
socket.getIOChannel().keyFor(socket.getPoller().getSelector());
+            final KeyAttachment att = (KeyAttachment) key.attachment();
+            try {
+                if (key != null) {
+                    key.interestOps(interestOps);
+                    att.interestOps(interestOps);
+                }
+            }
+            catch (CancelledKeyException ckx) {
+                try {
+                    if (key != null && key.attachment() != null) {
+                        KeyAttachment ka = (KeyAttachment) key.attachment();
+                        ka.setError(true); //set to collect this socket 
immediately
+                    }
+                    try {
+                        socket.close();
+                    }
+                    catch (Exception ignore) {}
+                    if (socket.isOpen())
+                        socket.close(true);
+                }
+                catch (Exception ignore) {}
+            }
+        }
+    }
+    /**
      * Poller class.
      */
     public class Poller implements Runnable {
 
         protected Selector selector;
-        protected ConcurrentLinkedQueue events = new ConcurrentLinkedQueue();
+        protected ConcurrentLinkedQueue<Runnable> events = new 
ConcurrentLinkedQueue<Runnable>();
+        protected ConcurrentLinkedQueue<PollerEvent> eventCache = new 
ConcurrentLinkedQueue<PollerEvent>();
         
         protected boolean close = false;
         protected long nextExpiration = 0;//optimize expiration handling
@@ -1000,30 +1068,15 @@
          * @param socket to add to the poller
          */
         public void add(final NioChannel socket) {
-            final SelectionKey key = socket.getIOChannel().keyFor(selector);
-            final KeyAttachment att = (KeyAttachment)key.attachment();
-            Runnable r = new Runnable() {
-                public void run() {
-                    try {
-                        if (key != null) {
-                            key.interestOps(SelectionKey.OP_READ);
-                            att.interestOps(SelectionKey.OP_READ);
-                        }
-                    }catch ( CancelledKeyException ckx ) {
-                        try {
-                            if ( key != null && key.attachment() != null ) {
-                                KeyAttachment ka = 
(KeyAttachment)key.attachment();
-                                ka.setError(true); //set to collect this 
socket immediately
-                            }
-                            try {socket.close();}catch (Exception ignore){}
-                            if ( socket.isOpen() ) socket.close(true);
-                        } catch ( Exception ignore ) {}
-                    }
-                }
-            };
+            add(socket,SelectionKey.OP_READ);
+        }
+        
+        public void add(final NioChannel socket, final int interestOps) {
+            PollerEvent r = this.eventCache.poll();
+            if ( r==null) r = new PollerEvent(socket,interestOps);
             addEvent(r);
         }
-
+        
         public boolean events() {
             boolean result = false;
             //synchronized (events) {
@@ -1032,6 +1085,10 @@
                 while ( (r = (Runnable)events.poll()) != null ) {
                     try {
                         r.run();
+                        if ( r instanceof PollerEvent ) {
+                            ((PollerEvent)r).reset();
+                            eventCache.offer((PollerEvent)r);
+                        }
                     } catch ( Exception x ) {
                         log.error("",x);
                     }
@@ -1049,7 +1106,6 @@
             Runnable r = new Runnable() {
                 public void run() {
                     try {
-                        
                         socket.getIOChannel().register(selector, 
SelectionKey.OP_READ, ka);
                     } catch (Exception x) {
                         log.error("", x);
@@ -1398,25 +1454,7 @@
                             final SelectionKey fk = key;
                             final int intops = handshake;
                             final KeyAttachment ka = 
(KeyAttachment)fk.attachment();
-                            //register for handshake ops
-                            Runnable r = new Runnable() {
-                                public void run() {
-                                    try {
-                                        fk.interestOps(intops);
-                                        ka.interestOps(intops);
-                                    } catch (CancelledKeyException ckx) {
-                                        try {
-                                            if ( fk != null && fk.attachment() 
!= null ) {
-                                                ka.setError(true); //set to 
collect this socket immediately
-                                                try 
{ka.getChannel().getIOChannel().socket().close();}catch(Exception ignore){}
-                                                try 
{ka.getChannel().close();}catch(Exception ignore){}
-                                            }
-                                        } catch (Exception ignore) {}
-                                    }
-
-                                }
-                            };
-                            ka.getPoller().addEvent(r);
+                            ka.getPoller().add(socket,intops);
                         }
                     }
                 } finally {

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?view=diff&rev=467787&r1=467786&r2=467787
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java 
Wed Oct 25 15:11:10 2006
@@ -68,8 +68,15 @@
         //initiate handshake
         sslEngine.beginHandshake();
         initHandshakeStatus = sslEngine.getHandshakeStatus();
-
     }
+    
+    public int getBufferSize() {
+        int size = super.getBufferSize();
+        size += netInBuffer!=null?netInBuffer.capacity():0;
+        size += netOutBuffer!=null?netOutBuffer.capacity():0;
+        return size;
+    }
+
     
 
//===========================================================================================
    
 //                  NIO SSL METHODS

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java?view=diff&rev=467787&r1=467786&r2=467787
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java 
Wed Oct 25 15:11:10 2006
@@ -4,21 +4,92 @@
 import java.net.SocketException;
 
 public class SocketProperties {
+    /**
+     * Enable/disable direct buffers for the network buffers
+     * Default value is enabled
+     */
     protected boolean directBuffer = true;
+    /**
+     * Socket receive buffer size in bytes (SO_RCVBUF)
+     * Default value is 25188
+     */
     protected int rxBufSize = 25188;
+    /**
+     * Socket send buffer size in bytes (SO_SNDBUF)
+     * Default value is 43800
+     */
     protected int txBufSize = 43800;
-    protected int directBufferPool = 500;
     
+    /**
+     * NioChannel pool size for the endpoint,
+     * this value is how many channels
+     * -1 means unlimited cached, 0 means no cache
+     * Default value is 500
+     */
+    protected int bufferPool = 500;
+    
+
+    /**
+     * Buffer pool size in bytes to be cached
+     * -1 means unlimited, 0 means no cache
+     * Default value is 100MB (1024*1024*100 bytes)
+     */
+    protected int bufferPoolSize = 1024*1024*100;
+    
+    /**
+     * TCP_NO_DELAY option, default is false
+     */
     protected boolean tcpNoDelay = false;
+    /**
+     * SO_KEEPALIVE option, default is false
+     */
     protected boolean soKeepAlive = false;
+    /**
+     * OOBINLINE option, default is true
+     */
     protected boolean ooBInline = true;
+    /**
+     * SO_REUSEADDR option, default is true
+     */
     protected boolean soReuseAddress = true;
+    /**
+     * SO_LINGER option, default is true, paired with the 
<code>soLingerTime</code> value
+     */
     protected boolean soLingerOn = true;
+    /**
+     * SO_LINGER option, default is 25 seconds.
+     */
     protected int soLingerTime = 25;
+    /**
+     * SO_TIMEOUT option, default is 5000 milliseconds
+     */
     protected int soTimeout = 5000;
+    /**
+     * Traffic class option, value between 0 and 255
+     * IPTOS_LOWCOST (0x02)
+     * IPTOS_RELIABILITY (0x04)
+     * IPTOS_THROUGHPUT (0x08)
+     * IPTOS_LOWDELAY (0x10)
+     * Default value is 0x04 | 0x08 | 0x010
+     */
     protected int soTrafficClass = 0x04 | 0x08 | 0x010;
+    /**
+     * Performance preferences according to
+     * 
http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int)
+     * Default value is 1
+     */
     protected int performanceConnectionTime = 1;
+    /**
+     * Performance preferences according to
+     * 
http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int)
+     * Default value is 0
+     */
     protected int performanceLatency = 0;
+    /**
+     * Performance preferences according to
+     * 
http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int)
+     * Default value is 1
+     */
     protected int performanceBandwidth = 1;
     
 
@@ -91,8 +162,16 @@
         return txBufSize;
     }
 
+    public int getBufferPool() {
+        return bufferPool;
+    }
+
+    public int getBufferPoolSize() {
+        return bufferPoolSize;
+    }
+
     public int getDirectBufferPool() {
-        return directBufferPool;
+        return bufferPool;
     }
 
     public void setPerformanceConnectionTime(int performanceConnectionTime) {
@@ -151,8 +230,16 @@
         this.soLingerOn = soLingerOn;
     }
 
+    public void setBufferPool(int bufferPool) {
+        this.bufferPool = bufferPool;
+    }
+
+    public void setBufferPoolSize(int bufferPoolSize) {
+        this.bufferPoolSize = bufferPoolSize;
+    }
+
     public void setDirectBufferPool(int directBufferPool) {
-        this.directBufferPool = directBufferPool;
+        this.bufferPool = directBufferPool;
     }
 
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to