/*
 *  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;


import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.cache.Cache;

import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.Cursor;
import org.apache.directory.api.ldap.model.cursor.CursorException;
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.Modification;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapAliasDereferencingException;
import org.apache.directory.api.ldap.model.exception.LdapAliasException;
import org.apache.directory.api.ldap.model.exception.LdapContextNotEmptyException;
import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.directory.api.ldap.model.exception.LdapNoSuchAttributeException;
import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
import org.apache.directory.api.ldap.model.exception.LdapOperationErrorException;
import org.apache.directory.api.ldap.model.exception.LdapOtherException;
import org.apache.directory.api.ldap.model.exception.LdapSchemaViolationException;
import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.name.Ava;
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.MatchingRule;
import org.apache.directory.api.ldap.model.schema.Normalizer;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.util.Strings;
import org.apache.directory.api.util.exception.MultiException;
import org.apache.directory.server.constants.ApacheSchemaConstants;
import org.apache.directory.server.core.api.DnFactory;
import org.apache.directory.server.core.api.entry.ClonedServerEntry;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursorImpl;
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.api.interceptor.context.ModDnAva;
import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.api.interceptor.context.OperationContext;
import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
import org.apache.directory.server.core.api.partition.AbstractPartition;
import org.apache.directory.server.core.api.partition.Partition;
import org.apache.directory.server.core.api.partition.PartitionTxn;
import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
import org.apache.directory.server.core.api.partition.Subordinates;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.xdbm.Index;
import org.apache.directory.server.xdbm.IndexEntry;
import org.apache.directory.server.xdbm.IndexNotFoundException;
import org.apache.directory.server.xdbm.MasterTable;
import org.apache.directory.server.xdbm.ParentIdAndRdn;
import org.apache.directory.server.xdbm.Store;
import org.apache.directory.server.xdbm.search.Optimizer;
import org.apache.directory.server.xdbm.search.PartitionSearchResult;
import org.apache.directory.server.xdbm.search.SearchEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An abstract {@link Partition} that uses general BTree operations.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public abstract class AbstractBTreePartition extends AbstractPartition implements Store
{
    /** static logger */
    private static final Logger LOG = LoggerFactory.getLogger( AbstractBTreePartition.class );

    /** the search engine used to search the database */
    private SearchEngine searchEngine;

    /** The optimizer to use during search operation */
    private Optimizer optimizer;

    /** Tells if the Optimizer is enabled */
    protected boolean optimizerEnabled = true;

    /** The default cache size is set to 10 000 objects */
    public static final int DEFAULT_CACHE_SIZE = 10000;

    /** The Entry cache size for this partition */
    protected int cacheSize = DEFAULT_CACHE_SIZE;

    /** The alias cache */
    protected Cache< String, Dn > aliasCache;

    /** The ParentIdAndRdn cache */
    protected Cache< String, ParentIdAndRdn > piarCache;

    /** true if we sync disks on every write operation */
    protected AtomicBoolean isSyncOnWrite = new AtomicBoolean( true );

    /** The suffix UUID */
    private volatile String suffixId;

    /** The path in which this Partition stores files */
    protected URI partitionPath;

    /** The set of indexed attributes */
    private Set<Index<?, String>> indexedAttributes;

    /** the master table storing entries by primary key */
    protected MasterTable master;

    /** a map of attributeType numeric UUID to user userIndices */
    protected Map<String, Index<?, String>> userIndices = new HashMap<>();

    /** a map of attributeType numeric UUID to system userIndices */
    protected Map<String, Index<?, String>> systemIndices = new HashMap<>();

    /** the relative distinguished name index */
    protected Index<ParentIdAndRdn, String> rdnIdx;

    /** a system index on objectClass attribute*/
    protected Index<String, String> objectClassIdx;

    /** the attribute presence index */
    protected Index<String, String> presenceIdx;

    /** a system index on entryCSN attribute */
    protected Index<String, String> entryCsnIdx;

    /** a system index on aliasedObjectName attribute */
    protected Index<Dn, String> aliasIdx;

    /** the subtree scope alias index */
    protected Index<String, String> subAliasIdx;

    /** the one level scope alias index */
    protected Index<String, String> oneAliasIdx;

    /** a system index on administrativeRole attribute */
    protected Index<String, String> adminRoleIdx;

    /** Cached attributes types to avoid lookup all over the code */
    protected AttributeType objectClassAT;
    private Normalizer objectClassNormalizer;
    protected AttributeType presenceAT;
    private Normalizer presenceNormalizer;
    protected AttributeType entryCsnAT;
    protected AttributeType entryDnAT;
    protected AttributeType entryUuidAT;
    protected AttributeType aliasedObjectNameAT;
    protected AttributeType administrativeRoleAT;
    protected AttributeType contextCsnAT;
    
    /** Cached value for TOP */
    private Value topOCValue;

    private static final boolean NO_REVERSE = Boolean.FALSE;
    private static final boolean WITH_REVERSE = Boolean.TRUE;

    protected static final boolean ADD_CHILD = true;
    protected static final boolean REMOVE_CHILD = false;

    /** A lock to protect the backend from concurrent reads/writes */
    private ReadWriteLock rwLock;

    /** a cache to hold <entryUUID, Dn> pairs, this is used for speeding up the buildEntryDn() method */
    private Cache<String, Dn> entryDnCache;
    
    /** a semaphore to serialize the writes on context entry while updating contextCSN attribute */
    private Semaphore ctxCsnSemaphore = new Semaphore( 1 );
    
    // ------------------------------------------------------------------------
    // C O N S T R U C T O R S
    // ------------------------------------------------------------------------

    /**
     * Creates a B-tree based context partition.
     * 
     * @param schemaManager the schema manager
     */
    protected AbstractBTreePartition( SchemaManager schemaManager )
    {
        this.schemaManager = schemaManager;

        initInstance();
    }


    /**
     * Creates a B-tree based context partition.
     * 
     * @param schemaManager the schema manager
     * @param dnFactory the DN factory
     */
    protected AbstractBTreePartition( SchemaManager schemaManager, DnFactory dnFactory )
    {
        this.schemaManager = schemaManager;
        this.dnFactory = dnFactory;

        initInstance();
    }


    /**
     * Intializes the instance.
     */
    private void initInstance()
    {
        indexedAttributes = new HashSet<>();

        // Initialize Attribute types used all over this method
        objectClassAT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
        objectClassNormalizer = objectClassAT.getEquality().getNormalizer();
        presenceAT = schemaManager.getAttributeType( ApacheSchemaConstants.APACHE_PRESENCE_AT );
        presenceNormalizer = presenceAT.getEquality().getNormalizer();
        aliasedObjectNameAT = schemaManager.getAttributeType( SchemaConstants.ALIASED_OBJECT_NAME_AT );
        entryCsnAT = schemaManager.getAttributeType( SchemaConstants.ENTRY_CSN_AT );
        entryDnAT = schemaManager.getAttributeType( SchemaConstants.ENTRY_DN_AT );
        entryUuidAT = schemaManager.getAttributeType( SchemaConstants.ENTRY_UUID_AT );
        administrativeRoleAT = schemaManager.getAttributeType( SchemaConstants.ADMINISTRATIVE_ROLE_AT );
        contextCsnAT = schemaManager.getAttributeType( SchemaConstants.CONTEXT_CSN_AT );
        
        // Initialize a Value for TOP_OC
        try
        {
            topOCValue = new Value( schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT_OID ), SchemaConstants.TOP_OC_OID );
        }
        catch ( LdapInvalidAttributeValueException e )
        {
            // There is nothing we can do...
        }
        
        // Relax the entryDnAT so that we don't check the EntryDN twice
        entryDnAT.setRelaxed( true );
    }


    // ------------------------------------------------------------------------
    // C O N F I G U R A T I O N   M E T H O D S
    // ------------------------------------------------------------------------
    /**
     * Gets the entry cache size for this BTreePartition.
     *
     * @return the maximum size of the cache as the number of entries maximum before paging out
     */
    @Override
    public int getCacheSize()
    {
        return cacheSize;
    }


    /**
     * Used to specify the entry cache size for a Partition.  Various Partition
     * implementations may interpret this value in different ways: i.e. total cache
     * size limit verses the number of entries to cache.
     *
     * @param cacheSize the maximum size of the cache in the number of entries
     */
    @Override
    public void setCacheSize( int cacheSize )
    {
        this.cacheSize = cacheSize;
    }


    /**
     * Tells if the Optimizer is enabled or not
     * @return true if the optimizer is enabled
     */
    public boolean isOptimizerEnabled()
    {
        return optimizerEnabled;
    }


    /**
     * Set the optimizer flag
     * @param optimizerEnabled The flag
     */
    public void setOptimizerEnabled( boolean optimizerEnabled )
    {
        this.optimizerEnabled = optimizerEnabled;
    }


    /**
     * Sets the path in which this Partition stores data. This may be an URL to
     * a file or directory, or an JDBC URL.
     *
     * @param partitionPath the path in which this Partition stores data.
     */
    @Override
    public void setPartitionPath( URI partitionPath )
    {
        checkInitialized( "partitionPath" );
        this.partitionPath = partitionPath;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isSyncOnWrite()
    {
        return isSyncOnWrite.get();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setSyncOnWrite( boolean isSyncOnWrite )
    {
        checkInitialized( "syncOnWrite" );
        this.isSyncOnWrite.set( isSyncOnWrite );
    }


    /**
     * Sets up the system indices.
     * 
     * @throws LdapException If the setup failed
     */
    @SuppressWarnings("unchecked")
    protected void setupSystemIndices() throws LdapException
    {
        // add missing system indices
        if ( getPresenceIndex() == null )
        {
            Index<String, String> index = createSystemIndex( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID,
                partitionPath, NO_REVERSE );
            addIndex( index );
        }

        if ( getRdnIndex() == null )
        {
            Index<ParentIdAndRdn, String> index = createSystemIndex(
                ApacheSchemaConstants.APACHE_RDN_AT_OID,
                partitionPath, WITH_REVERSE );
            addIndex( index );
        }

        if ( getAliasIndex() == null )
        {
            Index<Dn, String> index = createSystemIndex( ApacheSchemaConstants.APACHE_ALIAS_AT_OID,
                partitionPath, WITH_REVERSE );
            addIndex( index );
        }

        if ( getOneAliasIndex() == null )
        {
            Index<String, String> index = createSystemIndex( ApacheSchemaConstants.APACHE_ONE_ALIAS_AT_OID,
                partitionPath, NO_REVERSE );
            addIndex( index );
        }

        if ( getSubAliasIndex() == null )
        {
            Index<String, String> index = createSystemIndex( ApacheSchemaConstants.APACHE_SUB_ALIAS_AT_OID,
                partitionPath, NO_REVERSE );
            addIndex( index );
        }

        if ( getObjectClassIndex() == null )
        {
            Index<String, String> index = createSystemIndex( SchemaConstants.OBJECT_CLASS_AT_OID, partitionPath,
                NO_REVERSE );
            addIndex( index );
        }

        if ( getEntryCsnIndex() == null )
        {
            Index<String, String> index = createSystemIndex( SchemaConstants.ENTRY_CSN_AT_OID, partitionPath,
                NO_REVERSE );
            addIndex( index );
        }

        if ( getAdministrativeRoleIndex() == null )
        {
            Index<String, String> index = createSystemIndex( SchemaConstants.ADMINISTRATIVE_ROLE_AT_OID,
                partitionPath,
                NO_REVERSE );
            addIndex( index );
        }

        // convert and initialize system indices
        for ( Map.Entry<String, Index<?, String>> elem : systemIndices.entrySet() )
        {
            Index<?, String> index = elem.getValue();
            index = convertAndInit( index );
            systemIndices.put( elem.getKey(), index );
        }

        // set index shortcuts
        rdnIdx = ( Index<ParentIdAndRdn, String> ) systemIndices
            .get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
        presenceIdx = ( Index<String, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
        aliasIdx = ( Index<Dn, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
        oneAliasIdx = ( Index<String, String> ) systemIndices
            .get( ApacheSchemaConstants.APACHE_ONE_ALIAS_AT_OID );
        subAliasIdx = ( Index<String, String> ) systemIndices
            .get( ApacheSchemaConstants.APACHE_SUB_ALIAS_AT_OID );
        objectClassIdx = ( Index<String, String> ) systemIndices.get( SchemaConstants.OBJECT_CLASS_AT_OID );
        entryCsnIdx = ( Index<String, String> ) systemIndices.get( SchemaConstants.ENTRY_CSN_AT_OID );
        adminRoleIdx = ( Index<String, String> ) systemIndices.get( SchemaConstants.ADMINISTRATIVE_ROLE_AT_OID );
    }


    /**
     * Sets up the user indices.
     * 
     * @throws LdapException If the setup failed
     */
    protected void setupUserIndices() throws LdapException
    {
        // convert and initialize system indices
        Map<String, Index<?, String>> tmp = new HashMap<>();

        for ( Map.Entry<String, Index<?, String>> elem : userIndices.entrySet() )
        {
            String oid = elem.getKey();
            
            // check that the attributeType has an EQUALITY matchingRule
            AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( oid );
            MatchingRule mr = attributeType.getEquality();

            if ( mr != null )
            {
                Index<?, String> index = elem.getValue();
                index = convertAndInit( index );
                tmp.put( oid, index );
            }
            else
            {
                LOG.error( I18n.err( I18n.ERR_4, attributeType.getName() ) );
            }
        }

        userIndices = tmp;
    }


    /**
     * Gets the DefaultSearchEngine used by this ContextPartition to search the
     * Database.
     *
     * @return the search engine
     */
    public SearchEngine getSearchEngine()
    {
        return searchEngine;
    }


    // -----------------------------------------------------------------------
    // Miscellaneous abstract methods
    // -----------------------------------------------------------------------
    /**
     * Convert and initialize an index for a specific store implementation.
     *
     * @param index the index
     * @return the converted and initialized index
     * @throws LdapException If teh conversion failed
     */
    protected abstract Index<?, String> convertAndInit( Index<?, String> index ) throws LdapException;


    /**
     * Gets the path in which this Partition stores data.
     *
     * @return the path in which this Partition stores data.
     */
    @Override
    public URI getPartitionPath()
    {
        return partitionPath;
    }


    // ------------------------------------------------------------------------
    // Partition Interface Method Implementations
    // ------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    protected void doDestroy( PartitionTxn partitionTxn ) throws LdapException
    {
        LOG.debug( "destroy() called on store for {}", this.suffixDn );

        if ( !initialized )
        {
            return;
        }

        // don't reset initialized flag
        initialized = false;

        entryDnCache.clear();
        
        MultiException errors = new MultiException( I18n.err( I18n.ERR_577 ) );

        for ( Index<?, String> index : userIndices.values() )
        {
            try
            {
                index.close( partitionTxn );
                LOG.debug( "Closed {} user index for {} partition.", index.getAttributeId(), suffixDn );
            }
            catch ( Throwable t )
            {
                LOG.error( I18n.err( I18n.ERR_124 ), t );
                errors.addThrowable( t );
            }
        }

        for ( Index<?, String> index : systemIndices.values() )
        {
            try
            {
                index.close( partitionTxn );
                LOG.debug( "Closed {} system index for {} partition.", index.getAttributeId(), suffixDn );
            }
            catch ( Throwable t )
            {
                LOG.error( I18n.err( I18n.ERR_124 ), t );
                errors.addThrowable( t );
            }
        }

        try
        {
            master.close( partitionTxn );
            
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.err( I18n.ERR_125, suffixDn ) );
            }
        }
        catch ( Throwable t )
        {
            LOG.error( I18n.err( I18n.ERR_126 ), t );
            errors.addThrowable( t );
        }

        if ( errors.size() > 0 )
        {
            throw new LdapOtherException( errors.getMessage(), errors );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void repair() throws LdapException
    {
        // Do nothing by default
        doRepair();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected void doInit() throws LdapException
    {
        // First, inject the indexed attributes if any
        if ( ( indexedAttributes != null ) && ( !indexedAttributes.isEmpty() ) )
        {
            for ( Index index : indexedAttributes )
            {
                addIndex( index );
            }
        }

        // Now, initialize the configured index
        setupSystemIndices();
        setupUserIndices();

        if ( cacheService != null )
        {
            aliasCache = cacheService.getCache( "alias", String.class, Dn.class );
    
            //CacheConfiguration< String, Dn > aliasCacheConfig = aliasCache.getRuntimeConfiguration();
            
            piarCache = cacheService.getCache( "piar", String.class, ParentIdAndRdn.class );
            
            entryDnCache = cacheService.getCache( "entryDn", String.class, Dn.class );
        }
    }


    private void dumpAllRdnIdx( PartitionTxn partitionTxn ) throws LdapException, CursorException, IOException
    {
        if ( LOG.isDebugEnabled() )
        {
            dumpRdnIdx( partitionTxn, Partition.ROOT_ID, "" );
            System.out.println( "-----------------------------" );
        }
    }


    private void dumpRdnIdx( PartitionTxn partitionTxn ) throws LdapException, CursorException, IOException
    {
        if ( LOG.isDebugEnabled() )
        {
            dumpRdnIdx( partitionTxn, Partition.ROOT_ID, 1, "" );
            System.out.println( "-----------------------------" );
        }
    }


    /**
     * Dump the RDN index content
     *  
     * @param partitionTxn The transaction to use
     * @param id The root ID
     * @param tabs The space prefix
     * @throws LdapException If we had an issue while dumping the Rdn index
     * @throws CursorException If the cursor failed to browse the Rdn Index
     * @throws IOException If we weren't able to read teh Rdn Index file
     */
    public void dumpRdnIdx( PartitionTxn partitionTxn, String id, String tabs ) throws LdapException, CursorException, IOException
    {
        // Start with the root
        Cursor<IndexEntry<ParentIdAndRdn, String>> cursor = rdnIdx.forwardCursor( partitionTxn );

        IndexEntry<ParentIdAndRdn, String> startingPos = new IndexEntry<>();
        startingPos.setKey( new ParentIdAndRdn( id, ( Rdn[] ) null ) );
        cursor.before( startingPos );

        while ( cursor.next() )
        {
            IndexEntry<ParentIdAndRdn, String> entry = cursor.get();
            System.out.println( tabs + entry );
        }

        cursor.close();
    }


    private void dumpRdnIdx( PartitionTxn partitionTxn, String id, int nbSibbling, String tabs ) 
        throws LdapException, CursorException, IOException
    {
        // Start with the root
        Cursor<IndexEntry<ParentIdAndRdn, String>> cursor = rdnIdx.forwardCursor( partitionTxn );

        IndexEntry<ParentIdAndRdn, String> startingPos = new IndexEntry<>();
        startingPos.setKey( new ParentIdAndRdn( id, ( Rdn[] ) null ) );
        cursor.before( startingPos );
        int countChildren = 0;

        while ( cursor.next() && ( countChildren < nbSibbling ) )
        {
            IndexEntry<ParentIdAndRdn, String> entry = cursor.get();
            System.out.println( tabs + entry );
            countChildren++;

            // And now, the children
            int nbChildren = entry.getKey().getNbChildren();

            if ( nbChildren > 0 )
            {
                dumpRdnIdx( partitionTxn, entry.getId(), nbChildren, tabs + "  " );
            }
        }

        cursor.close();
    }


    //---------------------------------------------------------------------------------------------
    // The Add operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void add( AddOperationContext addContext ) throws LdapException
    {
        PartitionTxn partitionTxn = addContext.getTransaction();
        
        assert ( partitionTxn != null );
        assert ( partitionTxn instanceof PartitionWriteTxn );

        try
        {
            setRWLock( addContext );
            Entry entry = ( ( ClonedServerEntry ) addContext.getEntry() ).getClonedEntry();

            Dn entryDn = entry.getDn();

            // check if the entry already exists
            lockRead();

            try
            {
                if ( getEntryId( partitionTxn, entryDn ) != null )
                {
                    throw new LdapEntryAlreadyExistsException(
                        I18n.err( I18n.ERR_250_ENTRY_ALREADY_EXISTS, entryDn.getName() ) );
                }
            }
            finally
            {
                unlockRead();
            }

            String parentId = null;

            //
            // Suffix entry cannot have a parent since it is the root so it is
            // capped off using the zero value which no entry can have since
            // entry sequences start at 1.
            //
            Dn parentDn = null;
            ParentIdAndRdn key;

            if ( entryDn.getNormName().equals( suffixDn.getNormName() ) )
            {
                parentId = Partition.ROOT_ID;
                key = new ParentIdAndRdn( parentId, suffixDn.getRdns() );
            }
            else
            {
                parentDn = entryDn.getParent();

                lockRead();

                try
                {
                    parentId = getEntryId( partitionTxn, parentDn );
                }
                finally
                {
                    unlockRead();
                }

                key = new ParentIdAndRdn( parentId, entryDn.getRdn() );
            }

            // don't keep going if we cannot find the parent Id
            if ( parentId == null )
            {
                throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_216_ID_FOR_PARENT_NOT_FOUND, parentDn ) );
            }

            // Get a new UUID for the added entry if it does not have any already
            Attribute entryUUID = entry.get( entryUuidAT );

            String id;

            if ( entryUUID == null )
            {
                id = master.getNextId( entry );
            }
            else
            {
                id = entryUUID.getString();
            }
            
            if ( entryDn.getNormName().equals( suffixDn.getNormName() ) )
            {
                suffixId = id;
            }

            // Update the ObjectClass index
            Attribute objectClass = entry.get( objectClassAT );

            if ( objectClass == null )
            {
                String msg = I18n.err( I18n.ERR_217, entryDn.getName(), entry );
                ResultCodeEnum rc = ResultCodeEnum.OBJECT_CLASS_VIOLATION;
                
                throw new LdapSchemaViolationException( rc, msg );
            }

            for ( Value value : objectClass )
            {
                if ( value.equals( topOCValue ) )
                {
                    continue;
                }
                
                String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                objectClassIdx.add( partitionTxn, normalizedOc, id );
            }

            if ( objectClass.contains( SchemaConstants.ALIAS_OC ) )
            {
                Attribute aliasAttr = entry.get( aliasedObjectNameAT );
                
                addAliasIndices( partitionTxn, id, entryDn, new Dn( schemaManager, aliasAttr.getString() ) );
            }

            // Update the EntryCsn index
            Attribute entryCsn = entry.get( entryCsnAT );

            if ( entryCsn == null )
            {
                String msg = I18n.err( I18n.ERR_219, entryDn.getName(), entry );
                throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION, msg );
            }

            entryCsnIdx.add( partitionTxn, entryCsn.getString(), id );

            // Update the AdministrativeRole index, if needed
            if ( entry.containsAttribute( administrativeRoleAT ) )
            {
                // We may have more than one role
                Attribute adminRoles = entry.get( administrativeRoleAT );

                for ( Value value : adminRoles )
                {
                    adminRoleIdx.add( partitionTxn, value.getString(), id );
                }

                // Adds only those attributes that are indexed
                presenceIdx.add( partitionTxn, administrativeRoleAT.getOid(), id );
            }

            // Now work on the user defined userIndices
            for ( Attribute attribute : entry )
            {
                AttributeType attributeType = attribute.getAttributeType();
                String attributeOid = attributeType.getOid();

                if ( hasUserIndexOn( attributeType ) )
                {
                    Index<Object, String> userIndex = ( Index<Object, String> ) getUserIndex( attributeType );

                    // here lookup by attributeId is OK since we got attributeId from
                    // the entry via the enumeration - it's in there as is for sure

                    for ( Value value : attribute )
                    {
                        String normalized = value.getNormalized();
                        userIndex.add( partitionTxn, normalized, id );
                    }

                    // Adds only those attributes that are indexed
                    presenceIdx.add( partitionTxn, attributeOid, id );
                }
            }

            // Add the parentId in the entry
            entry.put( ApacheSchemaConstants.ENTRY_PARENT_ID_AT, parentId );

            lockWrite();

            try
            {
                // Update the RDN index
                rdnIdx.add( partitionTxn, key, id );

                // Update the parent's nbChildren and nbDescendants values
                if ( parentId != Partition.ROOT_ID )
                {
                    updateRdnIdx( partitionTxn, parentId, ADD_CHILD, 0 );
                }

                // Remove the EntryDN attribute
                entry.removeAttributes( entryDnAT );

                Attribute at = entry.get( SchemaConstants.ENTRY_CSN_AT );
                setContextCsn( at.getString() );

                // And finally add the entry into the master table
                master.put( partitionTxn, id, entry );
            }
            finally
            {
                unlockWrite();
            }
        }
        catch ( LdapException le )
        {
            throw le;
        }
        catch ( Exception e )
        {
            throw new LdapException( e );
        }
    }


    //---------------------------------------------------------------------------------------------
    // The Delete operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public Entry delete( DeleteOperationContext deleteContext ) throws LdapException
    {
        PartitionTxn partitionTxn = deleteContext.getTransaction();
        
        assert ( partitionTxn != null );
        assert ( partitionTxn instanceof PartitionWriteTxn );

        setRWLock( deleteContext );
        Dn dn = deleteContext.getDn();
        String id = null;

        lockRead();

        try
        {
            id = getEntryId( partitionTxn, dn );
        }
        finally
        {
            unlockRead();
        }

        // don't continue if id is null
        if ( id == null )
        {
            throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_699, dn ) );
        }

        long childCount = getChildCount( partitionTxn, id );

        if ( childCount > 0 )
        {
            throw new LdapContextNotEmptyException( I18n.err( I18n.ERR_700, dn ) );
        }

        // We now defer the deletion to the implementing class
        Entry deletedEntry = delete( partitionTxn, id );

        updateCache( deleteContext );
        
        return deletedEntry;
    }


    protected void updateRdnIdx( PartitionTxn partitionTxn, String parentId, boolean addRemove, int nbDescendant ) throws LdapException
    {
        boolean isFirst = true;
        ////dumpRdnIdx();

        if ( parentId.equals( Partition.ROOT_ID ) )
        {
            return;
        }

        ParentIdAndRdn parent = rdnIdx.reverseLookup( partitionTxn, parentId );

        while ( parent != null )
        {
            rdnIdx.drop( partitionTxn, parentId );
            ////dumpRdnIdx();
            
            if ( isFirst )
            {
                if ( addRemove == ADD_CHILD )
                {
                    parent.setNbChildren( parent.getNbChildren() + 1 );
                }
                else
                {
                    parent.setNbChildren( parent.getNbChildren() - 1 );
                }

                isFirst = false;
            }

            if ( addRemove == ADD_CHILD )
            {
                parent.setNbDescendants( parent.getNbDescendants() + ( nbDescendant + 1 ) );
            }
            else
            {
                parent.setNbDescendants( parent.getNbDescendants() - ( nbDescendant + 1 ) );
            }

            // Inject the modified element into the index
            rdnIdx.add( partitionTxn, parent, parentId );

            ////dumpRdnIdx();

            parentId = parent.getParentId();
            parent = rdnIdx.reverseLookup( partitionTxn, parentId );
        }
    }


    /**
     * Delete the entry associated with a given Id
     * 
     * @param partitionTxn The transaction to use
     * @param id The id of the entry to delete
     * @return the deleted entry if found
     * @throws LdapException If the deletion failed
     */
    @Override
    public Entry delete( PartitionTxn partitionTxn, String id ) throws LdapException
    {
        try
        {
            // First get the entry
            Entry entry = null;

            lockRead();

            try
            {
                 entry = master.get( partitionTxn, id );
            }
            finally
            {
                unlockRead();
            }

            if ( entry == null )
            {
                // Not allowed
                throw new LdapNoSuchObjectException( "Cannot find an entry for UUID " + id );
            }

            Attribute objectClass = entry.get( objectClassAT );

            if ( objectClass.contains( SchemaConstants.ALIAS_OC ) )
            {
                dropAliasIndices( partitionTxn, id );
            }

            // Update the ObjectClass index
            for ( Value value : objectClass )
            {
                if ( value.equals( topOCValue ) )
                {
                    continue;
                }
                
                String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                objectClassIdx.drop( partitionTxn, normalizedOc, id );
            }

            // Update the parent's nbChildren and nbDescendants values
            ParentIdAndRdn parent = rdnIdx.reverseLookup( partitionTxn, id );
            updateRdnIdx( partitionTxn, parent.getParentId(), REMOVE_CHILD, 0 );

            // Update the rdn, oneLevel, subLevel, and entryCsn indexes
            entryCsnIdx.drop( partitionTxn, entry.get( entryCsnAT ).getString(), id );

            // Update the AdministrativeRole index, if needed
            if ( entry.containsAttribute( administrativeRoleAT ) )
            {
                // We may have more than one role
                Attribute adminRoles = entry.get( administrativeRoleAT );

                for ( Value value : adminRoles )
                {
                    adminRoleIdx.drop( partitionTxn, value.getString(), id );
                }

                // Deletes only those attributes that are indexed
                presenceIdx.drop( partitionTxn, administrativeRoleAT.getOid(), id );
            }

            // Update the user indexes
            for ( Attribute attribute : entry )
            {
                AttributeType attributeType = attribute.getAttributeType();
                String attributeOid = attributeType.getOid();

                if ( hasUserIndexOn( attributeType ) )
                {
                    Index<?, String> userIndex = getUserIndex( attributeType );

                    // here lookup by attributeId is ok since we got attributeId from
                    // the entry via the enumeration - it's in there as is for sure
                    for ( Value value : attribute )
                    {
                        String normalized =  value.getNormalized();
                        ( ( Index ) userIndex ).drop( partitionTxn, normalized, id );
                    }

                    presenceIdx.drop( partitionTxn, attributeOid, id );
                }
            }

            lockWrite();

            try
            {
                rdnIdx.drop( partitionTxn, id );

                ////dumpRdnIdx();

                entryDnCache.remove( id );
                
                Attribute csn = entry.get( entryCsnAT );
                // can be null while doing subentry deletion
                if ( csn != null )
                {
                    setContextCsn( csn.getString() );
                }

                master.remove( partitionTxn, id );
            }
            finally
            {
                unlockWrite();
            }

            if ( isSyncOnWrite.get() )
            {
                sync();
            }

            return entry;
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    //---------------------------------------------------------------------------------------------
    // The Search operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
    {
        PartitionTxn partitionTxn = searchContext.getTransaction();
        
        assert ( partitionTxn != null );

        try
        {
            setRWLock( searchContext );

            if ( ctxCsnChanged && getSuffixDn().equals( searchContext.getDn() ) )
            {
                try
                {
                    ctxCsnSemaphore.acquire();
                    saveContextCsn( partitionTxn );
                    ctxCsnChanged = false;
                }
                catch ( Exception e )
                {
                    throw new LdapOperationErrorException( e.getMessage(), e );
                }
                finally
                {
                    ctxCsnSemaphore.release();
                }
            }
            
            PartitionSearchResult searchResult = searchEngine.computeResult( partitionTxn, schemaManager, searchContext );

            Cursor<Entry> result = new EntryCursorAdaptor( partitionTxn, this, searchResult );

            return new EntryFilteringCursorImpl( result, searchContext, schemaManager );
        }
        catch ( LdapException le )
        {
            // TODO: SearchEngine.cursor() should only throw LdapException, then the exception handling here can be removed
            throw le;
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    //---------------------------------------------------------------------------------------------
    // The Lookup operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
    {
        PartitionTxn partitionTxn = lookupContext.getTransaction();
        
        assert ( partitionTxn != null );

        try
        {
            setRWLock( lookupContext );
            String id = getEntryId( partitionTxn, lookupContext.getDn() );
    
            if ( id == null )
            {
                return null;
            }
    
            if ( ctxCsnChanged && getSuffixDn().getNormName().equals( lookupContext.getDn().getNormName() ) )
            {
                try
                {
                    ctxCsnSemaphore.acquire();
                    saveContextCsn( partitionTxn );
                }
                catch ( Exception e )
                {
                    throw new LdapOperationErrorException( e.getMessage(), e );
                }
                finally
                {
                    ctxCsnSemaphore.release();
                }
            }
    
            return fetch( partitionTxn, id, lookupContext.getDn() );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage() );
        }
    }


    /**
     * Get back an entry knowing its UUID
     *
     * @param partitionTxn The transaction to use
     * @param id The Entry UUID we want to get back
     * @return The found Entry, or null if not found
     * @throws LdapException If the lookup failed for any reason (except a not found entry)
     */
    @Override
    public Entry fetch( PartitionTxn partitionTxn, String id ) throws LdapException
    {
        try
        {
            rwLock.readLock().lock();

            if ( id == null )
            {
                id = "";
            }
            
            Dn dn = buildEntryDn( partitionTxn, id );

            return fetch( partitionTxn, id, dn );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
        finally
        {
            rwLock.readLock().unlock();
        }
    }


    /**
     * Get back an entry knowing its UUID
     *
     * @param partitionTxn The transaction to use
     * @param id The Entry UUID we want to get back
     * @return The found Entry, or null if not found
     * @throws LdapException If the lookup failed for any reason (except a not found entry)
     */
    @Override
    public Entry fetch( PartitionTxn partitionTxn, String id, Dn dn ) throws LdapException
    {
        try
        {
            Entry entry = lookupCache( id );

            if ( entry != null )
            {
                entry.setDn( dn );

                entry = new ClonedServerEntry( entry );

                // Replace the entry's DN with the provided one
                Attribute entryDnAt = entry.get( entryDnAT );
                Value dnValue = new Value( entryDnAT, dn.getName(), dn.getNormName() );

                if ( entryDnAt == null )
                {
                    entry.add( entryDnAT, dnValue );
                }
                else
                {
                    entryDnAt.clear();
                    entryDnAt.add( dnValue );
                }

                return entry;
            }

            try
            {
                rwLock.readLock().lock();
                entry = master.get( partitionTxn, id );
            }
            finally
            {
                rwLock.readLock().unlock();
            }

            if ( entry != null )
            {
                // We have to store the DN in this entry
                entry.setDn( dn );

                // always store original entry in the cache
                addToCache( id, entry );

                entry = new ClonedServerEntry( entry );

                if ( !entry.containsAttribute( entryDnAT ) )
                {
                    entry.add( entryDnAT, dn.getName() );
                }

                return entry;
            }

            return null;
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    //---------------------------------------------------------------------------------------------
    // The Modify operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        PartitionTxn partitionTxn = modifyContext.getTransaction();
        
        assert ( partitionTxn != null );
        assert ( partitionTxn instanceof PartitionWriteTxn );

        try
        {
            setRWLock( modifyContext );

            Entry modifiedEntry = modify( partitionTxn, modifyContext.getDn(),
                modifyContext.getModItems().toArray( new Modification[]
                    {} ) );

            modifyContext.setAlteredEntry( modifiedEntry );

            updateCache( modifyContext );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public final synchronized Entry modify( PartitionTxn partitionTxn, Dn dn, Modification... mods ) throws LdapException
    {
        String id = getEntryId( partitionTxn, dn );
        Entry entry = master.get( partitionTxn, id );

        for ( Modification mod : mods )
        {
            Attribute attrMods = mod.getAttribute();

            try
            { 
                switch ( mod.getOperation() )
                {
                    case ADD_ATTRIBUTE:
                        modifyAdd( partitionTxn, id, entry, attrMods );
                        break;
    
                    case REMOVE_ATTRIBUTE:
                        modifyRemove( partitionTxn, id, entry, attrMods );
                        break;
    
                    case REPLACE_ATTRIBUTE:
                        modifyReplace( partitionTxn, id, entry, attrMods );
                        break;
    
                    default:
                        throw new LdapException( I18n.err( I18n.ERR_221 ) );
                }
            }
            catch ( IndexNotFoundException infe )
            {
                throw new LdapOtherException( infe.getMessage(), infe );
            }
        }

        updateCsnIndex( partitionTxn, entry, id );

        // Remove the EntryDN
        entry.removeAttributes( entryDnAT );

        setContextCsn( entry.get( entryCsnAT ).getString() );
        
        master.put( partitionTxn, id, entry );

        return entry;
    }


    /**
     * Adds a set of attribute values while affecting the appropriate userIndices.
     * The entry is not persisted: it is only changed in anticipation for a put
     * into the master table.
     *
     * @param partitionTxn The transaction to use
     * @param id the primary key of the entry
     * @param entry the entry to alter
     * @param mods the attribute and values to add
     * @throws Exception if index alteration or attribute addition fails
     */
    @SuppressWarnings("unchecked")
    private void modifyAdd( PartitionTxn partitionTxn, String id, Entry entry, Attribute mods ) 
        throws LdapException, IndexNotFoundException
    {
        if ( entry instanceof ClonedServerEntry )
        {
            throw new LdapOtherException( I18n.err( I18n.ERR_215_CANNOT_STORE_CLONED_SERVER_ENTRY ) );
        }

        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
        String normalizedModsOid = presenceNormalizer.normalize( modsOid );

        AttributeType attributeType = mods.getAttributeType();

        // Special case for the ObjectClass index
        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
        {
            for ( Value value : mods )
            {
                if ( value.equals( topOCValue ) )
                {
                    continue;
                }
                
                String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                objectClassIdx.add( partitionTxn, normalizedOc, id );
            }
        }
        else if ( hasUserIndexOn( attributeType ) )
        {
            Index<?, String> userIndex = getUserIndex( attributeType );

            if ( mods.size() > 0 )
            {
                for ( Value value : mods )
                {
                    String normalized = value.getNormalized();
                    ( ( Index ) userIndex ).add( partitionTxn, normalized, id );
                }
            }
            else
            {
                // Special case when we have null values
                ( ( Index ) userIndex ).add( partitionTxn, null, id );
            }

            // If the attr didn't exist for this id add it to presence index
            if ( !presenceIdx.forward( partitionTxn, normalizedModsOid, id ) )
            {
                presenceIdx.add( partitionTxn, normalizedModsOid, id );
            }
        }
        // Special case for the AdministrativeRole index
        else if ( modsOid.equals( SchemaConstants.ADMINISTRATIVE_ROLE_AT_OID ) )
        {
            // We may have more than one role 
            for ( Value value : mods )
            {
                adminRoleIdx.add( partitionTxn, value.getString(), id );
            }

            // If the attr didn't exist for this id add it to presence index
            if ( !presenceIdx.forward( partitionTxn, normalizedModsOid, id ) )
            {
                presenceIdx.add( partitionTxn, normalizedModsOid, id );
            }
        }

        // add all the values in mods to the same attribute in the entry
        if ( mods.size() > 0 )
        {
            for ( Value value : mods )
            {
                entry.add( mods.getAttributeType(), value );
            }
        }
        else
        {
            // Special cases for null values
            if ( mods.getAttributeType().getSyntax().isHumanReadable() )
            {
                entry.add( mods.getAttributeType(), new Value( mods.getAttributeType(), ( String ) null ) );
            }
            else
            {
                entry.add( mods.getAttributeType(), new Value( mods.getAttributeType(), ( byte[] ) null ) );
            }
        }

        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
        {
            Dn ndn = getEntryDn( partitionTxn, id );
            addAliasIndices( partitionTxn, id, ndn, new Dn( schemaManager, mods.getString() ) );
        }
    }


    /**
     * Completely replaces the existing set of values for an attribute with the
     * modified values supplied affecting the appropriate userIndices.  The entry
     * is not persisted: it is only changed in anticipation for a put into the
     * master table.
     *
     * @param partitionTxn The transaction to use
     * @param id the primary key of the entry
     * @param entry the entry to alter
     * @param mods the replacement attribute and values
     * @throws Exception if index alteration or attribute modification
     * fails.
     */
    @SuppressWarnings("unchecked")
    private void modifyReplace( PartitionTxn partitionTxn, String id, Entry entry, Attribute mods ) 
        throws LdapException, IndexNotFoundException
    {
        if ( entry instanceof ClonedServerEntry )
        {
            throw new LdapOtherException( I18n.err( I18n.ERR_215_CANNOT_STORE_CLONED_SERVER_ENTRY ) );
        }

        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
        AttributeType attributeType = mods.getAttributeType();

        // Special case for the ObjectClass index
        if ( attributeType.equals( objectClassAT ) )
        {
            // if the id exists in the index drop all existing attribute
            // value index entries and add new ones
            for ( Value value : entry.get( objectClassAT ) )
            {
                if ( value.equals( topOCValue ) )
                {
                    continue;
                }
                
                String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                objectClassIdx.drop( partitionTxn, normalizedOc, id );
            }

            for ( Value value : mods )
            {
                if ( value.equals( topOCValue ) )
                {
                    continue;
                }
                
                String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                objectClassIdx.add( partitionTxn, normalizedOc, id );
            }
        }
        else if ( hasUserIndexOn( attributeType ) )
        {
            Index<?, String> userIndex = getUserIndex( attributeType );

            // Drop all the previous values
            Attribute oldAttribute = entry.get( mods.getAttributeType() );

            if ( oldAttribute != null )
            {
                for ( Value value : oldAttribute )
                {
                    String normalized = value.getNormalized();
                    ( ( Index<Object, String> ) userIndex ).drop( partitionTxn, normalized, id );
                }
            }

            // And add the new ones
            for ( Value value : mods )
            {
                String normalized = value.getNormalized();
                ( ( Index ) userIndex ).add( partitionTxn, normalized, id );
            }

            /*
             * If we have no new value, we have to drop the AT fro the presence index
             */
            if ( mods.size() == 0 )
            {
                presenceIdx.drop( partitionTxn, modsOid, id );
            }
        }
        // Special case for the AdministrativeRole index
        else if ( attributeType.equals( administrativeRoleAT ) )
        {
            // Remove the previous values
            for ( Value value : entry.get( administrativeRoleAT ) )
            {
                if ( value.equals( topOCValue ) )
                {
                    continue;
                }
                
                String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                objectClassIdx.drop( partitionTxn, normalizedOc, id );
            }

            // And add the new ones 
            for ( Value value : mods )
            {
                String valueStr = value.getString();

                if ( valueStr.equals( topOCValue ) )
                {
                    continue;
                }
                
                adminRoleIdx.add( partitionTxn, valueStr, id );
            }
        }

        String aliasAttributeOid = schemaManager.getAttributeTypeRegistry().getOidByName(
            SchemaConstants.ALIASED_OBJECT_NAME_AT );

        if ( mods.getAttributeType().equals( aliasedObjectNameAT ) )
        {
            dropAliasIndices( partitionTxn, id );
        }

        // replaces old attributes with new modified ones if they exist
        if ( mods.size() > 0 )
        {
            entry.put( mods );
        }
        else
        // removes old attributes if new replacements do not exist
        {
            entry.remove( mods );
        }

        if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
        {
            Dn entryDn = getEntryDn( partitionTxn, id );
            addAliasIndices( partitionTxn, id, entryDn, new Dn( schemaManager, mods.getString() ) );
        }
    }


    /**
     * Completely removes the set of values for an attribute having the values
     * supplied while affecting the appropriate userIndices.  The entry is not
     * persisted: it is only changed in anticipation for a put into the master
     * table.  Note that an empty attribute w/o values will remove all the
     * values within the entry where as an attribute w/ values will remove those
     * attribute values it contains.
     *
     * @param partitionTxn The transaction to use
     * @param id the primary key of the entry
     * @param entry the entry to alter
     * @param mods the attribute and its values to delete
     * @throws Exception if index alteration or attribute modification fails.
     */
    @SuppressWarnings("unchecked")
    private void modifyRemove( PartitionTxn partitionTxn, String id, Entry entry, Attribute mods ) 
        throws LdapException, IndexNotFoundException
    {
        if ( entry instanceof ClonedServerEntry )
        {
            throw new LdapOtherException( I18n.err( I18n.ERR_215_CANNOT_STORE_CLONED_SERVER_ENTRY ) );
        }

        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
        AttributeType attributeType = mods.getAttributeType();

        // Special case for the ObjectClass index
        if ( attributeType.equals( objectClassAT ) )
        {
            /*
             * If there are no attribute values in the modifications then this
             * implies the complete removal of the attribute from the index. Else
             * we remove individual tuples from the index.
             */
            if ( mods.size() == 0 )
            {
                for ( Value value : entry.get( objectClassAT ) )
                {
                    if ( value.equals( topOCValue ) )
                    {
                        continue;
                    }
                    
                    String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                    objectClassIdx.drop( partitionTxn, normalizedOc, id );
                }
            }
            else
            {
                for ( Value value : mods )
                {
                    if ( value.equals( topOCValue ) )
                    {
                        continue;
                    }
                    
                    String normalizedOc = objectClassNormalizer.normalize( value.getString() );

                    objectClassIdx.drop( partitionTxn, normalizedOc, id );
                }
            }
        }
        else if ( hasUserIndexOn( attributeType ) )
        {
            Index<?, String> userIndex = getUserIndex( attributeType );

            Attribute attribute = entry.get( attributeType ).clone();
            int nbValues = 0;

            if ( attribute != null )
            {
                nbValues = attribute.size();
            }

            /*
             * If there are no attribute values in the modifications then this
             * implies the complete removal of the attribute from the index. Else
             * we remove individual tuples from the index.
             */
            if ( mods.size() == 0 )
            {
                ( ( Index ) userIndex ).drop( partitionTxn, id );
                nbValues = 0;
            }
            else if ( nbValues > 0 )
            {
                for ( Value value : mods )
                {
                    if ( attribute.contains( value ) )
                    {
                        nbValues--;
                        attribute.remove( value );
                    }

                    String normalized = value.getNormalized();
                    ( ( Index ) userIndex ).drop( partitionTxn, normalized, id );
                }
            }

            /*
             * If no attribute values exist for this entryId in the index then
             * we remove the presence index entry for the removed attribute.
             */
            if ( nbValues == 0 )
            {
                presenceIdx.drop( partitionTxn, modsOid, id );
            }
        }
        // Special case for the AdministrativeRole index
        else if ( modsOid.equals( SchemaConstants.ADMINISTRATIVE_ROLE_AT_OID ) )
        {
            // We may have more than one role 
            for ( Value value : mods )
            {
                adminRoleIdx.drop( partitionTxn, value.getString(), id );
            }

            /*
             * If no attribute values exist for this entryId in the index then
             * we remove the presence index entry for the removed attribute.
             */
            if ( null == adminRoleIdx.reverseLookup( partitionTxn, id ) )
            {
                presenceIdx.drop( partitionTxn, modsOid, id );
            }
        }

        /*
         * If there are no attribute values in the modifications then this
         * implies the complete removal of the attribute from the entry. Else
         * we remove individual attribute values from the entry in mods one
         * at a time.
         */
        if ( mods.size() == 0 )
        {
            entry.removeAttributes( mods.getAttributeType() );
        }
        else
        {
            Attribute entryAttr = entry.get( mods.getAttributeType() );

            for ( Value value : mods )
            {
                entryAttr.remove( value );
            }

            // if nothing is left just remove empty attribute
            if ( entryAttr.size() == 0 )
            {
                entry.removeAttributes( entryAttr.getId() );
            }
        }

        // Aliases->single valued comp/partial attr removal is not relevant here
        if ( mods.getAttributeType().equals( aliasedObjectNameAT ) )
        {
            dropAliasIndices( partitionTxn, id );
        }
    }


    //---------------------------------------------------------------------------------------------
    // The Move operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void move( MoveOperationContext moveContext ) throws LdapException
    {
        if ( moveContext.getNewSuperior().isDescendantOf( moveContext.getDn() ) )
        {
            throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
                "cannot place an entry below itself" );
        }
        
        PartitionTxn partitionTxn = moveContext.getTransaction();

        assert ( partitionTxn != null );
        assert ( partitionTxn instanceof PartitionWriteTxn );

        try
        {
            setRWLock( moveContext );
            Dn oldDn = moveContext.getDn();
            Dn newSuperior = moveContext.getNewSuperior();
            Dn newDn = moveContext.getNewDn();
            Entry modifiedEntry = moveContext.getModifiedEntry();

            move( partitionTxn, oldDn, newSuperior, newDn, modifiedEntry );
            updateCache( moveContext );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public final synchronized void move( PartitionTxn partitionTxn, Dn oldDn, Dn newSuperiorDn, Dn newDn, Entry modifiedEntry )
        throws LdapException
    {
        // Check that the parent Dn exists
        String newParentId = getEntryId( partitionTxn, newSuperiorDn );

        if ( newParentId == null )
        {
            // This is not allowed : the parent must exist
            throw new LdapEntryAlreadyExistsException(
                I18n.err( I18n.ERR_256_NO_SUCH_OBJECT, newSuperiorDn.getName() ) );
        }

        // Now check that the new entry does not exist
        String newId = getEntryId( partitionTxn, newDn );

        if ( newId != null )
        {
            // This is not allowed : we should not be able to move an entry
            // to an existing position
            throw new LdapEntryAlreadyExistsException(
                I18n.err( I18n.ERR_250_ENTRY_ALREADY_EXISTS, newSuperiorDn.getName() ) );
        }

        // Get the entry and the old parent IDs
        String entryId = getEntryId( partitionTxn, oldDn );
        String oldParentId = getParentId( partitionTxn, entryId );

        /*
         * All aliases including and below oldChildDn, will be affected by
         * the move operation with respect to one and subtree userIndices since
         * their relationship to ancestors above oldChildDn will be
         * destroyed.  For each alias below and including oldChildDn we will
         * drop the index tuples mapping ancestor ids above oldChildDn to the
         * respective target ids of the aliases.
         */
        dropMovedAliasIndices( partitionTxn, oldDn );

        // Update the Rdn index
        // First drop the old entry
        ParentIdAndRdn movedEntry = rdnIdx.reverseLookup( partitionTxn, entryId );

        updateRdnIdx( partitionTxn, oldParentId, REMOVE_CHILD, movedEntry.getNbDescendants() );

        rdnIdx.drop( partitionTxn, entryId );

        // Now, add the new entry at the right position
        movedEntry.setParentId( newParentId );
        rdnIdx.add( partitionTxn, movedEntry, entryId );

        updateRdnIdx( partitionTxn, newParentId, ADD_CHILD, movedEntry.getNbDescendants() );

        /*
         * Read Alias Index Tuples
         *
         * If this is a name change due to a move operation then the one and
         * subtree userIndices for aliases were purged before the aliases were
         * moved.  Now we must add them for each alias entry we have moved.
         *
         * aliasTarget is used as a marker to tell us if we're moving an
         * alias.  If it is null then the moved entry is not an alias.
         */
        Dn aliasTarget = aliasIdx.reverseLookup( partitionTxn, entryId );

        if ( null != aliasTarget )
        {
            if ( !aliasTarget.isSchemaAware() )
            {
                aliasTarget = new Dn( schemaManager, aliasTarget );
            }
            

            addAliasIndices( partitionTxn, entryId, buildEntryDn( partitionTxn, entryId ), aliasTarget );
        }

        // the below case arises only when the move( Dn oldDn, Dn newSuperiorDn, Dn newDn  ) is called
        // directly using the Store API, in this case the value of modified entry will be null
        // we need to lookup the entry to update the parent UUID
        if ( modifiedEntry == null )
        {
            modifiedEntry = fetch( partitionTxn, entryId );
        }

        // Update the master table with the modified entry
        modifiedEntry.put( ApacheSchemaConstants.ENTRY_PARENT_ID_AT, newParentId );

        // Remove the EntryDN
        modifiedEntry.removeAttributes( entryDnAT );

        entryDnCache.clear();
        
        setContextCsn( modifiedEntry.get( entryCsnAT ).getString() );

        master.put( partitionTxn, entryId, modifiedEntry );

        if ( isSyncOnWrite.get() )
        {
            sync();
        }
    }


    //---------------------------------------------------------------------------------------------
    // The MoveAndRename operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
    {
        if ( moveAndRenameContext.getNewSuperiorDn().isDescendantOf( moveAndRenameContext.getDn() ) )
        {
            throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
                "cannot place an entry below itself" );
        }

        PartitionTxn partitionTxn = moveAndRenameContext.getTransaction();

        assert ( partitionTxn != null );
        assert ( partitionTxn instanceof PartitionWriteTxn );

        try
        {
            setRWLock( moveAndRenameContext );
            Dn oldDn = moveAndRenameContext.getDn();
            Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
            Rdn newRdn = moveAndRenameContext.getNewRdn();
            Entry modifiedEntry = moveAndRenameContext.getModifiedEntry();
            Map<String, List<ModDnAva>> modAvas = moveAndRenameContext.getModifiedAvas();

            moveAndRename( partitionTxn, oldDn, newSuperiorDn, newRdn, modAvas, modifiedEntry );
            updateCache( moveAndRenameContext );
        }
        catch ( LdapException le )
        {
            // In case we get an LdapException, just rethrow it as is to
            // avoid having it lost
            throw le;
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * Moves an entry under a new parent.  The operation causes a shift in the
     * parent child relationships between the old parent, new parent and the
     * child moved.  All other descendant entries under the child never change
     * their direct parent child relationships.  Hence after the parent child
     * relationship changes are broken at the old parent and set at the new
     * parent a modifyDn operation is conducted to handle name changes
     * propagating down through the moved child and its descendants.
     *
     * @param oldDn the normalized dn of the child to be moved
     * @param newSuperiorDn the id of the child being moved
     * @param newRdn the normalized dn of the new parent for the child
     * @param modAvas The modified Avas
     * @param modifiedEntry the modified entry
     * @throws LdapException if something goes wrong
     */
    @Override
    public void moveAndRename( PartitionTxn partitionTxn, Dn oldDn, Dn newSuperiorDn, Rdn newRdn, Map<String, 
            List<ModDnAva>> modAvas, Entry modifiedEntry ) throws LdapException
    {
        // Get the child and the new parent to be entries and Ids
        Attribute entryIdAt = modifiedEntry.get( SchemaConstants.ENTRY_UUID_AT );
        String entryId;
        
        if ( entryIdAt == null )
        {
            entryId = getEntryId( partitionTxn, modifiedEntry.getDn() );
        }
        else
        {
            entryId = modifiedEntry.get( SchemaConstants.ENTRY_UUID_AT ).getString();
        }

        Attribute oldParentIdAt = modifiedEntry.get( ApacheSchemaConstants.ENTRY_PARENT_ID_AT );
        String oldParentId;
        
        if ( oldParentIdAt == null )
        {
            oldParentId = getEntryId( partitionTxn, oldDn.getParent() );
        }
        else
        {
            oldParentId = oldParentIdAt.getString();
        }

        String newParentId = getEntryId( partitionTxn, newSuperiorDn );

        //Get the info about the moved entry
        ParentIdAndRdn movedEntry = rdnIdx.reverseLookup( partitionTxn, entryId );
        
        // First drop the moved entry from the rdn index
        rdnIdx.drop( partitionTxn, entryId );

        //
        // The update the Rdn index. We will remove the ParentIdAndRdn associated with the
        // moved entry, and update the nbChilden of its parent and the nbSubordinates
        // of all its ascendant, up to the common superior.
        // Then we will add a ParentidAndRdn for the moved entry under the new superior,
        // update its children number and the nbSubordinates of all the new ascendant.
        updateRdnIdx( partitionTxn, oldParentId, REMOVE_CHILD, movedEntry.getNbDescendants() );

        /*
         * All aliases including and below oldChildDn, will be affected by
         * the move operation with respect to one and subtree userIndices since
         * their relationship to ancestors above oldChildDn will be
         * destroyed.  For each alias below and including oldChildDn we will
         * drop the index tuples mapping ancestor ids above oldChildDn to the
         * respective target ids of the aliases.
         */
        dropMovedAliasIndices( partitionTxn, oldDn );

        // Now, add the new entry at the right position
        // First
        movedEntry.setParentId( newParentId );
        movedEntry.setRdns( new Rdn[]
            { newRdn } );
        rdnIdx.add( partitionTxn, movedEntry, entryId );

        updateRdnIdx( partitionTxn, newParentId, ADD_CHILD, movedEntry.getNbDescendants() );

        // Process the modified indexes now
        try
        {
            processModifiedAvas( partitionTxn, modAvas, entryId );
        }
        catch ( IndexNotFoundException infe )
        {
            throw new LdapOtherException( infe.getMessage(), infe );
        }

        /*
         * Read Alias Index Tuples
         *
         * If this is a name change due to a move operation then the one and
         * subtree userIndices for aliases were purged before the aliases were
         * moved.  Now we must add them for each alias entry we have moved.
         *
         * aliasTarget is used as a marker to tell us if we're moving an
         * alias.  If it is null then the moved entry is not an alias.
         */
        Dn aliasTarget = aliasIdx.reverseLookup( partitionTxn, entryId );

        if ( null != aliasTarget )
        {
            if ( !aliasTarget.isSchemaAware() )
            {
                aliasTarget = new Dn( schemaManager, aliasTarget );
            }
            
            addAliasIndices( partitionTxn, entryId, buildEntryDn( partitionTxn, entryId ), aliasTarget );
        }

        // Remove the EntryDN
        modifiedEntry.removeAttributes( entryDnAT );
        
        // Update the entryParentId attribute
        modifiedEntry.removeAttributes( ApacheSchemaConstants.ENTRY_PARENT_ID_OID );
        modifiedEntry.add( ApacheSchemaConstants.ENTRY_PARENT_ID_OID, newParentId );
        
        // Doom the DN cache now
        entryDnCache.clear();

        setContextCsn( modifiedEntry.get( entryCsnAT ).getString() );

        // save the modified entry at the new place
        master.put( partitionTxn, entryId, modifiedEntry );
    }
    
    
    /**
     * Update the index accordingly to the changed Attribute in the old and new RDN
     * 
     * @param partitionTxn The transaction to use
     * @param modAvs The modified AVAs
     * @param entryId The Entry ID
     * @throws {@link LdapException} If the AVA cannt be processed properly
     * @throws IndexNotFoundException If teh index is not found
     */
    private void processModifiedAvas( PartitionTxn partitionTxn, Map<String, List<ModDnAva>> modAvas, String entryId ) 
        throws LdapException, IndexNotFoundException
    {
        for ( List<ModDnAva> modDnAvas : modAvas.values() )
        {
            for ( ModDnAva modDnAva : modDnAvas )
            {
                AttributeType attributeType = modDnAva.getAva().getAttributeType();
                
                if ( !hasIndexOn( attributeType ) )
                {
                    break;
                }

                Index<?, String> index = getUserIndex( attributeType );
                
                switch ( modDnAva.getType() )
                {
                    case ADD :
                    case UPDATE_ADD :
                        // Add Value in the index
                        ( ( Index ) index ).add( partitionTxn, modDnAva.getAva().getValue().getNormalized(), entryId );

                        /*
                         * If there is no value for id in this index due to our
                         * add above we add the entry in the presence idx
                         */
                        if ( null == index.reverseLookup( partitionTxn, entryId ) )
                        {
                            presenceIdx.add( partitionTxn, attributeType.getOid(), entryId );
                        }
                        
                        break;

                    case DELETE :
                    case UPDATE_DELETE :
                        ( ( Index ) index ).drop( partitionTxn, modDnAva.getAva().getValue().getNormalized(), entryId );

                        /*
                         * If there is no value for id in this index due to our
                         * drop above we remove the oldRdnAttr from the presence idx
                         */
                        if ( null == index.reverseLookup( partitionTxn, entryId ) )
                        {
                            presenceIdx.drop( partitionTxn, attributeType.getOid(), entryId );
                        }
                        
                        break;
                        
                    default :
                        break;
                }
            }
        }
    }
    
    
    //---------------------------------------------------------------------------------------------
    // The Rename operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( RenameOperationContext renameContext ) throws LdapException
    {
        PartitionTxn partitionTxn = renameContext.getTransaction();

        assert ( partitionTxn != null );
        assert ( partitionTxn instanceof PartitionWriteTxn );

        try
        {
            setRWLock( renameContext );
            Dn oldDn = renameContext.getDn();
            Rdn newRdn = renameContext.getNewRdn();
            boolean deleteOldRdn = renameContext.getDeleteOldRdn();

            if ( renameContext.getEntry() != null )
            {
                Entry modifiedEntry = renameContext.getModifiedEntry();
                rename( partitionTxn, oldDn, newRdn, deleteOldRdn, modifiedEntry );
            }
            else
            {
                rename( partitionTxn, oldDn, newRdn, deleteOldRdn, null );
            }

            updateCache( renameContext );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * This will rename the entry, and deal with the deleteOldRdn flag. If set to true, we have
     * to remove the AVA which are not part of the new RDN from the entry.
     * If this flag is set to false, we have to take care of the special case of an AVA
     * which attributeType is SINGLE-VALUE : in this case, we remove the old value.
     */
    private void rename( PartitionTxn partitionTxn, String oldId, Rdn newRdn, boolean deleteOldRdn, Entry entry ) 
        throws LdapException, IndexNotFoundException
    {
        if ( entry == null )
        {
            entry = master.get( partitionTxn, oldId );
        }

        Dn updn = entry.getDn();

        if ( !newRdn.isSchemaAware() )
        {
            newRdn = new Rdn( schemaManager, newRdn );
        }

        /*
         * H A N D L E   N E W   R D N
         * ====================================================================
         * Add the new Rdn attribute to the entry.  If an index exists on the
         * new Rdn attribute we add the index for this attribute value pair.
         * Also we make sure that the presence index shows the existence of the
         * new Rdn attribute within this entry.
         * Last, not least, if the AttributeType is single value, take care
         * of removing the old value.
         */
        for ( Ava newAtav : newRdn )
        {
            String newNormType = newAtav.getNormType();
            Object newNormValue = newAtav.getValue().getString();

            AttributeType newRdnAttrType = schemaManager.lookupAttributeTypeRegistry( newNormType );

            if ( newRdnAttrType.isSingleValued() && entry.containsAttribute( newRdnAttrType ) )
            {
                Attribute oldAttribute = entry.get( newRdnAttrType );
                AttributeType oldAttributeType = oldAttribute.getAttributeType();
                
                // We have to remove the old attribute value, if we have some
                entry.removeAttributes( newRdnAttrType );
                
                // Deal with the index
                if ( hasUserIndexOn( newRdnAttrType ) )
                {
                    Index<?, String> userIndex = getUserIndex( newRdnAttrType );

                    String normalized = oldAttributeType.getEquality().getNormalizer().normalize( oldAttribute.get().getString() );
                    ( ( Index ) userIndex ).drop( partitionTxn, normalized, id );

                    /*
                     * If there is no value for id in this index due to our
                     * drop above we remove the oldRdnAttr from the presence idx
                     */
                    if ( null == userIndex.reverseLookup( partitionTxn, oldId ) )
                    {
                        presenceIdx.drop( partitionTxn, newRdnAttrType.getOid(), oldId );
                    }

                }
            }

            if ( newRdnAttrType.getSyntax().isHumanReadable() )
            {
                entry.add( newRdnAttrType, newAtav.getValue().getString() );
            }
            else
            {
                entry.add( newRdnAttrType, newAtav.getValue().getBytes() );
            }

            if ( hasUserIndexOn( newRdnAttrType ) )
            {
                Index<?, String> userIndex = getUserIndex( newRdnAttrType );
                
                /*
                if ( oldRemoved )
                {
                    String normalized = newRdnAttrType.getEquality().getNormalizer().normalize( newNormValue );
                    ( ( Index ) userIndex ).add( normalized, id );
                    ( ( Index ) index ).drop( newNormValue, oldId );
                }
                */
                
                String normalized = newRdnAttrType.getEquality().getNormalizer().normalize( ( String ) newNormValue );
                ( ( Index ) userIndex ).add( partitionTxn, normalized, oldId );
                
                
                //( ( Index ) index ).add( newNormValue, oldId );

                // Make sure the altered entry shows the existence of the new attrib
                String normTypeOid = presenceNormalizer.normalize( newNormType );
                
                if ( !presenceIdx.forward( partitionTxn, normTypeOid, oldId ) )
                {
                    presenceIdx.add( partitionTxn, normTypeOid, oldId );
                }
            }
        }

        /*
         * H A N D L E   O L D   R D N
         * ====================================================================
         * If the old Rdn is to be removed we need to get the attribute and
         * value for it.  Keep in mind the old Rdn need not be based on the
         * same attr as the new one.  We remove the Rdn value from the entry
         * and remove the value/id tuple from the index on the old Rdn attr
         * if any.  We also test if the delete of the old Rdn index tuple
         * removed all the attribute values of the old Rdn using a reverse
         * lookup.  If so that means we blew away the last value of the old
         * Rdn attribute.  In this case we need to remove the attrName/id
         * tuple from the presence index.
         *
         * We only remove an ATAV of the old Rdn if it is not included in the
         * new Rdn.
         */

        if ( deleteOldRdn )
        {
            Rdn oldRdn = updn.getRdn();

            for ( Ava oldAtav : oldRdn )
            {
                // check if the new ATAV is part of the old Rdn
                // if that is the case we do not remove the ATAV
                boolean mustRemove = true;

                for ( Ava newAtav : newRdn )
                {
                    if ( oldAtav.equals( newAtav ) )
                    {
                        mustRemove = false;
                        break;
                    }
                }

                if ( mustRemove )
                {
                    String oldNormType = oldAtav.getNormType();
                    String oldNormValue = oldAtav.getValue().getString();
                    AttributeType oldRdnAttrType = schemaManager.lookupAttributeTypeRegistry( oldNormType );
                    entry.remove( oldRdnAttrType, oldNormValue );

                    if ( hasUserIndexOn( oldRdnAttrType ) )
                    {
                        Index<?, String> userIndex = getUserIndex( oldRdnAttrType );
                        
                        String normalized = oldRdnAttrType.getEquality().getNormalizer().normalize( oldNormValue );
                        ( ( Index ) userIndex ).drop( partitionTxn, normalized, id );

                        /*
                         * If there is no value for id in this index due to our
                         * drop above we remove the oldRdnAttr from the presence idx
                         */
                        if ( null == userIndex.reverseLookup( partitionTxn, oldId ) )
                        {
                            String oldNormTypeOid = presenceNormalizer.normalize( oldNormType );
                            presenceIdx.drop( partitionTxn, oldNormTypeOid, oldId );
                        }
                    }
                }
            }
        }

        // Remove the EntryDN
        entry.removeAttributes( entryDnAT );

        setContextCsn( entry.get( entryCsnAT ).getString() );

        // And save the modified entry
        master.put( partitionTxn, oldId, entry );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public final synchronized void rename( PartitionTxn partitionTxn, Dn dn, Rdn newRdn, boolean deleteOldRdn, Entry entry ) 
        throws LdapException
    {
        String oldId = getEntryId( partitionTxn, dn );

        try
        {
            rename( partitionTxn, oldId, newRdn, deleteOldRdn, entry );
        }
        catch ( IndexNotFoundException infe )
        {
            throw new LdapOtherException( infe.getMessage(), infe );
        }

        /*
         * H A N D L E   D N   C H A N G E
         * ====================================================================
         * We only need to update the Rdn index.
         * No need to calculate the new Dn.
         */
        String parentId = getParentId( partitionTxn, oldId );

        // Get the old parentIdAndRdn to get the nb of children and descendant
        ParentIdAndRdn parentIdAndRdn = rdnIdx.reverseLookup( partitionTxn, oldId );

        // Now we can drop it
        rdnIdx.drop( partitionTxn, oldId );

        // Update the descendants
        parentIdAndRdn.setParentId( parentId );
        parentIdAndRdn.setRdns( newRdn );

        rdnIdx.add( partitionTxn, parentIdAndRdn, oldId );

        entryDnCache.clear();
        
        if ( isSyncOnWrite.get() )
        {
            sync();
        }
    }


    //---------------------------------------------------------------------------------------------
    // The Unbind operation
    //---------------------------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public final void unbind( UnbindOperationContext unbindContext ) throws LdapException
    {
        // does nothing
    }


    /**
     * This method calls {@link Partition#lookup(LookupOperationContext)} and return <tt>true</tt>
     * if it returns an entry by default.  Please override this method if
     * there is more effective way for your implementation.
     */
    @Override
    public boolean hasEntry( HasEntryOperationContext entryContext ) throws LdapException
    {
        PartitionTxn partitionTxn = entryContext.getTransaction();
        
        assert ( partitionTxn != null );

        try
        {
            setRWLock( entryContext );

            String id = getEntryId( partitionTxn, entryContext.getDn() );

            Entry entry = fetch( partitionTxn, id, entryContext.getDn() );

            return entry != null;
        }
        catch ( LdapException e )
        {
            return false;
        }
    }


    //---------------------------------------------------------------------------------------------
    // Helper methods
    //---------------------------------------------------------------------------------------------
    /**
     * updates the CSN index
     *
     * @param partitionTxn The transaction to use
     * @param entry the entry having entryCSN attribute
     * @param id UUID of the entry
     * @throws Exception
     */
    private void updateCsnIndex( PartitionTxn partitionTxn, Entry entry, String id ) throws LdapException
    {
        String entryCsn = entry.get( SchemaConstants.ENTRY_CSN_AT ).getString();
        entryCsnIdx.drop( partitionTxn, id );
        entryCsnIdx.add( partitionTxn, entryCsn, id );
    }


    // ------------------------------------------------------------------------
    // Index and master table Operations
    // ------------------------------------------------------------------------
    /**
     * builds the Dn of the entry identified by the given id
     *
     * @param partitionTxn The transaction to use
     * @param id the entry's id
     * @return the normalized Dn of the entry
     * @throws LdapException If we can't build the entry Dn
     */
    protected Dn buildEntryDn( PartitionTxn partitionTxn, String id ) throws LdapException
    {
        String parentId = id;
        String rootId = Partition.ROOT_ID;

        // Create an array of 10 rdns, just in case. We will extend it if needed
        Rdn[] rdnArray = new Rdn[10];
        int pos = 0;

        Dn dn = null;
        
        try
        {
            rwLock.readLock().lock();

            if ( entryDnCache != null )
            {
                Dn cachedDn = entryDnCache.get( id );
                
                if ( cachedDn != null )
                {
                    return cachedDn;
                }
            }
            
            do
            {
                ParentIdAndRdn cur;
            
                if ( piarCache != null )
                {
                    cur = piarCache.get( parentId );
                    
                    if ( cur == null )
                    {
                        cur = rdnIdx.reverseLookup( partitionTxn, parentId );
                        
                        if ( cur == null )
                        {
                            return null;
                        }
                        
                        piarCache.put( parentId, cur );
                    }
                }
                else
                {
                    cur = rdnIdx.reverseLookup( partitionTxn, parentId );
                    
                    if ( cur == null )
                    {
                        return null;
                    }
                }

                Rdn[] rdns = cur.getRdns();

                for ( Rdn rdn : rdns )
                {
                    if ( ( pos > 0 ) && ( pos % 10 == 0 ) )
                    {
                        // extend the array
                        Rdn[] newRdnArray = new Rdn[pos + 10];
                        System.arraycopy( rdnArray, 0, newRdnArray, 0, pos );
                        rdnArray = newRdnArray;
                    }

                    rdnArray[pos++] = rdn;
                }

                parentId = cur.getParentId();
            }
            while ( !parentId.equals( rootId ) );
            
            dn = new Dn( schemaManager, Arrays.copyOf( rdnArray, pos ) );
            
            entryDnCache.put( id, dn );
            return dn;
        }
        finally
        {
            rwLock.readLock().unlock();
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public long count( PartitionTxn partitionTxn ) throws LdapException
    {
        return master.count( partitionTxn );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public final long getChildCount( PartitionTxn partitionTxn, String id ) throws LdapException
    {
        try
        {
            ParentIdAndRdn parentIdAndRdn = rdnIdx.reverseLookup( partitionTxn, id );

            return parentIdAndRdn.getNbChildren();
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public final Dn getEntryDn( PartitionTxn partitionTxn, String id ) throws LdapException
    {
        return buildEntryDn( partitionTxn, id );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public final String getEntryId( PartitionTxn partitionTxn, Dn dn ) throws LdapException
    {
        try
        {
            if ( Dn.isNullOrEmpty( dn ) )
            {
                return Partition.ROOT_ID;
            }

            ParentIdAndRdn suffixKey = new ParentIdAndRdn( Partition.ROOT_ID, suffixDn.getRdns() );

            // Check into the Rdn index, starting with the partition Suffix
            try
            {
                rwLock.readLock().lock();
                String currentId = rdnIdx.forwardLookup( partitionTxn, suffixKey );

                for ( int i = dn.size() - suffixDn.size(); i > 0; i-- )
                {
                    Rdn rdn = dn.getRdn( i - 1 );
                    ParentIdAndRdn currentRdn = new ParentIdAndRdn( currentId, rdn );
                    
                    currentId = rdnIdx.forwardLookup( partitionTxn, currentRdn );

                    if ( currentId == null )
                    {
                        break;
                    }
                }

                return currentId;
            }
            finally
            {
                rwLock.readLock().unlock();
            }
        }
        catch ( Exception e )
        {
            throw new LdapException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public String getParentId( PartitionTxn partitionTxn, String childId ) throws LdapException
    {
        try
        {
            rwLock.readLock().lock();
            ParentIdAndRdn key = rdnIdx.reverseLookup( partitionTxn, childId );

            if ( key == null )
            {
                return null;
            }

            return key.getParentId();
        }
        finally
        {
            rwLock.readLock().unlock();
        }
    }


    /**
     * Retrieve the SuffixID
     * 
     * @param partitionTxn The transaction to use
     * @return The Suffix ID
     * @throws LdapException If we weren't able to retrieve the Suffix ID
     */
    public String getSuffixId( PartitionTxn partitionTxn ) throws LdapException
    {
        if ( suffixId == null )
        {
            ParentIdAndRdn key = new ParentIdAndRdn( Partition.ROOT_ID, suffixDn.getRdns() );

            try
            {
                rwLock.readLock().lock();
                suffixId = rdnIdx.forwardLookup( partitionTxn, key );
            }
            finally
            {
                rwLock.readLock().unlock();
            }
        }

        return suffixId;
    }


    //------------------------------------------------------------------------
    // Index handling
    //------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void addIndex( Index<?, String> index ) throws LdapException
    {
        checkInitialized( "addIndex" );

        // Check that the index String is valid
        AttributeType attributeType = null;

        try
        {
            attributeType = schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() );
        }
        catch ( LdapNoSuchAttributeException lnsae )
        {
            LOG.error( "Cannot initialize the index for AttributeType {}, this value does not exist",
                index.getAttributeId() );

            return;
        }

        String oid = attributeType.getOid();

        if ( SYS_INDEX_OIDS.contains( oid ) )
        {
            if ( !systemIndices.containsKey( oid ) )
            {
                systemIndices.put( oid, index );
            }
        }
        else
        {
            if ( !userIndices.containsKey( oid ) )
            {
                userIndices.put( oid, index );
            }
        }
    }


    /**
     * Add some new indexes
     * @param indexes The added indexes
     */
    public void addIndexedAttributes( Index<?, String>... indexes )
    {
        for ( Index<?, String> index : indexes )
        {
            indexedAttributes.add( index );
        }
    }


    /**
     * Set the list of indexes for this partition
     * @param indexedAttributes The list of indexes
     */
    public void setIndexedAttributes( Set<Index<?, String>> indexedAttributes )
    {
        this.indexedAttributes = indexedAttributes;
    }


    /**
     * @return The list of indexed attributes
     */
    public Set<Index<?, String>> getIndexedAttributes()
    {
        return indexedAttributes;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Iterator<String> getUserIndices()
    {
        return userIndices.keySet().iterator();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Iterator<String> getSystemIndices()
    {
        return systemIndices.keySet().iterator();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Index<?, String> getIndex( AttributeType attributeType ) throws IndexNotFoundException
    {
        String id = attributeType.getOid();

        if ( userIndices.containsKey( id ) )
        {
            return userIndices.get( id );
        }

        if ( systemIndices.containsKey( id ) )
        {
            return systemIndices.get( id );
        }

        throw new IndexNotFoundException( I18n.err( I18n.ERR_3, id, id ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Index<?, String> getUserIndex( AttributeType attributeType ) throws IndexNotFoundException
    {
        if ( attributeType == null )
        {
            throw new IndexNotFoundException( I18n.err( I18n.ERR_3, attributeType, attributeType ) );
        }

        String oid = attributeType.getOid();

        if ( userIndices.containsKey( oid ) )
        {
            return userIndices.get( oid );
        }

        throw new IndexNotFoundException( I18n.err( I18n.ERR_3, attributeType, attributeType ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Index<?, String> getSystemIndex( AttributeType attributeType ) throws IndexNotFoundException
    {
        if ( attributeType == null )
        {
            throw new IndexNotFoundException( I18n.err( I18n.ERR_2, attributeType, attributeType ) );
        }

        String oid = attributeType.getOid();

        if ( systemIndices.containsKey( oid ) )
        {
            return systemIndices.get( oid );
        }

        throw new IndexNotFoundException( I18n.err( I18n.ERR_2, attributeType, attributeType ) );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<Dn, String> getAliasIndex()
    {
        return ( Index<Dn, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<String, String> getOneAliasIndex()
    {
        return ( Index<String, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_ONE_ALIAS_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<String, String> getSubAliasIndex()
    {
        return ( Index<String, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_SUB_ALIAS_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<String, String> getObjectClassIndex()
    {
        return ( Index<String, String> ) systemIndices.get( SchemaConstants.OBJECT_CLASS_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<String, String> getEntryCsnIndex()
    {
        return ( Index<String, String> ) systemIndices.get( SchemaConstants.ENTRY_CSN_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public Index<String, String> getAdministrativeRoleIndex()
    {
        return ( Index<String, String> ) systemIndices.get( SchemaConstants.ADMINISTRATIVE_ROLE_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<String, String> getPresenceIndex()
    {
        return ( Index<String, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Index<ParentIdAndRdn, String> getRdnIndex()
    {
        return ( Index<ParentIdAndRdn, String> ) systemIndices.get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasUserIndexOn( AttributeType attributeType ) throws LdapException
    {
        String oid = attributeType.getOid();
        return userIndices.containsKey( oid );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasSystemIndexOn( AttributeType attributeType ) throws LdapException
    {
        return systemIndices.containsKey( attributeType.getOid() );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasIndexOn( AttributeType attributeType ) throws LdapException
    {
        return hasUserIndexOn( attributeType ) || hasSystemIndexOn( attributeType );
    }


    //---------------------------------------------------------------------------------------------
    // Alias index manipulation
    //---------------------------------------------------------------------------------------------
    /**
     * Adds userIndices for an aliasEntry to be added to the database while checking
     * for constrained alias constructs like alias cycles and chaining.
     *
     * @param partitionTxn The transaction to use
     * @param aliasDn normalized distinguished name for the alias entry
     * @param aliasTarget the user provided aliased entry dn as a string
     * @param aliasId the id of alias entry to add
     * @throws LdapException if index addition fails, and if the alias is
     * not allowed due to chaining or cycle formation.
     * @throws LdapException if the wrappedCursor btrees cannot be altered
     */
    protected void addAliasIndices( PartitionTxn partitionTxn, String aliasId, Dn aliasDn, Dn aliasTarget ) 
            throws LdapException
    {
        String targetId; // Id of the aliasedObjectName
        Dn ancestorDn; // Name of an alias entry relative
        String ancestorId; // Id of an alias entry relative

        /*
         * Check For Aliases External To Naming Context
         *
         * id may be null but the alias may be to a valid entry in
         * another namingContext.  Such aliases are not allowed and we
         * need to point it out to the user instead of saying the target
         * does not exist when it potentially could outside of this upSuffix.
         */
        if ( !aliasTarget.isDescendantOf( suffixDn ) )
        {
            String msg = I18n.err( I18n.ERR_225, suffixDn.getName() );
            throw new LdapAliasDereferencingException( msg );
        }

        // L O O K U P   T A R G E T   I D
        targetId = getEntryId( partitionTxn, aliasTarget );

        /*
         * Check For Target Existence
         *
         * We do not allow the creation of inconsistent aliases.  Aliases should
         * not be broken links.  If the target does not exist we start screaming
         */
        if ( null == targetId )
        {
            // Complain about target not existing
            String msg = I18n.err( I18n.ERR_581, aliasDn.getName(), aliasTarget );
            throw new LdapAliasException( msg );
        }

        /*
         * Detect Direct Alias Chain Creation
         *
         * Rather than resusitate the target to test if it is an alias and fail
         * due to chaing creation we use the alias index to determine if the
         * target is an alias.  Hence if the alias we are about to create points
         * to another alias as its target in the aliasedObjectName attribute,
         * then we have a situation where an alias chain is being created.
         * Alias chaining is not allowed so we throw and exception.
         */
        if ( null != aliasIdx.reverseLookup( partitionTxn, targetId ) )
        {
            String msg = I18n.err( I18n.ERR_227 );
            throw new LdapAliasDereferencingException( msg );
        }

        // Add the alias to the simple alias index
        aliasIdx.add( partitionTxn, aliasTarget, aliasId );
        
        if ( aliasCache != null )
        {
            aliasCache.put( aliasId, aliasTarget );
        }

        /*
         * Handle One Level Scope Alias Index
         *
         * The first relative is special with respect to the one level alias
         * index.  If the target is not a sibling of the alias then we add the
         * index entry maping the parent's id to the aliased target id.
         */
        ancestorDn = aliasDn.getParent();
        ancestorId = getEntryId( partitionTxn, ancestorDn );

        // check if alias parent and aliased entry are the same
        Dn normalizedAliasTargetParentDn = aliasTarget.getParent();

        if ( !aliasDn.isDescendantOf( normalizedAliasTargetParentDn ) )
        {
            oneAliasIdx.add( partitionTxn, ancestorId, targetId );
        }

        /*
         * Handle Sub Level Scope Alias Index
         *
         * Walk the list of relatives from the parents up to the upSuffix, testing
         * to see if the alias' target is a descendant of the relative.  If the
         * alias target is not a descentant of the relative it extends the scope
         * and is added to the sub tree scope alias index.  The upSuffix node is
         * ignored since everything is under its scope.  The first loop
         * iteration shall handle the parents.
         */
        while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
        {
            if ( !aliasTarget.isDescendantOf( ancestorDn ) )
            {
                subAliasIdx.add( partitionTxn, ancestorId, targetId );
            }

            ancestorDn = ancestorDn.getParent();
            ancestorId = getEntryId( partitionTxn, ancestorDn );
        }
    }


    /**
     * Removes the index entries for an alias before the entry is deleted from
     * the master table.
     *
     * TODO Optimize this by walking the hierarchy index instead of the name
     * 
     * @param partitionTxn The transaction to use
     * @param aliasId the id of the alias entry in the master table
     * @throws LdapException if we cannot delete index values in the database
     */
    protected void dropAliasIndices( PartitionTxn partitionTxn, String aliasId ) throws LdapException
    {
        Dn targetDn = aliasIdx.reverseLookup( partitionTxn, aliasId );
        
        if ( !targetDn.isSchemaAware() )
        {
            targetDn = new Dn( schemaManager, targetDn );
        }

        String targetId = getEntryId( partitionTxn, targetDn );

        if ( targetId == null )
        {
            // the entry doesn't exist, probably it has been deleted or renamed
            // TODO: this is just a workaround for now, the alias indices should be updated when target entry is deleted or removed
            return;
        }

        Dn aliasDn = getEntryDn( partitionTxn, aliasId );

        Dn ancestorDn = aliasDn.getParent();
        String ancestorId = getEntryId( partitionTxn, ancestorDn );

        /*
         * We cannot just drop all tuples in the one level and subtree userIndices
         * linking baseIds to the targetId.  If more than one alias refers to
         * the target then droping all tuples with a value of targetId would
         * make all other aliases to the target inconsistent.
         *
         * We need to walk up the path of alias ancestors until we reach the
         * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
         * subtree scope alias.  We only need to do this for the direct parent
         * of the alias on the one level subtree.
         */
        oneAliasIdx.drop( partitionTxn, ancestorId, targetId );
        subAliasIdx.drop( partitionTxn, ancestorId, targetId );

        while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
        {
            ancestorDn = ancestorDn.getParent();
            ancestorId = getEntryId( partitionTxn, ancestorDn );

            subAliasIdx.drop( partitionTxn, ancestorId, targetId );
        }

        // Drops all alias tuples pointing to the id of the alias to be deleted
        aliasIdx.drop( partitionTxn, aliasId );

        if ( aliasCache != null )
        {
            aliasCache.remove( aliasId );
        }
    }


    /**
     * For all aliases including and under the moved base, this method removes
     * one and subtree alias index tuples for old ancestors above the moved base
     * that will no longer be ancestors after the move.
     *
     * @param partitionTxn The transaction to use
     * @param movedBase the base at which the move occurred - the moved node
     * @throws LdapException if system userIndices fail
     */
    protected void dropMovedAliasIndices( PartitionTxn partitionTxn, Dn movedBase ) throws LdapException
    {
        String movedBaseId = getEntryId( partitionTxn, movedBase );

        Dn targetDn = aliasIdx.reverseLookup( partitionTxn, movedBaseId );
        
        if ( targetDn != null )
        {
            if ( !targetDn.isSchemaAware() )
            {
                targetDn = new Dn( schemaManager, targetDn );
            }

            String targetId = getEntryId( partitionTxn, targetDn );
            Dn aliasDn = getEntryDn( partitionTxn, movedBaseId );

            /*
             * Start droping index tuples with the first ancestor right above the
             * moved base.  This is the first ancestor effected by the move.
             */
            Dn ancestorDn = movedBase.getParent();
            String ancestorId = getEntryId( partitionTxn, ancestorDn );

            /*
             * We cannot just drop all tuples in the one level and subtree userIndices
             * linking baseIds to the targetId.  If more than one alias refers to
             * the target then droping all tuples with a value of targetId would
             * make all other aliases to the target inconsistent.
             *
             * We need to walk up the path of alias ancestors right above the moved
             * base until we reach the upSuffix, deleting each ( ancestorId,
             * targetId ) tuple in the subtree scope alias.  We only need to do
             * this for the direct parent of the alias on the one level subtree if
             * the moved base is the alias.
             */
            if ( aliasDn.equals( movedBase ) )
            {
                oneAliasIdx.drop( partitionTxn, ancestorId, targetId );
            }

            subAliasIdx.drop( partitionTxn, ancestorId, targetId );

            while ( !ancestorDn.equals( suffixDn ) )
            {
                ancestorDn = ancestorDn.getParent();
                ancestorId = getEntryId( partitionTxn, ancestorDn );

                subAliasIdx.drop( partitionTxn, ancestorId, targetId );
            }
        }
    }


    //---------------------------------------------------------------------------------------------
    // Debug methods
    //---------------------------------------------------------------------------------------------
    private void dumpIndex( PartitionTxn partitionTxn, OutputStream stream, Index<?, String> index )
    {
        try
        {
            Cursor<IndexEntry<?, String>> cursor = ( Cursor ) index.forwardCursor( partitionTxn );

            while ( cursor.next() )
            {
                IndexEntry<?, String> entry = cursor.get();

                System.out.println( entry );
            }
        }
        catch ( Exception e )
        {
            // TODO : fixme
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void dumpIndex( PartitionTxn partitionTxn, OutputStream stream, String name ) throws IOException
    {
        try
        {
            AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name );

            if ( attributeType == null )
            {
                stream.write( Strings.getBytesUtf8( "Cannot find an index for AttributeType names " + name ) );

                return;
            }

            if ( attributeType.getOid().equals( ApacheSchemaConstants.APACHE_RDN_AT_OID ) )
            {
                dumpIndex( partitionTxn, stream, rdnIdx );
            }
        }
        catch ( LdapException le )
        {
            stream.write( Strings.getBytesUtf8( "Cannot find an index for AttributeType names " + name ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        return "Partition<" + id + ">";
    }


    /**
     * Create a new Index for a given OID
     * 
     * @param indexOid The Attribute OID
     * @param path The working directory where this index will be stored
     * @param withReverse If the Reverse index must be created or not
     * @return The created index
     * @throws LdapException If the index can't be created
     */
    protected abstract Index createSystemIndex( String indexOid, URI path, boolean withReverse ) throws LdapException;


    /**
     * {@inheritDoc}
     */
    @Override
    public MasterTable getMasterTable()
    {
        return master;
    }


    /**
     * Acquire a Read lock
     */
    private void lockRead()
    {
        rwLock.readLock().lock();
    }


    /**
     * Release a Read lock
     */
    private void unlockRead()
    {
        rwLock.readLock().unlock();
    }


    /**
     * Acquire a Write lock
     */
    private void lockWrite()
    {
        rwLock.writeLock().lock();
    }


    /**
     * Release a Write lock
     */
    private void unlockWrite()
    {
        rwLock.writeLock().unlock();
    }


    /**
     * updates the cache based on the type of OperationContext
     * 
     * @param opCtx the operation's context
     */
    public void updateCache( OperationContext opCtx )
    {
        // partition implementations should override this if they want to use cache
    }


    /**
     * looks up for the entry with the given ID in the cache
     *
     * @param id the ID of the entry
     * @return the Entry if exists, null otherwise
     */
    public Entry lookupCache( String id )
    {
        return null;
    }


    /**
     * adds the given entry to cache
     *  
     * Note: this method is not called during add operation to avoid filling the cache
     *       with all the added entries
     *       
     * @param id ID of the entry
     * @param entry the Entry
     */
    public void addToCache( String id, Entry entry )
    {
    }


    /**
     * @return the optimizer
     */
    public Optimizer getOptimizer()
    {
        return optimizer;
    }


    /**
     * @param optimizer the optimizer to set
     */
    public void setOptimizer( Optimizer optimizer )
    {
        this.optimizer = optimizer;
    }


    /**
     * @param searchEngine the searchEngine to set
     */
    public void setSearchEngine( SearchEngine searchEngine )
    {
        this.searchEngine = searchEngine;
    }


    /**
     * Set and return the ReadWrite lock we use to protect the backend against concurrent modifications
     * 
     * @param operationContext The OperationContext which contain the reference to the OperationManager
     */
    private void setRWLock( OperationContext operationContext )
    {
        if ( operationContext.getSession() != null )
        {
            rwLock = operationContext.getSession().getDirectoryService().getOperationManager().getRWLock();
        }
        else
        {
            if ( rwLock == null )
            {
                // Create a ReadWrite lock from scratch
                rwLock = new ReentrantReadWriteLock();
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ReadWriteLock getReadWriteLock()
    {
        return rwLock;
    }

    
    /**
     * {@inheritDoc}
     */
    @Override
    public Cache<String, Dn> getAliasCache()
    {
        return aliasCache;
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public String getContextCsn( PartitionTxn partitionTxn )
    {
        if ( super.getContextCsn( partitionTxn ) == null )
        {
           loadContextCsn( partitionTxn ); 
        }
        
        return super.getContextCsn( partitionTxn );
    }


    /**
     * Loads the current context CSN present in the context entry of the partition
     *
     * @param partitionTxn The transaction to use
     */
    protected void loadContextCsn( PartitionTxn partitionTxn )
    {
        try
        {
            if ( rwLock == null )
            {
                // Create a ReadWrite lock from scratch
                rwLock = new ReentrantReadWriteLock();
            }

            // load the last stored valid CSN value
            String contextEntryId = getEntryId( partitionTxn, getSuffixDn() );
            
            if ( contextEntryId == null )
            {
                return;
            }
            
            Entry entry = fetch( partitionTxn, contextEntryId );
            
            Attribute ctxCsnAt = entry.get( contextCsnAT );
            
            if ( ctxCsnAt != null )
            {
                setContextCsn( ctxCsnAt.getString() );
                ctxCsnChanged = false; // this is just loaded, not new
            }
        }
        catch ( LdapException e )
        {
            throw new RuntimeException( e );
        }
    }
    
    
    /**
     * {@inheritDoc}
     */
    // store the contextCSN value in the context entry 
    // note that this modification shouldn't change the entryCSN value of the context entry
    @Override
    public void saveContextCsn( PartitionTxn partitionTxn ) throws LdapException
    {
        if ( !ctxCsnChanged )
        {
            return;
        }
        
        String contextCsn = super.getContextCsn( partitionTxn );
        
        if ( contextCsn == null )
        {
            return;
        }
        
        try
        {
            // we don't need to use the ctxCsnSemaphore here cause
            // the only other place this is called is from PartitionNexus.sync()
            // but that is protected by write lock in DefaultDirectoryService.shutdown()
            
            String contextEntryId = getEntryId( partitionTxn, getSuffixDn() );
            Entry origEntry = fetch( partitionTxn, contextEntryId );
            
            // The Context Entry may have been deleted. Get out if we don't find it
            if ( origEntry == null )
            {
                return;
            }

            origEntry = ( ( ClonedServerEntry ) origEntry ).getOriginalEntry();
            
            origEntry.removeAttributes( contextCsnAT, entryDnAT );
            
            origEntry.add( contextCsnAT, contextCsn );
            
            master.put( partitionTxn, contextEntryId, origEntry );
            
            ctxCsnChanged = false;
            
            LOG.debug( "Saved context CSN {} for the partition {}", contextCsn, suffixDn );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public Subordinates getSubordinates( PartitionTxn partitionTxn, Entry entry ) throws LdapException
    {
        Subordinates subordinates = new Subordinates();
        
        try
        {
            // Check into the Rdn index, starting with the partition Suffix
            try
            {
                rwLock.readLock().lock();
                ParentIdAndRdn parentIdAndRdn = rdnIdx.reverseLookup( partitionTxn, entry.get( SchemaConstants.ENTRY_UUID_AT ).getString() );

                subordinates.setNbChildren( parentIdAndRdn.getNbChildren() );
                subordinates.setNbSubordinates( parentIdAndRdn.getNbDescendants() );
            }
            finally
            {
                rwLock.readLock().unlock();
            }
        }
        catch ( Exception e )
        {
            throw new LdapException( e.getMessage(), e );
        }

        return subordinates;
    }
}
