You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2018/09/23 22:02:10 UTC

[directory-server] branch master updated: o Using Decorator in handlers to avoid using a big switch while encoding messages o Added the EndTransaction Handler o Added the missing txn extendedOperations in the ldap config o a bit of formating

This is an automated email from the ASF dual-hosted git repository.

elecharny pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-server.git


The following commit(s) were added to refs/heads/master by this push:
     new 8dba015  o Using Decorator in handlers to avoid using a big switch while encoding messages o Added the EndTransaction Handler o Added the missing txn extendedOperations in the ldap config o a bit of formating
8dba015 is described below

commit 8dba015d992d6531c41c906cc286607d327599a8
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Mon Sep 24 00:02:08 2018 +0200

    o Using Decorator in handlers to avoid using a big switch while encoding
    messages
    o Added the EndTransaction Handler
    o Added the missing txn extendedOperations in the ldap config
    o a bit of formating
---
 .../directory/server/core/api/CoreSession.java     |  3 +-
 .../directory/server/core/api/MockCoreSession.java |  2 +-
 .../core/operations/search/SearchPerfIT.java       |  5 +-
 .../server/core/shared/DefaultCoreSession.java     | 16 ++++-
 .../apache/directory/server/installers/config.ldif | 16 +++++
 .../server/core/referral/ReferralInterceptor.java  | 10 +--
 .../impl/btree/mavibot/MavibotPartition.java       |  3 +-
 .../directory/server/ldap/LdapProtocolHandler.java |  5 +-
 .../apache/directory/server/ldap/LdapServer.java   |  4 +-
 .../server/ldap/handlers/LdapRequestHandler.java   | 20 ++++--
 ...tionHandler.java => EndTransactionHandler.java} | 33 ++++-----
 .../handlers/extended/StartTransactionHandler.java |  7 +-
 .../ldap/handlers/request/AddRequestHandler.java   | 15 ++--
 .../ldap/handlers/request/BindRequestHandler.java  | 63 +++++++++--------
 .../handlers/request/CompareRequestHandler.java    | 19 ++++--
 .../handlers/request/DeleteRequestHandler.java     | 17 +++--
 .../handlers/request/ModifyDnRequestHandler.java   | 40 ++++++-----
 .../handlers/request/ModifyRequestHandler.java     | 17 +++--
 .../handlers/request/SearchRequestHandler.java     | 26 ++++---
 .../handlers/request/UnbindRequestHandler.java     |  2 +-
 server-config/src/main/resources/config.ldif       | 16 +++++
 .../server/operations/search/SearchPerfIT.java     | 79 ++++++++++++++++++++--
 22 files changed, 286 insertions(+), 132 deletions(-)

diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/CoreSession.java b/core-api/src/main/java/org/apache/directory/server/core/api/CoreSession.java
index 80f2dd9..5d96b28 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/CoreSession.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/CoreSession.java
@@ -843,9 +843,10 @@ public interface CoreSession
     /**
      * Set the flag indicating we have received the sendTransaction extended operation
      * 
+     * @param commit If we have to commit or rollback the transaction
      * @throws IOException If one of the transaction cannot be closed
      */
-    void endSessionTransaction() throws IOException;
+    void endSessionTransaction( boolean commit ) throws IOException;
     
     
     /**
diff --git a/core-api/src/test/java/org/apache/directory/server/core/api/MockCoreSession.java b/core-api/src/test/java/org/apache/directory/server/core/api/MockCoreSession.java
index bb07daa..8902ccb 100644
--- a/core-api/src/test/java/org/apache/directory/server/core/api/MockCoreSession.java
+++ b/core-api/src/test/java/org/apache/directory/server/core/api/MockCoreSession.java
@@ -1012,7 +1012,7 @@ public class MockCoreSession implements CoreSession
      * {@inheritDoc}
      */
     @Override
-    public void endSessionTransaction()
+    public void endSessionTransaction( boolean commit )
     {
         // Nothing to do
     }
diff --git a/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchPerfIT.java b/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchPerfIT.java
index 79d8ddd..5b45fa7 100644
--- a/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchPerfIT.java
+++ b/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchPerfIT.java
@@ -319,7 +319,7 @@ public class SearchPerfIT extends AbstractLdapTestUnit
             "ou: People" );
 
         connection.add( rootPeople );
-        int nbUsers = 10000;
+        int nbUsers = 1000;
         
         System.out.println( "Sleeping..." );
         //Thread.sleep( 10000 );
@@ -416,12 +416,13 @@ public class SearchPerfIT extends AbstractLdapTestUnit
 
             SearchCursor cursor = connection.search( searchRequest );
 
+            //System.out.println( cursor.getEntry() );
             boolean hasNext = firstNext( cursor );
             
             while ( hasNext )
             {
                 count++;
-                cursor.getEntry();
+                //System.out.println( cursor.getEntry() );
                 hasNext = innerNext( cursor );
             }
 
diff --git a/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java b/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java
index 61105ba..dd5e44d 100644
--- a/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java
+++ b/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java
@@ -1500,11 +1500,21 @@ public class DefaultCoreSession implements CoreSession
      * {@inheritDoc}
      */
     @Override
-    public void endSessionTransaction() throws IOException
+    public void endSessionTransaction( boolean commit ) throws IOException
     {
-        for ( Map.Entry<String, PartitionTxn> partitionTxn : transactionMap.entrySet() )
+        if ( commit )
         {
-            partitionTxn.getValue().commit();
+            for ( Map.Entry<String, PartitionTxn> partitionTxn : transactionMap.entrySet() )
+            {
+                partitionTxn.getValue().commit();
+            }
+        }
+        else
+        {
+            for ( Map.Entry<String, PartitionTxn> partitionTxn : transactionMap.entrySet() )
+            {
+                partitionTxn.getValue().abort();
+            }
         }
         
         hasSessionTransaction = false;
diff --git a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/config.ldif b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/config.ldif
index 8861253..f683290 100644
--- a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/config.ldif
+++ b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/config.ldif
@@ -772,6 +772,22 @@ objectclass: ads-base
 objectclass: top
 ads-enabled: TRUE
 
+dn: ads-extendedOpId=startTransactionHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: startTransactionHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.StartTransactionHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-extendedOpId=endTransactionHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: endTransactionHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.EndTransactionHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
 dn: ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
 ou: saslMechHandlers
 objectclass: organizationalUnit
diff --git a/interceptors/referral/src/main/java/org/apache/directory/server/core/referral/ReferralInterceptor.java b/interceptors/referral/src/main/java/org/apache/directory/server/core/referral/ReferralInterceptor.java
index ebb8712..21b839f 100644
--- a/interceptors/referral/src/main/java/org/apache/directory/server/core/referral/ReferralInterceptor.java
+++ b/interceptors/referral/src/main/java/org/apache/directory/server/core/referral/ReferralInterceptor.java
@@ -154,15 +154,7 @@ public class ReferralInterceptor extends BaseInterceptor
             return false;
         }
 
-        Attribute oc = entry.get( directoryService.getAtProvider().getObjectClass() );
-
-        if ( oc == null )
-        {
-            LOG.warn( "could not find objectClass attribute in entry: {}", entry );
-            return false;
-        }
-
-        if ( !oc.contains( SchemaConstants.REFERRAL_OC ) )
+        if ( !entry.contains( directoryService.getAtProvider().getObjectClass(), SchemaConstants.REFERRAL_OC ) )
         {
             return false;
         }
diff --git a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java b/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
index 0101d4e..3240429 100644
--- a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
+++ b/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
@@ -71,8 +71,7 @@ import org.slf4j.LoggerFactory;
 
 
 /**
- * 
- * TODO MavibotPartition.
+ * A Mavibot partition
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapProtocolHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapProtocolHandler.java
index 5a7a236..3f7a3f0 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapProtocolHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapProtocolHandler.java
@@ -24,8 +24,10 @@ import org.apache.directory.api.ldap.codec.api.LdapDecoder;
 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
 import org.apache.directory.api.ldap.codec.api.MessageDecorator;
 import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
+import org.apache.directory.api.ldap.codec.decorators.ExtendedResponseDecorator;
 import org.apache.directory.api.ldap.model.exception.ResponseCarryingMessageException;
 import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.ldap.model.message.Message;
 import org.apache.directory.api.ldap.model.message.Request;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
@@ -247,7 +249,8 @@ class LdapProtocolHandler extends DemuxingIoHandler
 
         LOG.warn( "Unexpected exception forcing session to close: sending disconnect notice to client.", cause );
 
-        session.write( NoticeOfDisconnect.PROTOCOLERROR );
+        session.write( new ExtendedResponseDecorator<ExtendedResponse>( 
+                ldapServer.getDirectoryService().getLdapCodecService(), NoticeOfDisconnect.PROTOCOLERROR ) );
         LdapSession ldapSession = this.ldapServer.getLdapSessionManager().removeLdapSession( session );
         cleanUpSession( ldapSession );
         session.closeNow();
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapServer.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapServer.java
index aea7fc0..a702523 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapServer.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/LdapServer.java
@@ -913,8 +913,8 @@ public class LdapServer extends DirectoryBackedService
     public ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> getExtendedOperationHandler(
         String oid )
     {
-        for ( ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> extendedOperationHandler : 
-            extendedOperationHandlers )
+        for ( ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> 
+                extendedOperationHandler : extendedOperationHandlers )
         {
             if ( extendedOperationHandler.getOid().equals( oid ) )
             {
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/LdapRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/LdapRequestHandler.java
index 27068b1..4b1c66a 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/LdapRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/LdapRequestHandler.java
@@ -21,6 +21,7 @@ package org.apache.directory.server.ldap.handlers;
 
 
 import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.model.exception.LdapOperationException;
 import org.apache.directory.api.ldap.model.exception.LdapReferralException;
 import org.apache.directory.api.ldap.model.message.AbandonRequest;
@@ -241,9 +242,9 @@ public abstract class LdapRequestHandler<T extends Request> implements MessageHa
      * @param req The response
      * @param e The associated exception 
      */
-    public void handleException( LdapSession session, ResultResponseRequest req, Exception e )
+    public void handleException( LdapSession session, ResultResponseRequest request, ResultResponse response, Exception e )
     {
-        LdapResult result = req.getResultResponse().getLdapResult();
+        LdapResult result = request.getResultResponse().getLdapResult();
 
         /*
          * Set the result code or guess the best option.
@@ -256,7 +257,7 @@ public abstract class LdapRequestHandler<T extends Request> implements MessageHa
         }
         else
         {
-            code = ResultCodeEnum.getBestEstimate( e, req.getType() );
+            code = ResultCodeEnum.getBestEstimate( e, request.getType() );
         }
 
         result.setResultCode( code );
@@ -266,7 +267,7 @@ public abstract class LdapRequestHandler<T extends Request> implements MessageHa
          * exception into the message if we are in debug mode.  Note we 
          * embed the result code name into the message.
          */
-        String msg = code.toString() + ": failed for " + req + ": " + e.getLocalizedMessage();
+        String msg = code.toString() + ": failed for " + request + ": " + e.getLocalizedMessage();
 
         LOG.debug( msg, e );
 
@@ -306,6 +307,15 @@ public abstract class LdapRequestHandler<T extends Request> implements MessageHa
             }
         }
 
-        session.getIoSession().write( req.getResultResponse() );
+        session.getIoSession().write( response );
+    }
+    
+    
+    /**
+     * @return The LDAP API Codec service
+     */
+    protected LdapApiService getLdapApiService()
+    {
+        return ldapServer.getDirectoryService().getLdapCodecService();
     }
 }
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/EndTransactionHandler.java
similarity index 63%
copy from protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java
copy to protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/EndTransactionHandler.java
index 60b3f18..9f77886 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/EndTransactionHandler.java
@@ -24,9 +24,11 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionRequest;
-import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponse;
-import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.EndTransactionRequestDecorator;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.EndTransactionResponseDecorator;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionRequest;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionResponse;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionResponseImpl;
 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.server.core.api.CoreSession;
@@ -36,24 +38,22 @@ import org.apache.directory.server.ldap.LdapSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import jdbm.helper.Conversion;
-
 
 /**
- * An handler to manage the StartTransaction extended request operation
+ * An handler to manage the EndTransaction extended request operation
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class StartTransactionHandler implements ExtendedOperationHandler<ExtendedRequest, ExtendedResponse>
+public class EndTransactionHandler implements ExtendedOperationHandler<ExtendedRequest, ExtendedResponse>
 {
-    private static final Logger LOG = LoggerFactory.getLogger( StartTransactionHandler.class );
+    private static final Logger LOG = LoggerFactory.getLogger( EndTransactionHandler.class );
     public static final Set<String> EXTENSION_OIDS;
 
     static
     {
         Set<String> set = new HashSet<>( 2 );
-        set.add( StartTransactionRequest.EXTENSION_OID );
-        set.add( StartTransactionResponse.EXTENSION_OID );
+        set.add( EndTransactionRequest.EXTENSION_OID );
+        set.add( EndTransactionResponse.EXTENSION_OID );
         EXTENSION_OIDS = Collections.unmodifiableSet( set );
     }
 
@@ -63,7 +63,7 @@ public class StartTransactionHandler implements ExtendedOperationHandler<Extende
      */
     public String getOid()
     {
-        return StartTransactionRequest.EXTENSION_OID;
+        return EndTransactionRequest.EXTENSION_OID;
     }
 
 
@@ -72,18 +72,19 @@ public class StartTransactionHandler implements ExtendedOperationHandler<Extende
      */
     public void handleExtendedOperation( LdapSession session, ExtendedRequest req ) throws Exception
     {
-        LOG.debug( "StartTransaction requested" );
+        LOG.debug( "EndTransaction requested" );
         
         // We need to create a new transaction ID for the current session.
         // If the current session is already processing a transaction, we will return an error
         CoreSession coreSession = session.getCoreSession();
-        long transactionId = coreSession.beginSessionTransaction();
+        coreSession.endSessionTransaction( ( ( EndTransactionRequestDecorator ) req ).getCommit() );
 
-        StartTransactionResponse startTransactionResponse = new StartTransactionResponseImpl( 
-                req.getMessageId(), Conversion.convertToByteArray( transactionId ) );
+        EndTransactionResponse endTransactionResponse = new EndTransactionResponseImpl( req.getMessageId() );
 
         // write the response
-        session.getIoSession().write( startTransactionResponse );
+        session.getIoSession().write( new EndTransactionResponseDecorator( 
+                session.getLdapServer().getDirectoryService().getLdapCodecService(), 
+                endTransactionResponse )  );
     }
 
 
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java
index 60b3f18..05d4082 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/StartTransactionHandler.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.directory.api.ldap.extras.extended.ads_impl.startTransaction.StartTransactionResponseDecorator;
 import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionRequest;
 import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponse;
 import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponseImpl;
@@ -53,7 +54,6 @@ public class StartTransactionHandler implements ExtendedOperationHandler<Extende
     {
         Set<String> set = new HashSet<>( 2 );
         set.add( StartTransactionRequest.EXTENSION_OID );
-        set.add( StartTransactionResponse.EXTENSION_OID );
         EXTENSION_OIDS = Collections.unmodifiableSet( set );
     }
 
@@ -83,7 +83,10 @@ public class StartTransactionHandler implements ExtendedOperationHandler<Extende
                 req.getMessageId(), Conversion.convertToByteArray( transactionId ) );
 
         // write the response
-        session.getIoSession().write( startTransactionResponse );
+        session.getIoSession().write( 
+                new StartTransactionResponseDecorator( 
+                        session.getLdapServer().getDirectoryService().getLdapCodecService(), 
+                        startTransactionResponse ) );
     }
 
 
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/AddRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/AddRequestHandler.java
index 7f74c27..01ebb27 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/AddRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/AddRequestHandler.java
@@ -20,7 +20,9 @@
 package org.apache.directory.server.ldap.handlers.request;
 
 
+import org.apache.directory.api.ldap.codec.decorators.AddResponseDecorator;
 import org.apache.directory.api.ldap.model.message.AddRequest;
+import org.apache.directory.api.ldap.model.message.AddResponse;
 import org.apache.directory.api.ldap.model.message.LdapResult;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.server.core.api.CoreSession;
@@ -45,26 +47,27 @@ public class AddRequestHandler extends LdapRequestHandler<AddRequest>
     /**
      * {@inheritDoc}
      */
-    public void handle( LdapSession session, AddRequest req )
+    public void handle( LdapSession session, AddRequest addRequest )
     {
-        LOG.debug( "Handling request: {}", req );
-        LdapResult result = req.getResultResponse().getLdapResult();
+        LOG.debug( "Handling request: {}", addRequest );
+        AddResponse addResponse = ( AddResponse ) addRequest.getResultResponse();
 
         try
         {
             // Call the underlying layer to inject the new entry 
             CoreSession coreSession = session.getCoreSession();
-            coreSession.add( req );
+            coreSession.add( addRequest );
 
             // If success, here now, otherwise, we would have an exception.
+            LdapResult result = addResponse.getLdapResult();
             result.setResultCode( ResultCodeEnum.SUCCESS );
 
             // Write the AddResponse message
-            session.getIoSession().write( req.getResultResponse() );
+            session.getIoSession().write( new AddResponseDecorator( getLdapApiService(), addResponse ) );
         }
         catch ( Exception e )
         {
-            handleException( session, req, e );
+            handleException( session, addRequest, new AddResponseDecorator( getLdapApiService(), addResponse ), e );
         }
     }
 }
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/BindRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/BindRequestHandler.java
index 372f690..599fbcc 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/BindRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/BindRequestHandler.java
@@ -26,6 +26,7 @@ import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
 import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.directory.api.ldap.codec.decorators.BindResponseDecorator;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
@@ -91,6 +92,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
     public void handleSimpleAuth( LdapSession ldapSession, BindRequest bindRequest ) throws Exception
     {
         DirectoryService directoryService = ldapServer.getDirectoryService();
+        BindResponse bindResponse = ( BindResponse ) bindRequest.getResultResponse();
 
         // if the user is already bound, we have to unbind him
         if ( ldapSession.isAuthenticated() )
@@ -175,7 +177,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
                 SchemaConstants.REFERRAL_OC ) )
             {
                 LOG.info( "Bind principalDn points to referral." );
-                LdapResult result = bindRequest.getResultResponse().getLdapResult();
+                LdapResult result = bindResponse.getLdapResult();
                 result.setDiagnosticMessage( "Bind principalDn points to referral." );
                 result.setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
 
@@ -183,7 +185,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
                 ldapSession.setAnonymous();
 
                 // Write the response
-                ldapSession.getIoSession().write( bindRequest.getResultResponse() );
+                ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
 
                 return;
             }
@@ -217,8 +219,8 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
             }
 
             // Return the successful response
-            bindRequest.getResultResponse().addAllControls( bindContext.getResponseControls() );
-            sendBindSuccess( ldapSession, bindRequest, null );
+            bindResponse.addAllControls( bindContext.getResponseControls() );
+            sendBindSuccess( ldapSession, bindResponse, null );
         }
         catch ( Exception e )
         {
@@ -226,7 +228,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
             // For BindRequest, it should be an InvalidCredentials, 
             // no matter what kind of exception we got.
             ResultCodeEnum code = null;
-            LdapResult result = bindRequest.getResultResponse().getLdapResult();
+            LdapResult result = bindResponse.getLdapResult();
 
             if ( e instanceof LdapUnwillingToPerformException )
             {
@@ -267,13 +269,13 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
             }
 
             result.setDiagnosticMessage( msg );
-            bindRequest.getResultResponse().addAllControls( bindContext.getResponseControls() );
+            bindResponse.addAllControls( bindContext.getResponseControls() );
 
             // Before writing the response, be sure the session is set to anonymous
             ldapSession.setAnonymous();
 
             // Write the response
-            ldapSession.getIoSession().write( bindRequest.getResultResponse() );
+            ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
         }
         finally
         {
@@ -316,7 +318,9 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
     private void generateSaslChallengeOrComplete( LdapSession ldapSession, SaslServer ss,
         BindRequest bindRequest ) throws Exception
     {
-        LdapResult result = bindRequest.getResultResponse().getLdapResult();
+        BindResponse bindResponse = ( BindResponse ) bindRequest.getResultResponse();
+
+        LdapResult result = bindResponse.getLdapResult();
 
         // SaslServer will throw an exception if the credentials are null.
         if ( bindRequest.getCredentials() == null )
@@ -375,7 +379,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
                 handler.cleanup( ldapSession );
 
                 // Return the successful response
-                sendBindSuccess( ldapSession, bindRequest, tokenBytes );
+                sendBindSuccess( ldapSession, bindResponse, tokenBytes );
             }
             else
             {
@@ -384,23 +388,22 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
 
                 // Build the response
                 result.setResultCode( ResultCodeEnum.SASL_BIND_IN_PROGRESS );
-                BindResponse resp = ( BindResponse ) bindRequest.getResultResponse();
 
                 // Store the challenge
-                resp.setServerSaslCreds( tokenBytes );
+                bindResponse.setServerSaslCreds( tokenBytes );
 
                 // Switch to SASLAuthPending
                 ldapSession.setSaslAuthPending();
 
                 // And write back the response
-                ldapSession.getIoSession().write( resp );
+                ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
 
                 LOG.debug( "Returning final authentication data to client to complete context." );
             }
         }
         catch ( SaslException se )
         {
-            sendInvalidCredentials( ldapSession, bindRequest, se );
+            sendInvalidCredentials( ldapSession, bindResponse, se );
         }
     }
 
@@ -410,19 +413,21 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
      */
     private void sendAuthMethNotSupported( LdapSession ldapSession, BindRequest bindRequest )
     {
-        // First, r-einit the state to Anonymous, and clear the
+        BindResponse bindResponse = ( BindResponse ) bindRequest.getResultResponse();
+        
+        // First, re-init the state to Anonymous, and clear the
         // saslProperty map
         ldapSession.clearSaslProperties();
         ldapSession.setAnonymous();
 
         // And send the response to the client
-        LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
+        LdapResult bindResult = bindResponse.getLdapResult();
         bindResult.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
         bindResult.setDiagnosticMessage( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED.toString() + ": "
             + bindRequest.getSaslMechanism() + " is not a supported mechanism." );
 
         // Write back the error
-        ldapSession.getIoSession().write( bindRequest.getResultResponse() );
+        ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
     }
 
 
@@ -430,9 +435,9 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
      * Send back an INVALID-CREDENTIAL error message to the user. If we have an exception
      * as a third argument, then send back the associated message to the client. 
      */
-    private void sendInvalidCredentials( LdapSession ldapSession, BindRequest bindRequest, Exception e )
+    private void sendInvalidCredentials( LdapSession ldapSession, BindResponse bindResponse, Exception e )
     {
-        LdapResult result = bindRequest.getResultResponse().getLdapResult();
+        LdapResult result = bindResponse.getLdapResult();
 
         String message = "";
 
@@ -454,19 +459,18 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
         ldapSession.setAnonymous();
 
         // Write back the error response
-        ldapSession.getIoSession().write( bindRequest.getResultResponse() );
+        ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
     }
 
 
     /**
      * Send a SUCCESS message back to the client.
      */
-    private void sendBindSuccess( LdapSession ldapSession, BindRequest bindRequest, byte[] tokenBytes )
+    private void sendBindSuccess( LdapSession ldapSession, BindResponse bindResponse, byte[] tokenBytes )
     {
         // Return the successful response
-        BindResponse response = ( BindResponse ) bindRequest.getResultResponse();
-        response.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
-        response.setServerSaslCreds( tokenBytes );
+        bindResponse.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+        bindResponse.setServerSaslCreds( tokenBytes );
 
         if ( !ldapSession.getCoreSession().isAnonymous() )
         {
@@ -487,9 +491,9 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
             handler.cleanup( ldapSession );
         }
 
-        ldapSession.getIoSession().write( response );
+        ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
 
-        LOG.debug( "Returned SUCCESS message: {}.", response );
+        LOG.debug( "Returned SUCCESS message: {}.", bindResponse );
     }
 
 
@@ -614,7 +618,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
             }
             catch ( SaslException se )
             {
-                sendInvalidCredentials( ldapSession, bindRequest, se );
+                sendInvalidCredentials( ldapSession, ( BindResponse ) bindRequest.getResultResponse(), se );
             }
         }
     }
@@ -634,11 +638,14 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
         // Guard clause:  LDAP version 3
         if ( !bindRequest.getVersion3() )
         {
+            BindResponse bindResponse = ( BindResponse ) bindRequest.getResultResponse();
+            
             LOG.error( I18n.err( I18n.ERR_162 ) );
-            LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
+            LdapResult bindResult = bindResponse.getLdapResult();
             bindResult.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
             bindResult.setDiagnosticMessage( I18n.err( I18n.ERR_163 ) );
-            ldapSession.getIoSession().write( bindRequest.getResultResponse() );
+            ldapSession.getIoSession().write( new BindResponseDecorator( getLdapApiService(), bindResponse ) );
+            
             return;
         }
 
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/CompareRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/CompareRequestHandler.java
index 32a3291..c0c083f 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/CompareRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/CompareRequestHandler.java
@@ -20,7 +20,9 @@
 package org.apache.directory.server.ldap.handlers.request;
 
 
+import org.apache.directory.api.ldap.codec.decorators.CompareResponseDecorator;
 import org.apache.directory.api.ldap.model.message.CompareRequest;
+import org.apache.directory.api.ldap.model.message.CompareResponse;
 import org.apache.directory.api.ldap.model.message.LdapResult;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.server.ldap.LdapSession;
@@ -42,14 +44,17 @@ public class CompareRequestHandler extends LdapRequestHandler<CompareRequest>
     /**
      * {@inheritDoc}
      */
-    public void handle( LdapSession session, CompareRequest req )
+    public void handle( LdapSession session, CompareRequest compareRequest )
     {
-        LOG.debug( "Handling compare request while ignoring referrals: {}", req );
-        LdapResult result = req.getResultResponse().getLdapResult();
+        LOG.debug( "Handling compare request while ignoring referrals: {}", compareRequest );
+        
+        CompareResponse compareResponse = ( CompareResponse ) compareRequest.getResultResponse();
+        
+        LdapResult result = compareRequest.getResultResponse().getLdapResult();
 
         try
         {
-            if ( session.getCoreSession().compare( req ) )
+            if ( session.getCoreSession().compare( compareRequest ) )
             {
                 result.setResultCode( ResultCodeEnum.COMPARE_TRUE );
             }
@@ -58,12 +63,12 @@ public class CompareRequestHandler extends LdapRequestHandler<CompareRequest>
                 result.setResultCode( ResultCodeEnum.COMPARE_FALSE );
             }
 
-            result.setMatchedDn( req.getName() );
-            session.getIoSession().write( req.getResultResponse() );
+            result.setMatchedDn( compareRequest.getName() );
+            session.getIoSession().write( new CompareResponseDecorator( getLdapApiService(), compareResponse ) );
         }
         catch ( Exception e )
         {
-            handleException( session, req, e );
+            handleException( session, compareRequest, new CompareResponseDecorator( getLdapApiService(), compareResponse ), e );
         }
     }
 }
\ No newline at end of file
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/DeleteRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/DeleteRequestHandler.java
index 47afc5b..ea182c5 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/DeleteRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/DeleteRequestHandler.java
@@ -20,7 +20,9 @@
 package org.apache.directory.server.ldap.handlers.request;
 
 
+import org.apache.directory.api.ldap.codec.decorators.DeleteResponseDecorator;
 import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.DeleteResponse;
 import org.apache.directory.api.ldap.model.message.LdapResult;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.server.core.api.CoreSession;
@@ -43,26 +45,29 @@ public class DeleteRequestHandler extends LdapRequestHandler<DeleteRequest>
     /**
      * {@inheritDoc}
      */
-    public void handle( LdapSession session, DeleteRequest req )
+    public void handle( LdapSession session, DeleteRequest deleteRequest )
     {
-        LOG.debug( "Handling request: {}", req );
-        LdapResult result = req.getResultResponse().getLdapResult();
+        LOG.debug( "Handling request: {}", deleteRequest );
+        
+        DeleteResponse deleteResponse = ( DeleteResponse ) deleteRequest.getResultResponse();
+        
+        LdapResult result = deleteResponse.getLdapResult();
 
         try
         {
             // Call the underlying layer to delete the entry 
             CoreSession coreSession = session.getCoreSession();
-            coreSession.delete( req );
+            coreSession.delete( deleteRequest );
 
             // If success, here now, otherwise, we would have an exception.
             result.setResultCode( ResultCodeEnum.SUCCESS );
 
             // Write the DeleteResponse message
-            session.getIoSession().write( req.getResultResponse() );
+            session.getIoSession().write( new DeleteResponseDecorator( getLdapApiService(), deleteResponse ) );
         }
         catch ( Exception e )
         {
-            handleException( session, req, e );
+            handleException( session, deleteRequest, new DeleteResponseDecorator( getLdapApiService(), deleteResponse ), e );
         }
     }
 }
\ No newline at end of file
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyDnRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyDnRequestHandler.java
index 3f78582..2262068 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyDnRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyDnRequestHandler.java
@@ -20,8 +20,10 @@
 package org.apache.directory.server.ldap.handlers.request;
 
 
+import org.apache.directory.api.ldap.codec.decorators.ModifyDnResponseDecorator;
 import org.apache.directory.api.ldap.model.message.LdapResult;
 import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
+import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
@@ -58,63 +60,65 @@ public class ModifyDnRequestHandler extends LdapRequestHandler<ModifyDnRequest>
      * - newSuperior : this is a move operation. The entry is removed from its
      * current location, and created in the new one.
      */
-    public void handle( LdapSession session, ModifyDnRequest req )
+    public void handle( LdapSession session, ModifyDnRequest modifyDnRequest )
     {
-        LdapResult result = req.getResultResponse().getLdapResult();
-        LOG.debug( "Handling modify dn request while ignoring referrals: {}", req );
+        ModifyDnResponse modifyDnResponse = ( ModifyDnResponse ) modifyDnRequest.getResultResponse(); 
+        LdapResult result = modifyDnResponse.getLdapResult();
+        LOG.debug( "Handling modify dn request while ignoring referrals: {}", modifyDnRequest );
 
-        if ( req.getName().isEmpty() )
+        if ( modifyDnRequest.getName().isEmpty() )
         {
             // it is not allowed to modify the name of the Root DSE
             String msg = "Modify Dn is not allowed on Root DSE.";
             result.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
             result.setDiagnosticMessage( msg );
-            session.getIoSession().write( req.getResultResponse() );
+            session.getIoSession().write( new ModifyDnResponseDecorator( getLdapApiService(), modifyDnResponse ) );
             return;
         }
 
         try
         {
             SchemaManager schemaManager = session.getCoreSession().getDirectoryService().getSchemaManager();
-            Dn newRdn = new Dn( schemaManager, req.getNewRdn().getName() );
+            Dn newRdn = new Dn( schemaManager, modifyDnRequest.getNewRdn().getName() );
 
-            Dn oldRdn = new Dn( schemaManager, req.getName().getRdn().getName() );
+            Dn oldRdn = new Dn( schemaManager, modifyDnRequest.getName().getRdn().getName() );
 
-            boolean rdnChanged = req.getNewRdn() != null && !newRdn.equals( oldRdn );
+            boolean rdnChanged = modifyDnRequest.getNewRdn() != null && !newRdn.equals( oldRdn );
 
             CoreSession coreSession = session.getCoreSession();
 
             if ( rdnChanged )
             {
-                if ( req.getNewSuperior() != null )
+                if ( modifyDnRequest.getNewSuperior() != null )
                 {
-                    coreSession.moveAndRename( req );
+                    coreSession.moveAndRename( modifyDnRequest );
                 }
                 else
                 {
-                    coreSession.rename( req );
+                    coreSession.rename( modifyDnRequest );
                 }
             }
-            else if ( req.getNewSuperior() != null )
+            else if ( modifyDnRequest.getNewSuperior() != null )
             {
-                req.setNewRdn( null );
-                coreSession.move( req );
+                modifyDnRequest.setNewRdn( null );
+                coreSession.move( modifyDnRequest );
             }
             else
             {
                 result.setDiagnosticMessage( "Attempt to move entry onto itself." );
                 result.setResultCode( ResultCodeEnum.ENTRY_ALREADY_EXISTS );
-                result.setMatchedDn( req.getName() );
-                session.getIoSession().write( req.getResultResponse() );
+                result.setMatchedDn( modifyDnRequest.getName() );
+                session.getIoSession().write( new ModifyDnResponseDecorator( getLdapApiService(), modifyDnResponse ) );
+                
                 return;
             }
 
             result.setResultCode( ResultCodeEnum.SUCCESS );
-            session.getIoSession().write( req.getResultResponse() );
+            session.getIoSession().write( new ModifyDnResponseDecorator( getLdapApiService(), modifyDnResponse ) );
         }
         catch ( Exception e )
         {
-            handleException( session, req, e );
+            handleException( session, modifyDnRequest, new ModifyDnResponseDecorator( getLdapApiService(), modifyDnResponse ), e );
         }
     }
 }
\ No newline at end of file
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyRequestHandler.java
index e2630b7..1e5da9a 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/ModifyRequestHandler.java
@@ -20,8 +20,10 @@
 package org.apache.directory.server.ldap.handlers.request;
 
 
+import org.apache.directory.api.ldap.codec.decorators.ModifyResponseDecorator;
 import org.apache.directory.api.ldap.model.message.LdapResult;
 import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyResponse;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.server.core.api.CoreSession;
 import org.apache.directory.server.ldap.LdapSession;
@@ -44,26 +46,29 @@ public class ModifyRequestHandler extends LdapRequestHandler<ModifyRequest>
     /**
      * {@inheritDoc}
      */
-    public void handle( LdapSession session, ModifyRequest req )
+    public void handle( LdapSession session, ModifyRequest modifyRequest )
     {
-        LOG.debug( "Handling request : {}", req );
-        LdapResult result = req.getResultResponse().getLdapResult();
+        LOG.debug( "Handling request : {}", modifyRequest );
+        
+        ModifyResponse modifyResponse = ( ModifyResponse ) modifyRequest.getResultResponse();
+        
+        LdapResult result = modifyResponse.getLdapResult();
 
         try
         {
             // Call the underlying layer to delete the entry
             CoreSession coreSession = session.getCoreSession();
-            coreSession.modify( req );
+            coreSession.modify( modifyRequest );
 
             // If success, here now, otherwise, we would have an exception.
             result.setResultCode( ResultCodeEnum.SUCCESS );
 
             // Write the DeleteResponse message
-            session.getIoSession().write( req.getResultResponse() );
+            session.getIoSession().write( new ModifyResponseDecorator( getLdapApiService(), modifyResponse ) );
         }
         catch ( Exception e )
         {
-            handleException( session, req, e );
+            handleException( session, modifyRequest, new ModifyResponseDecorator( getLdapApiService(), modifyResponse ), e );
         }
     }
 }
\ No newline at end of file
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/SearchRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/SearchRequestHandler.java
index a189663..448657b 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/SearchRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/SearchRequestHandler.java
@@ -30,6 +30,8 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsDecorator;
+import org.apache.directory.api.ldap.codec.decorators.SearchResultDoneDecorator;
+import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
 import org.apache.directory.api.ldap.extras.controls.syncrepl.syncRequest.SyncRequestValue;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.cursor.Cursor;
@@ -130,8 +132,7 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
      * @param psearchDecorator the persistent search decorator extracted
      * @throws Exception if failures are encountered while searching
      */
-    private void handlePersistentSearch( LdapSession session, SearchRequest req,
-        PersistentSearch psearch ) throws Exception
+    private void handlePersistentSearch( LdapSession session, SearchRequest req, PersistentSearch psearch ) throws Exception
     {
         /*
          * We want the search to complete first before we start listening to
@@ -144,7 +145,8 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
             // ok if normal search beforehand failed somehow quickly abandon psearch
             if ( done.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
             {
-                session.getIoSession().write( done );
+                session.getIoSession().write( new SearchResultDoneDecorator( getLdapApiService(), done ) );
+                
                 return;
             }
         }
@@ -221,6 +223,8 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
      */
     private void handleReplication( LdapSession session, SearchRequest searchRequest ) throws LdapException
     {
+        SearchResultDone done = ( SearchResultDone ) searchRequest.getResultResponse();
+        
         if ( replicationReqHandler != null )
         {
             replicationReqHandler.handleSyncRequest( session, searchRequest );
@@ -229,11 +233,11 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
         {
             // Replication is not allowed on this server. generate a error message
             LOG.warn( "This server does not allow replication" );
-            LdapResult result = searchRequest.getResultResponse().getLdapResult();
+            LdapResult result = done.getLdapResult();
 
             result.setDiagnosticMessage( "Replication is not allowed on this server" );
             result.setResultCode( ResultCodeEnum.OTHER );
-            session.getIoSession().write( searchRequest.getResultResponse() );
+            session.getIoSession().write( new SearchResultDoneDecorator( getLdapApiService(), done ) );
         }
     }
 
@@ -272,7 +276,7 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
         session.getIoSession().write( generateResponse( session, req, entry ) );
 
         // write the SearchResultDone message
-        session.getIoSession().write( req.getResultResponse() );
+        session.getIoSession().write( new SearchResultDoneDecorator( getLdapApiService(), ( SearchResultDone ) req.getResultResponse() ) );
     }
 
 
@@ -925,7 +929,7 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
                 respEntry.getEntry().removeAttributes( SchemaConstants.USER_PASSWORD_AT );
             }
 
-            return respEntry;
+            return new SearchResultEntryDecorator( getLdapApiService(), respEntry );
         }
     }
 
@@ -1145,7 +1149,7 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
             }
             
             SearchResultDone done = doSimpleSearch( session, req );
-            session.getIoSession().write( done );
+            session.getIoSession().write( new SearchResultDoneDecorator( getLdapApiService(), done ) );
             
             if ( isLogSearchTime )
             {
@@ -1627,10 +1631,10 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
     /**
      * Handles processing with referrals without ManageDsaIT decorator.
      */
-    @Override
     public void handleException( LdapSession session, ResultResponseRequest req, Exception e )
     {
-        LdapResult result = req.getResultResponse().getLdapResult();
+        SearchResultDone done = ( SearchResultDone ) req.getResultResponse();
+        LdapResult result = done.getLdapResult();
         Exception cause = null;
 
         /*
@@ -1692,7 +1696,7 @@ public class SearchRequestHandler extends LdapRequestHandler<SearchRequest>
             }
         }
 
-        session.getIoSession().write( req.getResultResponse() );
+        session.getIoSession().write( new SearchResultDoneDecorator( getLdapApiService(), done ) );
     }
 
 
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/UnbindRequestHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/UnbindRequestHandler.java
index 0da1938..7849393 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/UnbindRequestHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/UnbindRequestHandler.java
@@ -48,7 +48,7 @@ public class UnbindRequestHandler extends LdapRequestHandler<UnbindRequest>
         {
             session.closeAllPagedSearches();
             session.getCoreSession().unbind( unbindRequest );
-            session.getIoSession().close( true );
+            session.getIoSession().closeNow();
             ldapServer.getLdapSessionManager().removeLdapSession( session.getIoSession() );
         }
         catch ( Throwable t )
diff --git a/server-config/src/main/resources/config.ldif b/server-config/src/main/resources/config.ldif
index 8861253..f683290 100644
--- a/server-config/src/main/resources/config.ldif
+++ b/server-config/src/main/resources/config.ldif
@@ -772,6 +772,22 @@ objectclass: ads-base
 objectclass: top
 ads-enabled: TRUE
 
+dn: ads-extendedOpId=startTransactionHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: startTransactionHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.StartTransactionHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-extendedOpId=endTransactionHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: endTransactionHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.EndTransactionHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
 dn: ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
 ou: saslMechHandlers
 objectclass: organizationalUnit
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchPerfIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchPerfIT.java
index 88a2499..dec201e 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchPerfIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchPerfIT.java
@@ -25,6 +25,11 @@ import static org.junit.Assert.fail;
 
 import java.util.Random;
 
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionRequest;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionRequest;
+import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionRequestImpl;
+import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponse;
 import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.cursor.EntryCursor;
 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
@@ -44,10 +49,14 @@ import org.apache.directory.server.annotations.CreateLdapServer;
 import org.apache.directory.server.annotations.CreateTransport;
 import org.apache.directory.server.core.annotations.ContextEntry;
 import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateExtendedOperation;
 import org.apache.directory.server.core.annotations.CreateIndex;
 import org.apache.directory.server.core.annotations.CreatePartition;
 import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.ldap.handlers.extended.EndTransactionHandler;
+import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
+import org.apache.directory.server.ldap.handlers.extended.StartTransactionHandler;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -62,6 +71,15 @@ import org.junit.runner.RunWith;
 @RunWith(FrameworkRunner.class)
 @CreateDS(
     name = "AddPerfDS",
+    extendedOperations = 
+        {
+            @CreateExtendedOperation( 
+                    oid = StartTransactionRequest.EXTENSION_OID,
+                    FQCN = "org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionRequestImpl" ),
+            @CreateExtendedOperation( 
+                    oid = EndTransactionRequest.EXTENSION_OID,
+                    FQCN = "org.apache.directory.api.ldap.extras.extended.startTransaction.EndTransactionRequestImpl" ),
+        },
     partitions =
         {
             @CreatePartition(
@@ -85,7 +103,13 @@ import org.junit.runner.RunWith;
     enableChangeLog = false)
 @CreateLdapServer(transports =
     //{ @CreateTransport(address = "192.168.1.1", port = 10389, protocol = "LDAP") })
-    { @CreateTransport(protocol = "LDAP") })
+    { @CreateTransport(protocol = "LDAP") },
+    extendedOpHandlers =
+    {
+        StartTransactionHandler.class,
+        EndTransactionHandler.class,
+    } 
+)
 public class SearchPerfIT extends AbstractLdapTestUnit
 {
 
@@ -422,7 +446,9 @@ public class SearchPerfIT extends AbstractLdapTestUnit
     public void testSearch100kUsers() throws LdapException, CursorException, InterruptedException, Exception
     {
         LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() );
+        connection.setTimeOut(0L);
         connection.bind( "uid=admin,ou=system", "secret" );
+        int nbAdds = 10_000;
 
         Entry rootPeople = new DefaultEntry(
             "ou=People,dc=example,dc=com",
@@ -431,10 +457,37 @@ public class SearchPerfIT extends AbstractLdapTestUnit
             "ou: People" );
 
         connection.add( rootPeople );
+        EndTransactionRequest endTransactionRequest;
+        StartTransactionRequest startTransactionRequest;
+        StartTransactionResponse startTransactionResponse = null;
+        boolean startedTxn = false;
+        
 
         long tadd0 = System.currentTimeMillis();
-        for ( int i = 0; i < 100000; i++ )
+        long tadd = tadd0;
+
+        for ( int i = 0; i < nbAdds; i++ )
         {
+            /*
+            if ( i % 1000 == 0 )
+            {
+                if ( startedTxn )
+                {
+                    endTransactionRequest = new EndTransactionRequestImpl();
+                    endTransactionRequest.setTransactionId( startTransactionResponse.getTransactionId() );
+                    endTransactionRequest.setCommit( true );
+                    connection.extended( endTransactionRequest );
+                }
+                else
+                {
+                    startedTxn = true;
+                }
+                
+                startTransactionRequest = new StartTransactionRequestImpl();
+                startTransactionResponse = ( StartTransactionResponse ) connection.extended( startTransactionRequest );
+            }
+            */
+            
             Entry user = new DefaultEntry(
                 "uid=user." + i + ",ou=People,dc=example,dc=com",
                 "objectClass: top",
@@ -463,12 +516,28 @@ public class SearchPerfIT extends AbstractLdapTestUnit
 
             if ( i % 100 == 0 )
             {
-                System.out.println( "Injected " + i );
+                long t100add = System.currentTimeMillis();
+                System.out.println( "Injected " + i + " in " + ( t100add - tadd ) );
+                tadd = t100add;
             }
         }
+        
+        /*
+        if ( startedTxn )
+        {
+            endTransactionRequest = new EndTransactionRequestImpl();
+            endTransactionRequest.setTransactionId( startTransactionResponse.getTransactionId() );
+            endTransactionRequest.setCommit( true );
+            connection.extended( endTransactionRequest );
+        }
+        */
+        
         long tadd1 = System.currentTimeMillis();
 
-        System.out.println( "Time to inject 100k entries : " + ( ( tadd1 - tadd0 ) / 1000 ) + "s" );
+        long nbSeconds = ( ( tadd1 - tadd0 ) / 1000 );
+        System.out.println( "Time to inject " + nbAdds + " entries : " + nbSeconds + "s, add/s : " + ( nbAdds / nbSeconds ) );
+
+        connection.extended( new EndTransactionRequestImpl() );
 
         // Sleep forever
         //Thread.sleep( 3600000L );
@@ -503,7 +572,7 @@ public class SearchPerfIT extends AbstractLdapTestUnit
                 t00 = System.currentTimeMillis();
             }
 
-            searchRequest.setFilter( "(cn=user" + random.nextInt( 100000 ) + ")" );
+            searchRequest.setFilter( "(cn=user" + random.nextInt( nbAdds ) + ")" );
 
             SearchCursor cursor = connection.search( searchRequest );