From 67405dde9ba213331dab1fc46cb18c485070fd5b Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 05 Jun 2009 09:04:50 +0000
Subject: [PATCH] svn merge -r5333:5417 https://opends.dev.java.net/svn/opends/branches/b2.0

---
 opends/src/server/org/opends/server/protocols/ldap/LDAPRequestHandler.java |  106 +++++++++++++++++++++++++++++++++--------------------
 1 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPRequestHandler.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPRequestHandler.java
index ecf2be3..0301ec4 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPRequestHandler.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPRequestHandler.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.protocols.ldap;
 
@@ -40,7 +40,8 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.LinkedList;
+import java.util.List;
 
 import org.opends.messages.Message;
 import org.opends.server.api.DirectoryThread;
@@ -88,7 +89,11 @@
 
   // The queue that will be used to hold the set of pending connections that
   // need to be registered with the selector.
-  private final ConcurrentLinkedQueue<LDAPClientConnection> pendingConnections;
+  private List<LDAPClientConnection> pendingConnections =
+    new LinkedList<LDAPClientConnection>();
+
+  // Lock object for synchronizing access to the pending connections queue.
+  private final Object pendingConnectionsLock = new Object();
 
   // The selector that will be used to monitor the client connections.
   private final Selector selector;
@@ -120,7 +125,6 @@
 
 
     handlerName        = getName();
-    pendingConnections = new ConcurrentLinkedQueue<LDAPClientConnection>();
 
     try
     {
@@ -169,6 +173,7 @@
    * Operates in a loop, waiting for client requests to arrive and ensuring that
    * they are processed properly.
    */
+  @Override
   public void run()
   {
     // Operate in a loop until the server shuts down.  Each time through the
@@ -292,6 +297,12 @@
           }
           finally
           {
+            if (!key.isValid())
+            {
+              // Help GC - release the connection.
+              key.attach(null);
+            }
+
             iterator.remove();
           }
         }
@@ -300,26 +311,37 @@
 
       // Check to see if we have any pending connections that need to be
       // registered with the selector.
-      while (! pendingConnections.isEmpty())
+      List<LDAPClientConnection> tmp = null;
+      synchronized (pendingConnectionsLock)
       {
-        LDAPClientConnection c = pendingConnections.remove();
-
-        try
+        if (!pendingConnections.isEmpty())
         {
-          SocketChannel socketChannel = c.getSocketChannel();
-          socketChannel.configureBlocking(false);
-          socketChannel.register(selector, SelectionKey.OP_READ, c);
+          tmp = pendingConnections;
+          pendingConnections = new LinkedList<LDAPClientConnection>();
         }
-        catch (Exception e)
-        {
-          if (debugEnabled())
-          {
-            TRACER.debugCaught(DebugLogLevel.ERROR, e);
-          }
+      }
 
-          c.disconnect(DisconnectReason.SERVER_ERROR, true,
-                       ERR_LDAP_REQHANDLER_CANNOT_REGISTER.get(handlerName,
-                       String.valueOf(e)));
+      if (tmp != null)
+      {
+        for (LDAPClientConnection c : tmp)
+        {
+          try
+          {
+            SocketChannel socketChannel = c.getSocketChannel();
+            socketChannel.configureBlocking(false);
+            socketChannel.register(selector, SelectionKey.OP_READ, c);
+          }
+          catch (Exception e)
+          {
+            if (debugEnabled())
+            {
+              TRACER.debugCaught(DebugLogLevel.ERROR, e);
+            }
+
+            c.disconnect(DisconnectReason.SERVER_ERROR, true,
+                ERR_LDAP_REQHANDLER_CANNOT_REGISTER.get(handlerName,
+                    String.valueOf(e)));
+          }
         }
       }
     }
@@ -369,19 +391,21 @@
     }
 
     // Disconnect all pending connections.
-    while (!pendingConnections.isEmpty())
+    synchronized (pendingConnectionsLock)
     {
-      LDAPClientConnection c = pendingConnections.remove();
-      try
+      for (LDAPClientConnection c : pendingConnections)
       {
-        c.disconnect(DisconnectReason.SERVER_SHUTDOWN, true,
-            ERR_LDAP_REQHANDLER_DEREGISTER_DUE_TO_SHUTDOWN.get());
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
+        try
         {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
+          c.disconnect(DisconnectReason.SERVER_SHUTDOWN, true,
+              ERR_LDAP_REQHANDLER_DEREGISTER_DUE_TO_SHUTDOWN.get());
+        }
+        catch (Exception e)
+        {
+          if (debugEnabled())
+          {
+            TRACER.debugCaught(DebugLogLevel.ERROR, e);
+          }
         }
       }
     }
@@ -419,17 +443,13 @@
     // Try to add the new connection to the queue.  If it succeeds, then wake
     // up the selector so it will be picked up right away.  Otherwise,
     // disconnect the client.
-    if (pendingConnections.offer(clientConnection))
+    synchronized (pendingConnectionsLock)
     {
-      selector.wakeup();
-      return true;
+      pendingConnections.add(clientConnection);
     }
-    else
-    {
-      clientConnection.disconnect(DisconnectReason.ADMIN_LIMIT_EXCEEDED, true,
-           ERR_LDAP_REQHANDLER_REJECT_DUE_TO_QUEUE_FULL.get(handlerName));
-      return false;
-    }
+
+    selector.wakeup();
+    return true;
   }
 
 
@@ -447,7 +467,13 @@
       new ArrayList<LDAPClientConnection>(keys.length);
     for (SelectionKey key : keys)
     {
-      connList.add((LDAPClientConnection) key.attachment());
+      LDAPClientConnection c = (LDAPClientConnection) key.attachment();
+
+      // If the client has disconnected the attachment may be null.
+      if (c != null)
+      {
+        connList.add(c);
+      }
     }
 
     return connList;

--
Gitblit v1.10.0