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/01/23 07:20:55 UTC

[directory-server] branch master updated (6ae7af2 -> 1399b77)

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

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


    from 6ae7af2  Try to use new JVM for each test class
     new b18ea82  o Added a test for PersisteSearch that uses the LDAP API o Fixed a typo
     new 1a6205e  o Fixed Java 8 warnings o Removed useless comparator in JdbmMasterTable o Removed the useless adminTable in JdbmMasterTable o Removed the unused resetCounter method in JdbmMasterTable o Removed the useless close() method from the MavibotMasterTable
     new be82b0c  Adding transaction to partitions
     new f62c716  Merge branch 'master' of https://gitbox.apache.org/repos/asf/directory-server
     new 1399b77  Fix for DIRSERVER-2220

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../server/core/api/LdapCoreSessionConnection.java |   2 +-
 .../context/AbstractOperationContext.java          |  22 +
 .../server/core/api/partition/PartitionNexus.java  |  11 +
 .../core/api/partition/PartitionReadTxn.java       |   6 +
 .../server/core/api/partition/PartitionTxn.java    |  30 +
 .../core/api/partition/PartitionWriteTxn.java      |   6 +
 .../directory/server/core/jndi/ServerContext.java  |   1 +
 .../server/core/DefaultDirectoryService.java       |   2 +
 .../directory/server/installers}/config.ldif       |   0
 .../core/authn/AuthenticationInterceptor.java      |   4 +-
 .../core/partition/impl/btree/jdbm/JdbmIndex.java  |   4 +-
 .../partition/impl/btree/jdbm/JdbmMasterTable.java |  48 --
 .../core/partition/impl/btree/jdbm/JdbmTable.java  | 358 ++++-----
 .../impl/btree/jdbm/KeyTupleBTreeCursor.java       |   2 +-
 .../btree/jdbm/JdbmTableWithDuplicatesTest.java    |   9 -
 .../impl/btree/mavibot/MavibotMasterTable.java     |   7 -
 .../partition/impl/btree/mavibot/MavibotTable.java | 159 ++--
 {lmdb-partation => mavibotv2-partition}/pom.xml    |  20 +-
 .../impl/btree/mavibot/AbstractMavibotTxn.java     |  96 +++
 .../partition/impl/btree/mavibot/DnSerializer.java |  21 +-
 .../impl/btree/mavibot/KeyTupleValueCursor.java    |   0
 .../impl/btree/mavibot/LdifTupleComparator.java    |   6 +-
 .../impl/btree/mavibot/LdifTupleReaderWriter.java  |   0
 .../impl/btree/mavibot/MavibotCursor.java          |   0
 .../impl/btree/mavibot/MavibotDnIndex.java         |   0
 .../impl/btree/mavibot/MavibotEntrySerializer.java |   0
 .../partition/impl/btree/mavibot/MavibotIndex.java |  47 +-
 .../impl/btree/mavibot/MavibotMasterTable.java     |   7 -
 .../mavibot/MavibotParentIdAndRdnSerializer.java   |   0
 .../impl/btree/mavibot/MavibotPartition.java       |  17 +-
 .../impl/btree/mavibot/MavibotRdnIndex.java        |   0
 .../impl/btree/mavibot/MavibotReadTxn.java         |  11 +
 .../partition/impl/btree/mavibot/MavibotTable.java | 255 ++++---
 .../partition/impl/btree/mavibot/MavibotTxn.java   |   9 +
 .../impl/btree/mavibot/MavibotWriteTxn.java        |  18 +
 .../impl/btree/mavibot/ValueTreeCursor.java        |   0
 pom.xml                                            |   1 +
 .../ldap/handlers/extended/PwdModifyHandler.java   |   1 +
 .../ldap/handlers/request/BindRequestHandler.java  |   1 +
 .../ldap/handlers/sasl/SimpleMechanismHandler.java |   1 +
 .../ldap/handlers/sasl/ntlm/NtlmSaslServer.java    |   1 +
 .../ldap/handlers/sasl/plain/PlainSaslServer.java  |   1 +
 .../server/operations/modify/ModifyReferralIT.java |  14 +-
 .../{PagedSearchIT.java => PagedSearchApiIT.java}  | 803 +++++++++++----------
 .../server/operations/search/PagedSearchIT.java    |   2 +-
 ...entSearchIT.java => PersistentSearchApiIT.java} |   4 +-
 .../directory/server/xdbm/AbstractTable.java       |  36 +-
 .../org/apache/directory/server/xdbm/Table.java    |  95 ++-
 .../directory/server/xdbm/impl/avl/AvlTable.java   |  86 ++-
 49 files changed, 1236 insertions(+), 988 deletions(-)
 create mode 100644 core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionReadTxn.java
 create mode 100644 core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionTxn.java
 create mode 100644 core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionWriteTxn.java
 copy {server-config/src/main/resources => installers-maven-plugin/src/main/resources/org/apache/directory/server/installers}/config.ldif (100%)
 copy {lmdb-partation => mavibotv2-partition}/pom.xml (91%)
 create mode 100644 mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/AbstractMavibotTxn.java
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java (93%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleValueCursor.java (100%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleComparator.java (88%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleReaderWriter.java (100%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java (100%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java (100%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java (100%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java (92%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java (93%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java (100%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java (97%)
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotRdnIndex.java (100%)
 create mode 100644 mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotReadTxn.java
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java (64%)
 create mode 100644 mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTxn.java
 create mode 100644 mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotWriteTxn.java
 copy {mavibot-partition => mavibotv2-partition}/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/ValueTreeCursor.java (100%)
 copy server-integ/src/test/java/org/apache/directory/server/operations/search/{PagedSearchIT.java => PagedSearchApiIT.java} (51%)
 copy server-integ/src/test/java/org/apache/directory/server/operations/search/{PersistentSearchIT.java => PersistentSearchApiIT.java} (99%)

-- 
To stop receiving notification emails like this one, please contact
elecharny@apache.org.

[directory-server] 03/05: Adding transaction to partitions

Posted by el...@apache.org.
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

commit be82b0ce2b78fa903a1818d27a351d07f2a977ce
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Wed Jan 10 07:05:52 2018 +0100

    Adding transaction to partitions
---
 .../server/core/api/LdapCoreSessionConnection.java |   2 +-
 .../context/AbstractOperationContext.java          |  22 +
 .../server/core/api/partition/PartitionNexus.java  |  11 +
 .../core/api/partition/PartitionReadTxn.java       |   6 +
 .../server/core/api/partition/PartitionTxn.java    |  30 +
 .../core/api/partition/PartitionWriteTxn.java      |   6 +
 .../directory/server/core/jndi/ServerContext.java  |   1 +
 .../server/core/DefaultDirectoryService.java       |   2 +
 .../apache/directory/server/installers/config.ldif | 828 +++++++++++++++++++++
 .../core/partition/impl/btree/jdbm/JdbmIndex.java  |   4 +-
 .../core/partition/impl/btree/jdbm/JdbmTable.java  | 358 ++++-----
 .../impl/btree/jdbm/KeyTupleBTreeCursor.java       |   2 +-
 .../btree/jdbm/JdbmTableWithDuplicatesTest.java    |   9 -
 .../partition/impl/btree/mavibot/MavibotTable.java | 159 ++--
 mavibotv2-partition/pom.xml                        | 146 ++++
 .../impl/btree/mavibot/AbstractMavibotTxn.java     |  96 +++
 .../partition/impl/btree/mavibot/DnSerializer.java | 206 +++++
 .../impl/btree/mavibot/KeyTupleValueCursor.java    | 239 ++----
 .../impl/btree/mavibot/LdifTupleComparator.java    |  57 ++
 .../impl/btree/mavibot/LdifTupleReaderWriter.java  | 162 ++++
 .../impl/btree/mavibot/MavibotCursor.java          | 292 ++++----
 .../impl/btree/mavibot/MavibotDnIndex.java         | 123 +++
 .../impl/btree/mavibot/MavibotEntrySerializer.java | 382 ++++++++++
 .../partition/impl/btree/mavibot/MavibotIndex.java | 261 +++----
 .../impl/btree/mavibot/MavibotMasterTable.java     |  58 ++
 .../mavibot/MavibotParentIdAndRdnSerializer.java   | 302 ++++++++
 .../impl/btree/mavibot/MavibotPartition.java       | 540 ++++++++++++++
 .../impl/btree/mavibot/MavibotRdnIndex.java        | 126 ++++
 .../impl/btree/mavibot/MavibotReadTxn.java         |  11 +
 .../partition/impl/btree/mavibot/MavibotTable.java | 255 ++++---
 .../partition/impl/btree/mavibot/MavibotTxn.java   |   9 +
 .../impl/btree/mavibot/MavibotWriteTxn.java        |  18 +
 .../impl/btree/mavibot/ValueTreeCursor.java        | 155 ++++
 pom.xml                                            |   1 +
 .../ldap/handlers/extended/PwdModifyHandler.java   |   1 +
 .../ldap/handlers/request/BindRequestHandler.java  |   1 +
 .../ldap/handlers/sasl/SimpleMechanismHandler.java |   1 +
 .../ldap/handlers/sasl/ntlm/NtlmSaslServer.java    |   1 +
 .../ldap/handlers/sasl/plain/PlainSaslServer.java  |   1 +
 .../server/operations/modify/ModifyReferralIT.java |  14 +-
 .../server/operations/search/PagedSearchApiIT.java |   7 +-
 .../operations/search/PersistentSearchApiIT.java   | 740 ++++++++++++++++++
 .../directory/server/xdbm/AbstractTable.java       |  36 +-
 .../org/apache/directory/server/xdbm/Table.java    |  95 ++-
 .../directory/server/xdbm/impl/avl/AvlTable.java   |  62 +-
 45 files changed, 4877 insertions(+), 961 deletions(-)

diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java b/core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java
index b2b6d12..74cf1db 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java
@@ -1206,7 +1206,7 @@ public class LdapCoreSessionConnection extends AbstractLdapConnection
 
         int newId = messageId.incrementAndGet();
 
-        BindOperationContext bindContext = new BindOperationContext( null );
+        BindOperationContext bindContext = new BindOperationContext( directoryService, null );
         bindContext.setCredentials( bindRequest.getCredentials() );
 
         bindContext.setDn( bindRequest.getDn().apply( directoryService.getSchemaManager() ) );
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/interceptor/context/AbstractOperationContext.java b/core-api/src/main/java/org/apache/directory/server/core/api/interceptor/context/AbstractOperationContext.java
index 8fffa95..4f04179 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/interceptor/context/AbstractOperationContext.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/interceptor/context/AbstractOperationContext.java
@@ -31,6 +31,7 @@ import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.server.core.api.CoreSession;
 import org.apache.directory.server.core.api.LdapPrincipal;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
 
 
 /**
@@ -74,6 +75,9 @@ public abstract class AbstractOperationContext implements OperationContext
 
     /** A flag used to tell if we should consider referrals as standard entries */
     protected boolean throwReferral;
+    
+    /** The transaction this operation is ran into */
+    protected PartitionTxn transaction;
 
 
     /**
@@ -443,4 +447,22 @@ public abstract class AbstractOperationContext implements OperationContext
     {
         return !throwReferral;
     }
+
+
+    /**
+     * @return the transaction
+     */
+    public PartitionTxn getTransaction()
+    {
+        return transaction;
+    }
+
+
+    /**
+     * @param transaction the transaction to set
+     */
+    public void setTransaction( PartitionTxn transaction )
+    {
+        this.transaction = transaction;
+    }
 }
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionNexus.java b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionNexus.java
index f648618..0534282 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionNexus.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionNexus.java
@@ -50,6 +50,17 @@ public interface PartitionNexus extends Partition
 
     byte[] ADMIN_PASSWORD_BYTES = Strings.getBytesUtf8( ADMIN_PASSWORD_STRING );
 
+    
+    /**
+     * Start a read transaction
+     */
+    PartitionReadTxn beginReadTransaction();
+
+    
+    /**
+     * Start a write transaction
+     */
+    PartitionWriteTxn beginWriteTransaction();
 
     /**
      * Get's the RootDSE entry for the DSA.
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionReadTxn.java b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionReadTxn.java
new file mode 100644
index 0000000..d74c53f
--- /dev/null
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionReadTxn.java
@@ -0,0 +1,6 @@
+package org.apache.directory.server.core.api.partition;
+
+public interface PartitionReadTxn extends PartitionTxn
+{
+
+}
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionTxn.java b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionTxn.java
new file mode 100644
index 0000000..88841f9
--- /dev/null
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionTxn.java
@@ -0,0 +1,30 @@
+package org.apache.directory.server.core.api.partition;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+public interface PartitionTxn extends Closeable
+{
+    /**
+     * Commit a write transaction. It will apply the changes on 
+     * the database.Last, not least, a new version will be created.
+     * If called by a Read transaction, it will simply close it.
+     */
+    void commit() throws IOException;
+    
+    
+    /**
+     * Abort a transaction. If it's a {@link PartitionReadTxn}, it will unlink this transaction
+     * from the version it used. If it's a {@link PartitionWriteTxn}; it will drop all the pending
+     * changes. The latest version will remain the same.
+     */
+    void abort() throws IOException;
+
+    
+    /**
+     * Tells if the transaction has been committed/aborted or not.
+     *  
+     * @return <tt>true</tt> if the transaction has been completed.
+     */
+    boolean isClosed();
+}
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionWriteTxn.java b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionWriteTxn.java
new file mode 100644
index 0000000..effcd3d
--- /dev/null
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/partition/PartitionWriteTxn.java
@@ -0,0 +1,6 @@
+package org.apache.directory.server.core.api.partition;
+
+public interface PartitionWriteTxn extends PartitionTxn
+{
+
+}
diff --git a/core-jndi/src/main/java/org/apache/directory/server/core/jndi/ServerContext.java b/core-jndi/src/main/java/org/apache/directory/server/core/jndi/ServerContext.java
index 5610114..6285de9 100644
--- a/core-jndi/src/main/java/org/apache/directory/server/core/jndi/ServerContext.java
+++ b/core-jndi/src/main/java/org/apache/directory/server/core/jndi/ServerContext.java
@@ -679,6 +679,7 @@ public abstract class ServerContext implements EventContext
     {
         // setup the op context and populate with request controls
         BindOperationContext bindContext = new BindOperationContext( null );
+        bindContext.setTransaction( getDirectoryService().getPartitionNexus().beginReadTransaction() );
         bindContext.setDn( bindDn );
         bindContext.setCredentials( credentials );
         bindContext.setSaslMechanism( saslMechanism );
diff --git a/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java b/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
index dc4a7b8..5237313 100644
--- a/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
+++ b/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
@@ -994,6 +994,7 @@ public class DefaultDirectoryService implements DirectoryService
         }
 
         BindOperationContext bindContext = new BindOperationContext( null );
+        bindContext.setTransaction( partitionNexus.beginReadTransaction() );
         bindContext.setCredentials( credentials );
         bindContext.setDn( principalDn.apply( schemaManager ) );
         bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
@@ -1020,6 +1021,7 @@ public class DefaultDirectoryService implements DirectoryService
         }
 
         BindOperationContext bindContext = new BindOperationContext( null );
+        bindContext.setTransaction( partitionNexus.beginReadTransaction() );
         bindContext.setCredentials( credentials );
         bindContext.setDn( principalDn.apply( schemaManager ) );
         bindContext.setSaslMechanism( saslMechanism );
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
new file mode 100644
index 0000000..8861253
--- /dev/null
+++ b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/config.ldif
@@ -0,0 +1,828 @@
+version: 1
+dn: ou=config
+ou: config
+objectclass: top
+objectclass: organizationalUnit
+
+dn: ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-directoryService
+ads-directoryserviceid: default
+ads-dsreplicaid: 1
+ads-dssyncperiodmillis: 15000
+ads-dsPasswordHidden: FALSE
+ads-dsallowanonymousaccess: TRUE
+ads-dsaccesscontrolenabled: FALSE
+ads-dsdenormalizeopattrsenabled: FALSE
+ads-enabled: TRUE
+
+dn: ads-changeLogId=defaultChangeLog,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-changeLog
+ads-changeLogId: defaultChangeLog
+ads-changeLogExposed: FALSE
+ads-enabled: FALSE
+
+dn: ads-journalId=defaultJournal,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-journal
+ads-journalId: defaultJournal
+ads-journalFileName: Journal.txt
+ads-journalWorkingDir: /
+ads-journalRotation: 2
+ads-enabled: FALSE
+
+dn: ou=interceptors,ads-directoryServiceId=default,ou=config
+ou: interceptors
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-interceptorId=normalizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 1
+ads-interceptorclassname: org.apache.directory.server.core.normalization.NormalizationInterceptor
+ads-interceptorid: normalizationInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+objectclass: ads-authenticationInterceptor
+ads-interceptororder: 2
+ads-interceptorclassname: org.apache.directory.server.core.authn.AuthenticationInterceptor
+ads-interceptorid: authenticationInterceptor
+ads-enabled: TRUE
+
+dn: ou=authenticators,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+ou: authenticators
+objectclass: top
+objectclass: organizationalUnit
+
+dn: ads-authenticatorid=anonymousauthenticator,ou=authenticators,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+ads-authenticatorid: anonymousauthenticator
+objectclass: top
+objectclass: ads-base
+objectClass: ads-authenticator
+objectClass: ads-authenticatorImpl
+ads-authenticatorClass: org.apache.directory.server.core.authn.AnonymousAuthenticator
+ads-baseDn: 
+ads-enabled: TRUE
+
+dn: ads-authenticatorid=simpleauthenticator,ou=authenticators,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+ads-authenticatorid: simpleauthenticator
+objectclass: top
+objectclass: ads-base
+objectClass: ads-authenticator
+objectClass: ads-authenticatorImpl
+ads-authenticatorClass: org.apache.directory.server.core.authn.SimpleAuthenticator
+ads-baseDn: 
+ads-enabled: TRUE
+
+dn: ads-authenticatorid=strongauthenticator,ou=authenticators,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+ads-authenticatorid: strongauthenticator
+objectclass: top
+objectclass: ads-base
+objectClass: ads-authenticator
+objectClass: ads-authenticatorImpl
+ads-authenticatorClass: org.apache.directory.server.core.authn.StrongAuthenticator
+ads-baseDn: 
+ads-enabled: TRUE
+
+dn: ads-authenticatorid=delegatingauthenticator,ou=authenticators,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+ads-authenticatorid: delegatingauthenticator
+objectclass: top
+objectclass: ads-base
+objectClass: ads-authenticator
+objectClass: ads-authenticatorImpl
+ads-authenticatorClass: org.apache.directory.server.core.authn.DelegatingAuthenticator
+ads-baseDn: 
+ads-enabled: FALSE
+
+dn: ou=passwordPolicies,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectClass: organizationalUnit
+objectClass: top
+ou: passwordPolicies
+
+dn: ads-pwdId=default,ou=passwordPolicies,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectClass: top
+objectClass: ads-base
+objectClass: ads-passwordPolicy
+ads-pwdId: default
+ads-pwdSafeModify: FALSE
+ads-pwdMaxAge: 0
+ads-pwdFailureCountInterval: 30
+ads-pwdAttribute: userPassword
+ads-pwdMaxFailure: 5
+ads-pwdLockout: TRUE
+ads-pwdMustChange: FALSE
+ads-pwdLockoutDuration: 0
+ads-pwdMinLength: 5
+ads-pwdInHistory: 5
+ads-pwdExpireWarning: 600
+ads-pwdMinAge: 0
+ads-pwdAllowUserChange: TRUE
+ads-pwdGraceAuthNLimit: 5
+ads-pwdCheckQuality: 1
+ads-pwdMaxLength: 0 
+ads-pwdGraceExpire: 0
+ads-pwdMinDelay: 0
+ads-pwdMaxDelay: 0
+ads-pwdMaxIdle: 0
+ads-pwdValidator: org.apache.directory.server.core.api.authn.ppolicy.DefaultPasswordValidator
+ads-enabled: TRUE
+
+dn: ads-interceptorId=referralInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 3
+ads-interceptorclassname: org.apache.directory.server.core.referral.ReferralInterceptor
+ads-interceptorid: referralInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=aciAuthorizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 4
+ads-interceptorclassname: org.apache.directory.server.core.authz.AciAuthorizationInterceptor
+ads-interceptorid: aciAuthorizationInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=defaultAuthorizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 5
+ads-interceptorclassname: org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor
+ads-interceptorid: defaultAuthorizationInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=administrativePointInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 6
+ads-interceptorclassname: org.apache.directory.server.core.admin.AdministrativePointInterceptor
+ads-interceptorid: administrativePointInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=exceptionInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 7
+ads-interceptorclassname: org.apache.directory.server.core.exception.ExceptionInterceptor
+ads-interceptorid: exceptionInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=keyDerivationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-enabled: FALSE
+ads-interceptororder: 8
+ads-interceptorclassname: org.apache.directory.server.core.kerberos.KeyDerivationInterceptor
+ads-interceptorid: keyDerivationInterceptor
+
+dn: ads-interceptorId=passwordHashingInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+objectclass: ads-hashInterceptor
+ads-enabled: TRUE
+ads-interceptororder: 9
+ads-interceptorclassname: org.apache.directory.server.core.hash.ConfigurableHashingInterceptor
+ads-interceptorid: passwordHashingInterceptor
+ads-hashAlgorithm: SSHA
+ads-hashAttribute: 2.5.4.35
+
+dn: ads-interceptorId=schemaInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 10
+ads-interceptorclassname: org.apache.directory.server.core.schema.SchemaInterceptor
+ads-interceptorid: schemaInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=operationalAttributeInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 11
+ads-interceptorclassname: org.apache.directory.server.core.operational.OperationalAttributeInterceptor
+ads-interceptorid: operationalAttributeInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=collectiveAttributeInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 12
+ads-interceptorclassname: org.apache.directory.server.core.collective.CollectiveAttributeInterceptor
+ads-interceptorid: collectiveAttributeInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=subentryInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 13
+ads-interceptorclassname: org.apache.directory.server.core.subtree.SubentryInterceptor
+ads-interceptorid: subentryInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=eventInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 14
+ads-interceptorclassname: org.apache.directory.server.core.event.EventInterceptor
+ads-interceptorid: eventInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=triggerInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 15
+ads-interceptorclassname: org.apache.directory.server.core.trigger.TriggerInterceptor
+ads-interceptorid: triggerInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=journalInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 16
+ads-interceptorclassname: org.apache.directory.server.core.journal.JournalInterceptor
+ads-interceptorid: journalInterceptor
+ads-enabled: TRUE
+
+dn: ads-interceptorId=numberInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-interceptor
+ads-interceptororder: 17
+ads-interceptorclassname: org.apache.directory.server.core.number.NumberIncrementingInterceptor
+ads-interceptorId: numberInterceptor
+ads-enabled: FALSE
+
+dn: ou=partitions,ads-directoryServiceId=default,ou=config
+ou: partitions
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectClass: ads-base
+objectclass: ads-partition
+objectclass: ads-jdbmPartition
+ads-partitionSuffix: ou=system
+ads-jdbmpartitionoptimizerenabled: TRUE
+ads-partitioncachesize: 10000
+ads-partitionsynconwrite: TRUE
+ads-partitionid: system
+ads-enabled: TRUE
+
+dn: ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ou: indexes
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-indexAttributeId=apacheRdn,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheRdn
+ads-indexHasReverse: TRUE
+ads-indexcachesize: 1000
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apachePresence,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apachePresence
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apacheOneAlias,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheOneAlias
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apacheSubAlias,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheSubAlias
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apacheAlias,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheAlias
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=objectClass,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: objectClass
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=entryCSN,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: entryCSN
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=ou,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: ou
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=uid,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: uid
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=administrativeRole,ou=indexes,ads-partitionId=system,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: administrativeRole
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectClass: ads-base
+objectclass: ads-partition
+objectclass: ads-jdbmPartition
+ads-partitionSuffix: dc=example,dc=com
+ads-contextentry:: ZG46IGRjPWV4YW1wbGUsZGM9Y29tCmRjOiBleGFtcGxlCm9iamVjdGNsY
+ XNzOiBkb21haW4Kb2JqZWN0Y2xhc3M6IHRvcAoK
+ads-jdbmpartitionoptimizerenabled: TRUE
+ads-partitioncachesize: 10000
+ads-partitionsynconwrite: TRUE
+ads-partitionid: example
+ads-enabled: TRUE
+
+dn: ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ou: indexes
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-indexAttributeId=apacheRdn,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheRdn
+ads-indexHasReverse: TRUE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apachePresence,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apachePresence
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apacheOneAlias,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheOneAlias
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apacheSubAlias,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheSubAlias
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=apacheAlias,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: apacheAlias
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=dc,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: dc
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=krb5PrincipalName,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: krb5PrincipalName
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=objectClass,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: objectClass
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=entryCSN,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: entryCSN
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=ou,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: ou
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=uid,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: uid
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-indexAttributeId=administrativeRole,ou=indexes,ads-partitionId=example,ou=partitions,ads-directoryServiceId=default,ou=config
+ads-indexattributeid: administrativeRole
+ads-indexHasReverse: FALSE
+ads-indexcachesize: 100
+objectclass: ads-index
+objectclass: ads-jdbmIndex
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ou=servers,ads-directoryServiceId=default,ou=config
+ou: servers
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-serverId=changePasswordServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectclass: ads-server
+objectclass: ads-changePasswordServer
+objectclass: ads-dsBasedServer
+objectclass: ads-base
+objectclass: top
+ads-serverid: changePasswordServer
+ads-enabled: FALSE
+
+dn: ou=transports,ads-serverId=changePasswordServer,ou=servers,ads-directoryServiceId=default,ou=config
+ou: transports
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-transportId=tcp,ou=transports,ads-serverId=changePasswordServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-systemport: 60464
+ads-transportnbthreads: 2
+ads-transportaddress: 0.0.0.0
+ads-transportid: tcp
+objectclass: ads-transport
+objectclass: ads-tcpTransport
+objectClass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-transportId=udp,ou=transports,ads-serverId=changePasswordServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-systemport: 60464
+ads-transportnbthreads: 2
+ads-transportaddress: 0.0.0.0
+ads-transportid: udp
+objectclass: ads-transport
+objectclass: ads-udpTransport
+objectClass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-serverId=httpServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-serverid: httpServer
+ads-enabled: FALSE
+objectclass: ads-server
+objectclass: ads-httpServer
+objectclass: ads-base
+objectclass: top
+
+dn: ou=transports,ads-serverId=httpServer,ou=servers,ads-directoryServiceId=default,ou=config
+ou: transports
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-transportid=http,ou=transports,ads-serverId=httpServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-transport
+objectclass: ads-tcpTransport
+ads-transportid: http
+ads-systemport: 8080
+ads-transportaddress: 0.0.0.0
+ads-enabled: TRUE
+
+dn: ads-transportid=https,ou=transports,ads-serverId=httpServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectclass: top
+objectclass: ads-base
+objectclass: ads-transport
+objectclass: ads-tcpTransport
+ads-transportid: https
+ads-transportaddress: 0.0.0.0
+ads-systemport: 8443
+ads-enabled: TRUE
+
+dn: ou=httpWebApps,ads-serverId=httpServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectclass: organizationalUnit
+objectclass: top
+ou: httpWebApps
+
+dn: ads-id=testapp,ou=httpWebApps,ads-serverId=httpServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-httpwarfile: /path/to/foo/war
+ads-httpappctxpath: /foo
+ads-id: testapp
+objectclass: ads-httpWebApp
+objectclass: ads-base
+objectclass: top
+ads-enabled: FALSE
+
+dn: ads-serverId=kerberosServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectclass: ads-server
+objectclass: ads-kdcServer
+objectclass: ads-dsBasedServer
+objectclass: ads-base
+objectclass: top
+ads-serverid: kerberosServer
+ads-enabled: FALSE
+ads-krbAllowableClockSkew: 300000
+ads-krbBodyChecksumVerified: TRUE
+ads-krbEmptyAddressesAllowed: TRUE
+ads-krbEncryptionTypes: aes128-cts-hmac-sha1-96
+ads-krbEncryptionTypes: des3-cbc-sha1-kd
+ads-krbEncryptionTypes: des-cbc-md5
+ads-krbForwardableAllowed: TRUE
+ads-krbmaximumrenewablelifetime: 604800000
+ads-krbMaximumTicketLifetime: 86400000
+ads-krbPaEncTimestampRequired: TRUE
+ads-krbPostdatedAllowed: TRUE
+ads-krbPrimaryRealm: EXAMPLE.COM
+ads-krbProxiableAllowed: TRUE
+ads-krbRenewableAllowed: TRUE
+ads-searchBaseDN: ou=users,dc=example,dc=com
+
+dn: ou=transports,ads-serverId=kerberosServer,ou=servers,ads-directoryServiceId=default,ou=config
+ou: transports
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-transportid=tcp,ou=transports,ads-serverId=kerberosServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-systemport: 60088
+ads-transportnbthreads: 4
+ads-transportaddress: 0.0.0.0
+ads-transportid: tcp
+objectclass: ads-transport
+objectClass: ads-base
+objectclass: ads-tcpTransport
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-transportid=udp,ou=transports,ads-serverId=kerberosServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-systemport: 60088
+ads-transportnbthreads: 4
+ads-transportaddress: 0.0.0.0
+ads-transportid: udp
+objectclass: ads-transport
+objectclass: ads-udpTransport
+objectClass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectclass: ads-server
+objectclass: ads-ldapServer
+objectclass: ads-dsBasedServer
+objectclass: ads-base
+objectclass: top
+ads-serverId: ldapServer
+ads-confidentialityRequired: FALSE
+ads-maxSizeLimit: 1000
+ads-maxTimeLimit: 15000
+ads-maxpdusize: 2000000
+ads-saslHost: ldap.example.com
+ads-saslPrincipal: ldap/ldap.example.com@EXAMPLE.COM
+ads-saslRealms: example.com
+ads-saslRealms: apache.org
+ads-searchBaseDN: ou=users,ou=system
+ads-replEnabled: true
+ads-replPingerSleep: 5
+ads-enabled: TRUE
+
+dn: ou=replConsumers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+objectClass: organizationalUnit
+objectClass: top
+ou: replConsumers
+
+dn: ou=transports,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ou: transports
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-transportid=ldap,ou=transports,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-systemport: 10389
+ads-transportnbthreads: 8
+ads-transportaddress: 0.0.0.0
+ads-transportid: ldap
+objectclass: ads-transport
+objectclass: ads-tcpTransport
+objectClass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-transportid=ldaps,ou=transports,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-systemport: 10636
+ads-transportenablessl: TRUE
+ads-transportaddress: 0.0.0.0
+ads-transportid: ldaps
+objectclass: ads-transport
+objectclass: ads-tcpTransport
+objectClass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ou: extendedOpHandlers
+objectclass: organizationalUnit
+objectclass: top
+
+dn: ads-extendedOpId=gracefulShutdownHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: gracefulShutdownHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.GracefulShutdownHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-extendedOpId=starttlshandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: starttlshandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.StartTlsHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-extendedOpId=storedprochandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-enabled: FALSE
+ads-extendedOpId: storedprochandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.StoredProcedureExtendedOperationHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+
+dn: ads-extendedOpId=pwdModifyHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: pwdModifyHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.PwdModifyHandler
+objectclass: ads-extendedOpHandler
+objectclass: ads-base
+objectclass: top
+ads-enabled: TRUE
+
+dn: ads-extendedOpId=whoAmIHandler,ou=extendedOpHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-extendedOpId: whoAmIHandler
+ads-extendedOpHandlerclass: org.apache.directory.server.ldap.handlers.extended.WhoAmIHandler
+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
+objectclass: top
+
+dn: ads-saslMechName=CRAM-MD5,ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-saslMechClassName: org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler
+objectclass: ads-saslMechHandler
+objectclass: ads-base
+objectclass: top
+ads-saslMechName: CRAM-MD5
+ads-enabled: TRUE
+
+dn: ads-saslMechName=DIGEST-MD5,ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-saslMechClassName: org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler
+objectclass: ads-saslMechHandler
+objectclass: ads-base
+objectclass: top
+ads-saslMechName: DIGEST-MD5
+ads-enabled: TRUE
+
+dn: ads-saslMechName=GSS-SPNEGO,ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-saslMechClassName: org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler
+objectclass: ads-saslMechHandler
+objectclass: ads-base
+objectclass: top
+ads-saslMechName: GSS-SPNEGO
+ads-ntlmMechProvider: com.foo.Bar
+ads-enabled: TRUE
+
+dn: ads-saslMechName=GSSAPI,ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-saslMechClassName: org.apache.directory.server.ldap.handlers.sasl.gssapi.GssapiMechanismHandler
+objectclass: ads-saslMechHandler
+objectclass: ads-base
+objectclass: top
+ads-saslMechName: GSSAPI
+ads-enabled: TRUE
+
+dn: ads-saslMechName=NTLM,ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-saslMechClassName: org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler
+objectclass: ads-saslMechHandler
+objectclass: ads-base
+objectclass: top
+ads-saslMechName: NTLM
+ads-ntlmMechProvider: com.foo.Bar
+ads-enabled: TRUE
+
+dn: ads-saslMechName=SIMPLE,ou=saslMechHandlers,ads-serverId=ldapServer,ou=servers,ads-directoryServiceId=default,ou=config
+ads-saslMechClassName: org.apache.directory.server.ldap.handlers.sasl.SimpleMechanismHandler
+objectclass: ads-saslMechHandler
+objectclass: ads-base
+objectclass: top
+ads-saslMechName: SIMPLE
+ads-enabled: TRUE
diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java
index 90f84e4..b023652 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java
+++ b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java
@@ -60,9 +60,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     /** A logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( JdbmIndex.class );
 
-    /**
-     * default duplicate limit before duplicate keys switch to using a btree for values
-     */
+    /** default duplicate limit before duplicate keys switch to using a btree for values */
     public static final int DEFAULT_DUPLICATE_LIMIT = 512;
 
     /**  the key used for the forward btree name */
diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTable.java b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTable.java
index 85554e1..df94782 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTable.java
+++ b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTable.java
@@ -33,6 +33,7 @@ import jdbm.recman.BaseRecordManager;
 import jdbm.recman.CacheRecordManager;
 
 import org.apache.directory.api.ldap.model.cursor.Cursor;
+import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
 import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
 import org.apache.directory.api.ldap.model.exception.LdapException;
@@ -41,6 +42,8 @@ import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.comparators.SerializableComparator;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.api.util.SynchronizedLRUMap;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
+import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
 import org.apache.directory.server.core.avltree.ArrayMarshaller;
 import org.apache.directory.server.core.avltree.ArrayTree;
 import org.apache.directory.server.core.avltree.ArrayTreeCursor;
@@ -77,9 +80,6 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
     /** a cache of duplicate BTrees */
     private final Map<Long, BTree<K, V>> duplicateBtrees;
 
-    /** A Key serializer */
-    private final Serializer keySerializer;
-
     /** A value serializer */
     private final Serializer valueSerializer;
 
@@ -136,7 +136,6 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
         this.numDupLimit = numDupLimit;
         this.recMan = manager;
 
-        this.keySerializer = keySerializer;
         this.valueSerializer = valueSerializer;
 
         this.allowsDuplicates = true;
@@ -200,7 +199,6 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
         this.numDupLimit = Integer.MAX_VALUE;
         this.recMan = manager;
 
-        this.keySerializer = keySerializer;
         this.valueSerializer = valueSerializer;
 
         this.allowsDuplicates = false;
@@ -227,7 +225,7 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
         }
         else
         {
-            bt = new BTree<K, V>( recMan, keyComparator, keySerializer, valueSerializer );
+            bt = new BTree<>( recMan, keyComparator, keySerializer, valueSerializer );
             recId = bt.getRecordId();
             recMan.setNamedObject( name, recId );
             recId = recMan.insert( 0 );
@@ -237,57 +235,13 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
 
     // ------------------------------------------------------------------------
-    // Simple Table Properties
-    // ------------------------------------------------------------------------
-
-    public Serializer getKeySerializer()
-    {
-        return keySerializer;
-    }
-
-
-    public Serializer getValueSerializer()
-    {
-        return valueSerializer;
-    }
-
-
-    /**
-     * @see org.apache.directory.server.xdbm.Table#isDupsEnabled()
-     */
-    public boolean isDupsEnabled()
-    {
-        return allowsDuplicates;
-    }
-
-
-    // ------------------------------------------------------------------------
     // Count Overloads
     // ------------------------------------------------------------------------
     /**
-     * @see Table#greaterThanCount(Object)
-     */
-    public long greaterThanCount( K key ) throws IOException
-    {
-        // take a best guess
-        return Math.min( count, 10L );
-    }
-
-
-    /**
-     * @see Table#lessThanCount(Object)
-     */
-    public long lessThanCount( K key ) throws IOException
-    {
-        // take a best guess
-        return Math.min( count, 10L );
-    }
-
-
-    /**
      * @see org.apache.directory.server.xdbm.Table#count(java.lang.Object)
      */
-    public long count( K key ) throws LdapException
+    @Override
+    public long count( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -328,8 +282,12 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
     // get/has/put/remove Methods and Overloads
     // ------------------------------------------------------------------------
 
+    /**
+     * {@inheritDoc}
+     */
     @SuppressWarnings("unchecked")
-    public V get( K key ) throws LdapException
+    @Override
+    public V get( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -375,9 +333,10 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
 
     /**
-     * @see Table#hasGreaterOrEqual(Object,Object)
+     * {@inheritDoc}
      */
-    public boolean hasGreaterOrEqual( K key, V val ) throws LdapException
+    @Override
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -413,9 +372,10 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
 
     /**
-     * @see Table#hasLessOrEqual(Object,Object)
+     * {@inheritDoc}
      */
-    public boolean hasLessOrEqual( K key, V val ) throws LdapException
+    @Override
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -451,86 +411,95 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
 
     /**
-     * @see org.apache.directory.server.xdbm.Table#hasGreaterOrEqual(Object)
+     * {@inheritDoc}
      */
+    @Override
     @SuppressWarnings("unchecked")
-    public boolean hasGreaterOrEqual( K key ) throws IOException
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
-        // See if we can find the border between keys greater than and less
-        // than in the set of keys.  This will be the spot we search from.
-        jdbm.helper.Tuple tuple = bt.findGreaterOrEqual( key );
-
-        // Test for equality first since it satisfies both greater/less than
-        if ( null != tuple && keyComparator.compare( ( K ) tuple.getKey(), key ) == 0 )
+        try
         {
-            return true;
+            // See if we can find the border between keys greater than and less
+            // than in the set of keys.  This will be the spot we search from.
+            jdbm.helper.Tuple tuple = bt.findGreaterOrEqual( key );
+    
+            // Test for equality first since it satisfies both greater/less than
+            if ( null != tuple && keyComparator.compare( ( K ) tuple.getKey(), key ) == 0 )
+            {
+                return true;
+            }
+    
+            // Greater searches are easy and quick thanks to findGreaterOrEqual
+            // A null return above means there were no equal or greater keys
+            return ( null != tuple );
         }
-
-        // Greater searches are easy and quick thanks to findGreaterOrEqual
-        // A null return above means there were no equal or greater keys
-        if ( null == tuple )
+        catch ( IOException ioe )
         {
-            return false;
+            throw new LdapOtherException( ioe.getMessage() );
         }
-
-        // Not Null! - we found a tuple with equal or greater key value
-        return true;
     }
 
 
     /**
-     * @see Table#hasLessOrEqual(Object)
+     * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public boolean hasLessOrEqual( K key ) throws IOException
+    @Override
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
-        // Can only find greater than or equal to with JDBM so we find that
-        // and work backwards to see if we can find one less than the key
-        Tuple<K, V> tuple = bt.findGreaterOrEqual( key );
-
-        // Test for equality first since it satisfies equal to condition
-        if ( null != tuple && keyComparator.compare( tuple.getKey(), key ) == 0 )
-        {
-            return true;
-        }
-
-        if ( null == tuple )
-        {
-            /*
-             * Jdbm failed to find a key greater than or equal to the argument
-             * which means all the keys in the table are less than the
-             * supplied key argument.  We can hence return true if the table
-             * contains any Tuples.
-             */
-            return count > 0;
-        }
-        else
+        try
         {
-            /*
-             * We have the next tuple whose key is the next greater than the
-             * key argument supplied.  We use this key to advance a browser to
-             * that tuple and scan down to lesser Tuples until we hit one
-             * that is less than the key argument supplied.  Usually this will
-             * be the previous tuple if it exists.
-             */
-            TupleBrowser browser = bt.browse( tuple.getKey() );
-
-            if ( browser.getPrevious( tuple ) )
+            // Can only find greater than or equal to with JDBM so we find that
+            // and work backwards to see if we can find one less than the key
+            Tuple<K, V> tuple = bt.findGreaterOrEqual( key );
+    
+            // Test for equality first since it satisfies equal to condition
+            if ( null != tuple && keyComparator.compare( tuple.getKey(), key ) == 0 )
             {
                 return true;
             }
+    
+            if ( null == tuple )
+            {
+                /*
+                 * Jdbm failed to find a key greater than or equal to the argument
+                 * which means all the keys in the table are less than the
+                 * supplied key argument.  We can hence return true if the table
+                 * contains any Tuples.
+                 */
+                return count > 0;
+            }
+            else
+            {
+                /*
+                 * We have the next tuple whose key is the next greater than the
+                 * key argument supplied.  We use this key to advance a browser to
+                 * that tuple and scan down to lesser Tuples until we hit one
+                 * that is less than the key argument supplied.  Usually this will
+                 * be the previous tuple if it exists.
+                 */
+                TupleBrowser browser = bt.browse( tuple.getKey() );
+    
+                if ( browser.getPrevious( tuple ) )
+                {
+                    return true;
+                }
+            }
+    
+            return false;
+        }
+        catch ( IOException ioe )
+        {
+            throw new LdapOtherException( ioe.getMessage() );
         }
-
-        return false;
     }
 
 
     /**
-     * @see org.apache.directory.server.xdbm.Table#has(java.lang.Object,
-     * java.lang.Object)
+     * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public boolean has( K key, V value ) throws LdapException
+    public boolean has( PartitionTxn transaction, K key, V value ) throws LdapException
     {
         if ( key == null )
         {
@@ -562,20 +531,28 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
 
     /**
-     * @see Table#has(java.lang.Object)
+     * {@inheritDoc}
      */
-    public boolean has( K key ) throws IOException
+    @Override
+    public boolean has( PartitionTxn transaction, K key ) throws LdapException
     {
-        return key != null && bt.find( key ) != null;
+        try
+        {
+            return key != null && bt.find( key ) != null;
+        }
+        catch ( IOException ioe )
+        {
+            throw new LdapException( ioe );
+        }
     }
 
 
     /**
-     * @see org.apache.directory.server.xdbm.Table#put(java.lang.Object,
-     * java.lang.Object)
+     * {@inheritDoc}
      */
+    @Override
     @SuppressWarnings("unchecked")
-    public synchronized void put( K key, V value ) throws Exception
+    public synchronized void put( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -664,20 +641,20 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
             commit( recMan );
         }
-        catch ( Exception e )
+        catch ( IOException | CursorException | LdapException e )
         {
             LOG.error( I18n.err( I18n.ERR_131, key, name ), e );
-            throw e;
+            throw new LdapOtherException( e.getMessage(), e );
         }
     }
 
 
     /**
-     * @see org.apache.directory.server.xdbm.Table#remove(java.lang.Object,
-     * java.lang.Object)
+     * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public synchronized void remove( K key, V value ) throws IOException
+    @Override
+    public synchronized void remove( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -788,9 +765,10 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
 
 
     /**
-     * @see Table#remove(Object)
+     * {@inheritDoc}
      */
-    public synchronized void remove( K key )
+    @Override
+    public synchronized void remove( PartitionWriteTxn transaction, K key ) throws LdapException
     {
         try
         {
@@ -871,81 +849,107 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
     }
 
 
-    public Cursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>> cursor() throws LdapException
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Cursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>> cursor( PartitionTxn transaction ) throws LdapException
     {
         if ( allowsDuplicates )
         {
-            return new DupsCursor<K, V>( this );
+            return new DupsCursor<>( this );
         }
 
-        return new NoDupsCursor<K, V>( this );
+        return new NoDupsCursor<>( this );
     }
 
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     @SuppressWarnings("unchecked")
-    public Cursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>> cursor( K key ) throws Exception
+    public Cursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>> cursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
-            return new EmptyCursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>>();
-        }
-
-        V raw = bt.find( key );
-
-        if ( null == raw )
-        {
-            return new EmptyCursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
 
-        if ( !allowsDuplicates )
-        {
-            return new SingletonCursor<org.apache.directory.api.ldap.model.cursor.Tuple<K, V>>(
-                new org.apache.directory.api.ldap.model.cursor.Tuple<K, V>( key, raw ) );
+        try
+        { 
+            V raw = bt.find( key );
+    
+            if ( null == raw )
+            {
+                return new EmptyCursor<>();
+            }
+    
+            if ( !allowsDuplicates )
+            {
+                return new SingletonCursor<>(
+                    new org.apache.directory.api.ldap.model.cursor.Tuple<K, V>( key, raw ) );
+            }
+    
+            byte[] serialized = ( byte[] ) raw;
+    
+            if ( BTreeRedirectMarshaller.isRedirect( serialized ) )
+            {
+                BTree tree = getBTree( BTreeRedirectMarshaller.INSTANCE.deserialize( serialized ) );
+                return new KeyTupleBTreeCursor<>( tree, key, valueComparator );
+            }
+    
+            ArrayTree<V> set = marshaller.deserialize( serialized );
+    
+            return new KeyTupleArrayCursor<>( set, key );
         }
-
-        byte[] serialized = ( byte[] ) raw;
-
-        if ( BTreeRedirectMarshaller.isRedirect( serialized ) )
+        catch ( IOException ioe )
         {
-            BTree tree = getBTree( BTreeRedirectMarshaller.INSTANCE.deserialize( serialized ) );
-            return new KeyTupleBTreeCursor<K, V>( tree, key, valueComparator );
+            throw new LdapOtherException( ioe.getMessage(), ioe );
         }
-
-        ArrayTree<V> set = marshaller.deserialize( serialized );
-
-        return new KeyTupleArrayCursor<K, V>( set, key );
     }
 
 
+    /**
+     * {@inheritDoc}
+     */
     @SuppressWarnings("unchecked")
-    public Cursor<V> valueCursor( K key ) throws Exception
+    @Override
+    public Cursor<V> valueCursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
-            return new EmptyCursor<V>();
+            return new EmptyCursor<>();
         }
 
-        V raw = bt.find( key );
-
-        if ( null == raw )
-        {
-            return new EmptyCursor<V>();
-        }
-
-        if ( !allowsDuplicates )
+        try
         {
-            return new SingletonCursor<V>( raw );
+            V raw = bt.find( key );
+    
+            if ( null == raw )
+            {
+                return new EmptyCursor<>();
+            }
+    
+            if ( !allowsDuplicates )
+            {
+                return new SingletonCursor<>( raw );
+            }
+    
+            byte[] serialized = ( byte[] ) raw;
+    
+            if ( BTreeRedirectMarshaller.isRedirect( serialized ) )
+            {
+                BTree tree = getBTree( BTreeRedirectMarshaller.INSTANCE.deserialize( serialized ) );
+                return new KeyBTreeCursor<>( tree, valueComparator );
+            }
+    
+            return new ArrayTreeCursor<>( marshaller.deserialize( serialized ) );
         }
-
-        byte[] serialized = ( byte[] ) raw;
-
-        if ( BTreeRedirectMarshaller.isRedirect( serialized ) )
+        catch ( IOException ioe )
         {
-            BTree tree = getBTree( BTreeRedirectMarshaller.INSTANCE.deserialize( serialized ) );
-            return new KeyBTreeCursor<V>( tree, valueComparator );
+            throw new LdapOtherException( ioe.getMessage(), ioe );
         }
-
-        return new ArrayTreeCursor<V>( marshaller.deserialize( serialized ) );
     }
 
 
@@ -956,9 +960,17 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
     /**
      * @see Table#close()
      */
-    public synchronized void close() throws IOException
+    @Override
+    public synchronized void close( PartitionTxn transaction ) throws LdapException
     {
-        sync();
+        try
+        {
+            sync();
+        }
+        catch  ( IOException ioe )
+        {
+            throw new LdapOtherException( ioe.getMessage() );
+        }
     }
 
 
@@ -1143,7 +1155,7 @@ public class JdbmTable<K, V> extends AbstractTable<K, V>
     }
 
 
-    private BTree<V, K> convertToBTree( ArrayTree<V> arrayTree ) throws Exception
+    private BTree<V, K> convertToBTree( ArrayTree<V> arrayTree ) throws IOException, CursorException, LdapException
     {
         BTree<V, K> bTree;
 
diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
index be164b2..02549d8 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
+++ b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
@@ -69,7 +69,7 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      * @param comparator the Comparator used to determine <b>key</b> ordering
      * @throws Exception of there are problems accessing the BTree
      */
-    public KeyTupleBTreeCursor( BTree btree, K key, Comparator<V> comparator ) throws Exception
+    public KeyTupleBTreeCursor( BTree btree, K key, Comparator<V> comparator ) throws IOException
     {
         if ( IS_DEBUG )
         {
diff --git a/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTableWithDuplicatesTest.java b/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTableWithDuplicatesTest.java
index fc24a71..91aa2f6 100644
--- a/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTableWithDuplicatesTest.java
+++ b/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmTableWithDuplicatesTest.java
@@ -159,14 +159,6 @@ public class JdbmTableWithDuplicatesTest
 
 
     @Test
-    public void testSerializers() throws Exception
-    {
-        assertNotNull( table.getKeySerializer() );
-        assertNotNull( ( ( JdbmTable<?, ?> ) table ).getValueSerializer() );
-    }
-
-
-    @Test
     public void testCountOneArg() throws Exception
     {
         assertEquals( 0, table.count( "3" ) );
@@ -590,7 +582,6 @@ public class JdbmTableWithDuplicatesTest
 
         table = new JdbmTable<String, String>( schemaManager, "test", SIZE, recman,
             comparator, comparator, new DefaultSerializer(), null );
-        assertNull( table.getValueSerializer() );
 
         for ( int i = 0; i < SIZE + 1; i++ )
         {
diff --git a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java b/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
index 124d865..20d78df 100644
--- a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
+++ b/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
@@ -27,6 +27,7 @@ import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
 import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapOtherException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.mavibot.btree.BTree;
 import org.apache.directory.mavibot.btree.BTreeFactory;
@@ -36,6 +37,8 @@ import org.apache.directory.mavibot.btree.ValueCursor;
 import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
+import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
 import org.apache.directory.server.core.avltree.ArrayMarshaller;
 import org.apache.directory.server.core.avltree.ArrayTree;
 import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
@@ -140,18 +143,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean isDupsEnabled()
-    {
-        return allowsDuplicates;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     * @throws  
-     */
-    @Override
-    public boolean has( K key ) throws LdapException
+    public boolean has( PartitionTxn partitionTxn, K key ) throws LdapException
     {
         try
         {
@@ -172,7 +164,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean has( K key, V value ) throws LdapException
+    public boolean has( PartitionTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -189,7 +181,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasGreaterOrEqual( K key ) throws Exception
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
         TupleCursor<K, V> cursor = null;
 
@@ -199,6 +191,10 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
 
             return cursor.hasNext();
         }
+        catch ( IOException ioe )
+        {
+            throw new LdapOtherException( ioe.getMessage() );
+        }
         finally
         {
             if ( cursor != null )
@@ -213,7 +209,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasLessOrEqual( K key ) throws Exception
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
         TupleCursor<K, V> cursor = null;
 
@@ -248,6 +244,10 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
 
             return false;
         }
+        catch ( Exception e )
+        {
+            throw new LdapException( e );
+        }
         finally
         {
             if ( cursor != null )
@@ -262,7 +262,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasGreaterOrEqual( K key, V val ) throws LdapException
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -274,7 +274,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             throw new UnsupportedOperationException( I18n.err( I18n.ERR_593 ) );
         }
 
-        TupleCursor<V, V> cursor = null;
+        ValueCursor<V> valueCursor = null;
 
         try
         {
@@ -283,21 +283,21 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 return false;
             }
 
-            ValueCursor<V> valueCursor = bt.getValues( key );
+            valueCursor = bt.getValues( key );
 
             int equal = bt.getValueSerializer().compare( val, valueCursor.next() );
 
             return ( equal >= 0 );
         }
-        catch ( Exception e )
+        catch ( KeyNotFoundException | IOException e )
         {
-            throw new LdapException( e );
+            throw new LdapException( e.getMessage() );
         }
         finally
         {
-            if ( cursor != null )
+            if ( valueCursor != null )
             {
-                cursor.close();
+                valueCursor.close();
             }
         }
     }
@@ -307,7 +307,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasLessOrEqual( K key, V val ) throws Exception
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -334,7 +334,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public V get( K key ) throws LdapException
+    public V get( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -360,7 +360,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public void put( K key, V value ) throws Exception
+    public void put( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -376,10 +376,10 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 count++;
             }
         }
-        catch ( Exception e )
+        catch ( IOException ioe )
         {
-            LOG.error( I18n.err( I18n.ERR_131, key, name ), e );
-            throw e;
+            LOG.error( I18n.err( I18n.ERR_131, key, name ), ioe );
+            throw new LdapOtherException( ioe.getMessage(), ioe );
         }
     }
 
@@ -388,7 +388,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public void remove( K key ) throws Exception
+    public void remove( PartitionWriteTxn transaction, K key ) throws LdapException
     {
         try
         {
@@ -424,14 +424,11 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 count--;
             }
         }
-        catch ( Exception e )
+        catch ( IOException | KeyNotFoundException e )
         {
             LOG.error( I18n.err( I18n.ERR_133, key, name ), e );
 
-            if ( e instanceof IOException )
-            {
-                throw ( IOException ) e;
-            }
+            throw new LdapOtherException( e.getMessage(), e );
         }
     }
 
@@ -440,7 +437,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public void remove( K key, V value ) throws Exception
+    public void remove( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -468,9 +465,9 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public Cursor<Tuple<K, V>> cursor() throws LdapException
+    public Cursor<Tuple<K, V>> cursor( PartitionTxn transaction ) throws LdapException
     {
-        return new MavibotCursor<K, V>( this );
+        return new MavibotCursor<>( this );
     }
 
 
@@ -478,11 +475,11 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public Cursor<Tuple<K, V>> cursor( K key ) throws LdapException
+    public Cursor<Tuple<K, V>> cursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
-            return new EmptyCursor<Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
 
         try
@@ -491,19 +488,18 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             {
                 V val = bt.get( key );
 
-                return new SingletonCursor<Tuple<K, V>>(
-                    new Tuple<K, V>( key, val ) );
+                return new SingletonCursor<>( new Tuple<K, V>( key, val ) );
             }
             else
             {
                 ValueCursor<V> dupHolder = bt.getValues( key );
 
-                return new KeyTupleValueCursor<K, V>( dupHolder, key );
+                return new KeyTupleValueCursor<>( dupHolder, key );
             }
         }
         catch ( KeyNotFoundException knfe )
         {
-            return new EmptyCursor<Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
         catch ( Exception e )
         {
@@ -516,7 +512,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public Cursor<V> valueCursor( K key ) throws Exception
+    public Cursor<V> valueCursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -529,18 +525,18 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             {
                 V val = bt.get( key );
 
-                return new SingletonCursor<V>( val );
+                return new SingletonCursor<>( val );
             }
             else
             {
                 ValueCursor<V> dupCursor = bt.getValues( key );
 
-                return new ValueTreeCursor<V>( dupCursor );
+                return new ValueTreeCursor<>( dupCursor );
             }
         }
         catch ( KeyNotFoundException knfe )
         {
-            return new EmptyCursor<V>();
+            return new EmptyCursor<>();
         }
         catch ( Exception e )
         {
@@ -553,16 +549,16 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public long count( K key ) throws Exception
+    public long count( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
             return 0;
         }
 
-        if ( bt.isAllowDuplicates() )
+        try
         {
-            try
+            if ( bt.isAllowDuplicates() )
             {
                 ValueCursor<V> dupHolder = bt.getValues( key );
                 int size = dupHolder.size();
@@ -570,58 +566,27 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
 
                 return size;
             }
-            catch ( KeyNotFoundException knfe )
+            else
             {
-                // No key
-                return 0;
+                if ( bt.hasKey( key ) )
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 0;
+                }
             }
         }
-        else
+        catch ( KeyNotFoundException knfe )
         {
-            if ( bt.hasKey( key ) )
-            {
-                return 1;
-            }
-            else
-            {
-                return 0;
-            }
+            // No key
+            return 0;
+        }
+        catch ( IOException ioe )
+        {
+            throw new LdapOtherException( ioe.getMessage() );
         }
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public long greaterThanCount( K key ) throws Exception
-    {
-        // take a best guess
-        return Math.min( count, 10L );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public long lessThanCount( K key ) throws Exception
-    {
-        // take a best guess
-        return Math.min( count, 10L );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void close() throws Exception
-    {
-        // do nothing here, the RecordManager will be closed in MavibotMasterTable.close()
     }
 
 
diff --git a/mavibotv2-partition/pom.xml b/mavibotv2-partition/pom.xml
new file mode 100644
index 0000000..8419302
--- /dev/null
+++ b/mavibotv2-partition/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.directory.server</groupId>
+    <artifactId>apacheds-parent</artifactId>
+    <version>2.0.0-M25-SNAPSHOT</version>
+  </parent>
+  <artifactId>apacheds-mavibotv2-partition</artifactId>
+  <name>ApacheDS Mavibot v2 Partition</name>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.directory.junit</groupId>
+      <artifactId>junit-addons</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.mavibot</groupId>
+      <artifactId>mavibot</artifactId>
+      <version>1.0.0-M9-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-api</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-shared</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-avl</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-i18n</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-xdbm-partition</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-xdbm-partition</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.api</groupId>
+      <artifactId>api-ldap-model</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.api</groupId>
+      <artifactId>api-ldap-schema-data</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.api</groupId>
+      <artifactId>api-util</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <phase>verify</phase>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>META-INF/MANIFEST.MF</manifestFile>
+            <addMavenDescriptor>false</addMavenDescriptor>
+          </archive>
+        </configuration>
+      </plugin>
+      
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <inherited>true</inherited>
+        <extensions>true</extensions>
+        <configuration>
+          <manifestLocation>META-INF</manifestLocation>
+          <instructions>
+            <Bundle-SymbolicName>${project.groupId}.mavibotv2.partition</Bundle-SymbolicName>
+            <Export-Package>
+                org.apache.directory.server.core.partition.impl.btree.mavibotv2;version=${project.version};-noimport:=true
+            </Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/AbstractMavibotTxn.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/AbstractMavibotTxn.java
new file mode 100644
index 0000000..71d0639
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/AbstractMavibotTxn.java
@@ -0,0 +1,96 @@
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+import java.io.IOException;
+
+import org.apache.directory.mavibot.btree.BTree;
+import org.apache.directory.mavibot.btree.BTreeInfo;
+import org.apache.directory.mavibot.btree.Page;
+import org.apache.directory.mavibot.btree.RecordManager;
+import org.apache.directory.mavibot.btree.RecordManagerHeader;
+import org.apache.directory.mavibot.btree.Transaction;
+
+public abstract class AbstractMavibotTxn implements MavibotTxn
+{
+    protected Transaction transaction;
+    
+    protected AbstractMavibotTxn( Transaction transaction )
+    {
+        this.transaction = transaction;
+    }
+    
+    
+    @Override
+    public void commit() throws IOException
+    {
+        transaction.commit();
+    }
+
+    
+    @Override
+    public void abort() throws IOException
+    {
+        transaction.abort();
+    }
+
+    
+    @Override
+    public boolean isClosed()
+    {
+        return transaction.isClosed();
+    }
+
+    
+    @Override
+    public void close() throws IOException
+    {
+        transaction.close();
+    }
+
+    
+    @Override
+    public long getRevision()
+    {
+        return transaction.getRevision();
+    }
+
+    
+    @Override
+    public <K, V> Page<K, V> getPage( BTreeInfo<K, V> btreeInfo, long offset ) throws IOException
+    {
+        return transaction.getPage( btreeInfo, offset );
+    }
+
+    
+    @Override
+    public long getCreationDate()
+    {
+        return transaction.getCreationDate();
+    }
+
+    
+    @Override
+    public RecordManager getRecordManager()
+    {
+        return transaction.getRecordManager();
+    }
+
+    
+    @Override
+    public RecordManagerHeader getRecordManagerHeader()
+    {
+        return transaction.getRecordManagerHeader();
+    }
+
+    
+    @Override
+    public <K, V> BTree<K, V> getBTree( String name )
+    {
+        return transaction.getBTree( name );
+    }
+
+    
+    public Transaction getTransaction()
+    {
+        return transaction;
+    }
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java
new file mode 100644
index 0000000..2f60099
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java
@@ -0,0 +1,206 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
+import java.util.Comparator;
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.mavibot.btree.serializer.AbstractElementSerializer;
+import org.apache.directory.mavibot.btree.serializer.BufferHandler;
+import org.apache.directory.server.i18n.I18n;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Serialize and deserialize a Dn.
+ * </br></br>
+ * <b>This class must *not* be used outside of the server.</b>
+ *  
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class DnSerializer extends AbstractElementSerializer<Dn>
+{
+    /** The serialVersionUID */
+    private static final long serialVersionUID = 1L;
+
+    /** the logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( DnSerializer.class );
+
+    /**
+     * Speedup for logs
+     */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    private static Comparator<Dn> comp = new Comparator<Dn>()
+    {
+        @Override
+        public int compare( Dn dn1, Dn dn2 )
+        {
+            if ( dn1 == null )
+            {
+                if ( dn2 == null )
+                {
+                    return 0;
+                }
+
+                return -1;
+            }
+
+            if ( dn2 == null )
+            {
+                return 1;
+            }
+
+            return dn1.getNormName().compareTo( dn2.getNormName() );
+        }
+    };
+
+
+    /**
+     * Creates a new instance of DnSerializer.
+     * 
+     * @param schemaManager The reference to the global schemaManager
+     */
+    public DnSerializer()
+    {
+        super( comp );
+    }
+
+
+    /**
+     * <p>
+     * 
+     * This is the place where we serialize Dn
+     * <p>
+     */
+    public byte[] serialize( Dn dn )
+    {
+        try
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutput out = new ObjectOutputStream( baos );
+
+            // First, the Dn
+            dn.writeExternal( out );
+
+            out.flush();
+
+            if ( IS_DEBUG )
+            {
+                LOG.debug( ">------------------------------------------------" );
+                LOG.debug( "Serialized " + dn );
+            }
+
+            return baos.toByteArray();
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     *  Deserialize a Dn.
+     *  
+     *  @param bytes the byte array containing the serialized Dn
+     *  @return An instance of a Dn object 
+     *  @throws IOException if we can't deserialize the Dn
+     */
+    public Dn deserialize( ByteBuffer buffer ) throws IOException
+    {
+        return deserialize( new BufferHandler( buffer.array() ) );
+    }
+
+
+    @Override
+    public Dn deserialize( BufferHandler bufferHandler ) throws IOException
+    {
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( bufferHandler.getBuffer() ) );
+
+        try
+        {
+            Dn dn = new Dn();
+
+            dn.readExternal( in );
+
+            return dn;
+        }
+        catch ( ClassNotFoundException cnfe )
+        {
+            LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
+            throw new IOException( cnfe.getLocalizedMessage() );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Dn fromBytes( byte[] buffer ) throws IOException
+    {
+        return fromBytes( buffer, 0 );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Dn fromBytes( byte[] buffer, int pos ) throws IOException
+    {
+        int length = buffer.length - pos;
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( buffer, pos, length ) );
+
+        try
+        {
+            Dn dn = new Dn();
+
+            dn.readExternal( in );
+
+            return dn;
+        }
+        catch ( ClassNotFoundException cnfe )
+        {
+            LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
+            throw new IOException( cnfe.getLocalizedMessage() );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Class<?> getType()
+    {
+        return Dn.class;
+    }
+}
diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleValueCursor.java
similarity index 50%
copy from jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
copy to mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleValueCursor.java
index be164b2..20b5c06 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleValueCursor.java
@@ -16,14 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.directory.server.core.partition.impl.btree.jdbm;
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
 
 
 import java.io.IOException;
-import java.util.Comparator;
-
-import jdbm.btree.BTree;
-import jdbm.helper.TupleBrowser;
 
 import org.apache.directory.api.ldap.model.constants.Loggers;
 import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
@@ -31,19 +27,20 @@ import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.mavibot.btree.ValueCursor;
 import org.apache.directory.server.i18n.I18n;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 /**
- * Cursor over a set of values for the same key which are store in another
- * BTree.  This Cursor is limited to the same key and it's tuples will always
- * return the same key.
+ * Cursor over a set of values for the same key which are store in an in
+ * memory ArrayTree.  This Cursor is limited to the same key and it's tuples
+ * will always return the same key.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
+public class KeyTupleValueCursor<K, V> extends AbstractCursor<Tuple<K, V>>
 {
     /** A dedicated log for cursors */
     private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
@@ -51,35 +48,29 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     /** Speedup for logs */
     private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
 
-    private final Comparator<V> comparator;
-    private final BTree btree;
+    private final ValueCursor<V> wrapped;
     private final K key;
 
-    private jdbm.helper.Tuple<K, V> valueTuple = new jdbm.helper.Tuple<K, V>();
     private Tuple<K, V> returnedTuple = new Tuple<K, V>();
-    private TupleBrowser<K, V> browser;
     private boolean valueAvailable;
 
 
     /**
-     * Creates a Cursor over the tuples of a JDBM BTree.
+     * Creates a Cursor over the tuples of an ArrayTree.
      *
-     * @param btree the JDBM BTree to build a Cursor over
+     * @param arrayTree the ArrayTree to build a Tuple returning Cursor over
      * @param key the constant key for which values are returned
-     * @param comparator the Comparator used to determine <b>key</b> ordering
-     * @throws Exception of there are problems accessing the BTree
      */
-    public KeyTupleBTreeCursor( BTree btree, K key, Comparator<V> comparator ) throws Exception
+    public KeyTupleValueCursor( ValueCursor<V> cursor, K key )
     {
+        this.key = key;
+
+        this.wrapped = cursor;
+
         if ( IS_DEBUG )
         {
-            LOG_CURSOR.debug( "Creating KeyTupleBTreeCursor {}", this );
+            LOG_CURSOR.debug( "Creating KeyTupleArrayCursor {}", this );
         }
-
-        this.key = key;
-        this.btree = btree;
-        this.comparator = comparator;
-        this.browser = btree.browse();
     }
 
 
@@ -91,9 +82,6 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     }
 
 
-    /**
-     * {@inheritDoc}
-     */
     public boolean available()
     {
         return valueAvailable;
@@ -106,109 +94,35 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     }
 
 
-    /**
-     * {@inheritDoc}
-     */
     public void afterKey( K key ) throws Exception
     {
         throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
-    /**
-     * {@inheritDoc}
-     */
     public void beforeValue( K key, V value ) throws Exception
     {
-        checkNotClosed( "beforeValue()" );
-        if ( key != null && !key.equals( this.key ) )
-        {
-            throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
-        }
-
-        browser = btree.browse( value );
-        clearValue();
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings("unchecked")
-    public void afterValue( K key, V value ) throws LdapException, CursorException
+    public void afterValue( K key, V value ) throws Exception
     {
-        if ( key != null && !key.equals( this.key ) )
-        {
-            throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
-        }
-
-        try
-        {
-            browser = btree.browse( value );
-
-            /*
-             * While the next value is less than or equal to the element keep
-             * advancing forward to the next item.  If we cannot advance any
-             * further then stop and return.  If we find a value greater than
-             * the element then we stop, backup, and return so subsequent calls
-             * to getNext() will return a value greater than the element.
-             */
-            while ( browser.getNext( valueTuple ) )
-            {
-                checkNotClosed( "afterValue" );
-
-                V next = ( V ) valueTuple.getKey();
-
-                int nextCompared = comparator.compare( next, value );
-
-                if ( nextCompared > 0 )
-                {
-                    /*
-                     * If we just have values greater than the element argument
-                     * then we are before the first element and cannot backup, and
-                     * the call below to getPrevious() will fail.  In this special
-                     * case we just reset the Cursor's browser and return.
-                     */
-                    if ( !browser.getPrevious( valueTuple ) )
-                    {
-                        browser = btree.browse( this.key );
-                    }
-
-                    clearValue();
-
-                    return;
-                }
-            }
-
-            clearValue();
-        }
-        catch ( IOException e )
-        {
-            throw new CursorException( e );
-        }
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
     /**
      * Positions this Cursor over the same keys before the value of the
-     * supplied valueTuple.  The supplied element Tuple's key is not considered at
-     * all.
+     * supplied element Tuple.  The supplied element Tuple's key is not
+     * considered at all.
      *
      * @param element the valueTuple who's value is used to position this Cursor
      * @throws Exception if there are failures to position the Cursor
      */
     public void before( Tuple<K, V> element ) throws LdapException, CursorException
     {
-        checkNotClosed( "before()" );
-        try
-        {
-            browser = btree.browse( element.getValue() );
-            clearValue();
-        }
-        catch ( IOException e )
-        {
-            throw new CursorException( e );
-        }
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
@@ -217,7 +131,7 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      */
     public void after( Tuple<K, V> element ) throws LdapException, CursorException
     {
-        afterValue( key, element.getValue() );
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
@@ -226,16 +140,6 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      */
     public void beforeFirst() throws LdapException, CursorException
     {
-        checkNotClosed( "beforeFirst()" );
-        try
-        {
-            browser = btree.browse();
-            clearValue();
-        }
-        catch ( IOException e )
-        {
-            throw new CursorException( e );
-        }
     }
 
 
@@ -244,15 +148,6 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      */
     public void afterLast() throws LdapException, CursorException
     {
-        checkNotClosed( "afterLast()" );
-        try
-        {
-            browser = btree.browse( null );
-        }
-        catch ( IOException e )
-        {
-            throw new CursorException( e );
-        }
     }
 
 
@@ -261,9 +156,7 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      */
     public boolean first() throws LdapException, CursorException
     {
-        beforeFirst();
-
-        return next();
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
@@ -272,40 +165,29 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      */
     public boolean last() throws LdapException, CursorException
     {
-        afterLast();
-
-        return previous();
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
     public boolean previous() throws LdapException, CursorException
     {
         checkNotClosed( "previous()" );
 
         try
         {
-            if ( browser.getPrevious( valueTuple ) )
+            if ( wrapped.hasPrev() )
             {
-                // work around to fix direction change problem with jdbm browser
-                if ( ( returnedTuple.getValue() != null )
-                    && ( comparator.compare( ( V ) valueTuple.getKey(), returnedTuple.getValue() ) == 0 ) )
-                {
-                    browser.getPrevious( valueTuple );
-                }
                 returnedTuple.setKey( key );
-                returnedTuple.setValue( ( V ) valueTuple.getKey() );
-
+                returnedTuple.setValue( wrapped.prev() );
                 valueAvailable = true;
                 return true;
             }
             else
             {
                 clearValue();
-
                 return false;
             }
         }
@@ -319,24 +201,16 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
     public boolean next() throws LdapException, CursorException
     {
         checkNotClosed( "next()" );
 
         try
         {
-            if ( browser.getNext( valueTuple ) )
+            if ( wrapped.hasNext() )
             {
-                // work around to fix direction change problem with jdbm browser
-                if ( returnedTuple.getValue() != null
-                    && comparator.compare( ( V ) valueTuple.getKey(), returnedTuple.getValue() ) == 0 )
-                {
-                    browser.getNext( valueTuple );
-                }
-
                 returnedTuple.setKey( key );
-                returnedTuple.setValue( ( V ) valueTuple.getKey() );
+                returnedTuple.setValue( wrapped.next() );
 
                 valueAvailable = true;
                 return true;
@@ -374,12 +248,16 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     /**
      * {@inheritDoc}
      */
-    @Override
     public void close() throws IOException
     {
         if ( IS_DEBUG )
         {
-            LOG_CURSOR.debug( "Closing KeyTupleBTreeCursor {}", this );
+            LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
+        }
+
+        if ( wrapped != null )
+        {
+            wrapped.close();
         }
 
         super.close();
@@ -389,14 +267,55 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     /**
      * {@inheritDoc}
      */
-    @Override
-    public void close( Exception cause ) throws IOException
+    public void close( Exception reason ) throws IOException
     {
         if ( IS_DEBUG )
         {
-            LOG_CURSOR.debug( "Closing KeyTupleBTreeCursor {}", this );
+            LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
         }
 
-        super.close( cause );
+        if ( wrapped != null )
+        {
+            wrapped.close();
+        }
+
+        super.close( reason );
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString( String tabs )
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( tabs ).append( "KeyTupleArrayCursor (" );
+
+        if ( available() )
+        {
+            sb.append( "available)" );
+        }
+        else
+        {
+            sb.append( "absent)" );
+        }
+
+        sb.append( "#" ).append( key );
+
+        sb.append( " :\n" );
+
+        sb.append( wrapped.toString() );
+
+        return sb.toString();
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return toString( "" );
     }
 }
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleComparator.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleComparator.java
new file mode 100644
index 0000000..6779c66
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleComparator.java
@@ -0,0 +1,57 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+import java.util.Comparator;
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.mavibot.btree.Tuple;
+
+/**
+ * TODO LdifTupleComparator.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdifTupleComparator implements Comparator<Tuple<Dn, String>>
+{
+
+    @Override
+    public int compare( Tuple<Dn, String> t1, Tuple<Dn, String> t2 )
+    {
+        Dn dn1 = t1.getKey();
+        Dn dn2 = t2.getKey();
+
+        if ( dn1.isAncestorOf( dn2 ) )
+        {
+            return -1;
+        }
+        else if ( dn2.isAncestorOf( dn1 ) )
+        {
+            return 1;
+        }
+        else if ( dn1.equals( dn2 ) )
+        {
+            return 0;
+        }
+
+        return dn1.getNormName().compareTo( dn2.getNormName() );
+    }
+
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleReaderWriter.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleReaderWriter.java
new file mode 100644
index 0000000..1f16448
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/LdifTupleReaderWriter.java
@@ -0,0 +1,162 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.mavibot.btree.Tuple;
+import org.apache.directory.mavibot.btree.util.TupleReaderWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * TODO LdifTupleReaderWriter.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdifTupleReaderWriter<E> implements TupleReaderWriter<Dn, E>
+{
+
+    private LdifReader reader = null;
+
+    private static final Logger LOG = LoggerFactory.getLogger( LdifTupleReaderWriter.class );
+
+    private String ldifFile;
+    
+    private RandomAccessFile raf;
+    
+    private SchemaManager schemaManager;
+    
+    public LdifTupleReaderWriter( String ldifFile, SchemaManager schemaManager )
+    {
+        this.ldifFile = ldifFile;
+        this.schemaManager = schemaManager;
+        
+        try
+        {
+            raf = new RandomAccessFile( ldifFile, "r" );
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+    
+
+    @Override
+    public Tuple<Dn, E> readSortedTuple( DataInputStream in )
+    {
+        try
+        {
+            if ( in.available() > 0 )
+            {
+                Tuple<Dn, E> t = new Tuple<Dn, E>();
+                t.setKey( new Dn( in.readUTF() ) );
+                
+                String[] tokens = in.readUTF().split( ":" );
+                
+                long offset = Long.valueOf( tokens[0] );
+                
+                int length = Integer.valueOf( tokens[1] );
+                
+                raf.seek( offset );
+                
+                byte[] data = new byte[length];
+                
+                raf.read( data, 0, length );
+                
+                LdifReader reader = new LdifReader();
+                
+                LdifEntry ldifEntry = reader.parseLdif( new String( data ) ).get( 0 );
+                Entry entry = new DefaultEntry( schemaManager, ldifEntry.getEntry() );
+
+                t.setValue( ( E ) entry );
+                
+                return t;
+            }
+        }
+        catch ( Exception e )
+        {
+            LOG.error( "Failed to read a sorted tuple", e );
+        }
+        
+        return null;
+    }
+
+
+    @Override
+    public Tuple<Dn, E> readUnsortedTuple( DataInputStream in )
+    {
+        try
+        {
+            if ( reader == null )
+            {
+                reader = new LdifReader( in );
+            }
+        }
+        catch ( Exception e )
+        {
+            String msg = "Failed to open the LDIF input stream";
+            LOG.error( msg, e );
+
+            throw new RuntimeException( msg, e );
+        }
+
+        Tuple<Dn, E> t = null;
+
+        if ( reader.hasNext() )
+        {
+            LdifEntry ldifEntry = reader.next();
+
+            if ( ldifEntry == null )
+            {
+                throw new IllegalStateException(
+                    "Received null entry while parsing, check the LDIF file for possible incorrect/corrupted entries" );
+            }
+
+            t = new Tuple<Dn, E>();
+
+            t.setKey( ldifEntry.getDn() );
+            t.setValue( ( E ) ( ldifEntry.getOffset() + ":" + ldifEntry.getLengthBeforeParsing() ) );
+        }
+
+        return t;
+    }
+
+
+    @Override
+    public void storeSortedTuple( Tuple<Dn, E> t, DataOutputStream out ) throws IOException
+    {
+        out.writeUTF( t.getKey().getName() );
+        out.writeUTF( ( String ) t.getValue() );
+    }
+
+}
diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java
similarity index 50%
copy from jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
copy to mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java
index be164b2..32910b1 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/KeyTupleBTreeCursor.java
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java
@@ -16,76 +16,65 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.directory.server.core.partition.impl.btree.jdbm;
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
 
 
 import java.io.IOException;
-import java.util.Comparator;
 
-import jdbm.btree.BTree;
-import jdbm.helper.TupleBrowser;
-
-import org.apache.directory.api.ldap.model.constants.Loggers;
 import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
 import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.mavibot.btree.TupleCursor;
+import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.server.i18n.I18n;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 /**
- * Cursor over a set of values for the same key which are store in another
- * BTree.  This Cursor is limited to the same key and it's tuples will always
- * return the same key.
+ * Cursor over the Tuples of a Mavibot BTree. If the BTree allows duplicate values,
+ * we will browse each value and return a Tuple for each one of them.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
+class MavibotCursor<K, V> extends AbstractCursor<Tuple<K, V>>
 {
     /** A dedicated log for cursors */
-    private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
-
-    /** Speedup for logs */
-    private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
+    private static final Logger LOG_CURSOR = LoggerFactory.getLogger( "CURSOR" );
 
-    private final Comparator<V> comparator;
-    private final BTree btree;
-    private final K key;
+    /** The table we are building a cursor over */
+    private final MavibotTable<K, V> table;
 
-    private jdbm.helper.Tuple<K, V> valueTuple = new jdbm.helper.Tuple<K, V>();
+    /** The tuple which will be returned */
     private Tuple<K, V> returnedTuple = new Tuple<K, V>();
-    private TupleBrowser<K, V> browser;
-    private boolean valueAvailable;
+
+    /** A flag set when there is a Tuple available */
+    private boolean valueAvailable = false;
+
+    /** The Tuple browser */
+    private TupleCursor<K, V> browser;
 
 
     /**
-     * Creates a Cursor over the tuples of a JDBM BTree.
+     * Creates a Cursor over the tuples of a Mavibot table.
      *
-     * @param btree the JDBM BTree to build a Cursor over
-     * @param key the constant key for which values are returned
-     * @param comparator the Comparator used to determine <b>key</b> ordering
-     * @throws Exception of there are problems accessing the BTree
+     * @param table the JDBM Table to build a Cursor over
      */
-    public KeyTupleBTreeCursor( BTree btree, K key, Comparator<V> comparator ) throws Exception
+    MavibotCursor( MavibotTable<K, V> table )
     {
-        if ( IS_DEBUG )
-        {
-            LOG_CURSOR.debug( "Creating KeyTupleBTreeCursor {}", this );
-        }
-
-        this.key = key;
-        this.btree = btree;
-        this.comparator = comparator;
-        this.browser = btree.browse();
+        LOG_CURSOR.debug( "Creating MavibotCursor {}", this );
+        this.table = table;
     }
 
 
+    /**
+     * Cleanup the returned tuple before reusing it.
+     */
     private void clearValue()
     {
-        returnedTuple.setKey( key );
+        returnedTuple.setKey( null );
         returnedTuple.setValue( null );
         valueAvailable = false;
     }
@@ -100,83 +89,58 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     }
 
 
-    public void beforeKey( K key ) throws Exception
-    {
-        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
-    }
-
-
     /**
-     * {@inheritDoc}
+     * Sets the position before a given key
+     * @param key The key we want to start with
+     * @throws LdapException 
+     * @throws CursorException
      */
-    public void afterKey( K key ) throws Exception
+    public void beforeKey( K key ) throws LdapException, CursorException
     {
-        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
-    }
+        checkNotClosed( "beforeKey()" );
+        closeBrowser( browser );
 
-
-    /**
-     * {@inheritDoc}
-     */
-    public void beforeValue( K key, V value ) throws Exception
-    {
-        checkNotClosed( "beforeValue()" );
-        if ( key != null && !key.equals( this.key ) )
+        try
+        {
+            browser = table.getBTree().browseFrom( key );
+        }
+        catch ( IOException e )
         {
-            throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+            throw new CursorException( e );
         }
 
-        browser = btree.browse( value );
         clearValue();
     }
 
 
     /**
-     * {@inheritDoc}
+     * Sets the position before a given key
+     * @param key The key we want to start with
+     * @throws LdapException 
+     * @throws CursorException
      */
-    @SuppressWarnings("unchecked")
-    public void afterValue( K key, V value ) throws LdapException, CursorException
+    public void afterKey( K key ) throws LdapException, CursorException
     {
-        if ( key != null && !key.equals( this.key ) )
-        {
-            throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
-        }
+        checkNotClosed( "afterKey()" );
 
+        closeBrowser( browser );
         try
         {
-            browser = btree.browse( value );
-
-            /*
-             * While the next value is less than or equal to the element keep
-             * advancing forward to the next item.  If we cannot advance any
-             * further then stop and return.  If we find a value greater than
-             * the element then we stop, backup, and return so subsequent calls
-             * to getNext() will return a value greater than the element.
-             */
-            while ( browser.getNext( valueTuple ) )
-            {
-                checkNotClosed( "afterValue" );
+            browser = table.getBTree().browseFrom( key );
 
-                V next = ( V ) valueTuple.getKey();
-
-                int nextCompared = comparator.compare( next, value );
-
-                if ( nextCompared > 0 )
+            if ( table.isDupsEnabled() )
+            {
+                browser.nextKey();
+            }
+            else
+            {
+                if ( browser.hasNextKey() )
                 {
-                    /*
-                     * If we just have values greater than the element argument
-                     * then we are before the first element and cannot backup, and
-                     * the call below to getPrevious() will fail.  In this special
-                     * case we just reset the Cursor's browser and return.
-                     */
-                    if ( !browser.getPrevious( valueTuple ) )
-                    {
-                        browser = btree.browse( this.key );
-                    }
-
-                    clearValue();
-
-                    return;
+                    browser.nextKey();
+                }
+                else
+                {
+                    browser.afterLast();
                 }
             }
 
@@ -184,31 +148,44 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
         }
         catch ( IOException e )
         {
+            clearValue();
             throw new CursorException( e );
         }
     }
 
 
     /**
-     * Positions this Cursor over the same keys before the value of the
-     * supplied valueTuple.  The supplied element Tuple's key is not considered at
-     * all.
-     *
-     * @param element the valueTuple who's value is used to position this Cursor
-     * @throws Exception if there are failures to position the Cursor
+     * Sets the position before a given key and a given value for this key
+     * @param key The key we want to start with
+     * @param value The value we want to start with
+     * @throws LdapException 
+     * @throws CursorException
+     */
+    public void beforeValue( K key, V value ) throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_596 ) );
+    }
+
+
+    /**
+     * Sets the position after a given key and a given value for this key
+     * @param key The key we want to start with
+     * @param value The value we want to start with
+     * @throws LdapException 
+     * @throws CursorException
+     */
+    public void afterValue( K key, V value ) throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_596 ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
      */
     public void before( Tuple<K, V> element ) throws LdapException, CursorException
     {
-        checkNotClosed( "before()" );
-        try
-        {
-            browser = btree.browse( element.getValue() );
-            clearValue();
-        }
-        catch ( IOException e )
-        {
-            throw new CursorException( e );
-        }
+        beforeKey( element.getKey() );
     }
 
 
@@ -217,7 +194,7 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
      */
     public void after( Tuple<K, V> element ) throws LdapException, CursorException
     {
-        afterValue( key, element.getValue() );
+        afterKey( element.getKey() );
     }
 
 
@@ -227,15 +204,25 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     public void beforeFirst() throws LdapException, CursorException
     {
         checkNotClosed( "beforeFirst()" );
+
         try
         {
-            browser = btree.browse();
+            if ( browser == null )
+            {
+                browser = table.getBTree().browse();
+            }
+
+            browser.beforeFirst();
             clearValue();
         }
         catch ( IOException e )
         {
             throw new CursorException( e );
         }
+        catch ( KeyNotFoundException knfe )
+        {
+            throw new CursorException( knfe );
+        }
     }
 
 
@@ -245,14 +232,25 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     public void afterLast() throws LdapException, CursorException
     {
         checkNotClosed( "afterLast()" );
+
         try
         {
-            browser = btree.browse( null );
+            if ( browser == null )
+            {
+                browser = table.getBTree().browse();
+            }
+
+            browser.afterLast();
+            clearValue();
         }
         catch ( IOException e )
         {
             throw new CursorException( e );
         }
+        catch ( KeyNotFoundException knfe )
+        {
+            throw new CursorException( knfe );
+        }
     }
 
 
@@ -273,7 +271,6 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     public boolean last() throws LdapException, CursorException
     {
         afterLast();
-
         return previous();
     }
 
@@ -281,31 +278,28 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
     public boolean previous() throws LdapException, CursorException
     {
         checkNotClosed( "previous()" );
+        if ( browser == null )
+        {
+            afterLast();
+        }
 
         try
         {
-            if ( browser.getPrevious( valueTuple ) )
+            if ( browser.hasPrev() )
             {
-                // work around to fix direction change problem with jdbm browser
-                if ( ( returnedTuple.getValue() != null )
-                    && ( comparator.compare( ( V ) valueTuple.getKey(), returnedTuple.getValue() ) == 0 ) )
-                {
-                    browser.getPrevious( valueTuple );
-                }
-                returnedTuple.setKey( key );
-                returnedTuple.setValue( ( V ) valueTuple.getKey() );
+                org.apache.directory.mavibot.btree.Tuple<K, V> tuple = browser.prev();
 
+                returnedTuple.setKey( tuple.getKey() );
+                returnedTuple.setValue( tuple.getValue() );
                 valueAvailable = true;
                 return true;
             }
             else
             {
                 clearValue();
-
                 return false;
             }
         }
@@ -319,32 +313,29 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
     public boolean next() throws LdapException, CursorException
     {
-        checkNotClosed( "next()" );
+        checkNotClosed( "previous()" );
+
+        if ( browser == null )
+        {
+            beforeFirst();
+        }
 
         try
         {
-            if ( browser.getNext( valueTuple ) )
+            if ( browser.hasNext() )
             {
-                // work around to fix direction change problem with jdbm browser
-                if ( returnedTuple.getValue() != null
-                    && comparator.compare( ( V ) valueTuple.getKey(), returnedTuple.getValue() ) == 0 )
-                {
-                    browser.getNext( valueTuple );
-                }
-
-                returnedTuple.setKey( key );
-                returnedTuple.setValue( ( V ) valueTuple.getKey() );
+                org.apache.directory.mavibot.btree.Tuple<K, V> tuple = browser.next();
 
+                returnedTuple.setKey( tuple.getKey() );
+                returnedTuple.setValue( tuple.getValue() );
                 valueAvailable = true;
                 return true;
             }
             else
             {
                 clearValue();
-
                 return false;
             }
         }
@@ -361,7 +352,6 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     public Tuple<K, V> get() throws CursorException
     {
         checkNotClosed( "get()" );
-
         if ( valueAvailable )
         {
             return returnedTuple;
@@ -377,12 +367,9 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     @Override
     public void close() throws IOException
     {
-        if ( IS_DEBUG )
-        {
-            LOG_CURSOR.debug( "Closing KeyTupleBTreeCursor {}", this );
-        }
-
+        LOG_CURSOR.debug( "Closing MavibotCursor {}", this );
         super.close();
+        closeBrowser( browser );
     }
 
 
@@ -392,11 +379,20 @@ public class KeyTupleBTreeCursor<K, V> extends AbstractCursor<Tuple<K, V>>
     @Override
     public void close( Exception cause ) throws IOException
     {
-        if ( IS_DEBUG )
+        LOG_CURSOR.debug( "Closing MavibotCursor {}", this );
+        super.close( cause );
+        closeBrowser( browser );
+    }
+
+
+    /**
+     * Close the browser
+     */
+    private void closeBrowser( TupleCursor<K, V> browser )
+    {
+        if ( browser != null )
         {
-            LOG_CURSOR.debug( "Closing KeyTupleBTreeCursor {}", this );
+            browser.close();
         }
-
-        super.close( cause );
     }
 }
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java
new file mode 100644
index 0000000..49be1b5
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java
@@ -0,0 +1,123 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.MatchingRule;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.model.schema.comparators.UuidComparator;
+import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.directory.server.i18n.I18n;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A special index which stores DN objects.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MavibotDnIndex extends MavibotIndex<Dn>
+{
+
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotDnIndex.class );
+
+
+    public MavibotDnIndex( String oid )
+    {
+        super( oid, true );
+        initialized = false;
+    }
+
+
+    public void init( SchemaManager schemaManager, AttributeType attributeType ) throws IOException
+    {
+        LOG.debug( "Initializing an Index for attribute '{}'", attributeType.getName() );
+
+        this.attributeType = attributeType;
+
+        if ( attributeId == null )
+        {
+            setAttributeId( attributeType.getName() );
+        }
+
+        if ( this.wkDirPath == null )
+        {
+            NullPointerException e = new NullPointerException( "The index working directory has not be set" );
+            throw e;
+        }
+
+        try
+        {
+            initTables( schemaManager );
+        }
+        catch ( IOException e )
+        {
+            // clean up
+            close();
+            throw e;
+        }
+
+        initialized = true;
+    }
+
+
+    private void initTables( SchemaManager schemaManager ) throws IOException
+    {
+        MatchingRule mr = attributeType.getEquality();
+
+        if ( mr == null )
+        {
+            throw new IOException( I18n.err( I18n.ERR_574, attributeType.getName() ) );
+        }
+
+        /*
+         * The forward key/value map stores attribute values to master table
+         * primary keys.  A value for an attribute can occur several times in
+         * different entries so the forward map can have more than one value.
+         */
+        UuidComparator.INSTANCE.setSchemaManager( schemaManager );
+
+        DnSerializer dnSerializer = new DnSerializer();
+
+        String forwardTableName = attributeType.getOid() + FORWARD_BTREE;
+        forward = new MavibotTable<Dn, String>( recordMan, schemaManager, forwardTableName, dnSerializer,
+            StringSerializer.INSTANCE, true );
+
+        String reverseTableName = attributeType.getOid() + REVERSE_BTREE;
+        reverse = new MavibotTable<String, Dn>( recordMan, schemaManager, reverseTableName, StringSerializer.INSTANCE,
+            dnSerializer, !attributeType.isSingleValued() );
+
+        String path = new File( this.wkDirPath, attributeType.getOid() ).getAbsolutePath();
+        // finally write a text file in the format <OID>-<attribute-name>.txt
+        FileWriter fw = new FileWriter( new File( path + "-" + attributeType.getName() + ".txt" ) );
+        // write the AttributeType description
+        fw.write( attributeType.toString() );
+        fw.close();
+    }
+
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java
new file mode 100644
index 0000000..96fdf00
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java
@@ -0,0 +1,382 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
+import java.util.Comparator;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.mavibot.btree.serializer.AbstractElementSerializer;
+import org.apache.directory.mavibot.btree.serializer.BufferHandler;
+import org.apache.directory.server.i18n.I18n;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Serialize and deserialize a ServerEntry. There is a big difference with the standard
+ * Entry serialization : we don't serialize the entry's Dn, we just serialize it's Rdn.
+ * </br></br>
+ * <b>This class must *not* be used outside of the server.</b>
+ *  
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MavibotEntrySerializer extends AbstractElementSerializer<Entry>
+{
+    /** The serialVersionUID */
+    private static final long serialVersionUID = 1L;
+
+    /** the logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotEntrySerializer.class );
+
+    /**
+     * Speedup for logs
+     */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The schemaManager reference */
+    private static SchemaManager schemaManager;
+
+    private static class EntryComparator implements Comparator<Entry>
+    {
+
+        @Override
+        public int compare( Entry entry1, Entry entry2 )
+        {
+            return entry1.getDn().getName().compareTo( entry1.getDn().getName() );
+        }
+
+    }
+
+    private static Comparator<Entry> comparator = new EntryComparator();
+
+
+    /**
+     * Creates a new instance of ServerEntrySerializer.
+     * The schemaManager MUST be set explicitly using the static {@link #setSchemaManager(SchemaManager)}
+     */
+    public MavibotEntrySerializer()
+    {
+        super( comparator );
+    }
+
+
+    @Override
+    public Comparator<Entry> getComparator()
+    {
+        return comparator;
+    }
+
+
+    /**
+     * <p>
+     * 
+     * This is the place where we serialize entries, and all theirs
+     * elements. the reason why we don't call the underlying methods
+     * (<code>ServerAttribute.write(), Value.write()</code>) is that we need
+     * access to the registries to read back the values.
+     * <p>
+     * The structure used to store the entry is the following :
+     * <ul>
+     *   <li><b>[a byte]</b> : if the Dn is empty 0 will be written else 1</li>
+     *   <li><b>[Rdn]</b> : The entry's Rdn.</li>
+     *   <li><b>[numberAttr]</b> : the bumber of attributes. Can be 0</li>
+     *   <li>For each Attribute :
+     *     <ul>
+     *       <li><b>[attribute's oid]</b> : The attribute's OID to get back
+     *       the attributeType on deserialization</li>
+     *       <li><b>[Attribute]</b> The attribute</li>
+     *     </ul>
+     *   </li>
+     * </ul>
+     */
+    public byte[] serialize( Entry entry )
+    {
+        try
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+            ObjectOutput out = new ObjectOutputStream( baos );
+
+            // First, the Dn
+            Dn dn = entry.getDn();
+
+            // Write the Rdn of the Dn
+            if ( dn.isEmpty() )
+            {
+                out.writeByte( 0 );
+            }
+            else
+            {
+                out.writeByte( 1 );
+                Rdn rdn = dn.getRdn();
+                rdn.writeExternal( out );
+            }
+
+            // Then the attributes.
+            out.writeInt( entry.getAttributes().size() );
+
+            // Iterate through the keys. We store the Attribute
+            // here, to be able to restore it in the readExternal :
+            // we need access to the registries, which are not available
+            // in the ServerAttribute class.
+            for ( Attribute attribute : entry.getAttributes() )
+            {
+                AttributeType attributeType = attribute.getAttributeType();
+
+                // Write the oid to be able to restore the AttributeType when deserializing
+                // the attribute
+                String oid = attributeType.getOid();
+
+                out.writeUTF( oid );
+
+                // Write the attribute
+                attribute.writeExternal( out );
+            }
+
+            out.flush();
+
+            // Note : we don't store the ObjectClassAttribute. It has already
+            // been stored as an attribute.
+
+            if ( IS_DEBUG )
+            {
+                LOG.debug( ">------------------------------------------------" );
+                LOG.debug( "Serialize " + entry );
+            }
+
+            byte[] bytes = baos.toByteArray();
+
+            return bytes;
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     *  Deserialize a Entry.
+     *  
+     *  @param bytes the byte array containing the serialized entry
+     *  @return An instance of a Entry object 
+     *  @throws IOException if we can't deserialize the Entry
+     */
+    public Entry deserialize( ByteBuffer buffer ) throws IOException
+    {
+        // read the length
+        int len = buffer.limit();
+
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( buffer.array(), buffer.position(), len ) );
+
+        try
+        {
+            Entry entry = new DefaultEntry( schemaManager );
+
+            // Read the Dn, if any
+            byte hasDn = in.readByte();
+
+            if ( hasDn == 1 )
+            {
+                Rdn rdn = new Rdn( schemaManager );
+                rdn.readExternal( in );
+
+                try
+                {
+                    entry.setDn( new Dn( schemaManager, rdn ) );
+                }
+                catch ( LdapInvalidDnException lide )
+                {
+                    IOException ioe = new IOException( lide.getMessage() );
+                    ioe.initCause( lide );
+                    throw ioe;
+                }
+            }
+            else
+            {
+                entry.setDn( Dn.EMPTY_DN );
+            }
+
+            // Read the number of attributes
+            int nbAttributes = in.readInt();
+
+            // Read the attributes
+            for ( int i = 0; i < nbAttributes; i++ )
+            {
+                // Read the attribute's OID
+                String oid = in.readUTF();
+
+                try
+                {
+                    AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( oid );
+
+                    // Create the attribute we will read
+                    Attribute attribute = new DefaultAttribute( attributeType );
+
+                    // Read the attribute
+                    attribute.readExternal( in );
+
+                    entry.add( attribute );
+                }
+                catch ( LdapException ne )
+                {
+                    // We weren't able to find the OID. The attribute will not be added
+                    throw new ClassNotFoundException( ne.getMessage(), ne );
+                }
+            }
+
+            buffer.position( buffer.position() + len ); // previous position + length
+
+            return entry;
+        }
+        catch ( ClassNotFoundException cnfe )
+        {
+            LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
+            throw new IOException( cnfe.getLocalizedMessage() );
+        }
+    }
+
+
+    @Override
+    public Entry deserialize( BufferHandler bufferHandler ) throws IOException
+    {
+        return deserialize( ByteBuffer.wrap( bufferHandler.getBuffer() ) );
+    }
+
+
+    public static void setSchemaManager( SchemaManager schemaManager )
+    {
+        MavibotEntrySerializer.schemaManager = schemaManager;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Entry fromBytes( byte[] buffer ) throws IOException
+    {
+        return fromBytes( buffer, 0 );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Entry fromBytes( byte[] buffer, int pos ) throws IOException
+    {
+        // read the length
+        int len = buffer.length - pos;
+
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( buffer, pos, len ) );
+
+        try
+        {
+            Entry entry = new DefaultEntry( schemaManager );
+
+            // Read the Dn, if any
+            byte hasDn = in.readByte();
+
+            if ( hasDn == 1 )
+            {
+                Rdn rdn = new Rdn( schemaManager );
+                rdn.readExternal( in );
+
+                try
+                {
+                    entry.setDn( new Dn( schemaManager, rdn ) );
+                }
+                catch ( LdapInvalidDnException lide )
+                {
+                    IOException ioe = new IOException( lide.getMessage() );
+                    ioe.initCause( lide );
+                    throw ioe;
+                }
+            }
+            else
+            {
+                entry.setDn( Dn.EMPTY_DN );
+            }
+
+            // Read the number of attributes
+            int nbAttributes = in.readInt();
+
+            // Read the attributes
+            for ( int i = 0; i < nbAttributes; i++ )
+            {
+                // Read the attribute's OID
+                String oid = in.readUTF();
+
+                try
+                {
+                    AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( oid );
+
+                    // Create the attribute we will read
+                    Attribute attribute = new DefaultAttribute( attributeType );
+
+                    // Read the attribute
+                    attribute.readExternal( in );
+
+                    entry.add( attribute );
+                }
+                catch ( LdapException ne )
+                {
+                    // We weren't able to find the OID. The attribute will not be added
+                    throw new ClassNotFoundException( ne.getMessage(), ne );
+                }
+            }
+
+            return entry;
+        }
+        catch ( ClassNotFoundException cnfe )
+        {
+            LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
+            throw new IOException( cnfe.getLocalizedMessage() );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Class<?> getType()
+    {
+        return Entry.class;
+    }
+}
diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java
similarity index 65%
copy from jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java
copy to mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java
index 90f84e4..e295bad 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmIndex.java
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java
@@ -6,32 +6,27 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *    http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  *  KIND, either express or implied.  See the License for the
  *  specific language governing permissions and limitations
  *  under the License.
- * 
+ *
  */
-package org.apache.directory.server.core.partition.impl.btree.jdbm;
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
 
 
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.net.URI;
+import java.util.Comparator;
 
-import jdbm.RecordManager;
-import jdbm.helper.ByteArraySerializer;
-import jdbm.helper.MRU;
-import jdbm.recman.BaseRecordManager;
-import jdbm.recman.CacheRecordManager;
-import jdbm.recman.TransactionManager;
-
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.cursor.Cursor;
 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
@@ -40,7 +35,11 @@ import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.MatchingRule;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.ldap.model.schema.comparators.SerializableComparator;
-import org.apache.directory.api.ldap.model.schema.comparators.UuidComparator;
+import org.apache.directory.mavibot.btree.RecordManager;
+import org.apache.directory.mavibot.btree.serializer.ByteArraySerializer;
+import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
+import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
 import org.apache.directory.server.core.partition.impl.btree.IndexCursorAdaptor;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.server.xdbm.AbstractIndex;
@@ -51,18 +50,16 @@ import org.slf4j.LoggerFactory;
 
 
 /**
- * A Jdbm based index implementation. It creates an Index for a give AttributeType.
+ * A Mavibot based index implementation. It creates an Index for a give AttributeType.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class JdbmIndex<K> extends AbstractIndex<K, String>
+public class MavibotIndex<K> extends AbstractIndex<K, String>
 {
     /** A logger for this class */
-    private static final Logger LOG = LoggerFactory.getLogger( JdbmIndex.class );
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotIndex.class.getSimpleName() );
 
-    /**
-     * default duplicate limit before duplicate keys switch to using a btree for values
-     */
+    /** default duplicate limit before duplicate keys switch to using a btree for values */
     public static final int DEFAULT_DUPLICATE_LIMIT = 512;
 
     /**  the key used for the forward btree name */
@@ -76,46 +73,21 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
      * the value of the btree is the entry id of the entry containing an attribute with
      * that value
      */
-    protected JdbmTable<K, String> forward;
+    protected MavibotTable<K, String> forward;
 
     /**
      * the reverse btree where the btree key is the entry id of the entry containing a
      * value for the indexed attribute, and the btree value is the value of the indexed
      * attribute
      */
-    protected JdbmTable<String, K> reverse;
-
-    /**
-     * the JDBM record manager for the file containing this index
-     */
-    protected RecordManager recMan;
-
-    /**
-     * duplicate limit before duplicate keys switch to using a btree for values
-     */
-    protected int numDupLimit = DEFAULT_DUPLICATE_LIMIT;
+    protected MavibotTable<String, K> reverse;
 
     /** a custom working directory path when specified in configuration */
     protected File wkDirPath;
 
+    /** The recordManager */
+    protected RecordManager recordMan;
 
-    /*
-     * NOTE: Duplicate Key Limit
-     *
-     * Jdbm cannot store duplicate keys: meaning it cannot have more than one value
-     * for the same key in the btree.  Thus as a workaround we stuff values for the
-     * same key into a TreeSet.  This is only effective up to some threshold after
-     * which we run into problems with serialization on and off disk.  A threshold
-     * is used to determine when to switch from using a TreeSet to start using another
-     * btree in the same index file just for the values.  This value only btree just
-     * has keys populated without a value for it's btree entries. When the switch
-     * occurs the value for the key in the index btree contains a pointer to the
-     * btree containing it's values.
-     *
-     * This numDupLimit is the threshold at which we switch from using in memory
-     * containers for values of the same key to using a btree for those values
-     * instead with indirection.
-     */
 
     // ------------------------------------------------------------------------
     // C O N S T R U C T O R S
@@ -123,7 +95,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     /**
      * Creates a JdbmIndex instance for a give AttributeId
      */
-    public JdbmIndex( String attributeId, boolean withReverse )
+    public MavibotIndex( String attributeId, boolean withReverse )
     {
         super( attributeId, withReverse );
 
@@ -133,7 +105,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
 
     /**
      * Initialize the index for an Attribute, with a specific working directory (may be null).
-     * 
+     *
      * @param schemaManager The schemaManager to use to get back the Attribute
      * @param attributeType The attributeType this index is created for
      * @throws IOException If the initialization failed
@@ -142,6 +114,12 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     {
         LOG.debug( "Initializing an Index for attribute '{}'", attributeType.getName() );
 
+        // check if the RecordManager reference is null, if yes, then throw an IllegalStateException
+        if ( recordMan == null )
+        {
+            throw new IllegalStateException( "No RecordManager reference was set in the index " + getAttributeId() );
+        }
+
         this.attributeType = attributeType;
 
         if ( attributeId == null )
@@ -151,28 +129,9 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
 
         if ( this.wkDirPath == null )
         {
-            NullPointerException e = new NullPointerException( "The index working directory has not be set" );
-
-            throw e;
+            throw new NullPointerException( "The index working directory has not be set" );
         }
 
-        String path = new File( this.wkDirPath, attributeType.getOid() ).getAbsolutePath();
-
-        BaseRecordManager base = new BaseRecordManager( path );
-        TransactionManager transactionManager = base.getTransactionManager();
-        transactionManager.setMaximumTransactionsInLog( 2000 );
-
-        // see DIRSERVER-2002
-        // prevent the OOM when more than 50k users are loaded at a stretch
-        // adding this system property to make it configurable till JDBM gets replaced by Mavibot
-        String cacheSizeVal = System.getProperty( "jdbm.recman.cache.size", "100" );
-        
-        int recCacheSize = Integer.parseInt( cacheSizeVal );
-        
-        LOG.info( "Setting CacheRecondManager's cache size to {}", recCacheSize );
-
-        recMan = new CacheRecordManager( base, new MRU( recCacheSize ) );
-
         try
         {
             initTables( schemaManager );
@@ -184,27 +143,19 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
             throw e;
         }
 
-        // finally write a text file in the format <OID>-<attribute-name>.txt
-        FileWriter fw = new FileWriter( new File( path + "-" + attributeType.getName() + ".txt" ) );
-        // write the AttributeType description
-        fw.write( attributeType.toString() );
-        fw.close();
-
         initialized = true;
     }
 
 
     /**
      * Initializes the forward and reverse tables used by this Index.
-     * 
+     *
      * @param schemaManager The server schemaManager
      * @throws IOException if we cannot initialize the forward and reverse
      * tables
      */
     private void initTables( SchemaManager schemaManager ) throws IOException
     {
-        SerializableComparator<K> comp;
-
         MatchingRule mr = attributeType.getEquality();
 
         if ( mr == null )
@@ -212,29 +163,39 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
             throw new IOException( I18n.err( I18n.ERR_574, attributeType.getName() ) );
         }
 
-        comp = new SerializableComparator<K>( mr.getOid() );
+        SerializableComparator<K> comp = new SerializableComparator<>( mr.getOid() );
+        comp.setSchemaManager( schemaManager );
 
         /*
          * The forward key/value map stores attribute values to master table
          * primary keys.  A value for an attribute can occur several times in
          * different entries so the forward map can have more than one value.
          */
-        UuidComparator.INSTANCE.setSchemaManager( schemaManager );
-        comp.setSchemaManager( schemaManager );
 
-        if ( mr.getSyntax().isHumanReadable() )
+        ElementSerializer<K> forwardKeySerializer = null;
+
+        if ( !attributeType.getSyntax().isHumanReadable() )
         {
-            forward = new JdbmTable<K, String>( schemaManager, attributeType.getOid() + FORWARD_BTREE, numDupLimit,
-                recMan,
-                comp, UuidComparator.INSTANCE, StringSerializer.INSTANCE, UuidSerializer.INSTANCE );
+            forwardKeySerializer = ( ElementSerializer<K> ) new ByteArraySerializer( ( Comparator<byte[]> ) comp );
         }
         else
         {
-            forward = new JdbmTable<K, String>( schemaManager, attributeType.getOid() + FORWARD_BTREE, numDupLimit,
-                recMan,
-                comp, UuidComparator.INSTANCE, new ByteArraySerializer(), UuidSerializer.INSTANCE );
+            forwardKeySerializer = ( ElementSerializer<K> ) new StringSerializer( ( Comparator<String> ) comp );
+        }
+
+        boolean forwardDups = true;
+
+        String oid = attributeType.getOid();
+        // disable duplicates for entryCSN and entryUUID attribute indices
+        if ( oid.equals( SchemaConstants.ENTRY_CSN_AT_OID ) || oid.equals( SchemaConstants.ENTRY_UUID_AT_OID ) )
+        {
+            forwardDups = false;
         }
 
+        String forwardTableName = attributeType.getOid() + FORWARD_BTREE;
+        forward = new MavibotTable<>( recordMan, schemaManager, forwardTableName, forwardKeySerializer,
+            StringSerializer.INSTANCE, forwardDups, AbstractBTreePartition.DEFAULT_CACHE_SIZE );
+
         /*
          * Now the reverse map stores the primary key into the master table as
          * the key and the values of attributes as the value.  If an attribute
@@ -243,49 +204,37 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
          */
         if ( withReverse )
         {
-            if ( attributeType.isSingleValued() )
-            {
-                reverse = new JdbmTable<String, K>( schemaManager, attributeType.getOid() + REVERSE_BTREE, recMan,
-                    UuidComparator.INSTANCE, UuidSerializer.INSTANCE, null );
-            }
-            else
-            {
-                reverse = new JdbmTable<String, K>( schemaManager, attributeType.getOid() + REVERSE_BTREE, numDupLimit,
-                    recMan,
-                    UuidComparator.INSTANCE, comp, UuidSerializer.INSTANCE, null );
-            }
+            String reverseTableName = attributeType.getOid() + REVERSE_BTREE;
+            reverse = new MavibotTable<>( recordMan, schemaManager, reverseTableName, StringSerializer.INSTANCE,
+                forwardKeySerializer, !attributeType.isSingleValued() );
         }
-    }
-
 
-    // ------------------------------------------------------------------------
-    // C O N F I G U R A T I O N   M E T H O D S
-    // ------------------------------------------------------------------------
-    /**
-     * Gets the threshold at which point duplicate keys use btree indirection to store
-     * their values.
-     *
-     * @return the threshold for storing a keys values in another btree
-     */
-    public int getNumDupLimit()
-    {
-        return numDupLimit;
+        String path = new File( this.wkDirPath, attributeType.getOid() ).getAbsolutePath();
+        
+        // finally write a text file in the format <OID>-<attribute-name>.txt
+        try ( FileWriter fw = new FileWriter( new File( path + "-" + attributeType.getName() + ".txt" ) ) )
+        {
+            // write the AttributeType description
+            fw.write( attributeType.toString() );
+        } 
     }
 
 
     /**
-     * Sets the threshold at which point duplicate keys use btree indirection to store
-     * their values.
+     * Sets the RecordManager
      *
-     * @param numDupLimit the threshold for storing a keys values in another btree
+     * @param rm the RecordManager instance
      */
-    public void setNumDupLimit( int numDupLimit )
+    public void setRecordManager( RecordManager rm )
     {
-        protect( "numDupLimit" );
-        this.numDupLimit = numDupLimit;
+        this.recordMan = rm;
     }
 
 
+    // ------------------------------------------------------------------------
+    // C O N F I G U R A T I O N   M E T H O D S
+    // ------------------------------------------------------------------------
+
     /**
      * Sets the working directory path to something other than the default. Sometimes more
      * performance is gained by locating indices on separate disk spindles.
@@ -294,7 +243,6 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
      */
     public void setWkDirPath( URI wkDirPath )
     {
-        //.out.println( "IDX Defining a WorkingDir : " + wkDirPath );
         protect( "wkDirPath" );
         this.wkDirPath = new File( wkDirPath );
     }
@@ -386,7 +334,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
      */
     public synchronized void add( K attrVal, String id ) throws Exception
     {
-        // The pair to be added must exists
+        // The pair to be removed must exists
         forward.put( attrVal, id );
 
         if ( withReverse )
@@ -456,11 +404,11 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     {
         if ( withReverse )
         {
-            return new IndexCursorAdaptor<K>( ( Cursor ) reverse.cursor(), false );
+            return new IndexCursorAdaptor<>( ( Cursor ) reverse.cursor(), false );
         }
         else
         {
-            return new EmptyIndexCursor<K>();
+            return new EmptyIndexCursor<>();
         }
     }
 
@@ -477,11 +425,11 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     {
         if ( withReverse )
         {
-            return new IndexCursorAdaptor<K>( ( Cursor ) reverse.cursor( id ), false );
+            return new IndexCursorAdaptor<>( ( Cursor ) reverse.cursor( id ), false );
         }
         else
         {
-            return new EmptyIndexCursor<K>();
+            return new EmptyIndexCursor<>();
         }
     }
 
@@ -489,7 +437,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     @SuppressWarnings("unchecked")
     public Cursor<IndexEntry<K, String>> forwardCursor( K key ) throws Exception
     {
-        return new IndexCursorAdaptor<K>( ( Cursor ) forward.cursor( key ), true );
+        return new IndexCursorAdaptor<>( ( Cursor ) forward.cursor( key ), true );
     }
 
 
@@ -501,7 +449,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
         }
         else
         {
-            return new EmptyCursor<K>();
+            return new EmptyCursor<>();
         }
     }
 
@@ -536,7 +484,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     /**
      * {@inheritDoc}
      */
-    public boolean reverse( String id ) throws Exception
+    public boolean reverse( String id ) throws LdapException
     {
         if ( withReverse )
         {
@@ -552,7 +500,7 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
     /**
      * {@inheritDoc}
      */
-    public boolean reverse( String id, K attrVal ) throws Exception
+    public boolean reverse( String id, K attrVal ) throws LdapException
     {
         return forward.has( attrVal, id );
     }
@@ -566,18 +514,22 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
      */
     public synchronized void close() throws IOException
     {
-        if ( forward != null )
+        try
         {
-            forward.close();
-        }
+            if ( forward != null )
+            {
+                forward.close();
+            }
 
-        if ( reverse != null )
+            if ( reverse != null )
+            {
+                reverse.close();
+            }
+        }
+        catch ( Exception e )
         {
-            reverse.close();
+            throw new IOException( e );
         }
-
-        commit( recMan );
-        recMan.close();
     }
 
 
@@ -586,31 +538,14 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
      */
     public synchronized void sync() throws IOException
     {
-        // Commit
-        recMan.commit();
-
-        // And flush the journal
-        if ( ( commitNumber.get() % 4000 ) == 0 )
-        {
-            BaseRecordManager baseRecordManager = null;
-
-            if ( recMan instanceof CacheRecordManager )
-            {
-                baseRecordManager = ( ( BaseRecordManager ) ( ( CacheRecordManager ) recMan ).getRecordManager() );
-            }
-            else
-            {
-                baseRecordManager = ( ( BaseRecordManager ) recMan );
-            }
-
-            baseRecordManager.getTransactionManager().synchronizeLog();
-        }
+        // Nothing to do
     }
 
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean isDupsEnabled()
     {
         if ( withReverse )
@@ -625,20 +560,6 @@ public class JdbmIndex<K> extends AbstractIndex<K, String>
 
 
     /**
-     * Commit the modification on disk
-     * 
-     * @param recordManager The recordManager used for the commit
-     */
-    private void commit( RecordManager recordManager ) throws IOException
-    {
-        if ( commitNumber.incrementAndGet() % 2000 == 0 )
-        {
-            sync();
-        }
-    }
-
-
-    /**
      * @see Object#toString()
      */
     public String toString()
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
new file mode 100644
index 0000000..67bfb61
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.IOException;
+import java.util.UUID;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.mavibot.btree.RecordManager;
+import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.directory.server.xdbm.MasterTable;
+
+
+/**
+ * TODO MavibotMasterTable.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MavibotMasterTable extends MavibotTable<String, Entry> implements MasterTable
+{
+    public MavibotMasterTable( RecordManager recordMan, SchemaManager schemaManager, String name, int cacheSize )
+        throws IOException
+    {
+        super( recordMan, schemaManager, name, StringSerializer.INSTANCE, new MavibotEntrySerializer(), false, cacheSize );
+    }
+
+    public MavibotMasterTable( RecordManager recordMan, SchemaManager schemaManager, String name )
+        throws IOException
+    {
+        super( recordMan, schemaManager, name, StringSerializer.INSTANCE, new MavibotEntrySerializer(), false );
+    }
+
+
+    @Override
+    public String getNextId( Entry entry ) throws Exception
+    {
+        return UUID.randomUUID().toString();
+    }
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java
new file mode 100644
index 0000000..dd18529
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java
@@ -0,0 +1,302 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Comparator;
+
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.util.Serialize;
+import org.apache.directory.mavibot.btree.serializer.AbstractElementSerializer;
+import org.apache.directory.mavibot.btree.serializer.BufferHandler;
+import org.apache.directory.mavibot.btree.util.Strings;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.server.xdbm.ParentIdAndRdn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Serialize and deserialize a ParentidAndRdn.
+ * </br></br>
+ * <b>This class must *not* be used outside of the server.</b>
+ *  
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MavibotParentIdAndRdnSerializer extends AbstractElementSerializer<ParentIdAndRdn>
+{
+    /** The serialVersionUID */
+    private static final long serialVersionUID = 1L;
+
+    /** the logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotParentIdAndRdnSerializer.class );
+
+    /**
+     * Speedup for logs
+     */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** The schemaManager reference */
+    private static SchemaManager schemaManager;
+
+    private static Comparator<ParentIdAndRdn> comparator = new Comparator<ParentIdAndRdn>()
+    {
+
+        @Override
+        public int compare( ParentIdAndRdn rdn1, ParentIdAndRdn rdn2 )
+        {
+            return rdn1.compareTo( rdn2 );
+        }
+
+    };
+
+
+    /**
+     * Creates a new instance of ParentIdAndRdnSerializer.
+     * The schemaManager MUST be set explicitly using the static {@link #setSchemaManager(SchemaManager)}
+     */
+    public MavibotParentIdAndRdnSerializer()
+    {
+        super( comparator );
+    }
+
+
+    /**
+     * This is the place where we serialize ParentIdAndRdn. The format is the following :<br/>
+     * <ul>
+     * <li>length</li>
+     * <li>the RDN</li>
+     * <li>the parent ID</li>
+     * <li>Number of children</li>
+     * <li>Number of descendant</li>
+     * <li></li>
+     * <li></li>
+     * <li></li>
+     * </ul>
+     */
+    public byte[] serialize( ParentIdAndRdn parentIdAndRdn )
+    {
+        try
+        {
+            int bufferSize = 1024;
+
+            while ( bufferSize < Integer.MAX_VALUE )
+            {
+                // allocate a big enough buffer for most of the cases
+                byte[] buffer = new byte[bufferSize];
+
+                try
+                {
+                    // The current position.
+                    int pos = 0;
+
+                    // First, the Dn
+                    Rdn[] rdns;
+
+                    try
+                    {
+                        rdns = parentIdAndRdn.getRdns();
+                    }
+                    catch ( NullPointerException npe )
+                    {
+                        throw npe;
+                    }
+
+                    // Write the Rdn of the Dn
+                    // The number of RDN (we may have more than one)
+                    if ( ( rdns == null ) || ( rdns.length == 0 ) )
+                    {
+                        pos = Serialize.serialize( 0, buffer, pos );
+                    }
+                    else
+                    {
+                        pos = Serialize.serialize( rdns.length, buffer, pos );
+
+                        for ( Rdn rdn : rdns )
+                        {
+                            pos = rdn.serialize( buffer, pos );
+                        }
+                    }
+
+                    // Then the parentId.
+                    String parentId = parentIdAndRdn.getParentId();
+                    byte[] parentIdBytes = Strings.getBytesUtf8( parentId );
+                    pos = Serialize.serialize( parentIdBytes, buffer, pos );
+
+                    // The number of children
+                    pos = Serialize.serialize( parentIdAndRdn.getNbChildren(), buffer, pos );
+
+                    // The number of descendants
+                    pos = Serialize.serialize( parentIdAndRdn.getNbDescendants(), buffer, pos );
+
+                    if ( IS_DEBUG )
+                    {
+                        LOG.debug( ">------------------------------------------------" );
+                        LOG.debug( "Serialize " + parentIdAndRdn );
+                    }
+
+
+                    // Copy the serialized data
+                    byte[] result = new byte[pos];
+                    System.arraycopy( buffer, 0, result, 0, pos );
+
+                    return result;
+                }
+                catch ( ArrayIndexOutOfBoundsException aioobe )
+                {
+                    // Bad luck, try with a bigger buffer
+                    bufferSize += bufferSize;
+                }
+            }
+
+            // No reason we should reach this point
+            throw new RuntimeException();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     *  Deserialize a ParentIdAndRdn.
+     *  
+     *  @param bytes the byte array containing the serialized ParentIdAndRdn
+     *  @return An instance of a ParentIdAndRdn object 
+     *  @throws IOException if we can't deserialize the ParentIdAndRdn
+     */
+    public ParentIdAndRdn deserialize( BufferHandler bufferHandler ) throws IOException
+    {
+        return deserialize( ByteBuffer.wrap( bufferHandler.getBuffer() ) );
+    }
+
+
+    @Override
+    public ParentIdAndRdn deserialize( ByteBuffer buffer ) throws IOException
+    {
+        ParentIdAndRdn parentIdAndRdn = fromBytes( buffer.array(), buffer.position() );
+
+        return parentIdAndRdn;
+    }
+
+
+    @Override
+    public int compare( ParentIdAndRdn type1, ParentIdAndRdn type2 )
+    {
+        return type1.compareTo( type2 );
+    }
+
+
+    @Override
+    public Comparator<ParentIdAndRdn> getComparator()
+    {
+        return comparator;
+    }
+
+
+    public static void setSchemaManager( SchemaManager schemaManager )
+    {
+        MavibotParentIdAndRdnSerializer.schemaManager = schemaManager;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ParentIdAndRdn fromBytes( byte[] buffer ) throws IOException
+    {
+        return fromBytes( buffer, 0 );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ParentIdAndRdn fromBytes( byte[] buffer, int pos ) throws IOException
+    {
+        try
+        {
+            ParentIdAndRdn parentIdAndRdn = new ParentIdAndRdn();
+
+            // Read the number of rdns, if any
+            int nbRdns = Serialize.deserializeInt( buffer, pos );
+            pos += 4;
+
+            if ( nbRdns == 0 )
+            {
+                parentIdAndRdn.setRdns( new Rdn[0] );
+            }
+            else
+            {
+                Rdn[] rdns = new Rdn[nbRdns];
+
+                for ( int i = 0; i < nbRdns; i++ )
+                {
+                    Rdn rdn = new Rdn( schemaManager );
+                    pos = rdn.deserialize( buffer, pos );
+                    rdns[i] = rdn;
+                }
+
+                parentIdAndRdn.setRdns( rdns );
+            }
+
+            // Read the parent ID
+            byte[] uuidBytes = Serialize.deserializeBytes( buffer, pos );
+            pos += 4 + uuidBytes.length;
+            String uuid = Strings.utf8ToString( uuidBytes );
+
+            parentIdAndRdn.setParentId( uuid );
+
+            // Read the number of children and descendants
+            int nbChildren = Serialize.deserializeInt( buffer, pos );
+            pos += 4;
+
+            int nbDescendants = Serialize.deserializeInt( buffer, pos );
+            pos += 4;
+
+            parentIdAndRdn.setNbChildren( nbChildren );
+            parentIdAndRdn.setNbDescendants( nbDescendants );
+
+            return parentIdAndRdn;
+        }
+        catch ( LdapInvalidAttributeValueException cnfe )
+        {
+            LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
+            throw new IOException( cnfe.getLocalizedMessage() );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Class<?> getType()
+    {
+        return ParentIdAndRdn.class;
+    }
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
new file mode 100644
index 0000000..c9c83be
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
@@ -0,0 +1,540 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.Element;
+
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.Cursor;
+import org.apache.directory.api.ldap.model.cursor.Tuple;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.util.exception.MultiException;
+import org.apache.directory.mavibot.btree.RecordManager;
+import org.apache.directory.server.constants.ApacheSchemaConstants;
+import org.apache.directory.server.core.api.DnFactory;
+import org.apache.directory.server.core.api.entry.ClonedServerEntry;
+import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.OperationContext;
+import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
+import org.apache.directory.server.core.api.partition.Partition;
+import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.server.xdbm.Index;
+import org.apache.directory.server.xdbm.search.impl.CursorBuilder;
+import org.apache.directory.server.xdbm.search.impl.DefaultOptimizer;
+import org.apache.directory.server.xdbm.search.impl.DefaultSearchEngine;
+import org.apache.directory.server.xdbm.search.impl.EvaluatorBuilder;
+import org.apache.directory.server.xdbm.search.impl.NoOpOptimizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The Mavibot backed partition.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MavibotPartition extends AbstractBTreePartition
+{
+    /** static logger */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotPartition.class );
+
+    private static final String MAVIBOT_DB_FILE_EXTN = ".data";
+    
+    private static final FilenameFilter DB_FILTER = ( dir, name ) -> name.endsWith( MAVIBOT_DB_FILE_EXTN ) && !name.startsWith( "master." );
+    
+    private RecordManager recordMan;
+
+    /** the entry cache */
+    private Cache entryCache;
+
+
+    public MavibotPartition( SchemaManager schemaManager, DnFactory dnFactory )
+    {
+        super( schemaManager, dnFactory );
+
+        MavibotEntrySerializer.setSchemaManager( schemaManager );
+
+        // Initialize the cache size
+        if ( cacheSize < 0 )
+        {
+            cacheSize = DEFAULT_CACHE_SIZE;
+            LOG.debug( "Using the default entry cache size of {} for {} partition", cacheSize, id );
+        }
+        else
+        {
+            LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize, id );
+        }
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doRepair() throws Exception
+    {
+        // Nothing to do
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doInit() throws Exception
+    {
+        if ( !initialized )
+        {
+            // setup optimizer and registries for parent
+            if ( !isOptimizerEnabled() )
+            {
+                setOptimizer( new NoOpOptimizer() );
+            }
+            else
+            {
+                setOptimizer( new DefaultOptimizer<Entry>( this ) );
+            }
+
+            EvaluatorBuilder evaluatorBuilder = new EvaluatorBuilder( this, schemaManager );
+            CursorBuilder cursorBuilder = new CursorBuilder( this, evaluatorBuilder );
+
+            setSearchEngine( new DefaultSearchEngine( this, cursorBuilder, evaluatorBuilder, getOptimizer() ) );
+
+            // Create the underlying directories (only if needed)
+            File partitionDir = new File( getPartitionPath() );
+
+            if ( !partitionDir.exists() && !partitionDir.mkdirs() )
+            {
+                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY, partitionDir ) );
+            }
+
+            if ( cacheSize < 0 )
+            {
+                cacheSize = DEFAULT_CACHE_SIZE;
+                LOG.debug( "Using the default entry cache size of {} for {} partition", cacheSize, id );
+            }
+            else
+            {
+                LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize, id );
+            }
+
+            recordMan = new RecordManager( partitionDir.getPath() );
+
+            // Initialize the indexes
+            super.doInit();
+
+            // First, check if the file storing the data exists
+
+            // Create the master table (the table containing all the entries)
+            Cache masterTableCache = cacheService.getCache( suffixDn.getName() );
+            master = new MavibotMasterTable( recordMan, schemaManager, "master", masterTableCache.getCacheConfiguration().getMaxElementsInMemory() );
+
+            // get all index db files first
+            File[] allIndexDbFiles = partitionDir.listFiles( DB_FILTER );
+
+            // get the names of the db files also
+            List<String> indexDbFileNameList = Arrays.asList( partitionDir.list( DB_FILTER ) );
+
+            // then add all index objects to a list
+            List<String> allIndices = new ArrayList<String>();
+
+            for ( Index<?, String> index : systemIndices.values() )
+            {
+                allIndices.add( index.getAttribute().getOid() );
+            }
+
+            List<Index<?, String>> indexToBuild = new ArrayList<Index<?, String>>();
+
+            // this loop is used for two purposes
+            // one for collecting all user indices
+            // two for finding a new index to be built
+            // just to avoid another iteration for determining which is the new index
+            /* FIXME the below code needs to be modified to suit Mavibot
+                        for ( Index<?, Entry, String> index : userIndices.values() )
+                        {
+                            String indexOid = index.getAttribute().getOid();
+                            allIndices.add( indexOid );
+
+                            // take the part after removing .db from the
+                            String name = indexOid + MAVIBOT_DB_FILE_EXTN;
+
+                            // if the name doesn't exist in the list of index DB files
+                            // this is a new index and we need to build it
+                            if ( !indexDbFileNameList.contains( name ) )
+                            {
+                                indexToBuild.add( index );
+                            }
+                        }
+
+                        if ( indexToBuild.size() > 0 )
+                        {
+                            buildUserIndex( indexToBuild );
+                        }
+
+                        deleteUnusedIndexFiles( allIndices, allIndexDbFiles );
+            */
+
+            if ( cacheService != null )
+            {
+                entryCache = cacheService.getCache( getId() );
+                
+                int cacheSizeConfig = entryCache.getCacheConfiguration().getMaxElementsInMemory();
+
+                if ( cacheSizeConfig < cacheSize )
+                {
+                    entryCache.getCacheConfiguration().setMaxElementsInMemory( cacheSize );
+                }
+            }
+
+            // We are done !
+            initialized = true;
+        }
+    }
+
+
+    @Override
+    protected Index<?, String> convertAndInit( Index<?, String> index ) throws Exception
+    {
+        MavibotIndex<?> mavibotIndex;
+
+        if ( index instanceof MavibotRdnIndex )
+        {
+            mavibotIndex = ( MavibotRdnIndex ) index;
+        }
+        else if ( index instanceof MavibotDnIndex )
+        {
+            mavibotIndex = ( MavibotDnIndex ) index;
+        }
+        else if ( index instanceof MavibotIndex<?> )
+        {
+            mavibotIndex = ( MavibotIndex<?> ) index;
+
+            if ( mavibotIndex.getWkDirPath() == null )
+            {
+                mavibotIndex.setWkDirPath( partitionPath );
+            }
+        }
+        else
+        {
+            LOG.debug( "Supplied index {} is not a MavibotIndex.  "
+                + "Will create new MavibotIndex using copied configuration parameters.", index );
+            mavibotIndex = new MavibotIndex( index.getAttributeId(), true );
+            mavibotIndex.setCacheSize( index.getCacheSize() );
+            mavibotIndex.setWkDirPath( index.getWkDirPath() );
+        }
+
+        mavibotIndex.setRecordManager( recordMan );
+
+        mavibotIndex.init( schemaManager, schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() ) );
+
+        return mavibotIndex;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    protected synchronized void doDestroy() throws Exception
+    {
+        MultiException errors = new MultiException( I18n.err( I18n.ERR_577 ) );
+
+        if ( !initialized )
+        {
+            return;
+        }
+
+        try
+        {
+            super.doDestroy();
+        }
+        catch ( Exception e )
+        {
+            errors.addThrowable( e );
+        }
+
+        // This is specific to the MAVIBOT store : close the record manager
+        try
+        {
+            recordMan.close();
+            LOG.debug( "Closed record manager for {} partition.", suffixDn );
+        }
+        catch ( Throwable t )
+        {
+            LOG.error( I18n.err( I18n.ERR_127 ), t );
+            errors.addThrowable( t );
+        }
+        finally
+        {
+            if ( entryCache != null )
+            {
+                entryCache.removeAll();
+            }
+        }
+
+        if ( errors.size() > 0 )
+        {
+            throw errors;
+        }
+    }
+
+
+    @Override
+    protected Index createSystemIndex( String indexOid, URI path, boolean withReverse ) throws Exception
+    {
+        LOG.debug( "Supplied index {} is not a MavibotIndex.  "
+            + "Will create new MavibotIndex using copied configuration parameters." );
+        MavibotIndex<?> mavibotIndex;
+
+        if ( indexOid.equals( ApacheSchemaConstants.APACHE_RDN_AT_OID ) )
+        {
+            mavibotIndex = new MavibotRdnIndex();
+            mavibotIndex.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+        }
+        else if ( indexOid.equals( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ) )
+        {
+            mavibotIndex = new MavibotDnIndex( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
+            mavibotIndex.setAttributeId( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
+        }
+        else
+        {
+            mavibotIndex = new MavibotIndex( indexOid, withReverse );
+        }
+
+        mavibotIndex.setWkDirPath( path );
+
+        return mavibotIndex;
+    }
+
+
+    @Override
+    public void sync() throws Exception
+    {
+        if ( !initialized )
+        {
+            return;
+        }
+
+        // Sync all system indices
+        for ( Index<?, String> idx : systemIndices.values() )
+        {
+            idx.sync();
+        }
+
+        // Sync all user defined userIndices
+        for ( Index<?, String> idx : userIndices.values() )
+        {
+            idx.sync();
+        }
+
+        ( ( MavibotMasterTable ) master ).sync();
+    }
+
+
+    /**jdbm
+     * removes any unused/removed attribute index files present under the partition's
+     * working directory
+     */
+    private void deleteUnusedIndexFiles( List<String> allIndices, File[] dbFiles )
+    {
+
+    }
+
+
+    /**
+     * Builds user defined indexes on a attributes by browsing all the entries present in master db
+     * 
+     * @param userIndexes then user defined indexes to create
+     * @throws Exception in case of any problems while building the index
+     */
+    private void buildUserIndex( List<Index<?, String>> userIndexes ) throws Exception
+    {
+        Cursor<Tuple<String, Entry>> cursor = master.cursor();
+        cursor.beforeFirst();
+
+        while ( cursor.next() )
+        {
+            for ( Index index : userIndexes )
+            {
+                AttributeType atType = index.getAttribute();
+
+                String attributeOid = index.getAttribute().getOid();
+
+                LOG.info( "building the index for attribute type {}", atType );
+
+                Tuple<String, Entry> tuple = cursor.get();
+
+                String id = tuple.getKey();
+                Entry entry = tuple.getValue();
+
+                Attribute entryAttr = entry.get( atType );
+
+                if ( entryAttr != null )
+                {
+                    for ( Value<?> value : entryAttr )
+                    {
+                        index.add( value.getValue(), id );
+                    }
+
+                    // Adds only those attributes that are indexed
+                    presenceIdx.add( attributeOid, id );
+                }
+            }
+        }
+
+        cursor.close();
+    }
+
+
+    /**
+     * {@inheritDoc}}
+     */
+    public String getDefaultId()
+    {
+        return Partition.DEFAULT_ID;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getRootId()
+    {
+        return Partition.ROOT_ID;
+    }
+
+
+    public RecordManager getRecordMan()
+    {
+        return recordMan;
+    }
+
+
+    public Entry lookupCache( String id )
+    {
+        if ( entryCache == null )
+        {
+            return null;
+        }
+
+        Element el = entryCache.get( id );
+
+        if ( el != null )
+        {
+            return ( Entry ) el.getValue();
+        }
+
+        return null;
+    }
+
+
+    @Override
+    public void addToCache( String id, Entry entry )
+    {
+        if ( entryCache == null )
+        {
+            return;
+        }
+
+        if ( entry instanceof ClonedServerEntry )
+        {
+            entry = ( ( ClonedServerEntry ) entry ).getOriginalEntry();
+        }
+
+        entryCache.put( new Element( id, entry ) );
+    }
+
+
+    @Override
+    public void updateCache( OperationContext opCtx )
+    {
+        if ( entryCache == null )
+        {
+            return;
+        }
+
+        try
+        {
+            if ( opCtx instanceof ModifyOperationContext )
+            {
+                // replace the entry
+                ModifyOperationContext modCtx = ( ModifyOperationContext ) opCtx;
+                Entry entry = modCtx.getAlteredEntry();
+                String id = entry.get( SchemaConstants.ENTRY_UUID_AT ).getString();
+
+                if ( entry instanceof ClonedServerEntry )
+                {
+                    entry = ( ( ClonedServerEntry ) entry ).getOriginalEntry();
+                }
+
+                entryCache.replace( new Element( id, entry ) );
+            }
+            else if ( ( opCtx instanceof MoveOperationContext ) || ( opCtx instanceof MoveAndRenameOperationContext )
+                || ( opCtx instanceof RenameOperationContext ) )
+            {
+                // clear the cache it is not worth updating all the children
+                entryCache.removeAll();
+            }
+            else if ( opCtx instanceof DeleteOperationContext )
+            {
+                // delete the entry
+                DeleteOperationContext delCtx = ( DeleteOperationContext ) opCtx;
+                entryCache.remove( delCtx.getEntry().get( SchemaConstants.ENTRY_UUID_AT ).getString() );
+            }
+        }
+        catch ( LdapException e )
+        {
+            LOG.warn( "Failed to update entry cache", e );
+        }
+    }
+
+    
+    /**
+     * @return The set of system and user indexes
+     */
+    public Set<Index<?, String>> getAllIndices()
+    {
+        Set<Index<?, String>> all = new HashSet<Index<?, String>>( systemIndices.values() );
+        all.addAll( userIndices.values() );
+        
+        return all;
+    }
+
+}
\ No newline at end of file
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotRdnIndex.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotRdnIndex.java
new file mode 100644
index 0000000..4e8220e
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotRdnIndex.java
@@ -0,0 +1,126 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.MatchingRule;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.directory.server.constants.ApacheSchemaConstants;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.server.xdbm.ParentIdAndRdn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A special index which stores Rdn objects.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class MavibotRdnIndex extends MavibotIndex<ParentIdAndRdn>
+{
+
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotRdnIndex.class );
+
+
+    public MavibotRdnIndex()
+    {
+        super( ApacheSchemaConstants.APACHE_RDN_AT_OID, true );
+        initialized = false;
+    }
+
+
+    public void init( SchemaManager schemaManager, AttributeType attributeType ) throws IOException
+    {
+        LOG.debug( "Initializing an Index for attribute '{}'", attributeType.getName() );
+
+        this.attributeType = attributeType;
+
+        if ( attributeId == null )
+        {
+            setAttributeId( attributeType.getName() );
+        }
+
+        if ( this.wkDirPath == null )
+        {
+            NullPointerException e = new NullPointerException( "The index working directory has not be set" );
+            throw e;
+        }
+
+        String path = new File( this.wkDirPath, attributeType.getOid() ).getAbsolutePath();
+
+        try
+        {
+            initTables( schemaManager );
+        }
+        catch ( IOException e )
+        {
+            // clean up
+            close();
+            throw e;
+        }
+
+        // finally write a text file in the format <OID>-<attribute-name>.txt
+        FileWriter fw = new FileWriter( new File( path + "-" + attributeType.getName() + ".txt" ) );
+
+        // write the AttributeType description
+        fw.write( attributeType.toString() );
+        fw.close();
+
+        initialized = true;
+    }
+
+
+    /**
+     * Initializes the forward and reverse tables used by this Index.
+     *
+     * @param schemaManager The server schemaManager
+     * @throws IOException if we cannot initialize the forward and reverse
+     * tables
+     * @throws NamingException
+     */
+    private void initTables( SchemaManager schemaManager ) throws IOException
+    {
+        MatchingRule mr = attributeType.getEquality();
+
+        if ( mr == null )
+        {
+            throw new IOException( I18n.err( I18n.ERR_574, attributeType.getName() ) );
+        }
+
+        MavibotParentIdAndRdnSerializer.setSchemaManager( schemaManager );
+        MavibotParentIdAndRdnSerializer parentIdAndSerializer = new MavibotParentIdAndRdnSerializer();
+
+        String forwardTableName = attributeType.getOid() + FORWARD_BTREE;
+        forward = new MavibotTable<ParentIdAndRdn, String>( recordMan, schemaManager, forwardTableName,
+            parentIdAndSerializer, StringSerializer.INSTANCE, false );
+
+        String reverseTableName = attributeType.getOid() + REVERSE_BTREE;
+        reverse = new MavibotTable<String, ParentIdAndRdn>( recordMan, schemaManager, reverseTableName,
+            StringSerializer.INSTANCE, parentIdAndSerializer, false );
+    }
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotReadTxn.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotReadTxn.java
new file mode 100644
index 0000000..764cfa0
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotReadTxn.java
@@ -0,0 +1,11 @@
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+import org.apache.directory.mavibot.btree.Transaction;
+
+public class MavibotReadTxn extends AbstractMavibotTxn
+{
+    public MavibotReadTxn( Transaction transaction )
+    {
+        super( transaction );
+    }
+}
diff --git a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
similarity index 64%
copy from mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
copy to mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
index 124d865..ff03213 100644
--- a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
@@ -21,29 +21,41 @@ package org.apache.directory.server.core.partition.impl.btree.mavibot;
 
 
 import java.io.IOException;
+import java.util.Map;
 
 import org.apache.directory.api.ldap.model.cursor.Cursor;
 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
 import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapOtherException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.mavibot.btree.BTree;
 import org.apache.directory.mavibot.btree.BTreeFactory;
+import org.apache.directory.mavibot.btree.InsertResult;
 import org.apache.directory.mavibot.btree.RecordManager;
+import org.apache.directory.mavibot.btree.Transaction;
 import org.apache.directory.mavibot.btree.TupleCursor;
 import org.apache.directory.mavibot.btree.ValueCursor;
+import org.apache.directory.mavibot.btree.WriteTransaction;
 import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
+import org.apache.directory.mavibot.btree.serializer.LongSerializer;
+import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
+import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
 import org.apache.directory.server.core.avltree.ArrayMarshaller;
 import org.apache.directory.server.core.avltree.ArrayTree;
 import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
+import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotIndex;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.server.xdbm.AbstractTable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import jdbm.helper.Serializer;
+
 
 /**
  * A Mavibot Table. It extends the default Apache DS Table, when Mavibot is the
@@ -64,6 +76,15 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
     /** The used recordManager */
     protected RecordManager recordMan;
 
+    /** the limit at which we start using btree redirection for duplicates */
+    private int numDupLimit = MavibotIndex.DEFAULT_DUPLICATE_LIMIT;
+
+    /** a cache of duplicate BTrees */
+    private final Map<Long, BTree<K, V>> duplicateBtrees;
+
+    /** A value serializer */
+    private final ElementSerializer valueSerializer;
+
 
     /**
      * Creates a new instance of MavibotTable.
@@ -103,20 +124,27 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
     {
         super( schemaManager, name, keySerializer.getComparator(), valueSerializer.getComparator() );
         this.recordMan = recordMan;
+        this.valueSerializer = valueSerializer;
+        duplicateBtrees = null;
 
-        bt = recordMan.getManagedTree( name );
+        try ( Transaction transaction = recordMan.beginReadTransaction() )
+        {
+            bt = transaction.getBTree( name );
+        }
 
         if ( bt == null )
         {
-            bt = BTreeFactory.createPersistedBTree( name, keySerializer, valueSerializer, allowDuplicates, cacheSize );
-
+            // Create a new BTree
+            WriteTransaction writeTransaction = recordMan.beginWriteTransaction();
+                
             try
             {
-                recordMan.manage( bt );
+                bt = recordMan.addBTree( writeTransaction, name, keySerializer, valueSerializer );
+                writeTransaction.commit();
             }
-            catch ( BTreeAlreadyManagedException e )
+            catch ( Exception e )
             {
-                // should never happen
+                writeTransaction.abort();
                 throw new RuntimeException( e );
             }
         }
@@ -129,7 +157,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
         }
 
         this.allowsDuplicates = allowDuplicates;
-        arrayMarshaller = new ArrayMarshaller<V>( valueComparator );
+        arrayMarshaller = new ArrayMarshaller<>( valueComparator );
 
         // Initialize the count
         count = bt.getNbElems();
@@ -140,31 +168,16 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean isDupsEnabled()
-    {
-        return allowsDuplicates;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     * @throws  
-     */
-    @Override
-    public boolean has( K key ) throws LdapException
+    public boolean has( PartitionTxn transaction, K key ) throws LdapException
     {
         try
         {
-            return bt.hasKey( key );
+            return bt.hasKey( ( ( MavibotTxn ) transaction ).getTransaction(), key );
         }
         catch ( IOException ioe )
         {
             throw new LdapException( ioe );
         }
-        catch ( KeyNotFoundException knfe )
-        {
-            throw new LdapException( knfe );
-        }
     }
 
 
@@ -172,11 +185,11 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean has( K key, V value ) throws LdapException
+    public boolean has( PartitionTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
-            return bt.contains( key, value );
+            return bt.contains( ( ( MavibotTxn ) transaction ).getTransaction(), key, value );
         }
         catch ( IOException e )
         {
@@ -189,16 +202,20 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasGreaterOrEqual( K key ) throws Exception
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
         TupleCursor<K, V> cursor = null;
 
         try
         {
-            cursor = bt.browseFrom( key );
+            cursor = bt.browseFrom( ( ( MavibotTxn ) transaction ).getTransaction(), key );
 
             return cursor.hasNext();
         }
+        catch ( IOException ioe )
+        {
+            throw new LdapOtherException( ioe.getMessage() );
+        }
         finally
         {
             if ( cursor != null )
@@ -213,13 +230,13 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasLessOrEqual( K key ) throws Exception
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
         TupleCursor<K, V> cursor = null;
 
         try
         {
-            cursor = bt.browseFrom( key );
+            cursor = bt.browseFrom( ( ( MavibotTxn ) transaction ).getTransaction(), key );
 
             org.apache.directory.mavibot.btree.Tuple<K, V> tuple = null;
 
@@ -248,6 +265,10 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
 
             return false;
         }
+        catch ( IOException ioe )
+        {
+            throw new LdapOtherException( ioe.getMessage() );
+        }
         finally
         {
             if ( cursor != null )
@@ -262,7 +283,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasGreaterOrEqual( K key, V val ) throws LdapException
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -274,16 +295,16 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             throw new UnsupportedOperationException( I18n.err( I18n.ERR_593 ) );
         }
 
-        TupleCursor<V, V> cursor = null;
+        ValueCursor<V> valueCursor = null;
 
         try
         {
-            if ( !bt.hasKey( key ) )
+            if ( !bt.hasKey( ( ( MavibotTxn ) transaction ).getTransaction(), key ) )
             {
                 return false;
             }
 
-            ValueCursor<V> valueCursor = bt.getValues( key );
+            valueCursor = bt.getValues( ( ( MavibotTxn ) transaction ).getTransaction(), key );
 
             int equal = bt.getValueSerializer().compare( val, valueCursor.next() );
 
@@ -295,9 +316,9 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
         }
         finally
         {
-            if ( cursor != null )
+            if ( valueCursor != null )
             {
-                cursor.close();
+                valueCursor.close();
             }
         }
     }
@@ -307,7 +328,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public boolean hasLessOrEqual( K key, V val ) throws Exception
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -319,7 +340,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             throw new UnsupportedOperationException( I18n.err( I18n.ERR_593 ) );
         }
 
-        if ( !bt.hasKey( key ) )
+        if ( !bt.hasKey( ( ( MavibotTxn ) transaction ).getTransaction(), key ) )
         {
             return false;
         }
@@ -334,7 +355,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public V get( K key ) throws LdapException
+    public V get( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -343,7 +364,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
 
         try
         {
-            return bt.get( key );
+            return bt.get( ( ( MavibotTxn ) transaction ).getTransaction(), key );
         }
         catch ( KeyNotFoundException knfe )
         {
@@ -360,7 +381,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public void put( K key, V value ) throws Exception
+    public void put( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -369,17 +390,17 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 throw new IllegalArgumentException( I18n.err( I18n.ERR_594 ) );
             }
 
-            V existingVal = bt.insert( key, value );
+            InsertResult<K, V> existingVal = bt.insert( ( ( MavibotWriteTxn ) transaction ).getWriteTransaction(), key, value );
 
             if ( existingVal == null )
             {
                 count++;
             }
         }
-        catch ( Exception e )
+        catch ( IOException ioe )
         {
-            LOG.error( I18n.err( I18n.ERR_131, key, name ), e );
-            throw e;
+            LOG.error( I18n.err( I18n.ERR_131, key, name ), ioe );
+            throw new LdapOtherException( ioe.getMessage(), ioe);
         }
     }
 
@@ -388,7 +409,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public void remove( K key ) throws Exception
+    public void remove( PartitionWriteTxn transaction, K key ) throws LdapException
     {
         try
         {
@@ -398,12 +419,13 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             }
 
             // Get the associated valueHolder
-            if ( bt.isAllowDuplicates() )
+            if ( allowsDuplicates )
             {
-                ValueCursor<V> valueCursor = bt.getValues( key );
+                ValueCursor<V> valueCursor = bt.getValues( ( ( MavibotWriteTxn ) transaction ).getWriteTransaction(), key );
                 int size = valueCursor.size();
                 valueCursor.close();
-                org.apache.directory.mavibot.btree.Tuple<K, V> returned = bt.delete( key );
+                org.apache.directory.mavibot.btree.Tuple<K, V> returned = 
+                    bt.delete( ( ( MavibotWriteTxn ) transaction ).getWriteTransaction(), key );
 
                 if ( null == returned )
                 {
@@ -414,7 +436,8 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             }
             else
             {
-                org.apache.directory.mavibot.btree.Tuple<K, V> returned = bt.delete( key );
+                org.apache.directory.mavibot.btree.Tuple<K, V> returned = 
+                    bt.delete( ( ( MavibotWriteTxn ) transaction ).getWriteTransaction(), key );
 
                 if ( null == returned )
                 {
@@ -424,14 +447,11 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 count--;
             }
         }
-        catch ( Exception e )
+        catch ( IOException ioe )
         {
-            LOG.error( I18n.err( I18n.ERR_133, key, name ), e );
+            LOG.error( I18n.err( I18n.ERR_133, key, name ), ioe );
 
-            if ( e instanceof IOException )
-            {
-                throw ( IOException ) e;
-            }
+            throw new LdapOtherException( ioe.getMessage(), ioe );
         }
     }
 
@@ -440,7 +460,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public void remove( K key, V value ) throws Exception
+    public void remove( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         try
         {
@@ -449,7 +469,8 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 return;
             }
 
-            org.apache.directory.mavibot.btree.Tuple<K, V> tuple = bt.delete( key, value );
+            org.apache.directory.mavibot.btree.Tuple<K, V> tuple = 
+                bt.delete( ( ( MavibotWriteTxn ) transaction ).getWriteTransaction(), key, value );
 
             // We decrement the counter only when the key was found
             if ( tuple != null )
@@ -457,9 +478,11 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
                 count--;
             }
         }
-        catch ( Exception e )
+        catch ( IOException ioe )
         {
-            LOG.error( I18n.err( I18n.ERR_132, key, value, name ), e );
+            LOG.error( I18n.err( I18n.ERR_132, key, value, name ), ioe );
+
+            throw new LdapOtherException( ioe.getMessage(), ioe );
         }
     }
 
@@ -468,9 +491,9 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public Cursor<Tuple<K, V>> cursor() throws LdapException
+    public Cursor<Tuple<K, V>> cursor( PartitionTxn transaction ) throws LdapException
     {
-        return new MavibotCursor<K, V>( this );
+        return new MavibotCursor<>( this );
     }
 
 
@@ -478,11 +501,11 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public Cursor<Tuple<K, V>> cursor( K key ) throws LdapException
+    public Cursor<Tuple<K, V>> cursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
-            return new EmptyCursor<Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
 
         try
@@ -491,19 +514,18 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
             {
                 V val = bt.get( key );
 
-                return new SingletonCursor<Tuple<K, V>>(
-                    new Tuple<K, V>( key, val ) );
+                return new SingletonCursor<>( new Tuple<K, V>( key, val ) );
             }
             else
             {
                 ValueCursor<V> dupHolder = bt.getValues( key );
 
-                return new KeyTupleValueCursor<K, V>( dupHolder, key );
+                return new KeyTupleValueCursor<>( dupHolder, key );
             }
         }
         catch ( KeyNotFoundException knfe )
         {
-            return new EmptyCursor<Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
         catch ( Exception e )
         {
@@ -516,31 +538,31 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public Cursor<V> valueCursor( K key ) throws Exception
+    public Cursor<V> valueCursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
-            return new EmptyCursor<V>();
+            return new EmptyCursor<>();
         }
 
         try
         {
             if ( !allowsDuplicates )
             {
-                V val = bt.get( key );
+                V val = bt.get( ( ( MavibotTxn ) transaction ).getTransaction(), key );
 
-                return new SingletonCursor<V>( val );
+                return new SingletonCursor<>( val );
             }
             else
             {
-                ValueCursor<V> dupCursor = bt.getValues( key );
+                ValueCursor<V> dupCursor = bt.getValues( ( ( MavibotTxn ) transaction ).getTransaction(), key );
 
-                return new ValueTreeCursor<V>( dupCursor );
+                return new ValueTreeCursor<>( dupCursor );
             }
         }
         catch ( KeyNotFoundException knfe )
         {
-            return new EmptyCursor<V>();
+            return new EmptyCursor<>();
         }
         catch ( Exception e )
         {
@@ -553,39 +575,46 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
      * {@inheritDoc}
      */
     @Override
-    public long count( K key ) throws Exception
+    public long count( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
             return 0;
         }
 
-        if ( bt.isAllowDuplicates() )
+        try
         {
-            try
+            if ( allowsDuplicates )
             {
-                ValueCursor<V> dupHolder = bt.getValues( key );
-                int size = dupHolder.size();
-                dupHolder.close();
-
-                return size;
+                try
+                {
+                    ValueCursor dupHolder = (ValueCursor) bt.get( ( ( MavibotTxn ) transaction ).getTransaction(), key );
+                    int size = dupHolder.size();
+                    dupHolder.close();
+    
+                    return size;
+                }
+                catch ( KeyNotFoundException knfe )
+                {
+                    // No key
+                    return 0;
+                }
             }
-            catch ( KeyNotFoundException knfe )
+            else
             {
-                // No key
-                return 0;
+                if ( bt.hasKey( ( ( MavibotTxn ) transaction ).getTransaction(), key ) )
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 0;
+                }
             }
         }
-        else
+        catch ( IOException ioe )
         {
-            if ( bt.hasKey( key ) )
-            {
-                return 1;
-            }
-            else
-            {
-                return 0;
-            }
+            throw new LdapOtherException( ioe.getMessage() );
         }
     }
 
@@ -593,41 +622,6 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    @Override
-    public long greaterThanCount( K key ) throws Exception
-    {
-        // take a best guess
-        return Math.min( count, 10L );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public long lessThanCount( K key ) throws Exception
-    {
-        // take a best guess
-        return Math.min( count, 10L );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void close() throws Exception
-    {
-        // do nothing here, the RecordManager will be closed in MavibotMasterTable.close()
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public ArrayTree<V> getDupsContainer( byte[] serialized ) throws IOException
     {
         if ( serialized == null )
@@ -661,6 +655,7 @@ public class MavibotTable<K, V> extends AbstractTable<K, V>
     /**
      * @see Object#toString()
      */
+    @Override
     public String toString()
     {
         StringBuilder sb = new StringBuilder();
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTxn.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTxn.java
new file mode 100644
index 0000000..5205040
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTxn.java
@@ -0,0 +1,9 @@
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+import org.apache.directory.mavibot.btree.Transaction;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
+
+public interface MavibotTxn extends PartitionTxn, Transaction
+{
+    Transaction getTransaction();
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotWriteTxn.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotWriteTxn.java
new file mode 100644
index 0000000..bc13160
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotWriteTxn.java
@@ -0,0 +1,18 @@
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+import org.apache.directory.mavibot.btree.Transaction;
+import org.apache.directory.mavibot.btree.WriteTransaction;
+
+public class MavibotWriteTxn extends AbstractMavibotTxn
+{
+    public MavibotWriteTxn( Transaction transaction )
+    {
+        super( transaction );
+    }
+
+    
+    public WriteTransaction getWriteTransaction()
+    {
+        return ( WriteTransaction ) transaction;
+    }
+}
diff --git a/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/ValueTreeCursor.java b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/ValueTreeCursor.java
new file mode 100644
index 0000000..1ff6069
--- /dev/null
+++ b/mavibotv2-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/ValueTreeCursor.java
@@ -0,0 +1,155 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.server.core.partition.impl.btree.mavibot;
+
+
+import java.io.IOException;
+
+import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.mavibot.btree.ValueCursor;
+import org.apache.directory.server.i18n.I18n;
+
+
+/**
+ * TODO ValueTreeCursor.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ValueTreeCursor<V> extends AbstractCursor<V>
+{
+
+    private ValueCursor<V> wrapped;
+
+    private V available;
+
+    // marker to detect the availability (cause Mavibot supports null values also)
+    private V notAvailable = ( V ) new Object();
+
+
+    public ValueTreeCursor( ValueCursor<V> cursor )
+    {
+        this.wrapped = cursor;
+    }
+
+
+    @Override
+    public boolean available()
+    {
+        return ( available != notAvailable );
+    }
+
+
+    @Override
+    public void before( V element ) throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    @Override
+    public void after( V element ) throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    @Override
+    public void beforeFirst() throws LdapException, CursorException
+    {
+    }
+
+
+    @Override
+    public void afterLast() throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    @Override
+    public boolean first() throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    @Override
+    public boolean last() throws LdapException, CursorException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    @Override
+    public boolean previous() throws LdapException, CursorException
+    {
+        try
+        {
+            if ( wrapped.hasPrev() )
+            {
+                available = wrapped.prev();
+                return true;
+            }
+            else
+            {
+                available = notAvailable;
+                return false;
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new CursorException( e );
+        }
+    }
+
+
+    @Override
+    public boolean next() throws LdapException, CursorException
+    {
+        try
+        {
+            if ( wrapped.hasNext() )
+            {
+                available = wrapped.next();
+                return true;
+            }
+            else
+            {
+                available = notAvailable;
+                return false;
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new CursorException( e );
+        }
+    }
+
+
+    @Override
+    public V get() throws CursorException
+    {
+        return available;
+    }
+
+}
diff --git a/pom.xml b/pom.xml
index 3ecbb0a..149ca12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,6 +103,7 @@
     <module>all</module>
     <module>jdbm-partition</module>
     <module>mavibot-partition</module>
+    <!--module>mavibotv2-partition</module-->
     <module>xdbm-partition</module>
     <module>core-shared</module>
     <module>core-api</module>
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
index 6d6d503..4a97063 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
@@ -302,6 +302,7 @@ public class PwdModifyHandler implements ExtendedOperationHandler<PasswordModify
             // The user is not authenticated : we have to use the provided userIdentity
             // and the oldPassword to check if the user is present
             BindOperationContext bindContext = new BindOperationContext( adminSession );
+            bindContext.setTransaction( requestor.getCoreSession().getDirectoryService().getPartitionNexus().beginReadTransaction() );
             bindContext.setDn( userDn );
             bindContext.setCredentials( oldPassword );
 
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 e35328d..7192302 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
@@ -108,6 +108,7 @@ public class BindRequestHandler extends LdapRequestHandler<BindRequest>
         // create a new Bind context, with a null session, as we don't have 
         // any context yet.
         BindOperationContext bindContext = new BindOperationContext( null );
+        bindContext.setTransaction( ldapServer.getDirectoryService().getPartitionNexus().beginReadTransaction() );
 
         // Stores the Dn of the user to check, and its password
         bindContext.setDn( bindRequest.getDn() );
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/SimpleMechanismHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/SimpleMechanismHandler.java
index 76c77d0..ae22efa 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/SimpleMechanismHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/SimpleMechanismHandler.java
@@ -57,6 +57,7 @@ public class SimpleMechanismHandler implements MechanismHandler
         // create a new Bind context, with a null session, as we don't have 
         // any context yet.
         BindOperationContext bindContext = new BindOperationContext( null );
+        bindContext.setTransaction( ldapSession.getLdapServer().getDirectoryService().getPartitionNexus().beginReadTransaction() );
 
         // Stores the Dn of the user to check, and its password
         bindContext.setDn( bindRequest.getDn() );
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/ntlm/NtlmSaslServer.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/ntlm/NtlmSaslServer.java
index ca82431..d72a6d1 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/ntlm/NtlmSaslServer.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/ntlm/NtlmSaslServer.java
@@ -205,6 +205,7 @@ public class NtlmSaslServer extends AbstractSaslServer
     private CoreSession authenticate( String user, String password ) throws InvalidNameException, Exception
     {
         BindOperationContext bindContext = new BindOperationContext( getLdapSession().getCoreSession() );
+        bindContext.setTransaction( getLdapSession().getCoreSession().getDirectoryService().getPartitionNexus().beginReadTransaction() );
         bindContext.setDn( new Dn( user ) );
         bindContext.setCredentials( Strings.getBytesUtf8( password ) );
 
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/plain/PlainSaslServer.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/plain/PlainSaslServer.java
index 54343bc..91757cb 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/plain/PlainSaslServer.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/sasl/plain/PlainSaslServer.java
@@ -281,6 +281,7 @@ public class PlainSaslServer extends AbstractSaslServer
             try
             {
                 BindOperationContext bindContext = new BindOperationContext( ldapSession.getCoreSession() );
+                bindContext.setTransaction( ldapSession.getCoreSession().getDirectoryService().getPartitionNexus().beginReadTransaction() );
                 bindContext.setDn( entry.getDn() );
                 bindContext.setCredentials( Strings.getBytesUtf8( password ) );
                 bindContext.setIoSession( ldapSession.getIoSession() );
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/modify/ModifyReferralIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/modify/ModifyReferralIT.java
index 1fd1705..08998b7 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/modify/ModifyReferralIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/modify/ModifyReferralIT.java
@@ -32,6 +32,8 @@ import javax.naming.directory.DirContext;
 import javax.naming.directory.ModificationItem;
 import javax.naming.ldap.LdapContext;
 
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ModifyRequest;
 import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
 import org.apache.directory.api.ldap.model.message.ModifyResponse;
@@ -117,19 +119,29 @@ public class ModifyReferralIT extends AbstractLdapTestUnit
     public void testOnReferralWithManageDsaITControl() throws Exception
     {
         LdapConnection conn = getWiredConnection( getLdapServer() );
+        
+        Dn target = new Dn( "uid=akarasuluref,ou=users,ou=system" );
 
         ManageDsaIT manageDSAIT = new ManageDsaITImpl();
         manageDSAIT.setCritical( true );
 
         // modify success
         ModifyRequest modifyRequest = new ModifyRequestImpl();
-        modifyRequest.setName( new Dn( "uid=akarasuluref,ou=users,ou=system" ) );
+        modifyRequest.setName( target );
         modifyRequest.add( "description", "referral to akarasulu" );
         modifyRequest.addControl( manageDSAIT );
 
         conn.modify( modifyRequest );
 
         assertTrue( conn.compare( "uid=akarasuluref,ou=users,ou=system", "description", "referral to akarasulu" ) );
+        
+        Entry result = conn.lookup( target, new Control[] {manageDSAIT}, "*" );
+        
+        System.out.println( result );
+
+        result = conn.lookup( target, new Control[] {}, "*" );
+        
+        System.out.println( result );
 
         conn.close();
     }
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java
index 94e0a0f..09ebd90 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java
@@ -49,7 +49,6 @@ import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.message.controls.PagedResults;
 import org.apache.directory.api.ldap.model.message.controls.PagedResultsImpl;
 import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.api.ldap.util.JndiUtils;
 import org.apache.directory.api.util.Network;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.EntryCursorImpl;
@@ -269,9 +268,6 @@ public class PagedSearchApiIT extends AbstractLdapTestUnit
                     results.add( result );
                 }
 
-                // Now read the next ones
-                Map<String, Control> controls =  cursor.getSearchResultDone().getControls();
-
                 if ( cursor.getSearchResultDone().getLdapResult().getResultCode() == ResultCodeEnum.SIZE_LIMIT_EXCEEDED )
                 {
                     hasSizeLimitException = true;
@@ -279,6 +275,9 @@ public class PagedSearchApiIT extends AbstractLdapTestUnit
                     break;
                 }
                 
+                // Now read the next ones
+                Map<String, Control> controls =  cursor.getSearchResultDone().getControls();
+
                 PagedResults responseControl = ( PagedResults ) controls.get( PagedResults.OID );
                 assertEquals( 0, responseControl.getSize() );
 
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/PersistentSearchApiIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/PersistentSearchApiIT.java
new file mode 100644
index 0000000..75919ab
--- /dev/null
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/PersistentSearchApiIT.java
@@ -0,0 +1,740 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ * 
+ */
+package org.apache.directory.server.operations.search;
+
+
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchResult;
+import javax.naming.event.EventDirContext;
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.ObjectChangeListener;
+import javax.naming.ldap.HasControls;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.codec.controls.search.entryChange.EntryChangeDecorator;
+import org.apache.directory.api.ldap.codec.controls.search.persistentSearch.PersistentSearchDecorator;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.ldif.LdifUtils;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.message.controls.ChangeType;
+import org.apache.directory.api.ldap.model.message.controls.EntryChange;
+import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
+import org.apache.directory.api.ldap.model.message.controls.PersistentSearchImpl;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.util.JndiUtils;
+import org.apache.directory.api.util.Network;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifs;
+import org.apache.directory.server.core.api.event.EventService;
+import org.apache.directory.server.core.api.event.RegistrationEntry;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Test case which tests the correct operation of the persistent search decorator.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(FrameworkRunner.class)
+@CreateLdapServer(
+    transports =
+        {
+            @CreateTransport(protocol = "LDAP")
+    })
+@ApplyLdifs(
+    {
+        // Entry # 2
+        "dn: cn=Tori Amos,ou=system",
+        "objectClass: person",
+        "objectClass: top",
+        "cn: Tori Amos",
+        "description: an American singer-songwriter",
+        "sn: Amos" })
+public class PersistentSearchApiIT extends AbstractLdapTestUnit
+{
+    private static final Logger LOG = LoggerFactory.getLogger( PersistentSearchApiIT.class );
+
+    private static final String BASE = "ou=system";
+    private static final String PERSON_DESCRIPTION = "an American singer-songwriter";
+    private static final String RDN = "cn=Tori Amos";
+
+
+    /**
+     * Creation of required attributes of a person entry.
+     */
+    private Attributes getPersonAttributes( String sn, String cn ) throws LdapException
+    {
+        Attributes attributes = LdifUtils.createJndiAttributes(
+            "objectClass: top",
+            "objectClass: person",
+            "cn", cn,
+            "sn", sn );
+
+        return attributes;
+    }
+
+    EventDirContext ctx;
+    EventService eventService;
+    PSearchListener listener;
+    Thread t;
+
+
+    private void setUpListenerReturnECs() throws Exception
+    {
+        setUpListener( true, new PersistentSearchImpl(), false );
+    }
+
+
+    private void setUpListener( boolean returnECs, PersistentSearch persistentSearch, boolean ignoreEmptyRegistryCheck )
+        throws Exception
+    {
+        ctx = ( EventDirContext ) getWiredContext( getLdapServer() ).lookup( BASE );
+        eventService = getLdapServer().getDirectoryService().getEventService();
+        List<RegistrationEntry> registrationEntryList = eventService.getRegistrationEntries();
+
+        if ( !ignoreEmptyRegistryCheck )
+        {
+            assertTrue( registrationEntryList.isEmpty() );
+        }
+
+        persistentSearch.setReturnECs( returnECs );
+        listener = new PSearchListener( persistentSearch );
+        t = new Thread( listener, "PSearchListener" );
+        t.start();
+
+        // let's wait until the listener thread started
+        while ( eventService.getRegistrationEntries().isEmpty() )
+        {
+            Thread.sleep( 100 );
+        }
+
+        // Now we wait until the listener is registered (timing dependent crap)
+        Thread.sleep( 250 );
+    }
+
+
+    private void setUpListener() throws Exception
+    {
+        ctx = ( EventDirContext ) getWiredContext( getLdapServer() ).lookup( BASE );
+        eventService = getLdapServer().getDirectoryService().getEventService();
+        List<RegistrationEntry> registrationEntryList = eventService.getRegistrationEntries();
+        assertTrue( registrationEntryList.isEmpty() );
+
+        listener = new PSearchListener();
+        t = new Thread( listener, "PSearchListener" );
+        t.start();
+
+        // let's wait until the listener thread started
+        while ( eventService.getRegistrationEntries().isEmpty() )
+        {
+            Thread.sleep( 100 );
+        }
+
+        // Now we wait until the listener is registered (timing dependent crap)
+        Thread.sleep( 250 );
+    }
+
+
+    @After
+    public void tearDownListener() throws Exception
+    {
+        if( listener == null )
+        {
+            return;
+        }
+        
+        listener.close();
+        ctx.close();
+
+        while ( !eventService.getRegistrationEntries().isEmpty() )
+        {
+            Thread.sleep( 100 );
+        }
+    }
+
+
+    private void waitForThreadToDie( Thread t ) throws Exception
+    {
+        long start = System.currentTimeMillis();
+
+        while ( t.isAlive() )
+        {
+            Thread.sleep( 200 );
+            if ( System.currentTimeMillis() - start > 1000 )
+            {
+                break;
+            }
+        }
+    }
+
+
+    /**
+     * Shows correct notifications for modify(4) changes.
+     */
+    @Test
+    public void testPsearchModify() throws Exception
+    {
+        setUpListener();
+        ctx.modifyAttributes( RDN, DirContext.REMOVE_ATTRIBUTE,
+            new BasicAttributes( "description", PERSON_DESCRIPTION, true ) );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( RDN, listener.result.getName() );
+    }
+
+
+    /**
+     * Shows correct notifications for moddn(8) changes.
+     */
+    @Test
+    public void testPsearchModifyDn() throws Exception
+    {
+        setUpListener();
+        ctx.rename( RDN, "cn=Jack Black" );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+    }
+
+
+    /**
+     * Shows correct notifications for delete(2) changes.
+     */
+    @Test
+    public void testPsearchDelete() throws Exception
+    {
+        setUpListener();
+        ctx.destroySubcontext( RDN );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( RDN, listener.result.getName() );
+    }
+
+
+    /**
+     * Shows correct notifications for add(1) changes.
+     */
+    @Test
+    public void testPsearchAdd() throws Exception
+    {
+        setUpListener();
+        ctx.createSubcontext( "cn=Jack Black", getPersonAttributes( "Black", "Jack Black" ) );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+    }
+
+
+    /**
+     * Shows correct notifications for modify(4) changes with returned
+     * EntryChangeControl.
+     */
+    @Test
+    public void testPsearchModifyWithEC() throws Exception
+    {
+        setUpListenerReturnECs();
+        ctx.modifyAttributes( RDN, DirContext.REMOVE_ATTRIBUTE, new BasicAttributes( "description", PERSON_DESCRIPTION,
+            true ) );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( RDN, listener.result.getName() );
+        assertEquals( listener.result.control.getChangeType(), ChangeType.MODIFY );
+    }
+
+
+    /**
+     * Shows correct notifications for moddn(8) changes with returned
+     * EntryChangeControl.
+     */
+    @Test
+    public void testPsearchModifyDnWithEC() throws Exception
+    {
+        setUpListenerReturnECs();
+        ctx.rename( RDN, "cn=Jack Black" );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+        assertEquals( listener.result.control.getChangeType(), ChangeType.MODDN );
+        assertEquals( ( RDN + ",ou=system" ), listener.result.control.getPreviousDn().getName() );
+    }
+
+
+    /**
+     * Shows correct notifications for delete(2) changes with returned
+     * EntryChangeControl.
+     */
+    @Test
+    public void testPsearchDeleteWithEC() throws Exception
+    {
+        setUpListenerReturnECs();
+        ctx.destroySubcontext( RDN );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( RDN, listener.result.getName() );
+        assertEquals( listener.result.control.getChangeType(), ChangeType.DELETE );
+    }
+
+
+    /**
+     * Shows correct notifications for add(1) changes with returned
+     * EntryChangeControl.
+     */
+    @Test
+    public void testPsearchAddWithEC() throws Exception
+    {
+        setUpListenerReturnECs();
+        ctx.createSubcontext( "cn=Jack Black", getPersonAttributes( "Black", "Jack Black" ) );
+        waitForThreadToDie( t );
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+        assertEquals( listener.result.control.getChangeType(), ChangeType.ADD );
+    }
+
+
+    /**
+     * Shows correct notifications for only add(1) and modify(4) registered changes with returned
+     * EntryChangeControl but not deletes.
+     */
+    @Test
+    public void testPsearchAddModifyEnabledWithEC() throws Exception
+    {
+        PersistentSearch ctrl = new PersistentSearchImpl();
+        ctrl.setReturnECs( true );
+        ctrl.setChangeTypes( ChangeType.ADD.getValue() );
+        ctrl.enableNotification( ChangeType.MODIFY );
+        setUpListener( true, ctrl, false );
+        ctx.createSubcontext( "cn=Jack Black", getPersonAttributes( "Black", "Jack Black" ) );
+        waitForThreadToDie( t );
+
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+        assertEquals( listener.result.control.getChangeType(), ChangeType.ADD );
+        tearDownListener();
+
+        setUpListener( true, ctrl, true );
+        ctx.destroySubcontext( "cn=Jack Black" );
+        waitForThreadToDie( t );
+        assertNull( listener.result );
+
+        // thread is still waiting for notifications try a modify
+        ctx.modifyAttributes( RDN, DirContext.REMOVE_ATTRIBUTE, new BasicAttributes( "description", PERSON_DESCRIPTION,
+            true ) );
+        waitForThreadToDie( t );
+
+        assertNotNull( listener.result );
+        assertEquals( RDN, listener.result.getName() );
+        assertEquals( listener.result.control.getChangeType(), ChangeType.MODIFY );
+    }
+
+
+    /**
+     * Test for DIRSERVER-1908 
+     */
+    @Test
+    public void testPsearchMove() throws Exception
+    {
+        LdapNetworkConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );
+        connection.bind( "uid=admin,ou=system", "secret" );
+        
+        Entry newOu = new DefaultEntry( "uid=persist, ou=users,ou=system" );
+        newOu.add( "objectClass", "inetOrgPerson" );
+        newOu.add( "cn", "persist_cn" );
+        newOu.add( "sn", "persist_sn" );
+        
+        connection.add( newOu );
+        
+        SearchRequest sr = new SearchRequestImpl();
+        sr.setBase( new Dn( BASE ) );
+        sr.setFilter( "(objectClass=*)" );
+        sr.setScope( SearchScope.SUBTREE );
+        
+        PersistentSearch ps = new PersistentSearchImpl();
+        ps.setChangesOnly( true );
+        ps.setReturnECs( true );
+        ps.setCritical( true );
+        
+        sr.addControl( ps );
+        
+        final SearchCursor cursor = connection.search( sr );
+        
+        final List<Entry> entryList = new ArrayList<Entry>();
+        
+        Runnable r = new Runnable()
+        {
+            
+            @Override
+            public void run()
+            {
+                try
+                {
+                    while( cursor.next() )
+                    {
+                        entryList.add( cursor.getEntry() );
+                    }
+                }
+                catch( Exception e )
+                {
+                    throw new RuntimeException( e );
+                }
+            }
+        };
+        
+        new Thread( r ).start();
+        
+        connection.move( newOu.getDn(), newOu.getDn().getParent().getParent() );
+        Thread.sleep( 1000 );
+        assertFalse( entryList.isEmpty() );
+        assertEquals( 1, entryList.size() );
+        assertEquals( "uid=persist,ou=system", entryList.get( 0 ).getDn().getName() );
+        
+        connection.close();
+    }
+
+    
+    /**
+     * Shows correct notifications for add(1) changes with returned
+     * EntryChangeControl and changesOnly set to false so we return
+     * the first set of entries.
+     * 
+     * This test is commented out because it exhibits some producer
+     * consumer lockups (server and client being in same process)
+     * 
+     * PLUS ALL THIS GARBAGE IS TIME DEPENDENT!!!!!
+     */
+    //    public void testPsearchAddWithECAndFalseChangesOnly() throws Exception
+    //    {
+    //        PersistentSearchDecorator decorator = new PersistentSearchDecorator();
+    //        decorator.setReturnECs( true );
+    //        decorator.setChangesOnly( false );
+    //        PSearchListener listener = new PSearchListener( decorator );
+    //        Thread t = new Thread( listener );
+    //        t.start();
+    //
+    //        Thread.sleep( 3000 );
+    //
+    //        assertEquals( 5, listener.count );
+    //        ctx.createSubcontext( "cn=Jack Black", getPersonAttributes( "Black", "Jack Black" ) );
+    //
+    //        long start = System.currentTimeMillis();
+    //        while ( t.isAlive() )
+    //        {
+    //            Thread.sleep( 100 );
+    //            if ( System.currentTimeMillis() - start > 3000 )
+    //            {
+    //                break;
+    //            }
+    //        }
+    //
+    //        assertEquals( 6, listener.count );
+    //        assertNotNull( listener.result );
+    //        assertEquals( "cn=Jack Black", listener.result.getName() );
+    //        assertEquals( listener.result.decorator.getChangeType(), ChangeType.ADD );
+    //    }
+
+    /**
+     * Shows notifications functioning with the JNDI notification API of the SUN
+     * provider.
+     *
+    @Test
+    public void testPsearchAbandon() throws Exception
+    {
+        PersistentSearchDecorator decorator = new PersistentSearchDecorator();
+        decorator.setReturnECs( true );
+        PSearchListener listener = new PSearchListener( decorator );
+        Thread t = new Thread( listener );
+        t.start();
+    
+        while ( !listener.isReady )
+        {
+            Thread.sleep( 100 );
+        }
+        Thread.sleep( 250 );
+    
+        ctx.createSubcontext( "cn=Jack Black", getPersonAttributes( "Black", "Jack Black" ) );
+    
+        long start = System.currentTimeMillis();
+        while ( t.isAlive() )
+        {
+            Thread.sleep( 100 );
+            if ( System.currentTimeMillis() - start > 3000 )
+            {
+                break;
+            }
+        }
+    
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+        assertEquals( listener.result.decorator.getChangeType(), ChangeType.ADD );
+        
+        listener = new PSearchListener( decorator );
+    
+        t = new Thread( listener );
+        t.start();
+    
+        ctx.destroySubcontext( "cn=Jack Black" );
+    
+        start = System.currentTimeMillis();
+        while ( t.isAlive() )
+        {
+            Thread.sleep( 100 );
+            if ( System.currentTimeMillis() - start > 3000 )
+            {
+                break;
+            }
+        }
+    
+        // there seems to be a race condition here
+        // assertNull( listener.result );
+        assertNotNull( listener.result );
+        assertEquals( "cn=Jack Black", listener.result.getName() );
+        assertEquals( ChangeType.DELETE, listener.result.decorator.getChangeType() );
+        listener.result = null;
+    
+        // thread is still waiting for notifications try a modify
+        ctx.modifyAttributes( Rdn, DirContext.REMOVE_ATTRIBUTE, new AttributesImpl( "description", PERSON_DESCRIPTION,
+            true ) );
+        start = System.currentTimeMillis();
+        while ( t.isAlive() )
+        {
+            Thread.sleep( 200 );
+            if ( System.currentTimeMillis() - start > 3000 )
+            {
+                break;
+            }
+        }
+    
+        assertNull( listener.result );
+        //assertEquals( Rdn, listener.result.getName() );
+        //assertEquals( listener.result.decorator.getChangeType(), ChangeType.MODIFY );
+    }*/
+
+    class JndiNotificationListener implements NamespaceChangeListener, ObjectChangeListener
+    {
+        boolean hasError = false;
+        ArrayList<EventObject> list = new ArrayList<EventObject>();
+        NamingExceptionEvent exceptionEvent = null;
+
+
+        public void objectAdded( NamingEvent evt )
+        {
+            list.add( 0, evt );
+        }
+
+
+        public void objectRemoved( NamingEvent evt )
+        {
+            list.add( 0, evt );
+        }
+
+
+        public void objectRenamed( NamingEvent evt )
+        {
+            list.add( 0, evt );
+        }
+
+
+        public void namingExceptionThrown( NamingExceptionEvent evt )
+        {
+            hasError = true;
+            exceptionEvent = evt;
+            list.add( 0, evt );
+        }
+
+
+        public void objectChanged( NamingEvent evt )
+        {
+            list.add( 0, evt );
+        }
+    }
+
+    class PSearchListener implements Runnable
+    {
+        boolean isReady = false;
+        PSearchNotification result;
+        final PersistentSearchDecorator persistentSearch;
+        LdapContext ctx;
+        NamingEnumeration<SearchResult> list;
+
+
+        PSearchListener()
+        {
+            persistentSearch = new PersistentSearchDecorator( getLdapServer().getDirectoryService()
+                .getLdapCodecService() );
+        }
+
+
+        PSearchListener( PersistentSearch persistentSearch )
+        {
+            CodecControl<? extends Control> wrapped =
+                getLdapServer().getDirectoryService().getLdapCodecService().newControl( persistentSearch );
+            this.persistentSearch = ( PersistentSearchDecorator ) wrapped;
+        }
+
+
+        void close()
+        {
+            if ( list != null )
+            {
+                try
+                {
+                    list.close();
+                    LOG.debug( "PSearchListener: search naming enumeration closed()" );
+                }
+                catch ( Exception e )
+                {
+                    LOG.error( "Error closing NamingEnumeration on PSearchListener", e );
+                }
+            }
+
+            if ( ctx != null )
+            {
+                try
+                {
+                    ctx.close();
+                    LOG.debug( "PSearchListener: search context closed()" );
+                }
+                catch ( Exception e )
+                {
+                    LOG.error( "Error closing connection on PSearchListener", e );
+                }
+            }
+        }
+
+
+        public void run()
+        {
+            LOG.debug( "PSearchListener.run() called." );
+            LdapApiService codec = getLdapServer().getDirectoryService().getLdapCodecService();
+            persistentSearch.setCritical( true );
+            persistentSearch.setValue( persistentSearch.getValue() );
+
+            Control[] ctxCtls = new Control[]
+                { persistentSearch };
+
+            try
+            {
+                ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
+                ctx.setRequestControls( JndiUtils.toJndiControls( codec, ctxCtls ) );
+                isReady = true;
+                LOG.debug( "PSearchListener is ready and about to issue persistent search request." );
+                list = ctx.search( "", "objectClass=*", null );
+                LOG.debug( "PSearchListener search request returned." );
+                EntryChange ecControl = null;
+
+                while ( list.hasMore() )
+                {
+                    LOG.debug( "PSearchListener search request got an item." );
+                    javax.naming.ldap.Control[] controls;
+                    SearchResult sresult = list.next();
+
+                    if ( sresult instanceof HasControls )
+                    {
+                        controls = ( ( HasControls ) sresult ).getControls();
+
+                        if ( controls != null )
+                        {
+                            for ( javax.naming.ldap.Control jndiControl : controls )
+                            {
+                                if ( jndiControl.getID().equals(
+                                    EntryChange.OID ) )
+                                {
+                                    ecControl = ( EntryChange ) JndiUtils.fromJndiControl( codec, jndiControl );
+                                    ( ( EntryChangeDecorator ) ecControl ).decode( jndiControl.getEncodedValue() );
+                                }
+                            }
+                        }
+                    }
+
+                    result = new PSearchNotification( sresult, ecControl );
+                    break;
+                }
+
+                LOG.debug( "PSearchListener broke out of while loop." );
+            }
+            catch ( Exception e )
+            {
+                e.printStackTrace();
+                LOG.error( "PSearchListener encountered error", e );
+            }
+            finally
+            {
+            }
+        }
+    }
+
+    class PSearchNotification extends SearchResult
+    {
+        private static final long serialVersionUID = 1L;
+        final EntryChange control;
+
+
+        public PSearchNotification( SearchResult result, EntryChange control )
+        {
+            super( result.getName(), result.getClassName(), result.getObject(), result.getAttributes(), result
+                .isRelative() );
+            this.control = control;
+        }
+
+
+        public String toString()
+        {
+            StringBuffer buf = new StringBuffer();
+            buf.append( "Dn: " ).append( getName() ).append( "\n" );
+
+            if ( control != null )
+            {
+                buf.append( "    EntryChangeControl =\n" );
+                buf.append( "       changeType   : " ).append( control.getChangeType() ).append( "\n" );
+                buf.append( "       previousDN   : " ).append( control.getPreviousDn() ).append( "\n" );
+                buf.append( "       changeNumber : " ).append( control.getChangeNumber() ).append( "\n" );
+            }
+
+            return buf.toString();
+        }
+    }
+}
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/AbstractTable.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/AbstractTable.java
index 4173d42..9050fed 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/AbstractTable.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/AbstractTable.java
@@ -24,7 +24,9 @@ import java.io.IOException;
 import java.util.Comparator;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
 import org.apache.directory.server.i18n.I18n;
 
 
@@ -119,13 +121,45 @@ public abstract class AbstractTable<K, V> implements Table<K, V>
     /**
      * {@inheritDoc}
      */
-    public long count() throws IOException
+    public long count( PartitionTxn transaction ) throws LdapException
     {
         return count;
     }
 
 
     /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long greaterThanCount( PartitionTxn transaction, K key ) throws LdapException
+    {
+        // take a best guess
+        return Math.min( count, 10L );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long lessThanCount( PartitionTxn transaction, K key ) throws LdapException
+    {
+        // take a best guess
+        return Math.min( count, 10L );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isDupsEnabled()
+    {
+        return allowsDuplicates;
+    }
+
+
+    /**
      * @see Object#toString()
      */
     public String toString()
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Table.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Table.java
index 1f723e2..d13819c 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Table.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Table.java
@@ -24,6 +24,9 @@ import java.util.Comparator;
 
 import org.apache.directory.api.ldap.model.cursor.Cursor;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
+import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
 
 
 /**
@@ -80,22 +83,24 @@ public interface Table<K, V>
      * this is exactly the same as a get call with a check to see if the
      * returned value is null or not.
      *
+     * @param transaction The transaction we are running in
      * @param key the Object of the key to check for
      * @return true if the key exists, false otherwise
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    boolean has( K key ) throws Exception;
+    boolean has( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
      * Checks to see if this table has a key with a specific value.
      *
+     * @param transaction The transaction we are running in
      * @param key the key to check for
      * @param value the value to check for
      * @return true if a record with the key and value exists, false otherwise
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    boolean has( K key, V value ) throws Exception;
+    boolean has( PartitionTxn transaction, K key, V value ) throws LdapException;
 
 
     /**
@@ -104,12 +109,13 @@ public interface Table<K, V>
      * call to return true.  The underlying database must sort keys based on a
      * key comparator because this method depends on key ordering.
      *
+     * @param transaction The transaction we are running in
      * @param key the key to compare keys to
      * @return true if a Tuple with a key greater than or equal to the key
      * argument exists, false otherwise
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    boolean hasGreaterOrEqual( K key ) throws Exception;
+    boolean hasGreaterOrEqual( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
@@ -118,12 +124,13 @@ public interface Table<K, V>
      * call to return true.  The underlying database must sort keys based on a
      * key comparator because this method depends on key ordering.
      *
+     * @param transaction The transaction we are running in
      * @param key the key to compare keys to
      * @return true if a Tuple with a key less than or equal to the key
      * argument exists, false otherwise
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    boolean hasLessOrEqual( K key ) throws Exception;
+    boolean hasLessOrEqual( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
@@ -138,15 +145,16 @@ public interface Table<K, V>
      * If the table does not support duplicates then an
      * UnsupportedOperationException is thrown.
      *
+     * @param transaction The transaction we are running in
      * @param key the key
      * @param val the value to compare values to
      * @return true if a Tuple with a key equal to the key argument and a
      * value greater than the value argument exists, false otherwise
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      * or if the underlying Db is not of the Btree type that allows sorted
      * duplicate values.
      */
-    boolean hasGreaterOrEqual( K key, V val ) throws Exception;
+    boolean hasGreaterOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException;
 
 
     /**
@@ -161,15 +169,16 @@ public interface Table<K, V>
      * If the table does not support duplicates then an
      * UnsupportedOperationException is thrown.
      *
+     * @param transaction The transaction we are running in
      * @param key the key
      * @param val the value to compare values to
      * @return true if a Tuple with a key equal to the key argument and a
      * value less than the value argument exists, false otherwise
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      * or if the underlying Db is not of the Btree type that allows sorted
      * duplicate values.
      */
-    boolean hasLessOrEqual( K key, V val ) throws Exception;
+    boolean hasLessOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException;
 
 
     // ------------------------------------------------------------------------
@@ -180,59 +189,64 @@ public interface Table<K, V>
      * Gets the value of a record by key if the key exists.  If this Table
      * allows duplicate keys then the first key will be returned.  If this
      * Table sorts keys then the key will be the smallest key in the Table as
-     * specificed by this Table's comparator or the default bytewise lexical
+     * specified by this Table's comparator or the default byte-wise lexical
      * comparator.
      *
+     * @param transaction The transaction we are running in
      * @param key the key of the record
      * @return the value of the record with the specified key if key exists or
      * null if no such key exists.
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    V get( K key ) throws Exception;
+    V get( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
      * Puts a record into this Table.  Null is not allowed for keys or values
      * and should result in an IllegalArgumentException.
      *
+     * @param writeTransaction The transaction we are running in
      * @param key the key of the record
      * @param value the value of the record.
-     * @throws Exception if there is a failure to read or write to the
+     * @throws LdapException if there is a failure to read or write to the
      * underlying Db
      * @throws IllegalArgumentException if a null key or value is used
      */
-    void put( K key, V value ) throws Exception;
+    void put( PartitionWriteTxn writeTransaction, K key, V value ) throws LdapException;
 
 
     /**
      * Removes all records with a specified key from this Table.
      *
+     * @param writeTransaction The transaction we are running in
      * @param key the key of the records to remove
-     * @throws Exception if there is a failure to read or write to
+     * @throws LdapException if there is a failure to read or write to
      * the underlying Db
      */
-    void remove( K key ) throws Exception;
+    void remove( PartitionWriteTxn writeTransaction, K key ) throws LdapException;
 
 
     /**
      * Removes a single key value pair with a specified key and value from
      * this Table.
      *
+     * @param writeTransaction The transaction we are running in
      * @param key the key of the record to remove
      * @param value the value of the record to remove
-     * @throws Exception if there is a failure to read or write to
+     * @throws LdapException if there is a failure to read or write to
      * the underlying Db
      */
-    void remove( K key, V value ) throws Exception;
+    void remove( PartitionWriteTxn writeTransaction, K key, V value ) throws LdapException;
 
 
     /**
      * Creates a Cursor that traverses Tuples in a Table.
      *
+     * @param transaction The transaction we are running in
      * @return a Cursor over Tuples containing the key value pairs
-     * @throws Exception if there are failures accessing underlying stores
+     * @throws LdapException if there are failures accessing underlying stores
      */
-    Cursor<Tuple<K, V>> cursor() throws Exception;
+    Cursor<Tuple<K, V>> cursor( PartitionTxn transaction ) throws LdapException;
 
 
     /**
@@ -244,11 +258,12 @@ public interface Table<K, V>
      * to a specific key.  This Cursor is naturally limited to return only
      * the tuples for the same key.
      *
+     * @param transaction The transaction we are running in
      * @param key the duplicate key to return the Tuples of
      * @return a Cursor over Tuples containing the same key
-     * @throws Exception if there are failures accessing underlying stores
+     * @throws LdapException if there are failures accessing underlying stores
      */
-    Cursor<Tuple<K, V>> cursor( K key ) throws Exception;
+    Cursor<Tuple<K, V>> cursor( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
@@ -261,11 +276,12 @@ public interface Table<K, V>
      * reused to return key value pairs.  This Cursor is naturally limited to
      * return only the values for the same key.
      *
+     * @param transaction The transaction we are running in
      * @param key the duplicate key to return the values of
      * @return a Cursor over values of a key
-     * @throws Exception if there are failures accessing underlying stores
+     * @throws LdapException if there are failures accessing underlying stores
      */
-    Cursor<V> valueCursor( K key ) throws Exception;
+    Cursor<V> valueCursor( PartitionTxn transaction, K key ) throws LdapException;
 
 
     // ------------------------------------------------------------------------
@@ -275,21 +291,23 @@ public interface Table<K, V>
     /**
      * Gets the count of the number of Tuples in this Table.
      *
+     * @param transaction The transaction we are running in
      * @return the number of records
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    long count() throws Exception;
+    long count( PartitionTxn transaction ) throws LdapException;
 
 
     /**
      * Gets the count of the number of records in this Table with a specific
      * key: returns the number of duplicates for a key.
      *
+     * @param transaction The transaction we are running in
      * @param key the Object key to count.
      * @return the number of duplicate records for a key.
-     * @throws Exception if there is a failure to read the underlying Db
+     * @throws LdapException if there is a failure to read the underlying Db
      */
-    long count( K key ) throws Exception;
+    long count( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
@@ -297,11 +315,12 @@ public interface Table<K, V>
      * specific key argument provided need not exist for this call to return 
      * a non-zero value.
      *
+     * @param transaction The transaction we are running in
      * @param key the key to use in comparisons
      * @return the number of keys greater than or equal to the key
-     * @throws Exception if there is a failure to read the underlying db
+     * @throws LdapException if there is a failure to read the underlying db
      */
-    long greaterThanCount( K key ) throws Exception;
+    long greaterThanCount( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
@@ -309,17 +328,19 @@ public interface Table<K, V>
      * specific key argument provided need not exist for this call to return 
      * a non-zero value.
      *
+     * @param transaction The transaction we are running in
      * @param key the key to use in comparisons
      * @return the number of keys less than or equal to the key
-     * @throws Exception if there is a failure to read the underlying db
+     * @throws LdapException if there is a failure to read the underlying db
      */
-    long lessThanCount( K key ) throws Exception;
+    long lessThanCount( PartitionTxn transaction, K key ) throws LdapException;
 
 
     /**
      * Closes the underlying Db of this Table.
      *
-     * @throws Exception on any failures
+     * @param transaction The transaction we are running in
+     * @throws LdapException on any failures
      */
-    void close() throws Exception;
+    void close( PartitionTxn transaction ) throws LdapException;
 }
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java
index 7d53c3b..d398c4c 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java
@@ -27,6 +27,8 @@ import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
 import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
 import org.apache.directory.api.ldap.model.cursor.Tuple;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.server.core.api.partition.PartitionTxn;
+import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
 import org.apache.directory.server.core.avltree.AvlSingletonOrOrderedSetCursor;
 import org.apache.directory.server.core.avltree.AvlTree;
 import org.apache.directory.server.core.avltree.AvlTreeCursor;
@@ -69,7 +71,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public void close() throws Exception
+    @Override
+    public void close( PartitionTxn transaction ) throws LdapException
     {
         ( ( AvlTreeMapImpl<K, V> ) avl ).removeAll();
     }
@@ -78,7 +81,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public long count( K key ) throws Exception
+    @Override
+    public long count( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -106,7 +110,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public V get( K key ) throws LdapException
+    @Override
+    public V get( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -134,7 +139,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public long greaterThanCount( K key ) throws Exception
+    @Override
+    public long greaterThanCount( PartitionTxn transaction, K key ) throws LdapException
     {
         return avl.getSize();
     }
@@ -143,7 +149,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean has( K key ) throws Exception
+    @Override
+    public boolean has( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -157,7 +164,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean has( K key, V value ) throws LdapException
+    @Override
+    public boolean has( PartitionTxn transaction, K key, V value ) throws LdapException
     {
         if ( key == null )
         {
@@ -171,7 +179,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean hasGreaterOrEqual( K key ) throws Exception
+    @Override
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -185,7 +194,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean hasGreaterOrEqual( K key, V val ) throws LdapException
+    @Override
+    public boolean hasGreaterOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -212,7 +222,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean hasLessOrEqual( K key ) throws Exception
+    @Override
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -226,7 +237,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean hasLessOrEqual( K key, V val ) throws Exception
+    @Override
+    public boolean hasLessOrEqual( PartitionTxn transaction, K key, V val ) throws LdapException
     {
         if ( key == null )
         {
@@ -253,16 +265,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public boolean isDupsEnabled()
-    {
-        return allowsDuplicates;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public long lessThanCount( K key ) throws Exception
+    @Override
+    public long lessThanCount( PartitionTxn transaction, K key ) throws LdapException
     {
         return count;
     }
@@ -271,7 +275,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public void put( K key, V value ) throws Exception
+    @Override
+    public void put( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         if ( ( key == null ) || ( value == null ) )
         {
@@ -288,7 +293,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public void remove( K key ) throws Exception
+    @Override
+    public void remove( PartitionWriteTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -316,7 +322,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public void remove( K key, V value ) throws Exception
+    @Override
+    public void remove( PartitionWriteTxn transaction, K key, V value ) throws LdapException
     {
         if ( avl.remove( key, value ) != null )
         {
@@ -328,7 +335,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public Cursor<Tuple<K, V>> cursor() throws LdapException
+    @Override
+    public Cursor<Tuple<K, V>> cursor( PartitionTxn transaction ) throws LdapException
     {
         if ( !allowsDuplicates )
         {
@@ -343,7 +351,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public Cursor<Tuple<K, V>> cursor( K key ) throws Exception
+    @Override
+    public Cursor<Tuple<K, V>> cursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {
@@ -370,7 +379,8 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     /**
      * {@inheritDoc}
      */
-    public Cursor<V> valueCursor( K key ) throws Exception
+    @Override
+    public Cursor<V> valueCursor( PartitionTxn transaction, K key ) throws LdapException
     {
         if ( key == null )
         {

-- 
To stop receiving notification emails like this one, please contact
elecharny@apache.org.

[directory-server] 02/05: o Fixed Java 8 warnings o Removed useless comparator in JdbmMasterTable o Removed the useless adminTable in JdbmMasterTable o Removed the unused resetCounter method in JdbmMasterTable o Removed the useless close() method from the MavibotMasterTable

Posted by el...@apache.org.
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

commit 1a6205e780ec66e2a6094b0f65f6cab62d4b8d0b
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Fri Jan 5 19:44:44 2018 +0100

    o Fixed Java 8 warnings
    o Removed useless comparator in JdbmMasterTable
    o Removed the useless adminTable in JdbmMasterTable
    o Removed the unused resetCounter method in JdbmMasterTable
    o Removed the useless close() method from the MavibotMasterTable
---
 .../partition/impl/btree/jdbm/JdbmMasterTable.java | 48 ----------------------
 .../impl/btree/mavibot/MavibotMasterTable.java     |  7 ----
 .../directory/server/xdbm/impl/avl/AvlTable.java   | 24 +++++------
 3 files changed, 12 insertions(+), 67 deletions(-)

diff --git a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmMasterTable.java b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmMasterTable.java
index a96e306..0553f81 100644
--- a/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmMasterTable.java
+++ b/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmMasterTable.java
@@ -24,11 +24,9 @@ import java.util.UUID;
 
 import jdbm.RecordManager;
 import jdbm.helper.Serializer;
-import jdbm.helper.StringComparator;
 
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.model.schema.comparators.SerializableComparator;
 import org.apache.directory.api.ldap.model.schema.comparators.UuidComparator;
 import org.apache.directory.server.xdbm.MasterTable;
 
@@ -40,23 +38,6 @@ import org.apache.directory.server.xdbm.MasterTable;
  */
 public class JdbmMasterTable extends JdbmTable<String, Entry> implements MasterTable
 {
-    private static final StringComparator STRCOMP = new StringComparator();
-
-    private static final SerializableComparator<String> STRING_COMPARATOR =
-        new SerializableComparator<String>( "1.3.6.1.4.1.18060.0.4.1.1.3" )
-        {
-            private static final long serialVersionUID = 3258689922792961845L;
-
-
-            public int compare( String o1, String o2 )
-            {
-                return STRCOMP.compare( o1, o2 );
-            }
-        };
-
-    protected final JdbmTable<String, String> adminTbl;
-
-
     /**
      * Creates the master table using JDBM B+Trees for the backing store.
      *
@@ -68,17 +49,8 @@ public class JdbmMasterTable extends JdbmTable<String, Entry> implements MasterT
     {
         super( schemaManager, DBF, recMan, UuidComparator.INSTANCE, UuidSerializer.INSTANCE,
             new EntrySerializer( schemaManager ) );
-        adminTbl = new JdbmTable<String, String>( schemaManager, "admin", recMan, STRING_COMPARATOR,
-            StringSerializer.INSTANCE, StringSerializer.INSTANCE );
-        String seqValue = adminTbl.get( SEQPROP_KEY );
-
-        if ( null == seqValue )
-        {
-            adminTbl.put( SEQPROP_KEY, "0" );
-        }
 
         UuidComparator.INSTANCE.setSchemaManager( schemaManager );
-        STRING_COMPARATOR.setSchemaManager( schemaManager );
     }
 
 
@@ -86,14 +58,6 @@ public class JdbmMasterTable extends JdbmTable<String, Entry> implements MasterT
         throws Exception
     {
         super( schemaManager, DBF, recMan, UuidComparator.INSTANCE, UuidSerializer.INSTANCE, serializer );
-        adminTbl = new JdbmTable<String, String>( schemaManager, dbName, recMan, STRING_COMPARATOR,
-            StringSerializer.INSTANCE, StringSerializer.INSTANCE );
-        String seqValue = adminTbl.get( SEQPROP_KEY );
-
-        if ( null == seqValue )
-        {
-            adminTbl.put( SEQPROP_KEY, "0" );
-        }
     }
 
 
@@ -111,16 +75,4 @@ public class JdbmMasterTable extends JdbmTable<String, Entry> implements MasterT
     {
         return UUID.randomUUID().toString();
     }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void resetCounter() throws Exception
-    {
-        synchronized ( adminTbl )
-        {
-            adminTbl.put( SEQPROP_KEY, "0" );
-        }
-    }
 }
diff --git a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java b/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
index 55b0aa6..67bfb61 100644
--- a/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
+++ b/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
@@ -55,11 +55,4 @@ public class MavibotMasterTable extends MavibotTable<String, Entry> implements M
     {
         return UUID.randomUUID().toString();
     }
-
-
-    @Override
-    public void close() throws Exception
-    {
-        // do nothing here, the RecordManager will be closed in MavibotMasterTable.close()
-    }
 }
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java
index 00a44ba..7d53c3b 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/impl/avl/AvlTable.java
@@ -54,7 +54,7 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
         boolean dupsEnabled )
     {
         super( null, name, keyComparator, valueComparator );
-        this.avl = new AvlTreeMapImpl<K, V>( keyComparator, valueComparator, dupsEnabled );
+        this.avl = new AvlTreeMapImpl<>( keyComparator, valueComparator, dupsEnabled );
         allowsDuplicates = this.avl.isDupsAllowed();
         this.keyOnlytupleComparator = new Comparator<Tuple<K, V>>()
         {
@@ -71,7 +71,7 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
      */
     public void close() throws Exception
     {
-        ( ( AvlTreeMapImpl ) avl ).removeAll();
+        ( ( AvlTreeMapImpl<K, V> ) avl ).removeAll();
     }
 
 
@@ -332,11 +332,11 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     {
         if ( !allowsDuplicates )
         {
-            return new AvlTreeMapNoDupsWrapperCursor<K, V>(
+            return new AvlTreeMapNoDupsWrapperCursor<>(
                 new AvlSingletonOrOrderedSetCursor<K, V>( avl ) );
         }
 
-        return new AvlTableDupsCursor<K, V>( this );
+        return new AvlTableDupsCursor<>( this );
     }
 
 
@@ -347,22 +347,22 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     {
         if ( key == null )
         {
-            return new EmptyCursor<Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
 
         LinkedAvlMapNode<K, V> node = avl.find( key );
 
         if ( node == null )
         {
-            return new EmptyCursor<Tuple<K, V>>();
+            return new EmptyCursor<>();
         }
 
         if ( node.getValue().isOrderedSet() )
         {
-            return new KeyTupleAvlCursor<K, V>( node.getValue().getOrderedSet(), key );
+            return new KeyTupleAvlCursor<>( node.getValue().getOrderedSet(), key );
         }
 
-        return new SingletonCursor<Tuple<K, V>>( new Tuple<K, V>( key, node.getValue().getSingleton() ),
+        return new SingletonCursor<>( new Tuple<K, V>( key, node.getValue().getSingleton() ),
             keyOnlytupleComparator );
     }
 
@@ -374,22 +374,22 @@ public class AvlTable<K, V> extends AbstractTable<K, V>
     {
         if ( key == null )
         {
-            return new EmptyCursor<V>();
+            return new EmptyCursor<>();
         }
 
         LinkedAvlMapNode<K, V> node = avl.find( key );
 
         if ( node == null )
         {
-            return new EmptyCursor<V>();
+            return new EmptyCursor<>();
         }
 
         if ( node.getValue().isOrderedSet() )
         {
-            return new AvlTreeCursor<V>( node.getValue().getOrderedSet() );
+            return new AvlTreeCursor<>( node.getValue().getOrderedSet() );
         }
 
-        return new SingletonCursor<V>( node.getValue().getSingleton(), valueComparator );
+        return new SingletonCursor<>( node.getValue().getSingleton(), valueComparator );
     }
 
 

-- 
To stop receiving notification emails like this one, please contact
elecharny@apache.org.

[directory-server] 05/05: Fix for DIRSERVER-2220

Posted by el...@apache.org.
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

commit 1399b77e0205b8b5dd8f67fe188f8fc99979ca8e
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Tue Jan 23 08:20:36 2018 +0100

    Fix for DIRSERVER-2220
---
 .../apache/directory/server/core/authn/AuthenticationInterceptor.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java b/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
index 2843f53..9a51000 100644
--- a/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
+++ b/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
@@ -537,12 +537,12 @@ public class AuthenticationInterceptor extends BaseInterceptor
         catch ( LdapAuthenticationException e )
         {
             // authentication failed, try the next authenticator
-            LOG.info( "Authenticator {} failed to authenticate: {}", authenticator, bindContext );
+            LOG.info( "Authenticator {} failed to authenticate: {}", authenticator, bindContext.getDn() );
         }
         catch ( Exception e )
         {
             // Log other exceptions than LdapAuthenticationException
-            LOG.info( "Unexpected failure for Authenticator {} : {}", authenticator, bindContext );
+            LOG.info( "Unexpected failure for Authenticator {} : {}", authenticator, bindContext.getDn() );
         }
 
         if ( ppe != null )

-- 
To stop receiving notification emails like this one, please contact
elecharny@apache.org.

[directory-server] 04/05: Merge branch 'master' of https://gitbox.apache.org/repos/asf/directory-server

Posted by el...@apache.org.
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

commit f62c7167b65c453230dcba79bfb0c6a8874bb813
Merge: be82b0c 6ae7af2
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Wed Jan 10 07:06:06 2018 +0100

    Merge branch 'master' of https://gitbox.apache.org/repos/asf/directory-server

 NOTICE                                             |   2 +-
 README.txt                                         |   1 -
 all/pom.xml                                        |   2 +-
 apache-felix/ApacheDS-OSGI.launch                  |   2 -
 benchmarks/installers-maven-plugin/.classpath      |  31 +
 benchmarks/installers-maven-plugin/.project        |  28 +
 .../.settings/org.eclipse.core.resources.prefs     |   4 +
 .../.settings/org.eclipse.jdt.core.prefs           |   5 +
 .../.settings/org.eclipse.m2e.core.prefs           |   4 +
 .../server/installers/AbstractMojoCommand.class    | Bin 0 -> 7057 bytes
 .../directory/server/installers/GenerateMojo.class | Bin 0 -> 6838 bytes
 .../org/apache/directory/server/installers/LICENSE | 364 +++++++++
 .../server/installers/LinuxInstallerCommand.class  | Bin 0 -> 3757 bytes
 .../server/installers/MojoHelperUtils.class        | Bin 0 -> 8173 bytes
 .../org/apache/directory/server/installers/NOTICE  |   4 +-
 .../server/installers/ReflectionProperties.class   | Bin 0 -> 1768 bytes
 .../directory/server/installers/Target.class       | Bin 0 -> 2442 bytes
 .../apache/directory/server/installers/apacheds    | 590 +++++++++++++++
 .../archive/ArchiveInstallerCommand.class          | Bin 0 -> 9552 bytes
 .../server/installers/archive/ArchiveTarget.class  | Bin 0 -> 754 bytes
 .../server/installers/archive/ArchiveType.class    | Bin 0 -> 1875 bytes
 .../server/installers/archive/apacheds.bat         |  41 +
 .../server/installers/archive/apacheds.sh          |  32 -
 .../server/installers/archive/cpappend.bat         |  36 +
 .../server/installers/archive/log4j.properties     |  43 ++
 .../installers/bin/BinInstallerCommand.class       | Bin 0 -> 7188 bytes
 .../server/installers/bin/BinTarget.class          | Bin 0 -> 479 bytes
 .../directory/server/installers/bin/bootstrap.sh   | 281 +++++++
 .../server/installers/bin/createInstaller.sh       |  35 +
 .../directory/server/installers/bin/functions.sh   | 127 ++++
 .../directory/server/installers/bin/install.sh     | 163 ++++
 .../directory/server/installers/bin/variables.sh   |  25 +
 .../installers/deb/DebInstallerCommand.class       | Bin 0 -> 8155 bytes
 .../server/installers/deb/DebTarget.class          | Bin 0 -> 482 bytes
 .../apache/directory/server/installers/deb/control |  13 +
 .../directory/server/installers/deb/postinst       |  40 +
 .../apache/directory/server/installers/deb/prerm   |  38 +
 .../directory/server/installers/etc-initd-script   |  36 +
 .../directory/server/installers/log4j.properties   |  47 ++
 .../directory/server/installers/macosxpkg/DS_Store | Bin 0 -> 12292 bytes
 .../server/installers/macosxpkg/Info.plist         |  58 ++
 .../server/installers/macosxpkg/License.rtf        |  80 ++
 .../macosxpkg/MacOsXPkgInstallerCommand.class      | Bin 0 -> 13317 bytes
 .../installers/macosxpkg/MacOsXPkgTarget.class     | Bin 0 -> 515 bytes
 .../installers/macosxpkg/apacheds-usr-bin.sh       |  20 +
 .../server/installers/macosxpkg/dmg-background.png | Bin 0 -> 12138 bytes
 .../macosxpkg/org.apache.directory.server.plist    |  42 ++
 .../installers/macosxpkg/pkg-background.tiff       | Bin 0 -> 162064 bytes
 .../server/installers/macosxpkg/postflight         |  30 +
 .../server/installers/macosxpkg/preflight          |  32 +
 .../server/installers/nsis/Manage ApacheDS.exe     | Bin 0 -> 26112 bytes
 .../installers/nsis/NsisInstallerCommand.class     | Bin 0 -> 7359 bytes
 .../server/installers/nsis/NsisTarget.class        | Bin 0 -> 486 bytes
 .../directory/server/installers/nsis/header.bmp    | Bin 0 -> 25818 bytes
 .../directory/server/installers/nsis/installer.ico | Bin 0 -> 26694 bytes
 .../directory/server/installers/nsis/installer.nsi | 659 ++++++++++++++++
 .../server/installers/nsis/uninstaller.ico         | Bin 0 -> 17542 bytes
 .../directory/server/installers/nsis/welcome.bmp   | Bin 0 -> 154542 bytes
 .../installers/rpm/RpmInstallerCommand.class       | Bin 0 -> 8990 bytes
 .../server/installers/rpm/RpmTarget.class          | Bin 0 -> 480 bytes
 .../directory/server/installers/rpm/apacheds.spec  | 100 +++
 .../server/installers/wrapper-installation.conf    | 115 +++
 .../server/installers/wrapper-instance.conf        |  40 +
 .../installers/wrapper/bin/wrapper-linux-ppc-64    | Bin 0 -> 140198 bytes
 .../installers/wrapper/bin/wrapper-linux-x86-32    | Bin 0 -> 99401 bytes
 .../installers/wrapper/bin/wrapper-linux-x86-64    | Bin 0 -> 111027 bytes
 .../installers/wrapper/bin/wrapper-macosx-ppc-32   | Bin 0 -> 114052 bytes
 .../wrapper/bin/wrapper-macosx-universal-32        | Bin 0 -> 233604 bytes
 .../wrapper/bin/wrapper-macosx-universal-64        | Bin 0 -> 129136 bytes
 .../wrapper/bin/wrapper-solaris-sparc-32           | Bin 0 -> 112536 bytes
 .../wrapper/bin/wrapper-solaris-sparc-64           | Bin 0 -> 148512 bytes
 .../installers/wrapper/bin/wrapper-solaris-x86-32  | Bin 0 -> 110992 bytes
 .../wrapper/bin/wrapper-windows-x86-32.exe         | Bin 0 -> 204800 bytes
 .../server/installers/wrapper/conf/wrapper.conf    | 118 +++
 .../wrapper/lib/libwrapper-linux-ppc-64.so         | Bin 0 -> 23839 bytes
 .../wrapper/lib/libwrapper-linux-x86-32.so         | Bin 0 -> 11887 bytes
 .../wrapper/lib/libwrapper-linux-x86-64.so         | Bin 0 -> 15248 bytes
 .../wrapper/lib/libwrapper-macosx-ppc-32.jnilib    | Bin 0 -> 15400 bytes
 .../lib/libwrapper-macosx-universal-32.jnilib      | Bin 0 -> 35332 bytes
 .../lib/libwrapper-macosx-universal-64.jnilib      | Bin 0 -> 15168 bytes
 .../wrapper/lib/libwrapper-solaris-sparc-32.so     | Bin 0 -> 13760 bytes
 .../wrapper/lib/libwrapper-solaris-sparc-64.so     | Bin 0 -> 21032 bytes
 .../wrapper/lib/libwrapper-solaris-x86-32.so       | Bin 0 -> 12572 bytes
 .../wrapper/lib/wrapper-windows-x86-32.dll         | Bin 0 -> 81920 bytes
 .../server/installers/wrapper/src/App.bat.in       |  72 ++
 .../installers/wrapper/src/AppCommand.bat.in       | 114 +++
 .../installers/wrapper/src/AppNoWrapper.bat.in     |  29 +
 .../installers/wrapper/src/InstallApp-NT.bat.in    |  67 ++
 .../installers/wrapper/src/PauseApp-NT.bat.in      |  67 ++
 .../installers/wrapper/src/ResumeApp-NT.bat.in     |  67 ++
 .../server/installers/wrapper/src/SimpleApp.bat.in |  32 +
 .../wrapper/src/SimpleInstallApp-NT.bat.in         |  32 +
 .../wrapper/src/SimpleUninstallApp-NT.bat.in       |  32 +
 .../installers/wrapper/src/StartApp-NT.bat.in      |  67 ++
 .../installers/wrapper/src/StopApp-NT.bat.in       |  67 ++
 .../installers/wrapper/src/UninstallApp-NT.bat.in  |  67 ++
 .../server/installers/wrapper/src/sh.script.in     | 617 +++++++++++++++
 .../directory/mavibot/btree/LdifDataLoader.java    |   2 +-
 core-annotations/pom.xml                           |  44 +-
 .../factory/DefaultDirectoryServiceFactory.java    |   2 +-
 .../server/core/factory/JdbmPartitionFactory.java  |   2 +-
 core-api/pom.xml                                   |  54 +-
 .../server/core/api/LdapCoreSessionConnection.java | 127 +++-
 .../directory/server/core/api/LdapPrincipal.java   |  20 +-
 .../directory/server/core/api/ReferralManager.java |   2 +-
 .../server/core/api/entry/ClonedServerEntry.java   |  20 +-
 .../server/core/api/entry/ServerEntryUtils.java    |  19 +-
 .../server/core/api/event/LeafEvaluator.java       |  30 +-
 .../core/api/event/NotificationCriteria.java       |  11 +-
 .../server/core/api/event/RegistrationEntry.java   |   5 +-
 .../server/core/api/event/SubstringEvaluator.java  |   4 +-
 .../context/AbstractChangeOperationContext.java    |   3 +
 .../context/AbstractOperationContext.java          |  33 +-
 .../context/CompareOperationContext.java           |  13 +-
 .../core/api/interceptor/context/ModDnAva.java     |  89 +++
 .../context/MoveAndRenameOperationContext.java     |  42 +-
 .../interceptor/context/MoveOperationContext.java  |  42 +-
 .../normalization/FilterNormalizingVisitor.java    | 267 ++-----
 .../core/api/partition/AbstractPartition.java      |  22 +-
 .../server/core/api/partition/PartitionNexus.java  |   2 +-
 .../server/core/api/schema/DescriptionParsers.java |  76 +-
 .../AbstractRegistrySynchronizer.java              |  14 +-
 .../synchronizers/AttributeTypeSynchronizer.java   |  20 +-
 .../synchronizers/ComparatorSynchronizer.java      |  28 +-
 .../synchronizers/MatchingRuleSynchronizer.java    |  22 +-
 .../synchronizers/NormalizerSynchronizer.java      |  22 +-
 .../synchronizers/ObjectClassSynchronizer.java     |  56 +-
 .../synchronizers/RegistrySynchronizerAdaptor.java |  41 +-
 .../synchronizers/SchemaSynchronizer.java          |  30 +-
 .../synchronizers/SyntaxCheckerSynchronizer.java   |  18 +-
 .../synchronizers/SyntaxSynchronizer.java          |  43 +-
 .../server/core/api/sp/LdapClassLoader.java        |  24 +-
 .../core/api/sp/StoredProcExecutionManager.java    |   6 +-
 .../server/core/api/sp/StoredProcUtils.java        |   8 +-
 .../core/api/sp/java/JavaStoredProcEngine.java     |   9 +-
 .../api/sp/java/JavaStoredProcEngineConfig.java    |   2 +
 .../api/sp/java/LdapJavaStoredProcClassLoader.java |   4 +
 .../core/api/subtree/RefinementLeafEvaluator.java  |   2 +-
 .../server/core/api/subtree/SubentryUtils.java     |   8 +-
 .../directory/server/core/api/MockCoreSession.java |  14 +-
 .../core/api/entry/SchemaAwareEntryTest.java       | 288 ++++---
 .../FilterNormalizingVisitorTest.java              |   6 +-
 core-avl/pom.xml                                   |  12 +-
 .../server/core/avltree/AvlTreeMapImpl.java        |  53 +-
 core-constants/pom.xml                             |   4 +-
 .../server/constants/ServerDNConstants.java        |   4 +-
 core-integ/pom.xml                                 |  46 +-
 .../server/core/integ/IntegrationUtils.java        |   2 +-
 .../server/core/authn/SimpleAuthenticationIT.java  |  20 +-
 .../core/authz/AuthorizationServiceAsAdminIT.java  |   5 +-
 .../server/core/authz/ModifyAuthorizationIT.java   |  38 +-
 .../server/core/exception/ExceptionServiceIT.java  |  12 +-
 .../server/core/jndi/ObjStateFactoryIT.java        |   4 +-
 .../operational/OperationalAttributeServiceIT.java |  12 +
 .../server/core/operations/add/AddIT.java          |   8 +-
 .../server/core/operations/lookup/LookupIT.java    |   1 -
 .../core/operations/lookup/LookupPerfIT.java       |   2 +-
 .../server/core/operations/modify/ModifyAddIT.java |   2 +-
 .../server/core/operations/move/MoveIT.java        |  50 +-
 .../operations/moveAndRename/MoveAndRenameIT.java  | 211 +++++-
 .../server/core/operations/rename/RenameIT.java    | 277 ++++++-
 .../server/core/operations/search/SearchIT.java    |  85 ++-
 .../operations/search/SearchWithIndicesIT.java     |  28 +-
 .../server/core/schema/SubschemaSubentryIT.java    |  42 +-
 .../server/core/subtree/BadSubentryServiceIT.java  |   9 +-
 .../server/core/schema/DummyNormalizer.bytecode    | Bin 1695 -> 1629 bytes
 core-jndi/pom.xml                                  |  46 +-
 .../directory/server/core/jndi/ServerContext.java  |  15 +-
 .../server/core/jndi/ServerDirContext.java         |  13 +-
 .../server/core/jndi/ServerLdapContext.java        |  12 +-
 core-shared/pom.xml                                |  44 +-
 .../server/core/shared/DefaultCoreSession.java     | 167 ++--
 .../server/core/shared/DefaultDnFactory.java       |  17 +-
 .../server/core/shared/ReferralManagerImpl.java    |  18 +-
 .../server/core/shared/SchemaService.java          |   4 +-
 .../server/core/shared/SortedEntryComparator.java  |  88 ++-
 .../server/core/shared/SortedEntryCursor.java      |   2 +-
 .../server/core/shared/SortedEntrySerializer.java  |   4 +-
 .../shared/partition/DefaultPartitionNexus.java    | 146 ++--
 core/pom.xml                                       |  56 +-
 .../server/core/DefaultDirectoryService.java       |  66 +-
 .../server/core/DefaultOperationManager.java       | 116 ++-
 http-directory-bridge/pom.xml                      |  10 +-
 http-integration/pom.xml                           |  22 +-
 .../server/integration/http/HttpServer.java        |   3 +-
 i18n/pom.xml                                       |   4 +-
 .../org/apache/directory/server/i18n/I18n.java     |   4 +-
 installers-maven-plugin/pom.xml                    |   2 +-
 .../server/installers/archive/apacheds.sh          |   1 +
 .../server/installers/archive/cpappend.bat.orig    |  36 +
 installers/pom.xml                                 |   2 +-
 interceptor-kerberos/pom.xml                       |  24 +-
 .../core/kerberos/KeyDerivationInterceptor.java    |  19 +-
 interceptors/admin/pom.xml                         |  24 +-
 .../core/admin/AdministrativePointInterceptor.java |  71 +-
 interceptors/authn/pom.xml                         |  32 +-
 .../server/core/authn/AbstractAuthenticator.java   |  20 +-
 .../server/core/authn/AnonymousAuthenticator.java  |   1 +
 .../core/authn/AuthenticationInterceptor.java      | 105 +--
 .../directory/server/core/authn/Authenticator.java |   8 -
 .../server/core/authn/DelegatingAuthenticator.java |   3 +
 .../server/core/authn/PasswordHistory.java         |  16 +
 .../server/core/authn/SimpleAuthenticator.java     |   8 +-
 .../server/core/authn/StrongAuthenticator.java     |   1 +
 .../core/authn/ppolicy/PpolicyConfigContainer.java |   4 +-
 interceptors/authz/pom.xml                         |  32 +-
 .../core/authz/AciAuthorizationInterceptor.java    | 181 ++---
 .../authz/DefaultAuthorizationInterceptor.java     |  23 +-
 .../directory/server/core/authz/GroupCache.java    | 141 ++--
 .../directory/server/core/authz/TupleCache.java    |  39 +-
 .../server/core/authz/support/ACDFEngine.java      |   4 +-
 .../server/core/authz/support/AciContext.java      |  12 +-
 .../authz/support/HighestPrecedenceFilter.java     |   4 +
 .../server/core/authz/support/MaxImmSubFilter.java |   6 +-
 .../core/authz/support/MaxValueCountFilter.java    |   6 +-
 .../core/authz/support/MicroOperationFilter.java   |   6 +-
 .../support/MostSpecificProtectedItemFilter.java   |  10 +-
 .../authz/support/MostSpecificUserClassFilter.java |  12 +-
 .../server/core/authz/support/OperationScope.java  |   1 +
 .../authz/support/RelatedProtectedItemFilter.java  |  15 +-
 .../core/authz/support/RelatedUserClassFilter.java |  19 +-
 .../core/authz/support/RestrictedByFilter.java     |   4 +-
 .../support/MostSpecificUserClassFilterTest.java   |   3 +-
 .../support/RelatedProtectedItemFilterTest.java    |   8 +-
 .../authz/support/RelatedUserClassFilterTest.java  |  16 +-
 .../core/authz/support/RestrictedByFilterTest.java |   8 +-
 interceptors/changelog/pom.xml                     |  26 +-
 .../core/changelog/ChangeLogInterceptor.java       |  15 +-
 .../server/core/changelog/DefaultChangeLog.java    |  32 +-
 .../core/changelog/MemoryChangeLogStore.java       |  59 +-
 .../core/changelog/MemoryChangeLogStoreTest.java   |   3 -
 interceptors/collective/pom.xml                    |  19 +-
 .../collective/CollectiveAttributeInterceptor.java |  21 +-
 interceptors/event/pom.xml                         |  21 +-
 .../server/core/event/DefaultEventService.java     |  12 +-
 .../server/core/event/EventInterceptor.java        |  16 +-
 interceptors/exception/pom.xml                     |  18 +-
 .../core/exception/ExceptionInterceptor.java       |  14 +-
 interceptors/hash/pom.xml                          |  16 +-
 .../core/hash/ConfigurableHashingInterceptor.java  |   7 +-
 .../core/hash/PasswordHashingInterceptor.java      |  16 +-
 interceptors/journal/pom.xml                       |  15 +-
 .../server/core/journal/DefaultJournal.java        |  11 +
 .../server/core/journal/DefaultJournalStore.java   |   9 +
 .../server/core/journal/JournalInterceptor.java    |  15 +-
 interceptors/logger/pom.xml                        |  14 +-
 .../server/core/logger/TimerInterceptor.java       |  19 +-
 interceptors/normalization/pom.xml                 |  21 +-
 .../core/normalization/ExpandingVisitor.java       |  18 +-
 .../normalization/NormalizationInterceptor.java    | 174 ++++-
 .../normalization/NormalizationVisitorTest.java    |   4 +-
 interceptors/number/pom.xml                        |  17 +-
 .../core/number/NumberIncrementingInterceptor.java |  17 +-
 interceptors/operational/pom.xml                   |  23 +-
 .../OperationalAttributeInterceptor.java           |  45 +-
 interceptors/pom.xml                               |   2 +-
 interceptors/referral/pom.xml                      |  21 +-
 .../server/core/referral/ReferralInterceptor.java  |  42 +-
 interceptors/schema/pom.xml                        |  34 +-
 .../server/core/schema/SchemaInterceptor.java      | 441 +++++++----
 .../schema/SchemaLdifToPartitionExtractor.java     |  27 +-
 .../server/core/schema/SchemaSubentryManager.java  |  50 +-
 .../server/core/schema/SchemaSubentryModifier.java |   4 +-
 interceptors/subtree/pom.xml                       |  27 +-
 .../server/core/subtree/SubentryInterceptor.java   | 117 ++-
 .../core/subtree/RefinementEvaluatorTest.java      |  22 +-
 .../core/subtree/RefinementLeafEvaluatorTest.java  |  26 +-
 interceptors/trigger/pom.xml                       |  28 +-
 .../AbstractStoredProcedureParameterInjector.java  |  57 +-
 .../AddStoredProcedureParameterInjector.java       |   1 +
 .../ModifyDNStoredProcedureParameterInjector.java  |   4 +-
 .../trigger/StoredProcedureParameterInjector.java  |   2 +-
 .../server/core/trigger/TriggerInterceptor.java    |  54 +-
 .../server/core/trigger/TriggerSpecCache.java      |  32 +-
 jdbm-partition/pom.xml                             |  36 +-
 .../impl/btree/jdbm/DnSerializerComparator.java    |  21 +-
 .../partition/impl/btree/jdbm/JdbmPartition.java   |  49 +-
 .../partition/impl/btree/jdbm/JdbmIndexTest.java   | 134 ++--
 .../partition/impl/btree/jdbm/JdbmStoreTest.java   |  35 +-
 kerberos-client/pom.xml                            |   2 +-
 .../directory/kerberos/client/KdcConnection.java   |   4 +-
 .../directory/kerberos/client/KerberosChannel.java |  10 +-
 .../credentials/cache/CredentialsCache.java        |   2 +-
 kerberos-codec/pom.xml                             |  41 +-
 .../server/kerberos/shared/keytab/Keytab.java      |   4 +-
 .../shared/store/PrincipalStoreEntryModifier.java  |   5 +-
 .../principalName/actions/StoreNameString.java     |   3 +-
 kerberos-test/pom.xml                              |   2 +-
 ldap-client-test/pom.xml                           |   2 +-
 .../shared/client/api/LdapConnectionTest.java      |   4 +-
 .../shared/client/api/LdapSSLConnectionTest.java   |  12 +-
 .../api/operations/ClientAddRequestTest.java       |  12 +-
 .../api/operations/ClientModifyDnRequestTest.java  |   2 +-
 .../api/operations/bind/BogusNtlmProvider.java     |  64 --
 .../client/api/operations/bind/SaslBindIT.java     | 832 --------------------
 .../api/operations/bind/SimpleBindRequestTest.java |   1 +
 .../shared/client/api/operations/bind/Test.java    |  15 +
 .../search/AnonymousClientSearchRequestTest.java   | 490 ++++++------
 .../operations/search/ClientSearchRequestTest.java |   4 +-
 ldif-partition/pom.xml                             |  24 +-
 .../server/core/partition/ldif/LdifPartition.java  |  16 +-
 .../partition/ldif/SingleFileLdifPartition.java    |  33 +-
 .../core/partition/ldif/LdifPartitionTest.java     |  76 +-
 ...SingleFileLdifPartitionSingeValueAttribute.java |  76 +-
 .../ldif/SingleFileLdifPartitionTest.java          |  65 +-
 {mavibot-partition => lmdb-partation}/pom.xml      |  17 +-
 mavibot-partition/pom.xml                          |  33 +-
 .../partition/impl/btree/mavibot/DnSerializer.java |  21 +-
 .../impl/btree/mavibot/LdifTupleComparator.java    |   6 +-
 .../impl/btree/mavibot/MavibotPartition.java       |   2 +-
 .../impl/btree/mavibot/MavibotStoreTest.java       |  35 +-
 osgi-integ/pom.xml                                 |  12 +-
 .../server/osgi/integ/ServerOsgiTestBase.java      |   9 +-
 pom.xml                                            |  13 +-
 protocol-dhcp/pom.xml                              |  28 +-
 protocol-dns/pom.xml                               |  37 +-
 protocol-kerberos/pom.xml                          |  60 +-
 .../kerberos/kdc/DirectoryPrincipalStore.java      |   2 +-
 protocol-ldap/pom.xml                              | 101 ++-
 .../apache/directory/server/ldap/LdapServer.java   |   5 +-
 .../ldap/handlers/controls/PagedSearchContext.java |  11 +-
 .../ldap/handlers/extended/PwdModifyHandler.java   |   9 +-
 .../ldap/handlers/request/BindRequestHandler.java  |  18 +
 .../handlers/request/ModifyDnRequestHandler.java   |   2 +-
 .../handlers/request/SearchRequestHandler.java     |  38 +-
 .../ldap/handlers/sasl/ntlm/NtlmSaslServer.java    |  11 +-
 .../ldap/handlers/sasl/plain/PlainSaslServer.java  |  13 +-
 .../consumer/ReplicationConsumerImpl.java          |   9 +-
 .../replication/provider/ReplConsumerManager.java  |   8 +-
 .../ldap/replication/provider/ReplicaEventLog.java |   2 +-
 .../provider/SyncReplRequestHandler.java           |  18 +-
 protocol-ntp/pom.xml                               |  19 +-
 protocol-shared/pom.xml                            |  32 +-
 .../protocol/shared/kerberos/StoreUtils.java       |   3 +-
 server-annotations/pom.xml                         |  29 +-
 server-config/pom.xml                              |  30 +-
 .../server/config/ConfigPartitionReader.java       |  65 +-
 .../directory/server/config/ConfigWriter.java      |   4 +-
 .../server/config/beans/AuthenticatorBean.java     |   2 +-
 .../config/ChangePasswordConfigReaderTest.java     |   2 +-
 .../server/config/ConfigPartitionReaderTest.java   |   2 +-
 .../directory/server/config/ConfigWriterTest.java  |   4 +-
 .../server/config/HttpServerConfigReaderTest.java  |   2 +-
 .../config/KerberosServerConfigReaderTest.java     |   2 +-
 .../server/config/LdapServerConfigReaderTest.java  |   2 +-
 server-integ/pom.xml                               | 100 +--
 .../test/java/org/apache/directory/IndexIT.java    |   7 +-
 .../directory/server/operations/add/AddIT.java     |  65 +-
 .../AddingEntriesWithSpecialCharactersInRDNIT.java |   8 +-
 .../server/operations/extended/PwdModifyIT.java    |   4 +-
 .../directory/server/operations/ldapsdk/AddIT.java |   2 +-
 .../server/operations/modifydn/ModifyRdnIT.java    |  30 +-
 .../server/operations/search/SearchIT.java         |  60 --
 .../directory/server/ppolicy/PasswordPolicyIT.java |   4 +-
 .../server/replication/MockSyncReplConsumer.java   |   8 +-
 .../server/ssl/BogusSSLContextFactory.java         |  73 +-
 .../org/apache/directory/server/ssl/bogus.cert     | Bin 2247 -> 0 bytes
 server-jndi/pom.xml                                |  30 +-
 service-builder/pom.xml                            |  48 +-
 .../server/config/builder/ServiceBuilder.java      |   2 +-
 .../config/listener/ConfigChangeListener.java      |   3 +-
 service/ApacheDS.launch                            |   2 -
 service/pom.xml                                    |   2 +-
 .../apache/directory/server/ApacheDsService.java   |  15 +-
 .../org/apache/directory/server/UberjarMain.java   |  25 +-
 src/site/site.xml                                  |  34 +-
 test-framework/pom.xml                             |  36 +-
 .../server/core/integ/FrameworkRunner.java         |   4 +-
 .../server/core/integ/TestClassServer.java         |   6 +-
 wrapper/pom.xml                                    |   2 +-
 .../server/wrapper/ApacheDsTanukiWrapper.java      |  22 +-
 xdbm-partition/pom.xml                             |  46 +-
 .../impl/btree/AbstractBTreePartition.java         | 838 ++++++++++-----------
 .../directory/server/xdbm/ParentIdAndRdn.java      |  29 +-
 .../org/apache/directory/server/xdbm/Store.java    |  24 +-
 .../xdbm/search/cursor/ApproximateCursor.java      |   4 +-
 .../server/xdbm/search/cursor/EqualityCursor.java  |   5 +-
 .../server/xdbm/search/cursor/GreaterEqCursor.java |   3 +-
 .../server/xdbm/search/cursor/LessEqCursor.java    |   6 +-
 .../server/xdbm/search/cursor/SubstringCursor.java |   5 +-
 .../server/xdbm/search/evaluator/AndEvaluator.java |  72 +-
 .../search/evaluator/ApproximateEvaluator.java     |   9 +-
 .../xdbm/search/evaluator/EqualityEvaluator.java   |  71 +-
 .../xdbm/search/evaluator/GreaterEqEvaluator.java  |  21 +-
 .../xdbm/search/evaluator/LessEqEvaluator.java     |  24 +-
 .../xdbm/search/evaluator/SubstringEvaluator.java  |  40 +-
 .../search/evaluator/SubtreeScopeEvaluator.java    |   2 +-
 .../server/xdbm/search/impl/CursorBuilder.java     |  81 +-
 .../server/xdbm/search/impl/DefaultOptimizer.java  |  47 +-
 .../xdbm/search/impl/DefaultSearchEngine.java      |  31 +-
 .../directory/server/xdbm/ParentIdAndRdnTest.java  |  49 +-
 .../directory/server/xdbm/PartitionTest.java       |  49 +-
 .../apache/directory/server/xdbm/StoreUtils.java   | 112 ++-
 .../server/xdbm/impl/avl/AvlPartitionTest.java     |  33 +-
 .../server/xdbm/search/impl/AndCursorTest.java     |   2 +
 .../server/xdbm/search/impl/EqualityTest.java      |  29 +-
 .../xdbm/search/impl/FilterNormalizingVisitor.java |  46 +-
 ...terEqTest.java => GreaterEqNotIndexedTest.java} | 325 +-------
 .../server/xdbm/search/impl/GreaterEqTest.java     |  50 +-
 .../server/xdbm/search/impl/LessEqTest.java        |  53 +-
 .../server/xdbm/search/impl/NestedFilterTest.java  |   2 +
 .../server/xdbm/search/impl/NotCursorTest.java     |   2 +
 .../server/xdbm/search/impl/OrCursorTest.java      |   2 +
 .../server/xdbm/search/impl/PresenceTest.java      |  23 +-
 .../server/xdbm/search/impl/SubstringTest.java     | 121 +--
 405 files changed, 11461 insertions(+), 4794 deletions(-)

diff --cc core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java
index 74cf1db,57b444c..9d7f5a9
--- a/core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/LdapCoreSessionConnection.java
@@@ -1206,10 -1294,17 +1294,17 @@@ public class LdapCoreSessionConnection 
  
          int newId = messageId.incrementAndGet();
  
 -        BindOperationContext bindContext = new BindOperationContext( null );
 +        BindOperationContext bindContext = new BindOperationContext( directoryService, null );
          bindContext.setCredentials( bindRequest.getCredentials() );
  
-         bindContext.setDn( bindRequest.getDn().apply( directoryService.getSchemaManager() ) );
+         Dn bindDn =  bindRequest.getDn();
+         
+         if ( !bindDn.isSchemaAware() )
+         {
+             bindDn = new Dn( directoryService.getSchemaManager(), bindDn );
+         }
+         
+         bindContext.setDn( bindDn );
          bindContext.setInterceptors( directoryService.getInterceptors( OperationEnum.BIND ) );
  
          for ( Control control : bindRequest.getControls().values() )
diff --cc core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
index 5237313,9300d79..845715b
--- a/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
+++ b/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
@@@ -994,9 -993,17 +993,18 @@@ public class DefaultDirectoryService im
          }
  
          BindOperationContext bindContext = new BindOperationContext( null );
 +        bindContext.setTransaction( partitionNexus.beginReadTransaction() );
          bindContext.setCredentials( credentials );
-         bindContext.setDn( principalDn.apply( schemaManager ) );
+         
+         if ( principalDn.isSchemaAware() )
+         {
+             bindContext.setDn( principalDn );
+         }
+         else
+         {
+             bindContext.setDn( new Dn( schemaManager, principalDn ) );
+         }
+         
          bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
  
          operationManager.bind( bindContext );
@@@ -1021,9 -1028,17 +1029,18 @@@
          }
  
          BindOperationContext bindContext = new BindOperationContext( null );
 +        bindContext.setTransaction( partitionNexus.beginReadTransaction() );
          bindContext.setCredentials( credentials );
-         bindContext.setDn( principalDn.apply( schemaManager ) );
+ 
+         if ( principalDn.isSchemaAware() )
+         {
+             bindContext.setDn( principalDn );
+         }
+         else
+         {
+             bindContext.setDn( new Dn( schemaManager, principalDn ) );
+         }
+ 
          bindContext.setSaslMechanism( saslMechanism );
          bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
  
diff --cc protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/request/BindRequestHandler.java
index 7192302,47e5276..43587ee
--- 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
@@@ -108,9 -108,26 +108,27 @@@ public class BindRequestHandler extend
          // create a new Bind context, with a null session, as we don't have 
          // any context yet.
          BindOperationContext bindContext = new BindOperationContext( null );
 +        bindContext.setTransaction( ldapServer.getDirectoryService().getPartitionNexus().beginReadTransaction() );
  
          // Stores the Dn of the user to check, and its password
+         Dn bindDn = bindRequest.getDn();
+         
+         if ( bindDn == null )
+         {
+             String name = bindRequest.getName();
+             
+             try
+             {
+                 bindDn = new Dn( directoryService.getSchemaManager(), name );
+                 bindRequest.setDn( bindDn );
+             }
+             catch ( LdapInvalidDnException e )
+             {
+                 // This might still be a valid DN (Windows AD binding for instance)
+                 LOG.debug( "Unable to convert the name to a DN." );
+             }
+         }
+         
          bindContext.setDn( bindRequest.getDn() );
          bindContext.setCredentials( bindRequest.getCredentials() );
          bindContext.setIoSession( ldapSession.getIoSession() );

-- 
To stop receiving notification emails like this one, please contact
elecharny@apache.org.

[directory-server] 01/05: o Added a test for PersisteSearch that uses the LDAP API o Fixed a typo

Posted by el...@apache.org.
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

commit b18ea82d406519a8ba75db9bc06519d31a643ff1
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Fri Dec 29 00:52:41 2017 +0100

    o Added a test for PersisteSearch that uses the LDAP API
    o Fixed a typo
---
 .../{PagedSearchIT.java => PagedSearchApiIT.java}  | 806 +++++++++++----------
 .../server/operations/search/PagedSearchIT.java    |   2 +-
 2 files changed, 431 insertions(+), 377 deletions(-)

diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java
similarity index 51%
copy from server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
copy to server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java
index bc012de..94e0a0f 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchApiIT.java
@@ -20,30 +20,26 @@
 package org.apache.directory.server.operations.search;
 
 
-import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.SizeLimitExceededException;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.naming.ldap.LdapContext;
-import javax.naming.ldap.PagedResultsResponseControl;
-
 import org.apache.directory.api.asn1.EncoderException;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsDecorator;
+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;
 import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.message.SearchRequest;
@@ -51,11 +47,13 @@ import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
 import org.apache.directory.api.ldap.model.message.SearchResultDone;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.message.controls.PagedResults;
+import org.apache.directory.api.ldap.model.message.controls.PagedResultsImpl;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.util.JndiUtils;
 import org.apache.directory.api.util.Network;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.EntryCursorImpl;
+import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.server.annotations.CreateLdapServer;
 import org.apache.directory.server.annotations.CreateTransport;
@@ -70,7 +68,7 @@ import org.junit.runner.RunWith;
 /**
  * Test the PagedSearchControl. The following tables covers all the
  * possible cases for both an admin and a simple user, combining the
- * Server SizeLimit (SL), the requested SizeLimit (SL) and the paged
+ * Server SizeLimit (SL), the request SizeLimit (RL) and the paged
  * size limit (PL). The 'X' column tells if we are supposed to receive
  * a SizeLimitExceededException.<br>
  * <br>
@@ -111,15 +109,13 @@ import org.junit.runner.RunWith;
  * |test23 | 0  | 9  | 5  | 2 ( 5 + 4 )         | 9  | Y |<br>
  * |test24 | 5  | 0  | 5  | 1 ( 5 )             | 5  | Y |<br>
  * |test25 | 0  | 5  | 5  | 1 ( 5 )             | 5  | Y |<br>
- * |test26 | 5  | 4  | 3  | 2 ( 3 + 1 )         | 4  | Y |<br>
- * |test27 | 4  | 5  | 3  | 2 ( 3 + 1 )         | 4  | Y |<br>
- * |test28 | 5  | 3  | 4  | 1 ( 3 )             | 3  | Y |<br>
- * |test29 | 5  | 4  | 3  | 2 ( 3 + 1 )         | 4  | Y |<br>
- * |test30 | 4  | 5  | 3  | 2 ( 3 + 1 )         | 4  | Y |<br>
- * |test31 | 4  | 3  | 5  | 1 ( 3 )             | 3  | Y |<br>
- * |test32 | 3  | 5  | 4  | 1 ( 3 )             | 3  | Y |<br>
- * |test33 | 3  | 4  | 5  | 1 ( 3 )             | 3  | Y |<br>
- * |test34 | 5  | 5  | 5  | 1 ( 5 )             | 5  | Y |<br>
+ * |test26 | 5  | 3  | 4  | 1 ( 3 )             | 3  | Y |<br>
+ * |test27 | 5  | 4  | 3  | 2 ( 3 + 1 )         | 4  | Y |<br>
+ * |test28 | 4  | 5  | 3  | 2 ( 3 + 1 )         | 4  | Y |<br>
+ * |test29 | 4  | 3  | 5  | 1 ( 3 )             | 3  | Y |<br>
+ * |test30 | 3  | 5  | 4  | 1 ( 3 )             | 3  | Y |<br>
+ * |test31 | 3  | 4  | 5  | 1 ( 3 )             | 3  | Y |<br>
+ * |test32 | 5  | 5  | 5  | 1 ( 5 )             | 5  | Y |<br>
  * +-------+----+----+----+---------------------+----+---+<br>
  *</pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
@@ -205,52 +201,18 @@ import org.junit.runner.RunWith;
         "cn: user",
         "userPassword: secret",
         "sn: user" })
-public class PagedSearchIT extends AbstractLdapTestUnit
+public class PagedSearchApiIT extends AbstractLdapTestUnit
 {
     private LdapApiService codec = LdapApiServiceFactory.getSingleton();
 
 
     /**
-     * Create the searchControls with a paged size
-     * @throws EncoderException on codec failures
-     */
-    private SearchControls createSearchControls( DirContext ctx, int sizeLimit, int pagedSize )
-        throws NamingException, EncoderException
-    {
-        SearchControls controls = new SearchControls();
-        controls.setCountLimit( sizeLimit );
-        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        PagedResultsDecorator pagedSearchControl = new PagedResultsDecorator( codec );
-        pagedSearchControl.setSize( pagedSize );
-
-        ( ( LdapContext ) ctx ).setRequestControls( JndiUtils.toJndiControls( codec, new Control[]
-            { pagedSearchControl } ) );
-
-        return controls;
-    }
-
-
-    /**
-     * Create the searchControls with a paged size
-     * @throws EncoderException on codec failures
-     */
-    private void createNextSearchControls( DirContext ctx, byte[] cookie, int pagedSize )
-        throws NamingException, EncoderException
-    {
-        PagedResultsDecorator pagedSearchControl = new PagedResultsDecorator( codec );
-        pagedSearchControl.setCookie( cookie );
-        pagedSearchControl.setSize( pagedSize );
-        ( ( LdapContext ) ctx ).setRequestControls( JndiUtils.toJndiControls( codec, new Control[]
-            { pagedSearchControl } ) );
-    }
-
-
-    /**
      * Check that we got the correct result set
+     * @throws LdapInvalidAttributeValueException 
      */
-    private void checkResults( List<SearchResult> results, int expectedSize ) throws NamingException
+    private void checkResults( List<Entry> entries, int expectedSize ) throws LdapInvalidAttributeValueException
     {
-        assertEquals( expectedSize, results.size() );
+        assertEquals( expectedSize, entries.size() );
         Set<String> expected = new HashSet<String>();
 
         for ( int i = 0; i < 10; i++ )
@@ -261,8 +223,8 @@ public class PagedSearchIT extends AbstractLdapTestUnit
         // check that we have correctly read all the entries
         for ( int i = 0; i < expectedSize; i++ )
         {
-            SearchResult entry = results.get( i );
-            String user = ( String ) entry.getAttributes().get( "cn" ).get();
+            Entry entry = entries.get( i );
+            String user = ( String ) entry.get( "cn" ).getString();
             assertTrue( expected.contains( user ) );
 
             expected.remove( user );
@@ -277,89 +239,65 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * reach a limit. It will check that we have got all the expected entries.
      * @throws EncoderException  on codec failures
      */
-    private void doLoop( DirContext ctx, SearchControls controls, int pagedSizeLimit,
-        int expectedLoop, int expectedNbEntries, boolean expectedException ) throws NamingException, EncoderException
+    private void doLoop( LdapConnection connection, long searchLimit, int pagedSizeLimit, 
+        int expectedLoop, int expectedNbEntries, boolean expectedException ) throws LdapException, IOException, CursorException
     {
         // Loop over all the elements
         int loop = 0;
         boolean hasSizeLimitException = false;
-        List<SearchResult> results = new ArrayList<SearchResult>();
+        List<Entry> results = new ArrayList<>();
+
+        SearchRequest searchRequest = new SearchRequestImpl();
+        searchRequest.setBase( new Dn( "dc=users,ou=system" ) );
+        searchRequest.setFilter( "(cn=*)" );
+        searchRequest.setScope( SearchScope.SUBTREE );
+        searchRequest.setSizeLimit( searchLimit );
+
+        PagedResults pagedControl = new PagedResultsImpl();
+        pagedControl.setSize( pagedSizeLimit );
 
         while ( true )
         {
             loop++;
-            NamingEnumeration<SearchResult> list = null;
+            searchRequest.addControl( pagedControl );
 
-            try
+            try ( SearchCursor cursor = connection.search( searchRequest ) )
             {
-                list = ctx.search( "dc=users,ou=system", "(cn=*)", controls );
-
-                while ( list.hasMore() )
+                while ( cursor.next() )
                 {
-                    SearchResult result = list.next();
+                    Entry result = cursor.getEntry();
                     results.add( result );
                 }
-            }
-            catch ( SizeLimitExceededException e )
-            {
-                hasSizeLimitException = true;
-                break;
-            }
-            finally
-            {
-                // Close the NamingEnumeration
-                if ( list != null )
-                {
-                    list.close();
-                }
-            }
-
-            // Now read the next ones
-            javax.naming.ldap.Control[] responseControls = ( ( LdapContext ) ctx ).getResponseControls();
 
-            PagedResultsResponseControl responseControl =
-                ( PagedResultsResponseControl ) responseControls[0];
-            assertEquals( 0, responseControl.getResultSize() );
+                // Now read the next ones
+                Map<String, Control> controls =  cursor.getSearchResultDone().getControls();
 
-            // check if this is over
-            byte[] cookie = responseControl.getCookie();
-
-            if ( Strings.isEmpty( cookie ) )
-            {
-                // If so, exit the loop
-                break;
+                if ( cursor.getSearchResultDone().getLdapResult().getResultCode() == ResultCodeEnum.SIZE_LIMIT_EXCEEDED )
+                {
+                    hasSizeLimitException = true;
+                    
+                    break;
+                }
+                
+                PagedResults responseControl = ( PagedResults ) controls.get( PagedResults.OID );
+                assertEquals( 0, responseControl.getSize() );
+
+                // check if this is over
+                byte[] cookie = responseControl.getCookie();
+            
+                if ( Strings.isEmpty( cookie ) )
+                {
+                    // If so, exit the loop
+                    break;
+                }
+                
+                // Prepare the next iteration
+                pagedControl.setCookie( cookie );
             }
-
-            // Prepare the next iteration
-            createNextSearchControls( ctx, responseControl.getCookie(), pagedSizeLimit );
         }
 
         assertEquals( expectedException, hasSizeLimitException );
         assertEquals( expectedLoop, loop );
-        checkResults( results, expectedNbEntries );
-
-        // And close the connection
-        closeConnection( ctx );
-    }
-
-
-    /**
-     * Close a connection, and wait a bit to be sure it's done
-     */
-    private void closeConnection( DirContext ctx ) throws NamingException
-    {
-        if ( ctx != null )
-        {
-            ctx.close();
-
-            try
-            {
-                Thread.sleep( 10 );
-            }
-            catch ( Exception e )
-            {
-            }
-        }
     }
 
 
@@ -375,10 +313,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest1() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 3 );
 
-        doLoop( ctx, controls, 3, 4, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 3, 4, 10, false );
+        }
     }
 
 
@@ -394,10 +335,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest2() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 5 );
 
-        doLoop( ctx, controls, 5, 2, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 5, 2, 10, false );
+        }
     }
 
 
@@ -413,10 +357,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest3() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 3 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 5 );
 
-        doLoop( ctx, controls, 5, 2, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 5, 2, 10, false );
+        }
     }
 
 
@@ -432,10 +379,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest4() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 3, 5 );
 
-        doLoop( ctx, controls, 5, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 3L, 5, 1, 3, true );
+        }
     }
 
 
@@ -451,10 +401,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest5() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 3 );
 
-        doLoop( ctx, controls, 3, 4, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 3, 4, 10, false );
+        }
     }
 
 
@@ -470,10 +423,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest6() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 9, 5 );
 
-        doLoop( ctx, controls, 5, 2, 9, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 9L, 5, 2, 9, true );
+        }
     }
 
 
@@ -489,10 +445,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest7() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 5 );
 
-        doLoop( ctx, controls, 5, 2, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 5, 2, 10, false );
+        }
     }
 
 
@@ -508,10 +467,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest8() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 5, 5 );
 
-        doLoop( ctx, controls, 5, 1, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 5, 1, 5, true );
+        }
     }
 
 
@@ -527,10 +489,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest9() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 4, 3 );
 
-        doLoop( ctx, controls, 3, 2, 4, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 4L, 3, 2, 4, true );
+        }
     }
 
 
@@ -546,10 +511,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest10() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 4 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 5, 3 );
 
-        doLoop( ctx, controls, 3, 2, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 3, 2, 5, true );
+        }
     }
 
 
@@ -565,10 +533,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest11() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 3, 4 );
 
-        doLoop( ctx, controls, 4, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 3L, 4, 1, 3, true );
+        }
     }
 
 
@@ -584,10 +555,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest12() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 4, 3 );
 
-        doLoop( ctx, controls, 3, 2, 4, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 4L, 3, 2, 4, true );
+        }
     }
 
 
@@ -603,10 +577,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest13() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 4 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 5, 3 );
 
-        doLoop( ctx, controls, 3, 2, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 3, 2, 5, true );
+        }
     }
 
 
@@ -622,10 +599,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest14() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 4 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 3, 5 );
 
-        doLoop( ctx, controls, 5, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 3L, 5, 1, 3, true );
+        }
     }
 
 
@@ -641,10 +621,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest15() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 3 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 5, 4 );
 
-        doLoop( ctx, controls, 4, 2, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 4, 2, 5, true );
+        }
     }
 
 
@@ -660,10 +643,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest16() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 3 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 4, 5 );
 
-        doLoop( ctx, controls, 5, 1, 4, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 4L, 5, 1, 4, true );
+        }
     }
 
 
@@ -679,10 +665,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest17() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer() );
-        SearchControls controls = createSearchControls( ctx, 5, 5 );
 
-        doLoop( ctx, controls, 5, 1, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "uid=admin,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 5, 1, 5, true );
+        }
     }
 
 
@@ -698,10 +687,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest18() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 3 );
 
-        doLoop( ctx, controls, 3, 4, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 3, 4, 10, false );
+        }
     }
 
 
@@ -717,10 +709,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest19() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 5 );
 
-        doLoop( ctx, controls, 5, 2, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 5, 2, 10, false );
+        }
     }
 
 
@@ -736,10 +731,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest20() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 3 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 5 );
 
-        doLoop( ctx, controls, 5, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 5, 1, 3, true );
+        }
     }
 
 
@@ -755,10 +753,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest21() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 3, 5 );
 
-        doLoop( ctx, controls, 5, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 3L, 5, 1, 3, true );
+        }
     }
 
 
@@ -774,10 +775,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest22() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 3 );
 
-        doLoop( ctx, controls, 3, 2, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 3, 2, 5, true );
+        }
     }
 
 
@@ -793,10 +797,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest23() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 9, 5 );
 
-        doLoop( ctx, controls, 5, 2, 9, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 9L, 5, 2, 9, true );
+        }
     }
 
 
@@ -812,10 +819,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchtest24() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 5 );
 
-        doLoop( ctx, controls, 5, 1, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, 5, 1, 5, true );
+        }
     }
 
 
@@ -831,48 +841,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchTest25() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 5, 5 );
-
-        doLoop( ctx, controls, 5, 1, 5, true );
-    }
-
 
-    /**
-     * Admin = no <br>
-     * SL = 5<br>
-     * RL = 4<br>
-     * PL = 3<br>
-     * expected exception : yes<br>
-     * expected number of entries returned : 2 ( 3 + 1 )<br>
-     */
-    @Test
-    public void testPagedSearchTest26() throws Exception
-    {
-        getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 4, 3 );
-
-        doLoop( ctx, controls, 3, 2, 4, true );
-    }
-
-
-    /**
-     * Admin = no <br>
-     * SL = 4<br>
-     * RL = 5<br>
-     * PL = 3<br>
-     * expected exception : yes<br>
-     * expected number of entries returned : 4 ( 3 + 1 )<br>
-     */
-    @Test
-    public void testPagedSearchtest27() throws Exception
-    {
-        getLdapServer().setMaxSizeLimit( 4 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 5, 3 );
-
-        doLoop( ctx, controls, 3, 2, 4, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 5, 1, 5, true );
+        }
     }
 
 
@@ -885,13 +860,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 3<br>
      */
     @Test
-    public void testPagedSearchtest28() throws Exception
+    public void testPagedSearchtest26() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 3, 4 );
 
-        doLoop( ctx, controls, 4, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 3L, 4, 1, 3, true );
+        }
     }
 
 
@@ -904,13 +882,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 4 ( 3 + 1 )<br>
      */
     @Test
-    public void testPagedSearchtest29() throws Exception
+    public void testPagedSearchtest27() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 4, 3 );
 
-        doLoop( ctx, controls, 3, 2, 4, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 4L, 3, 2, 4, true );
+        }
     }
 
 
@@ -923,13 +904,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 4 ( 3 + 1 )<br>
      */
     @Test
-    public void testPagedSearchtest30() throws Exception
+    public void testPagedSearchtest28() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 4 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 5, 3 );
 
-        doLoop( ctx, controls, 3, 2, 4, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 3, 2, 4, true );
+        }
     }
 
 
@@ -942,13 +926,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 3 <br>
      */
     @Test
-    public void testPagedSearchtest31() throws Exception
+    public void testPagedSearchtest29() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 4 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 3, 5 );
 
-        doLoop( ctx, controls, 3, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 3L, 5, 1, 3, true );
+        }
     }
 
 
@@ -961,13 +948,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 3 <br>
      */
     @Test
-    public void testPagedSearchtest32() throws Exception
+    public void testPagedSearchtest30() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 3 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 5, 4 );
 
-        doLoop( ctx, controls, 3, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 4, 1, 3, true );
+        }
     }
 
 
@@ -980,13 +970,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 3 <br>
      */
     @Test
-    public void testPagedSearchtest33() throws Exception
+    public void testPagedSearchtest31() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 3 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 4, 5 );
 
-        doLoop( ctx, controls, 3, 1, 3, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 4L, 5, 1, 3, true );
+        }
     }
 
 
@@ -999,13 +992,16 @@ public class PagedSearchIT extends AbstractLdapTestUnit
      * expected number of entries returned : 5 <br>
      */
     @Test
-    public void testPagedSearchtest34() throws Exception
+    public void testPagedSearchtest32() throws Exception
     {
         getLdapServer().setMaxSizeLimit( 5 );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, 5, 5 );
 
-        doLoop( ctx, controls, 5, 1, 5, true );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+            
+            doLoop( connection, 5L, 5, 1, 5, true );
+        }
     }
 
 
@@ -1021,10 +1017,13 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchWithNegativePL() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, -2 );
 
-        doLoop( ctx, controls, -2, 1, 10, false );
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+    
+            doLoop( connection, LdapServer.NO_SIZE_LIMIT, -2, 1, 10, false );
+        }
     }
 
 
@@ -1034,85 +1033,131 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     @Test
     public void testPagedSearchWrongCookie() throws Exception
     {
-        LdapNetworkConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() );
-        connection.bind( "uid=admin,ou=system", "secret" );
-
-        SearchControls controls = new SearchControls();
-        controls.setCountLimit( ( int ) LdapServer.NO_SIZE_LIMIT );
-        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        PagedResults pagedSearchControl = new PagedResultsDecorator( codec );
-        pagedSearchControl.setSize( 3 );
-
-        // Loop over all the elements
-        int loop = 0;
-        List<Entry> results = new ArrayList<Entry>();
-        boolean hasUnwillingToPerform = false;
-
-        while ( true )
+        try ( LdapNetworkConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
         {
-            loop++;
-
-            EntryCursor cursor = null;
-
-            try
+            connection.bind( "uid=admin,ou=system", "secret" );
+    
+            PagedResults pagedSearchControl = new PagedResultsDecorator( codec );
+            pagedSearchControl.setSize( 3 );
+    
+            SearchRequest searchRequest = new SearchRequestImpl();
+            searchRequest.setBase( new Dn( "ou=system" ) );
+            searchRequest.setFilter( "(ObjectClass=*)" );
+            searchRequest.setScope( SearchScope.SUBTREE );
+            searchRequest.addAttributes( "*" );
+    
+            // Loop over all the elements
+            List<Entry> results = new ArrayList<>();
+            boolean hasUnwillingToPerform = false;
+    
+            while ( true )
             {
-                SearchRequest searchRequest = new SearchRequestImpl();
-                searchRequest.setBase( new Dn( "ou=system" ) );
-                searchRequest.setFilter( "(ObjectClass=*)" );
-                searchRequest.setScope( SearchScope.SUBTREE );
-                searchRequest.addAttributes( "*" );
                 searchRequest.addControl( pagedSearchControl );
 
-                cursor = new EntryCursorImpl( connection.search( searchRequest ) );
-
-                int i = 0;
-
-                while ( cursor.next() )
+                try ( EntryCursor cursor = new EntryCursorImpl( connection.search( searchRequest ) ) )
                 {
-                    Entry result = cursor.get();
-                    results.add( result );
-                    ++i;
+    
+                    while ( cursor.next() )
+                    {
+                        Entry result = cursor.get();
+                        results.add( result );
+                    }
+    
+                    SearchResultDone result = cursor.getSearchResultDone();
+                    pagedSearchControl = ( PagedResults ) result.getControl( PagedResults.OID );
+    
+                    if ( result.getLdapResult().getResultCode() == ResultCodeEnum.UNWILLING_TO_PERFORM )
+                    {
+                        hasUnwillingToPerform = true;
+                        
+                        break;
+                    }
                 }
-
-                SearchResultDone result = cursor.getSearchResultDone();
-                pagedSearchControl = ( PagedResults ) result.getControl( PagedResults.OID );
-
-                if ( result.getLdapResult().getResultCode() == ResultCodeEnum.UNWILLING_TO_PERFORM )
+    
+                // Now read the next ones
+                assertEquals( 0, pagedSearchControl.getSize() );
+    
+                // check if this is over
+                byte[] cookie = pagedSearchControl.getCookie();
+    
+                if ( Strings.isEmpty( cookie ) )
                 {
-                    hasUnwillingToPerform = true;
+                    // If so, exit the loop
                     break;
                 }
+    
+                // Prepare the next iteration, sending a bad cookie
+                pagedSearchControl.setCookie( "test".getBytes( "UTF-8" ) );
+                pagedSearchControl.setSize( 3 );
             }
-            finally
-            {
-                if ( cursor != null )
-                {
-                    cursor.close();
-                }
-            }
-
-            // Now read the next ones
-            assertEquals( 0, pagedSearchControl.getSize() );
+    
+            assertTrue( hasUnwillingToPerform );
+        }
+    }
 
-            // check if this is over
-            byte[] cookie = pagedSearchControl.getCookie();
 
-            if ( Strings.isEmpty( cookie ) )
+    /**
+     * Do a test with a paged search, reading all the entries
+     */
+    @Test
+    public void testPagedSearchAll() throws Exception
+    {
+        getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
+        
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
+        {
+            connection.bind( "cn=user,ou=system", "secret" );
+
+            // Create the control, and tell it we want 4 entries for every call
+            PagedResults pagedControl = new PagedResultsImpl();
+            pagedControl.setSize( 4 );
+        
+            // Read all the elements
+            List<Entry> results = new ArrayList<>();
+
+            // Create the SearchRequest
+            SearchRequest searchRequest = new SearchRequestImpl();
+            searchRequest.setBase( new Dn( "dc=users,ou=system" ) );
+            searchRequest.setFilter( "(cn=*)" );
+            searchRequest.setScope( SearchScope.SUBTREE );
+        
+            while ( true )
             {
-                // If so, exit the loop
-                break;
+                // Add the PagedSearch control to teh SearchRequest
+                searchRequest.addControl( pagedControl );
+                    
+                // Do the search now
+                try ( SearchCursor cursor = connection.search( searchRequest ) )
+                {
+                    // Loop on all teh entries we got back (Should be 4, or less)
+                    while ( cursor.next() )
+                    {
+                        Entry result = cursor.getEntry();
+                        results.add( result );
+                    }
+            
+                    // Now check the returned controls
+                    Map<String, Control> controls =  cursor.getSearchResultDone().getControls();
+    
+                    // We should get a PagedResult response
+                    PagedResults responseControl = ( PagedResults ) controls.get( PagedResults.OID );
+    
+                    // check if this is over, ie teh cookie is empty
+                    byte[] cookie = responseControl.getCookie();
+                    
+                    if ( Strings.isEmpty( cookie ) )
+                    {
+                        // Ok, we are done
+                        break;
+                    }
+    
+                    // Prepare the next iteration, sending a bad cookie
+                    pagedControl.setCookie( cookie );
+                }
             }
-
-            // Prepare the next iteration, sending a bad cookie
-            pagedSearchControl.setCookie( "test".getBytes( "UTF-8" ) );
-            pagedSearchControl.setSize( 3 );
+            
+            assertEquals( 10, results.size() );
         }
-
-        assertTrue( hasUnwillingToPerform );
-
-        // Cleanup the session
-        connection.unBind();
-        connection.close();
     }
 
 
@@ -1124,55 +1169,64 @@ public class PagedSearchIT extends AbstractLdapTestUnit
     public void testPagedSearchModifyingPagedLimit() throws Exception
     {
         getLdapServer().setMaxSizeLimit( LdapServer.NO_SIZE_LIMIT );
-        DirContext ctx = getWiredContext( getLdapServer(), "cn=user,ou=system", "secret" );
-        SearchControls controls = createSearchControls( ctx, ( int ) LdapServer.NO_SIZE_LIMIT, 4 );
-
-        // Loop over all the elements
-        int loop = 0;
-        List<SearchResult> results = new ArrayList<SearchResult>();
-
-        // The expected size after each loop.
-        int[] expectedSize = new int[]
-            { 4, 7, 9, 10 };
-
-        while ( true )
+        
+        try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) )
         {
-            loop++;
-
-            NamingEnumeration<SearchResult> list =
-                ctx.search( "dc=users,ou=system", "(cn=*)", controls );
-
-            while ( list.hasMore() )
+            connection.bind( "cn=user,ou=system", "secret" );
+            PagedResults pagedControl = new PagedResultsImpl();
+            pagedControl.setSize( 4 );
+    
+            // Loop over all the elements
+            int loop = 0;
+            List<Entry> results = new ArrayList<>();
+    
+            // The expected size after each loop.
+            int[] expectedSize = new int[] { 4, 7, 9, 10 };
+            SearchRequest searchRequest = new SearchRequestImpl();
+            searchRequest.setBase( new Dn( "dc=users,ou=system" ) );
+            searchRequest.setFilter( "(cn=*)" );
+            searchRequest.setScope( SearchScope.SUBTREE );
+    
+            while ( true )
             {
-                SearchResult result = list.next();
-                results.add( result );
-            }
-
-            list.close();
-
-            // Now read the next ones
-            javax.naming.ldap.Control[] responseControls = ( ( LdapContext ) ctx ).getResponseControls();
-
-            PagedResultsResponseControl responseControl =
-                ( PagedResultsResponseControl ) responseControls[0];
-            assertEquals( 0, responseControl.getResultSize() );
-
-            // check if this is over
-            byte[] cookie = responseControl.getCookie();
+                loop++;
+    
+                searchRequest.addControl( pagedControl );
+                
+                try ( SearchCursor cursor = connection.search( searchRequest ) )
+                {
+                    while ( cursor.next() )
+                    {
+                        Entry result = cursor.getEntry();
+                        results.add( result );
+                    }
+        
+                    // Now read the next ones
+                    Map<String, Control> controls =  cursor.getSearchResultDone().getControls();
+    
+                    PagedResults responseControl = ( PagedResults ) controls.get( PagedResults.OID );
+                    assertEquals( 0, responseControl.getSize() );
+    
+                    // check if this is over
+                    byte[] cookie = responseControl.getCookie();
+                
+                    if ( Strings.isEmpty( cookie ) )
+                    {
+                        // If so, exit the loop
+                        break;
+                    }
+        
+                    // Prepare the next iteration, sending a bad cookie
+                    pagedControl.setSize( 4 - loop );
+                    pagedControl.setCookie( cookie );
 
-            if ( Strings.isEmpty( cookie ) )
-            {
-                // If so, exit the loop
-                break;
+                }
+    
+                assertEquals( expectedSize[loop - 1], results.size() );
             }
-
-            // Prepare the next iteration, sending a bad cookie
-            createNextSearchControls( ctx, responseControl.getCookie(), 4 - loop );
-
-            assertEquals( expectedSize[loop - 1], results.size() );
+    
+            assertEquals( 4, loop );
+            checkResults( results, 10 );
         }
-
-        assertEquals( 4, loop );
-        checkResults( results, 10 );
     }
 }
\ No newline at end of file
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
index bc012de..c28ea18 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
@@ -70,7 +70,7 @@ import org.junit.runner.RunWith;
 /**
  * Test the PagedSearchControl. The following tables covers all the
  * possible cases for both an admin and a simple user, combining the
- * Server SizeLimit (SL), the requested SizeLimit (SL) and the paged
+ * Server SizeLimit (SL), the requested SizeLimit (RL) and the paged
  * size limit (PL). The 'X' column tells if we are supposed to receive
  * a SizeLimitExceededException.<br>
  * <br>

-- 
To stop receiving notification emails like this one, please contact
elecharny@apache.org.