Author: fhanik
Date: Tue Jul  7 17:21:15 2009
New Revision: 791914

URL: http://svn.apache.org/viewvc?rev=791914&view=rev
Log:
Improve shutdown time for NIO connectors, to block in a minimal fashion, yet 
leave the pollers time to close out their connections

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SocketProperties.java
    tomcat/trunk/webapps/docs/config/http.xml

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=791914&r1=791913&r2=791914&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Tue Jul  7 
17:21:15 2009
@@ -23,6 +23,8 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
 import java.nio.ByteBuffer;
 import java.nio.channels.CancelledKeyException;
 import java.nio.channels.FileChannel;
@@ -171,7 +173,10 @@
      */
     protected AtomicInteger activeSocketProcessors = new AtomicInteger(0);
     
-    
+    /**
+     * 
+     */
+    protected volatile CountDownLatch stopLatch = null;
     
     /**
      * Cache for SocketProcessor objects
@@ -791,6 +796,7 @@
         InetSocketAddress addr = (address!=null?new 
InetSocketAddress(address,port):new InetSocketAddress(port));
         serverSock.socket().bind(addr,backlog); 
         serverSock.configureBlocking(true); //mimic APR behavior
+        serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout());
 
         // Initialize thread count defaults for acceptor, poller
         if (acceptorThreadCount == 0) {
@@ -801,6 +807,7 @@
             //minimum one poller thread
             pollerThreadCount = 1;
         }
+        stopLatch = new CountDownLatch(pollerThreadCount);
 
         // Initialize SSL if needed
         if (isSSLEnabled()) {
@@ -933,6 +940,7 @@
                 pollers[i].destroy();
                 pollers[i] = null;
             }
+            try { stopLatch.await(selectorTimeout+100,TimeUnit.MILLISECONDS); 
} catch (InterruptedException ignore ) {}
         }
         eventCache.clear();
         keyCache.clear();
@@ -942,7 +950,7 @@
             if ( executor instanceof ThreadPoolExecutor ) {
                 //this is our internal one, so we need to shut it down
                 ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor;
-                tpe.shutdown();
+                tpe.shutdownNow();
                 TaskQueue queue = (TaskQueue) tpe.getQueue();
                 queue.setParent(null);
             }
@@ -956,6 +964,9 @@
      * Deallocate NIO memory pools, and close server socket.
      */
     public void destroy() throws Exception {
+        if (log.isDebugEnabled()) {
+            log.debug("Destroy initiated for "+new 
InetSocketAddress(address,port));
+        }
         if (running) {
             stop();
         }
@@ -967,6 +978,9 @@
         initialized = false;
         releaseCaches();
         selectorPool.close();
+        if (log.isDebugEnabled()) {
+            log.debug("Destroy completed for "+new 
InetSocketAddress(address,port));
+        }
     }
 
 
@@ -1007,17 +1021,23 @@
      */
     protected void unlockAccept() {
         java.net.Socket s = null;
+        InetSocketAddress saddr = null;
         try {
             // Need to create a connection to unlock the accept();
             if (address == null) {
-                s = new java.net.Socket("127.0.0.1", port);
-                s.setSoTimeout(2000);
+                saddr = new InetSocketAddress("127.0.0.1", port);
             } else {
-                s = new java.net.Socket(address, port);
-                s.setSoTimeout(2000);
-                // setting soLinger to a small value will help shutdown the
-                // connection quicker
-                s.setSoLinger(true, 0);
+                saddr = new InetSocketAddress(address,port);
+            }
+            s = new java.net.Socket();
+            s.setSoTimeout(getSocketProperties().getSoTimeout());
+            
s.setSoLinger(getSocketProperties().getSoLingerOn(),getSocketProperties().getSoLingerTime());
+            if (log.isDebugEnabled()) {
+                log.debug("About to unlock socket for:"+saddr);
+            }
+            s.connect(saddr,getSocketProperties().getUnlockTimeout());
+            if (log.isDebugEnabled()) {
+                log.debug("Socket unlock completed for:"+saddr);
             }
         } catch(Exception e) {
             if (log.isDebugEnabled()) {
@@ -1177,6 +1197,8 @@
                             }
                         } 
                     }
+                }catch (SocketTimeoutException sx) {
+                    //normal condition
                 }catch ( IOException x ) {
                     if ( running ) 
log.error(sm.getString("endpoint.accept.fail"), x);
                 } catch (OutOfMemoryError oom) {
@@ -1279,13 +1301,11 @@
         protected Selector selector;
         protected ConcurrentLinkedQueue<Runnable> events = new 
ConcurrentLinkedQueue<Runnable>();
         
-        protected boolean close = false;
+        protected volatile boolean close = false;
         protected long nextExpiration = 0;//optimize expiration handling
         
         protected AtomicLong wakeupCounter = new AtomicLong(0l);
         
-        protected CountDownLatch stopLatch = new CountDownLatch(1);
-
         protected volatile int keyCount = 0;
 
         public Poller() throws IOException {
@@ -1301,12 +1321,11 @@
          */
         protected void destroy() {
             // Wait for polltime before doing anything, so that the poller 
threads
-            // exit, otherwise parallel descturction of sockets which are still
+            // exit, otherwise parallel closure of sockets which are still
             // in the poller can cause problems
             close = true;
             events.clear();
             selector.wakeup();
-            try { stopLatch.await(5,TimeUnit.SECONDS); } catch 
(InterruptedException ignore ) {}
         }
         
         public void addEvent(Runnable event) {
@@ -1420,7 +1439,7 @@
                     // Loop if endpoint is paused
                     while (paused && (!close) ) {
                         try {
-                            Thread.sleep(500);
+                            Thread.sleep(100);
                         } catch (InterruptedException e) {
                             // Ignore
                         }
@@ -1431,8 +1450,7 @@
                     // Time to terminate?
                     if (close) {
                         timeout(0, false);
-                        stopLatch.countDown();
-                        return;
+                        break;
                     }
                     int keyCount = 0;
                     try {
@@ -1450,9 +1468,8 @@
                         }
                         if (close) {
                             timeout(0, false);
-                            stopLatch.countDown();
                             selector.close(); 
-                            return; 
+                            break; 
                         }
                     } catch ( NullPointerException x ) {
                         //sun bug 5076772 on windows JDK 1.5

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketProperties.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketProperties.java?rev=791914&r1=791913&r2=791914&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SocketProperties.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketProperties.java Tue Jul  
7 17:21:15 2009
@@ -177,6 +177,11 @@
      * poller going boinkers during high traffic
      */
     protected long timeoutInterval = 1000;
+    
+    /**
+     * Timeout in milliseconds for an unlock to take place.
+     */
+    protected int unlockTimeout = 250;
 
     public void setProperties(Socket socket) throws SocketException{
         if (rxBufSize != null)
@@ -407,4 +412,14 @@
         this.bufferPool = directBufferPool;
     }
 
+    public int getUnlockTimeout() {
+        return unlockTimeout;
+    }
+
+    public void setUnlockTimeout(int unlockTimeout) {
+        this.unlockTimeout = unlockTimeout;
+    }
+    
+    
+
 }
\ No newline at end of file

Modified: tomcat/trunk/webapps/docs/config/http.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=791914&r1=791913&r2=791914&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/trunk/webapps/docs/config/http.xml Tue Jul  7 17:21:15 2009
@@ -452,7 +452,11 @@
         <a 
href="http://java.sun.com/j2se/1.6.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int)">Socket
 Performance Options</a>
         All three performance attributes must be set else the JVM defaults will
         be used for all three.</p>
-      </attribute>      
+      </attribute> 
+      <attribute name="socket.unlockTimeout" required="false">
+        <p>(int) The timeout for a socket unlock. When a connector is stopped, 
it will try to release the acceptor thread by opening a connector to itself.
+           The default value is <code>250</code> and the value is in 
milliseconds</p>
+      </attribute> 
     </attributes>
   </subsection>
   



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to