You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2013/05/14 05:09:54 UTC

svn commit: r1482179 [1/3] - in /directory/apacheds/trunk/mavibot-partition: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/server/ src/main/java/org/...

Author: kayyagari
Date: Tue May 14 03:09:53 2013
New Revision: 1482179

URL: http://svn.apache.org/r1482179
Log:
mavibot based partition implementation

Added:
    directory/apacheds/trunk/mavibot-partition/
    directory/apacheds/trunk/mavibot-partition/pom.xml
    directory/apacheds/trunk/mavibot-partition/src/
    directory/apacheds/trunk/mavibot-partition/src/main/
    directory/apacheds/trunk/mavibot-partition/src/main/java/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleArrayCursor.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotRdnIndex.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotTable.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/ValueTreeCursor.java
    directory/apacheds/trunk/mavibot-partition/src/test/
    directory/apacheds/trunk/mavibot-partition/src/test/java/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/mavibot/
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializationTest.java
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndexTest.java
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTableTest.java
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotRdnIndexTest.java
    directory/apacheds/trunk/mavibot-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotStoreTest.java

Added: directory/apacheds/trunk/mavibot-partition/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/pom.xml?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/pom.xml (added)
+++ directory/apacheds/trunk/mavibot-partition/pom.xml Tue May 14 03:09:53 2013
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.directory.server</groupId>
+    <artifactId>apacheds-parent</artifactId>
+    <version>2.0.0-M13-SNAPSHOT</version>
+  </parent>
+  <artifactId>apacheds-mavibot-partition</artifactId>
+  <name>ApacheDS Mavibot Partition</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.directory.junit</groupId>
+      <artifactId>junit-addons</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.labs.mavibot</groupId>
+      <artifactId>apache-mavibot</artifactId>
+      <version>1.0.0-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-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>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </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>
+</project>

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/DnSerializer.java Tue May 14 03:09:53 2013
@@ -0,0 +1,154 @@
+/*
+ *  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.server.i18n.I18n;
+import org.apache.mavibot.btree.serializer.AbstractElementSerializer;
+import org.apache.mavibot.btree.serializer.BufferHandler;
+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 dn0, Dn dn1 )
+        {
+            if ( dn0.equals( dn1 ) )
+            {
+                return 0;
+            }
+            else
+            {
+                return -1;
+            }
+        }
+    };
+
+
+    /**
+     * 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() );
+        }
+    }
+
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleArrayCursor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleArrayCursor.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleArrayCursor.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/KeyTupleArrayCursor.java Tue May 14 03:09:53 2013
@@ -0,0 +1,310 @@
+/*
+ * 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.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.server.i18n.I18n;
+import org.apache.mavibot.btree.BTree;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 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 KeyTupleArrayCursor<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 final org.apache.mavibot.btree.Cursor<V,V> wrapped;
+    private final K key;
+
+    private Tuple<K, V> returnedTuple = new Tuple<K, V>();
+    private boolean valueAvailable;
+
+
+    /**
+     * Creates a Cursor over the tuples of an ArrayTree.
+     *
+     * @param arrayTree the ArrayTree to build a Tuple returning Cursor over
+     * @param key the constant key for which values are returned
+     */
+    public KeyTupleArrayCursor( BTree<V,V> arrayTree, K key )
+    {
+        this.key = key;
+        
+        try
+        {
+            this.wrapped = arrayTree.browse();
+        }
+        catch( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+        
+        if ( IS_DEBUG )
+        {
+            LOG_CURSOR.debug( "Creating KeyTupleArrayCursor {}", this );
+        }
+    }
+
+
+    private void clearValue()
+    {
+        returnedTuple.setKey( key );
+        returnedTuple.setValue( null );
+        valueAvailable = false;
+    }
+
+
+    public boolean available()
+    {
+        return valueAvailable;
+    }
+
+
+    public void beforeKey( K key ) throws Exception
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    public void afterKey( K key ) throws Exception
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    public void beforeValue( K key, V value ) throws Exception
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    public void afterValue( K key, V value ) throws Exception
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    /**
+     * Positions this Cursor over the same keys before the value of the
+     * 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, IOException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void after( Tuple<K, V> element ) throws LdapException, CursorException, IOException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void beforeFirst() throws LdapException, CursorException, IOException
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void afterLast() throws LdapException, CursorException, IOException
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean first() throws LdapException, CursorException, IOException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean last() throws LdapException, CursorException, IOException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean previous() throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "previous()" );
+        if ( wrapped.hasPrev() )
+        {
+            org.apache.mavibot.btree.Tuple<V, V> t = wrapped.prev();
+            returnedTuple.setKey( key );
+            returnedTuple.setValue( t.getKey() );
+            return valueAvailable = true;
+        }
+        else
+        {
+            clearValue();
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean next() throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "next()" );
+        if ( wrapped.hasNext() )
+        {
+            org.apache.mavibot.btree.Tuple<V, V> t = wrapped.next();
+            returnedTuple.setKey( key );
+            returnedTuple.setValue( t.getKey() );
+            return valueAvailable = true;
+        }
+        else
+        {
+            clearValue();
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Tuple<K, V> get() throws CursorException, IOException
+    {
+        checkNotClosed( "get()" );
+
+        if ( valueAvailable )
+        {
+            return returnedTuple;
+        }
+
+        throw new InvalidCursorPositionException();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void close()
+    {
+        if ( IS_DEBUG )
+        {
+            LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
+        }
+
+        if ( wrapped != null )
+        {
+            wrapped.close();
+        }
+
+        super.close();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void close( Exception reason )
+    {
+        if ( IS_DEBUG )
+        {
+            LOG_CURSOR.debug( "Closing KeyTupleArrayCursor {}", this );
+        }
+
+        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( "" );
+    }
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotCursor.java Tue May 14 03:09:53 2013
@@ -0,0 +1,281 @@
+/*
+ * 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.cursor.InvalidCursorPositionException;
+import org.apache.directory.api.ldap.model.cursor.Tuple;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.server.i18n.I18n;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Cursor over the Tuples of a Mavibot BTree.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class MavibotCursor<K, V> extends AbstractCursor<Tuple<K, V>>
+{
+    /** A dedicated log for cursors */
+    private static final Logger LOG_CURSOR = LoggerFactory.getLogger( "CURSOR" );
+
+    private final MavibotTable<K, V> table;
+
+    private Tuple<K, V> returnedTuple = new Tuple<K, V>();
+    private boolean valueAvailable;
+
+    private org.apache.mavibot.btree.Cursor<K, V> browser;
+
+    /**
+     * Creates a Cursor over the tuples of a Mavibot table.
+     *
+     * @param table the JDBM Table to build a Cursor over
+     * @throws IOException of there are problems accessing the BTree
+     */
+    public MavibotCursor( MavibotTable<K, V> table )
+    {
+        LOG_CURSOR.debug( "Creating MavibotCursor {}", this );
+        this.table = table;
+    }
+
+
+    private void clearValue()
+    {
+        returnedTuple.setKey( null );
+        returnedTuple.setValue( null );
+        valueAvailable = false;
+    }
+
+
+    public boolean available()
+    {
+        return valueAvailable;
+    }
+
+
+    public void beforeKey( K key ) throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "beforeKey()" );
+        closeBrowser( browser );
+        browser = table.getBTree().browseFrom( key );
+
+        clearValue();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public void afterKey( K key ) throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "afterKey()" );
+        closeBrowser( browser );
+        browser = table.getBTree().browseFrom( key );
+        
+        if( table.isDupsEnabled() )
+        {
+            browser.moveToNextNonDuplicateKey();
+        }
+        else
+        {
+            if( browser.hasNext() )
+            {
+                browser.next();
+            }
+            else
+            {
+                browser.afterLast();
+            }
+        }
+        
+        clearValue();
+    }
+
+
+    public void beforeValue( K key, V value ) throws LdapException, CursorException, IOException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_596 ) );
+    }
+
+
+    public void afterValue( K key, V value ) throws LdapException, CursorException, IOException
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_596 ) );
+    }
+
+
+    /**
+     * Positions this Cursor before the key of the supplied tuple.
+     *
+     * @param element the tuple who's key is used to position this Cursor
+     * @throws IOException if there are failures to position the Cursor
+     */
+    public void before( Tuple<K, V> element )throws LdapException, CursorException, IOException
+    {
+        beforeKey( element.getKey() );
+    }
+
+
+    public void after( Tuple<K, V> element )throws LdapException, CursorException, IOException
+    {
+        afterKey( element.getKey() );
+    }
+
+
+    public void beforeFirst() throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "beforeFirst()" );
+        
+        if( browser == null )
+        {
+            browser = table.getBTree().browse();
+        }
+        
+        browser.beforeFirst();
+        clearValue();
+    }
+
+
+    public void afterLast() throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "afterLast()" );
+        
+        if( browser == null )
+        {
+            browser = table.getBTree().browse();
+        }
+        
+        browser.afterLast();
+        clearValue();
+    }
+
+
+    public boolean first() throws LdapException, CursorException, IOException
+    {
+        beforeFirst();
+        return next();
+    }
+
+
+    public boolean last() throws LdapException, CursorException, IOException
+    {
+        afterLast();
+        return previous();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public boolean previous() throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "previous()" );
+        if ( browser == null )
+        {
+            afterLast();
+        }
+
+        if ( browser.hasPrev() )
+        {
+        	org.apache.mavibot.btree.Tuple<K, V> tuple = browser.prev();
+
+            returnedTuple.setKey( tuple.getKey() );
+            returnedTuple.setValue( ( V ) tuple.getValue() );
+            return valueAvailable = true;
+        }
+        else
+        {
+            clearValue();
+            return false;
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public boolean next() throws LdapException, CursorException, IOException
+    {
+        checkNotClosed( "previous()" );
+
+        if ( browser == null )
+        {
+            beforeFirst();
+        }
+
+        if ( browser.hasNext() )
+        {
+        	org.apache.mavibot.btree.Tuple<K, V> tuple = browser.next();
+        	
+            returnedTuple.setKey( tuple.getKey() );
+            returnedTuple.setValue( tuple.getValue() );
+            return valueAvailable = true;
+        }
+        else
+        {
+            clearValue();
+            return false;
+        }
+    }
+
+
+    public Tuple<K, V> get() throws CursorException, IOException
+    {
+        checkNotClosed( "get()" );
+        if ( valueAvailable )
+        {
+            return returnedTuple;
+        }
+
+        throw new InvalidCursorPositionException();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close()
+    {
+        LOG_CURSOR.debug( "Closing MavibotCursor {}", this );
+        super.close();
+        closeBrowser( browser );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close( Exception cause )
+    {
+        LOG_CURSOR.debug( "Closing MavibotCursor {}", this );
+        super.close( cause );
+        closeBrowser( browser );
+    }
+
+
+    private void closeBrowser( org.apache.mavibot.btree.Cursor<K, V> browser )
+    {
+        if ( browser != null )
+        {
+            browser.close();
+        }
+    }
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotDnIndex.java Tue May 14 03:09:53 2013
@@ -0,0 +1,125 @@
+/*
+ *   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.entry.Entry;
+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.server.i18n.I18n;
+import org.apache.mavibot.btree.RecordManager;
+import org.apache.mavibot.btree.serializer.StringSerializer;
+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, Entry>
+{
+
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotDnIndex.class );
+
+
+    public MavibotDnIndex( RecordManager recordMan, String oid )
+    {
+        super( recordMan, 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" );
+
+            e.printStackTrace();
+            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, new StringSerializer(), false );
+
+        String reverseTableName = attributeType.getOid() + REVERSE_BTREE;
+        reverse = new MavibotTable<String, Dn>( recordMan, schemaManager, reverseTableName, new StringSerializer(), 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();
+    }
+    
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotEntrySerializer.java Tue May 14 03:09:53 2013
@@ -0,0 +1,297 @@
+/*
+ *  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.server.i18n.I18n;
+import org.apache.mavibot.btree.serializer.BufferHandler;
+import org.apache.mavibot.btree.serializer.ElementSerializer;
+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 implements ElementSerializer<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;
+
+
+    /**
+     * Creates a new instance of ServerEntrySerializer.
+     * The schemaManager MUST be set explicitly using the static {@link #setSchemaManager(SchemaManager)}
+     */
+    public MavibotEntrySerializer()
+    {
+    }
+
+    
+    @Override
+    public int compare( Entry entry1, Entry entry2 )
+    {
+        return entry1.getDn().getName().compareTo( entry1.getDn().getName() );
+    }
+
+
+
+    @Override
+    public Comparator<Entry> getComparator()
+    {
+        return null;
+    }
+
+
+
+    /**
+     * <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();
+
+            int totalBytes = 0;
+            // write dummy length for preserving the space for 'length' to be filled later
+            baos.write( 0 );
+            baos.write( 0 );
+            baos.write( 0 );
+            baos.write( 0 );
+            
+            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();
+            
+            totalBytes = bytes.length - 4; //subtract the first 4 dummy bytes
+
+            // replace the dummy length with the actual length
+            bytes[0] = ( byte ) ( totalBytes >>> 24 );
+            bytes[1] = ( byte ) ( totalBytes >>> 16 );
+            bytes[2] = ( byte ) ( totalBytes >>> 8 );
+            bytes[3] = ( byte ) ( totalBytes );
+
+            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.getInt();
+
+        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;
+    }
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotIndex.java Tue May 14 03:09:53 2013
@@ -0,0 +1,639 @@
+/*
+ *  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 java.net.URI;
+
+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;
+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.MatchingRule;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.server.core.partition.impl.btree.IndexCursorAdaptor;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.server.xdbm.AbstractIndex;
+import org.apache.directory.server.xdbm.EmptyIndexCursor;
+import org.apache.directory.server.xdbm.Index;
+import org.apache.directory.server.xdbm.IndexEntry;
+import org.apache.mavibot.btree.BTreeConfiguration;
+import org.apache.mavibot.btree.RecordManager;
+import org.apache.mavibot.btree.serializer.ByteArraySerializer;
+import org.apache.mavibot.btree.serializer.ElementSerializer;
+import org.apache.mavibot.btree.serializer.StringSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 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 MavibotIndex<K, V> extends AbstractIndex<K, V, String>
+{
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( MavibotIndex.class.getSimpleName() );
+
+    /**  the key used for the forward btree name */
+    public static final String FORWARD_BTREE = "_forward";
+
+    /**  the key used for the reverse btree name */
+    public static final String REVERSE_BTREE = "_reverse";
+
+    /**
+     * the forward btree where the btree key is the value of the indexed attribute and
+     * the value of the btree is the entry id of the entry containing an attribute with
+     * that value
+     */
+    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 MavibotTable<String, K> reverse;
+
+
+    /** a custom working directory path when specified in configuration */
+    protected File wkDirPath;
+
+    protected RecordManager recordMan;
+    
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ----------------------------------------------------------------------
+    /**
+     * Creates a JdbmIndex instance for a give AttributeId
+     */
+    public MavibotIndex( RecordManager recordMan, String attributeId, boolean withReverse )
+    {
+        super( attributeId, withReverse );
+
+        this.recordMan = recordMan;
+        
+        initialized = false;
+    }
+
+
+    /**
+     * 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
+     */
+    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" );
+
+            e.printStackTrace();
+            throw e;
+        }
+
+        try
+        {
+            initTables( schemaManager );
+        }
+        catch ( IOException e )
+        {
+            // clean up
+            close();
+            throw e;
+        }
+
+        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
+    {
+        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.
+         */
+
+        ElementSerializer<K> forwardKeySerializer = null;
+        
+        if( !attributeType.getSyntax().isHumanReadable() )
+        {
+            forwardKeySerializer = ( ElementSerializer<K> ) new ByteArraySerializer();
+        }
+        else
+        {
+            forwardKeySerializer = ( ElementSerializer<K> ) new StringSerializer();
+        }
+        
+        String forwardTableName = attributeType.getOid() + FORWARD_BTREE;
+        forward = new MavibotTable<K, String>( recordMan, schemaManager, forwardTableName, forwardKeySerializer, new StringSerializer(), true );
+
+        /*
+         * 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
+         * is single valued according to its specification based on a schema
+         * then duplicate keys should not be allowed within the reverse table.
+         */
+        if ( withReverse )
+        {
+            String reverseTableName = attributeType.getOid() + REVERSE_BTREE;
+            reverse = new MavibotTable<String, K>( recordMan, schemaManager, reverseTableName, new StringSerializer(), forwardKeySerializer, !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();
+    }
+
+
+    // ------------------------------------------------------------------------
+    // 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.
+     *
+     * @param wkDirPath optional working directory path
+     */
+    public void setWkDirPath( URI wkDirPath )
+    {
+        //.out.println( "IDX Defining a WorkingDir : " + wkDirPath );
+        protect( "wkDirPath" );
+        this.wkDirPath = new File( wkDirPath );
+    }
+
+
+    /**
+     * Gets the working directory path to something other than the default. Sometimes more
+     * performance is gained by locating indices on separate disk spindles.
+     *
+     * @return optional working directory path
+     */
+    public URI getWkDirPath()
+    {
+        return wkDirPath != null ? wkDirPath.toURI() : null;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Scan Count Methods
+    // ------------------------------------------------------------------------
+    /**
+     * {@inheritDoc}
+     */
+    public int count() throws IOException
+    {
+        return forward.count();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int count( K attrVal ) throws Exception
+    {
+        return forward.count( attrVal );
+    }
+
+
+    public int greaterThanCount( K attrVal ) throws Exception
+    {
+        return forward.greaterThanCount( attrVal );
+    }
+
+
+    /**
+     * @see org.apache.directory.server.xdbm.Index#lessThanCount(java.lang.Object)
+     */
+    public int lessThanCount( K attrVal ) throws Exception
+    {
+        return forward.lessThanCount( attrVal );
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Forward and Reverse Lookups
+    // ------------------------------------------------------------------------
+
+    /**
+     * @see Index#forwardLookup(java.lang.Object)
+     */
+    public String forwardLookup( K attrVal ) throws Exception
+    {
+        return forward.get( attrVal );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public K reverseLookup( String id ) throws LdapException
+    {
+        if ( withReverse )
+        {
+            return reverse.get( id );
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Add/Drop Methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void add( K attrVal, String id ) throws Exception
+    {
+        // The pair to be removed must exists
+        forward.put( attrVal, id );
+
+        if ( withReverse )
+        {
+            reverse.put( id, attrVal );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void drop( K attrVal, String id ) throws Exception
+    {
+        // The pair to be removed must exists
+        if ( forward.has( attrVal, id ) )
+        {
+            forward.remove( attrVal, id );
+
+            if ( withReverse )
+            {
+                reverse.remove( id, attrVal );
+            }
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void drop( String entryId ) throws Exception
+    {
+        if ( withReverse )
+        {
+            if ( isDupsEnabled() )
+            {
+                // Build a cursor to iterate on all the keys referencing
+                // this entryId
+                Cursor<Tuple<String, K>> values = reverse.cursor( entryId );
+
+                while ( values.next() )
+                {
+                    // Remove the Key -> entryId from the index
+                    forward.remove( values.get().getValue(), entryId );
+                }
+
+                values.close();
+            }
+            else
+            {
+                K key = reverse.get( entryId );
+
+                forward.remove( key );
+            }
+
+            // Remove the id -> key from the reverse index
+            reverse.remove( entryId );
+        }
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Index Cursor Operations
+    // ------------------------------------------------------------------------
+    @SuppressWarnings("unchecked")
+    public Cursor<IndexEntry<K, String>> reverseCursor() throws Exception
+    {
+        if ( withReverse )
+        {
+            return new IndexCursorAdaptor<K>( ( Cursor ) reverse.cursor(), false );
+        }
+        else
+        {
+            return new EmptyIndexCursor<K>();
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public Cursor<IndexEntry<K, String>> forwardCursor() throws LdapException
+    {
+        return new IndexCursorAdaptor<K>( ( Cursor ) forward.cursor(), true );
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public Cursor<IndexEntry<K, String>> reverseCursor( String id ) throws Exception
+    {
+        if ( withReverse )
+        {
+            return new IndexCursorAdaptor<K>( ( Cursor ) reverse.cursor( id ), false );
+        }
+        else
+        {
+            return new EmptyIndexCursor<K>();
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public Cursor<IndexEntry<K, String>> forwardCursor( K key ) throws Exception
+    {
+        return new IndexCursorAdaptor<K>( ( Cursor ) forward.cursor( key ), true );
+    }
+
+
+    public Cursor<K> reverseValueCursor( String id ) throws Exception
+    {
+        if ( withReverse )
+        {
+            return reverse.valueCursor( id );
+        }
+        else
+        {
+            return new EmptyCursor<K>();
+        }
+    }
+
+
+    public Cursor<String> forwardValueCursor( K key ) throws Exception
+    {
+        return forward.valueCursor( key );
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Value Assertion (a.k.a Index Lookup) Methods //
+    // ------------------------------------------------------------------------
+    /**
+     * {@inheritDoc}
+     */
+    public boolean forward( K attrVal ) throws Exception
+    {
+        return forward.has( attrVal );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean forward( K attrVal, String id ) throws LdapException
+    {
+        return forward.has( attrVal, id );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean reverse( String id ) throws Exception
+    {
+        if ( withReverse )
+        {
+            return reverse.has( id );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean reverse( String id, K attrVal ) throws Exception
+    {
+        return forward.has( attrVal, id );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean forwardGreaterOrEq( K attrVal ) throws Exception
+    {
+        return forward.hasGreaterOrEqual( attrVal );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean forwardGreaterOrEq( K attrVal, String id ) throws Exception
+    {
+        return forward.hasGreaterOrEqual( attrVal, id );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean forwardLessOrEq( K attrVal ) throws Exception
+    {
+        return forward.hasLessOrEqual( attrVal );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean forwardLessOrEq( K attrVal, String id ) throws Exception
+    {
+        return forward.hasLessOrEqual( attrVal, id );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean reverseGreaterOrEq( String id ) throws Exception
+    {
+        if ( withReverse )
+        {
+            return reverse.hasGreaterOrEqual( id );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean reverseGreaterOrEq( String id, K attrVal ) throws LdapException
+    {
+        if ( withReverse )
+        {
+            return reverse.hasGreaterOrEqual( id, attrVal );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean reverseLessOrEq( String id ) throws Exception
+    {
+        if ( withReverse )
+        {
+            return reverse.hasLessOrEqual( id );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean reverseLessOrEq( String id, K attrVal ) throws Exception
+    {
+        if ( withReverse )
+        {
+            return reverse.hasLessOrEqual( id, attrVal );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Maintenance Methods
+    // ------------------------------------------------------------------------
+    /**
+     * @see org.apache.directory.server.xdbm.Index#close()
+     */
+    public synchronized void close() throws IOException
+    {
+        try
+        {
+            if ( forward != null )
+            {
+                forward.close();
+            }
+
+            if ( reverse != null )
+            {
+                reverse.close();
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new IOException( e );
+        }
+    }
+
+
+    /**
+     * @see Index#sync()
+     */
+    public synchronized void sync() throws IOException
+    {
+        forward.getBTree().flush();
+        if ( reverse != null )
+        {
+            reverse.getBTree().flush();
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isDupsEnabled()
+    {
+        if ( withReverse )
+        {
+            return reverse.isDupsEnabled();
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "Index<" + attributeId + ">";
+    }
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotMasterTable.java Tue May 14 03:09:53 2013
@@ -0,0 +1,60 @@
+/*
+ *  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.server.xdbm.MasterTable;
+import org.apache.mavibot.btree.RecordManager;
+import org.apache.mavibot.btree.serializer.StringSerializer;
+
+/**
+ * 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 )
+        throws IOException
+    {
+        super( recordMan, schemaManager, name, new StringSerializer(), new MavibotEntrySerializer(), false );
+    }
+
+
+    @Override
+    public String getNextId( Entry entry ) throws Exception
+    {
+        return UUID.randomUUID().toString();
+    }
+
+
+    @Override
+    public void close() throws Exception
+    {
+        recordMan.close();
+    }
+
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotParentIdAndRdnSerializer.java Tue May 14 03:09:53 2013
@@ -0,0 +1,247 @@
+/*
+ *  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.Rdn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.server.xdbm.ParentIdAndRdn;
+import org.apache.mavibot.btree.serializer.BufferHandler;
+import org.apache.mavibot.btree.serializer.ElementSerializer;
+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 implements ElementSerializer<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 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()
+    {
+    }
+
+
+    /**
+     * <p>
+     * 
+     * This is the place where we serialize ParentIdAndRdn
+     * <p>
+     */
+    public byte[] serialize( ParentIdAndRdn parentIdAndRdn )
+    {
+        try
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            
+            int totalBytes = 0;
+            // write dummy length for preserving the space for 'length' to be filled later
+            baos.write( 0 );
+            baos.write( 0 );
+            baos.write( 0 );
+            baos.write( 0 );
+            
+            ObjectOutput out = new ObjectOutputStream( baos );
+            
+            
+            // First, the Dn
+            Rdn[] rdns = parentIdAndRdn.getRdns();
+            
+            // Write the Rdn of the Dn
+            if ( ( rdns == null ) || ( rdns.length == 0 ) )
+            {
+                out.writeByte( 0 );
+            }
+            else
+            {
+                out.writeByte( rdns.length );
+                
+                for ( Rdn rdn : rdns )
+                {
+                    rdn.writeExternal( out );
+                }
+            }
+            
+            // Then the parentId.
+            out.writeUTF( parentIdAndRdn.getParentId() );
+            
+            // The number of children
+            out.writeInt( parentIdAndRdn.getNbChildren() );
+            
+            // The number of descendants
+            out.writeInt( parentIdAndRdn.getNbDescendants() );
+            
+            out.flush();
+            
+            if ( IS_DEBUG )
+            {
+                LOG.debug( ">------------------------------------------------" );
+                LOG.debug( "Serialize " + parentIdAndRdn );
+            }
+            
+            byte[] bytes = baos.toByteArray();
+            
+            totalBytes = bytes.length - 4; //subtract the first 4 dummy bytes
+            
+            // replace the dummy length with the actual length
+            bytes[0] = ( byte ) ( totalBytes >>> 24 );
+            bytes[1] = ( byte ) ( totalBytes >>> 16 );
+            bytes[2] = ( byte ) ( totalBytes >>> 8 );
+            bytes[3] = ( byte ) ( totalBytes );
+            
+            return bytes;
+        }
+        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
+    {
+        int len = buffer.getInt();
+
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( buffer.array(), buffer.position(), len ) );
+
+        try
+        {
+            ParentIdAndRdn parentIdAndRdn = new ParentIdAndRdn();
+
+            // Read the number of rdns, if any
+            byte nbRdns = in.readByte();
+
+            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 );
+                    rdn.readExternal( in );
+                    rdns[i] = rdn;
+                }
+
+                parentIdAndRdn.setRdns( rdns );
+            }
+
+            // Read the parent ID
+            String uuid = in.readUTF();
+
+            parentIdAndRdn.setParentId( uuid );
+
+            // Read the nulber of children and descendants
+            int nbChildren = in.readInt();
+            int nbDescendants = in.readInt();
+
+            parentIdAndRdn.setNbChildren( nbChildren );
+            parentIdAndRdn.setNbDescendants( nbDescendants );
+
+            buffer.position( buffer.position() + len );
+            
+            return parentIdAndRdn;
+        }
+        catch ( ClassNotFoundException cnfe )
+        {
+            LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
+            throw new IOException( cnfe.getLocalizedMessage() );
+        }        
+    }
+
+
+    @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;
+    }
+
+}

Added: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java?rev=1482179&view=auto
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java (added)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java Tue May 14 03:09:53 2013
@@ -0,0 +1,355 @@
+/*
+ *  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.List;
+
+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.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.server.constants.ApacheSchemaConstants;
+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.apache.mavibot.btree.RecordManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 
+ * TODO MavibotPartition.
+ *
+ * @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 = new FilenameFilter()
+    {
+
+        public boolean accept( File dir, String name )
+        {
+            // really important to filter master.db and master.lg files
+            return ( name.endsWith( MAVIBOT_DB_FILE_EXTN ) && !name.startsWith( "master." ) );
+        }
+    };
+
+    private RecordManager recordMan;
+    
+    public MavibotPartition( SchemaManager schemaManager )
+    {
+        super( schemaManager );
+        
+        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 );
+        }
+    }
+
+
+    @Override
+    protected void doInit() throws Exception
+    {
+        if ( !initialized )
+        {
+            // setup optimizer and registries for parent
+            if ( !optimizerEnabled )
+            {
+                optimizer = new NoOpOptimizer();
+            }
+            else
+            {
+                optimizer = new DefaultOptimizer<Entry>( this );
+            }
+
+            EvaluatorBuilder evaluatorBuilder = new EvaluatorBuilder( this, schemaManager );
+            CursorBuilder cursorBuilder = new CursorBuilder( this, evaluatorBuilder );
+
+            searchEngine = new DefaultSearchEngine( this, cursorBuilder, evaluatorBuilder, optimizer );
+
+            // 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 ) );
+            }
+
+            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)
+            master = new MavibotMasterTable( recordMan, schemaManager, "master" );
+
+            // 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<?, Entry, String> index : systemIndices.values() )
+            {
+                allIndices.add( index.getAttribute().getOid() );
+            }
+
+            List<Index<?, Entry, String>> indexToBuild = new ArrayList<Index<?, Entry, 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 );
+*/
+            // We are done !
+            initialized = true;
+        }
+    }
+
+
+    @Override
+    protected Index<?, Entry, String> convertAndInit( Index<?, Entry, String> index ) throws Exception
+    {
+        MavibotIndex<?, Entry> mavibotIndex;
+
+        if ( index instanceof MavibotRdnIndex )
+        {
+            mavibotIndex = ( MavibotRdnIndex ) index;
+        }
+        else if ( index instanceof MavibotDnIndex )
+        {
+            mavibotIndex = ( MavibotDnIndex ) index;
+        }
+        else if ( index instanceof MavibotIndex<?, ?> )
+        {
+            mavibotIndex = ( MavibotIndex<?, Entry> ) 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( recordMan, index.getAttributeId(), true );
+            mavibotIndex.setCacheSize( index.getCacheSize() );
+            mavibotIndex.setWkDirPath( index.getWkDirPath() );
+        }
+
+        // during restart the indices will contain reference to an old recordmanager
+        mavibotIndex.recordMan = recordMan;
+        
+        mavibotIndex.init( schemaManager, schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() ) );
+
+        return mavibotIndex;
+    }
+
+
+    @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<?, Entry> mavibotIndex;
+
+        if ( indexOid.equals( ApacheSchemaConstants.APACHE_RDN_AT_OID ) )
+        {
+            mavibotIndex = new MavibotRdnIndex( recordMan );
+            mavibotIndex.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+        }
+        else if ( indexOid.equals( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ) )
+        {
+            mavibotIndex = new MavibotDnIndex( recordMan, ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
+            mavibotIndex.setAttributeId( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
+        }
+        else
+        {
+            mavibotIndex = new MavibotIndex( recordMan, indexOid, withReverse );
+        }
+
+        mavibotIndex.setWkDirPath( path );
+
+        return mavibotIndex;
+    }
+
+
+    @Override
+    public void sync() throws Exception
+    {
+        if ( !initialized )
+        {
+            return;
+        }
+
+        // Sync all system indices
+        for ( Index<?, Entry, String> idx : systemIndices.values() )
+        {
+            idx.sync();
+        }
+
+        // Sync all user defined userIndices
+        for ( Index<?, Entry, 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<?, Entry, 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;
+    }
+
+}
\ No newline at end of file