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