From e8fab617142b411bff3d3cacc34cd9e5c20b9d53 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Mon, 18 Jan 2010 14:23:40 +0000
Subject: [PATCH] - [Issue 4491]  Severe memory leak during after many connect/disconnect : get rid of leaking ThreadLocal [ Sun Java Bug ID: 6254531 ] by replacing it with thread to asn1writer mapping.

---
 opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java |   48 ++++++++++++++++++++++++------------------------
 1 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 96cdcfb..d1c1b50 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2009 Sun Microsystems, Inc.
+ *      Copyright 2006-2010 Sun Microsystems, Inc.
  */
 package org.opends.server.protocols.ldap;
 
@@ -47,6 +47,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
@@ -351,6 +352,10 @@
   // client has connected.
   private final String serverAddress;
 
+  // Holds the mapping between the worker thread and ASN1
+  // writer to allow for parallel, non-blocking encoding.
+  private Map<Thread,ASN1Writer> asn1WriterMap;
+
   private ASN1ByteChannelReader asn1Reader;
 
   private int APPLICATION_BUFFER_SIZE = 4096;
@@ -361,28 +366,6 @@
   private volatile ConnectionSecurityProvider tlsPendingProvider = null;
   private volatile ConnectionSecurityProvider saslPendingProvider = null;
 
-  /**
-   * Thread local storage to provide each worker thread with its
-   * own ASN1Writer to allow for parallel, non-blocking encoding.
-   */
-  private final ThreadLocal<ASN1Writer> threadLocalASN1Writer =
-          new ThreadLocal<ASN1Writer>()
-  {
-    @Override
-    protected ASN1Writer initialValue()
-    {
-      if (isSecure())
-      {
-        int appBufSize = activeProvider.getAppBufSize();
-        return ASN1.getWriter(saslChannel, appBufSize);
-      }
-      else
-      {
-        return ASN1.getWriter(saslChannel,
-          APPLICATION_BUFFER_SIZE);
-      }
-    }
-  };
 
   /**
    * Creates a new LDAP client connection with the provided information.
@@ -445,6 +428,7 @@
         ASN1.getReader(saslChannel, APPLICATION_BUFFER_SIZE, connectionHandler
             .getMaxRequestSize());
 
+    asn1WriterMap = new ConcurrentHashMap<Thread,ASN1Writer>();
 
     if (connectionHandler.useSSL())
     {
@@ -940,9 +924,25 @@
   public void sendLDAPMessage(LDAPMessage message)
   {
     // Get the writer used by this thread.
-    ASN1Writer asn1Writer = threadLocalASN1Writer.get();
+    Thread currentThread = Thread.currentThread();
+    ASN1Writer asn1Writer = asn1WriterMap.get(currentThread);
     try
     {
+      if (asn1Writer == null)
+      {
+        if (isSecure())
+        {
+          int appBufSize = activeProvider.getAppBufSize();
+          asn1Writer = ASN1.getWriter(saslChannel, appBufSize);
+        }
+        else
+        {
+          asn1Writer = ASN1.getWriter(saslChannel,
+                  APPLICATION_BUFFER_SIZE);
+        }
+        asn1WriterMap.put(currentThread, asn1Writer);
+      }
+
       message.write(asn1Writer);
       asn1Writer.flush();
 

--
Gitblit v1.10.0