From 09f4651f340aee430254c8b367cb9830162efe55 Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Mon, 07 Nov 2016 16:40:20 +0000
Subject: [PATCH] OPENDJ-3179: Migrate LDAP Connection Handler to SDK Grizzly transport

---
 opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferWriter.java         |    9 ++--
 opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LdapCodec.java                |   55 ++++++++++-----------------
 opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPClientFilter.java         |   20 +++++++--
 opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java |    4 +-
 opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java         |    1 
 opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java                     |    2 
 opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyUtils.java             |    4 +-
 7 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
index 7c8a436..02486f1 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
@@ -546,6 +546,6 @@
         if (!isRunning) {
             throw new IllegalStateException("Server is not running");
         }
-        return (InetSocketAddress) listener.getSocketAddresses().iterator().next();
+        return listener.firstSocketAddress();
     }
 }
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java
index 87d9905..f67783c 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java
@@ -150,6 +150,7 @@
     ASN1BufferReader(final int maxElementSize, final Buffer buffer) {
         this.readLimiter = new RootSequenceLimiter();
         this.buffer = buffer;
+        this.buffer.allowBufferDispose(false);
         this.maxElementSize = maxElementSize;
     }
 
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferWriter.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferWriter.java
index d752449..9cc966e 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferWriter.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferWriter.java
@@ -139,19 +139,19 @@
     /** Default maximum size for cached protocol/entry encoding buffers. */
     private static final int DEFAULT_MAX_INTERNAL_BUFFER_SIZE = 32 * 1024;
 
-    private final MemoryManager<Buffer> memoryManager;
+    private MemoryManager<Buffer> memoryManager;
     private SequenceBuffer sequenceBuffer;
     private Buffer outBuffer;
     private final RootSequenceBuffer rootBuffer;
 
     /** Creates a new ASN.1 writer that writes to a StreamWriter. */
-    ASN1BufferWriter(MemoryManager memoryManager) {
+    ASN1BufferWriter() {
         this.rootBuffer = new RootSequenceBuffer();
-        this.memoryManager = memoryManager;
     }
 
     /** Reset the writer. */
-    void reset() {
+    void reset(final MemoryManager memoryManager) {
+        this.memoryManager = memoryManager;
         sequenceBuffer = rootBuffer;
         outBuffer = memoryManager.allocate(BUFFER_INIT_SIZE);
     }
@@ -189,6 +189,7 @@
     /** Recycle the writer to allow re-use. */
     @Override
     public void recycle() {
+        memoryManager = null;
         sequenceBuffer = null;
         outBuffer = null;
     }
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyUtils.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyUtils.java
index 4ec6f9e..8718e18 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyUtils.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyUtils.java
@@ -165,9 +165,9 @@
                 ? ThreadCache.takeFromCache(WRITER_INDEX)
                 : ThreadCache.takeFromCache(WRITER_INDEX_V2);
         if (writer == null) {
-            writer = LDAP.getWriter(new ASN1BufferWriter(memoryManager), protocolVersion);
+            writer = LDAP.getWriter(new ASN1BufferWriter(), protocolVersion);
         }
-        writer.getASN1Writer().reset();
+        writer.getASN1Writer().reset(memoryManager);
         return writer;
     }
 
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPClientFilter.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPClientFilter.java
index b6f059d..a3ed311 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPClientFilter.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPClientFilter.java
@@ -422,16 +422,26 @@
         final Buffer buffer = (Buffer) ctx.getMessage();
 
         try (final ASN1BufferReader reader = new ASN1BufferReader(maxASN1ElementSize, buffer)) {
-            final LDAPReader<? extends ASN1Reader> ldapReader = LDAP.getReader(reader, decodeOptions);
-            while (ldapReader.hasMessageAvailable()) {
-                ldapReader.readMessage(handler);
+            buffer.mark();
+            if (!reader.elementAvailable()) {
+                buffer.reset();
+                return ctx.getStopAction(buffer);
             }
-            buffer.shrink();
+            final int length = reader.peekLength();
+            final Buffer remainder = buffer.remaining() > length ? buffer.split(buffer.position() + length) : null;
+            buffer.reset();
+            try (final ASN1BufferReader packetReader = new ASN1BufferReader(maxASN1ElementSize, buffer)) {
+                final LDAPReader<? extends ASN1Reader> ldapReader = LDAP.getReader(packetReader, decodeOptions);
+                ctx.setMessage(null);
+                ldapReader.readMessage(handler);
+            } finally {
+                buffer.tryDispose();
+            }
+            return ctx.getInvokeAction(remainder);
         } catch (IOException e) {
             handleReadException(ctx, e);
             throw e;
         }
-        return ctx.getStopAction(buffer.hasRemaining() ? buffer : null);
     }
 
     private final void handleReadException(FilterChainContext ctx, IOException e) {
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LdapCodec.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LdapCodec.java
index b20e71c..2130e0a 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LdapCodec.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LdapCodec.java
@@ -36,7 +36,6 @@
 import org.forgerock.opendj.ldap.spi.LdapMessages.LdapRequestEnvelope;
 import org.forgerock.opendj.ldap.spi.LdapMessages.LdapResponseMessage;
 import org.glassfish.grizzly.Buffer;
-import org.glassfish.grizzly.attributes.AttributeStorage;
 import org.glassfish.grizzly.filterchain.FilterChainContext;
 import org.glassfish.grizzly.filterchain.NextAction;
 
@@ -57,14 +56,26 @@
     public NextAction handleRead(final FilterChainContext ctx) throws IOException {
         try {
             final Buffer buffer = ctx.getMessage();
-            final LdapRequestEnvelope message;
-
-            message = readMessage(buffer, ctx.getConnection());
-            if (message != null) {
-                ctx.setMessage(message);
-                return ctx.getInvokeAction(getRemainingBuffer(buffer));
+            try (final ASN1BufferReader reader = new ASN1BufferReader(maxASN1ElementSize, buffer)) {
+                buffer.mark();
+                if (!reader.elementAvailable()) {
+                    buffer.reset();
+                    return ctx.getStopAction(buffer);
+                }
+                final int length = reader.peekLength();
+                if (length > maxASN1ElementSize) {
+                    buffer.reset();
+                    throw DecodeException.fatalError(
+                            ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(length, maxASN1ElementSize));
+                }
+                final Buffer remainder = (buffer.remaining() > length)
+                        ? buffer.split(buffer.position() + length)
+                        : null;
+                buffer.reset();
+                ctx.setMessage(decodePacket(new ASN1BufferReader(maxASN1ElementSize, buffer)));
+                buffer.tryDispose();
+                return ctx.getInvokeAction(remainder);
             }
-            return ctx.getStopAction(getRemainingBuffer(buffer));
         } catch (Exception e) {
             onLdapCodecError(ctx, e);
             ctx.getConnection().closeSilently();
@@ -76,29 +87,7 @@
 
     protected abstract void onLdapCodecError(FilterChainContext ctx, Throwable error);
 
-    private LdapRequestEnvelope readMessage(final Buffer buffer, final AttributeStorage attributeStorage)
-            throws IOException {
-        try (final ASN1BufferReader reader = new ASN1BufferReader(maxASN1ElementSize, buffer)) {
-            final int packetStart = buffer.position();
-            if (!reader.elementAvailable()) {
-                buffer.position(packetStart);
-                return null;
-            }
-            final int length = reader.peekLength();
-            if (length > maxASN1ElementSize) {
-                buffer.position(packetStart);
-                throw DecodeException.fatalError(
-                        ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(length, maxASN1ElementSize));
-            }
-
-            final Buffer packet = buffer.slice(packetStart, buffer.position() + length);
-            buffer.position(buffer.position() + length);
-
-            return decodePacket(new ASN1BufferReader(maxASN1ElementSize, packet), attributeStorage);
-        }
-    }
-
-    private LdapRequestEnvelope decodePacket(final ASN1BufferReader reader, final AttributeStorage attributeStorage)
+    private LdapRequestEnvelope decodePacket(final ASN1BufferReader reader)
             throws IOException {
         reader.mark();
         try {
@@ -138,10 +127,6 @@
         }
     }
 
-    private Buffer getRemainingBuffer(final Buffer buffer) {
-        return buffer.hasRemaining() ? buffer : null;
-    }
-
     @Override
     public NextAction handleWrite(final FilterChainContext ctx) throws IOException {
         final LdapResponseMessage response = ctx.<LdapResponseMessage>getMessage();
diff --git a/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java b/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
index 5f7b650..cefb260 100644
--- a/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
+++ b/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
@@ -35,7 +35,7 @@
 @Test
 public class ASN1BufferWriterTestCase extends ASN1WriterTestCase {
 
-    private final ASN1BufferWriter writer = new ASN1BufferWriter(MemoryManager.DEFAULT_MEMORY_MANAGER);
+    private final ASN1BufferWriter writer = new ASN1BufferWriter();
 
     @Override
     protected byte[] getEncodedBytes() throws IOException, DecodeException {
@@ -53,7 +53,7 @@
     @Override
     protected ASN1Writer getWriter() throws IOException {
         writer.flush();
-        writer.reset();
+        writer.reset(MemoryManager.DEFAULT_MEMORY_MANAGER);
         return writer;
     }
 }

--
Gitblit v1.10.0