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


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.directory.api.ldap.extras.controls.ad.TreeDelete;
import org.apache.directory.api.ldap.model.constants.Loggers;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
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.Value;
import org.apache.directory.api.ldap.model.exception.LdapAffectMultipleDsaException;
import org.apache.directory.api.ldap.model.exception.LdapException;
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.LdapPartialResultException;
import org.apache.directory.api.ldap.model.exception.LdapReferralException;
import org.apache.directory.api.ldap.model.exception.LdapServiceUnavailableException;
import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
import org.apache.directory.api.ldap.model.filter.PresenceNode;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.message.SearchScope;
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.url.LdapUrl;
import org.apache.directory.server.constants.ApacheSchemaConstants;
import org.apache.directory.server.core.api.CoreSession;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.OperationManager;
import org.apache.directory.server.core.api.ReferralManager;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.api.interceptor.Interceptor;
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext;
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.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.Partition;
import org.apache.directory.server.core.api.partition.PartitionTxn;
import org.apache.directory.server.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * The default implementation of an OperationManager.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class DefaultOperationManager implements OperationManager
{
    /** A logger specifically for operations */
    private static final Logger OPERATION_LOG = LoggerFactory.getLogger( Loggers.OPERATION_LOG.getName() );

    /** A logger specifically for operations time */
    private static final Logger OPERATION_TIME = LoggerFactory.getLogger( Loggers.OPERATION_TIME.getName() );

    /** A logger specifically for operations statistics */
    private static final Logger OPERATION_STAT = LoggerFactory.getLogger( Loggers.OPERATION_STAT.getName() );

    /** Speedup for logs */
    private static final boolean IS_DEBUG = OPERATION_LOG.isDebugEnabled();
    private static final boolean IS_TIME = OPERATION_TIME.isDebugEnabled();
    private static final boolean IS_STAT = OPERATION_STAT.isDebugEnabled();

    /** The directory service instance */
    private final DirectoryService directoryService;

    /** A lock used to protect against concurrent operations */
    private ReadWriteLock rwLock = new ReentrantReadWriteLock( true );

    /** A reference to the ObjectClass AT */
    protected AttributeType objectClassAT;
    
    /** The nbChildren count attributeType */
    protected AttributeType nbChildrenAT;
    
    public DefaultOperationManager( DirectoryService directoryService )
    {
        this.directoryService = directoryService;
    }


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


    /**
     * Acquires a ReadLock
     */
    public void lockRead()
    {
        rwLock.readLock().lock();
    }


    /**
     * Acquires a WriteLock
     */
    public void lockWrite()
    {
        rwLock.writeLock().lock();
    }


    /**
     * Releases a WriteLock
     */
    public void unlockWrite()
    {
        rwLock.writeLock().unlock();
    }


    /**
     * Releases a ReadLock
     */
    public void unlockRead()
    {
        rwLock.readLock().unlock();
    }


    /**
     * Eagerly populates fields of operation contexts so multiple Interceptors
     * in the processing pathway can reuse this value without performing a
     * redundant lookup operation.
     *
     * @param opContext the operation context to populate with cached fields
     */
    private void eagerlyPopulateFields( OperationContext opContext ) throws LdapException
    {
        // If the entry field is not set for ops other than add for example
        // then we set the entry but don't freak if we fail to do so since it
        // may not exist in the first place

        if ( opContext.getEntry() == null )
        {
            // We have to use the admin session here, otherwise we may have
            // trouble reading the entry due to insufficient access rights
            CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();

            LookupOperationContext lookupContext = new LookupOperationContext( adminSession, opContext.getDn(),
                SchemaConstants.ALL_ATTRIBUTES_ARRAY );
            lookupContext.setPartition( opContext.getPartition() );
            lookupContext.setTransaction( opContext.getTransaction() );
            Entry foundEntry = opContext.getSession().getDirectoryService().getPartitionNexus().lookup( lookupContext );

            if ( foundEntry != null )
            {
                opContext.setEntry( foundEntry );
            }
            else
            {
                // This is an error : we *must* have an entry if we want to be able to rename.
                throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_256_NO_SUCH_OBJECT, opContext.getDn() ) );
            }
        }
    }


    private Entry getOriginalEntry( OperationContext opContext ) throws LdapException
    {
        // We have to use the admin session here, otherwise we may have
        // trouble reading the entry due to insufficient access rights
        CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();

        Entry foundEntry = adminSession.lookup( opContext.getDn(), SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES,
            SchemaConstants.ALL_USER_ATTRIBUTES );

        if ( foundEntry != null )
        {
            return foundEntry;
        }
        else
        {
            // This is an error : we *must* have an entry if we want to be able to rename.
            throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_256_NO_SUCH_OBJECT,
                opContext.getDn() ) );
        }
    }


    private LdapReferralException buildReferralException( Entry parentEntry, Dn childDn ) throws LdapException
    {
        // Get the Ref attributeType
        Attribute refs = parentEntry.get( SchemaConstants.REF_AT );

        List<String> urls = new ArrayList<>();

        try
        {
            // manage each Referral, building the correct URL for each of them
            for ( Value url : refs )
            {
                // we have to replace the parent by the referral
                LdapUrl ldapUrl = new LdapUrl( url.getString() );

                // We have a problem with the Dn : we can't use the UpName,
                // as we may have some spaces around the ',' and '+'.
                // So we have to take the Rdn one by one, and create a
                // new Dn with the type and value UP form

                Dn urlDn = ldapUrl.getDn().add( childDn );

                ldapUrl.setDn( urlDn );
                urls.add( ldapUrl.toString() );
            }
        }
        catch ( LdapURLEncodingException luee )
        {
            throw new LdapOperationErrorException( luee.getMessage(), luee );
        }

        // Return with an exception
        LdapReferralException lre = new LdapReferralException( urls );
        lre.setRemainingDn( childDn );
        lre.setResolvedDn( parentEntry.getDn() );
        lre.setResolvedObject( parentEntry );

        return lre;
    }


    private LdapReferralException buildReferralExceptionForSearch( Entry parentEntry, Dn childDn, SearchScope scope )
        throws LdapException
    {
        // Get the Ref attributeType
        Attribute refs = parentEntry.get( SchemaConstants.REF_AT );

        List<String> urls = new ArrayList<>();

        // manage each Referral, building the correct URL for each of them
        for ( Value url : refs )
        {
            // we have to replace the parent by the referral
            try
            {
                LdapUrl ldapUrl = new LdapUrl( url.getString() );

                StringBuilder urlString = new StringBuilder();

                if ( ( ldapUrl.getDn() == null ) || ( ldapUrl.getDn() == Dn.ROOT_DSE ) )
                {
                    ldapUrl.setDn( parentEntry.getDn() );
                }
                else
                {
                    // We have a problem with the Dn : we can't use the UpName,
                    // as we may have some spaces around the ',' and '+'.
                    // So we have to take the Rdn one by one, and create a
                    // new Dn with the type and value UP form

                    Dn urlDn = ldapUrl.getDn().add( childDn );

                    ldapUrl.setDn( urlDn );
                }

                urlString.append( ldapUrl.toString() ).append( "??" );

                switch ( scope )
                {
                    case OBJECT:
                        urlString.append( "base" );
                        break;

                    case SUBTREE:
                        urlString.append( "sub" );
                        break;

                    case ONELEVEL:
                        urlString.append( "one" );
                        break;

                    default:
                        throw new IllegalArgumentException( "Unexpected scope " + scope );
                }

                urls.add( urlString.toString() );
            }
            catch ( LdapURLEncodingException luee )
            {
                // The URL is not correct, returns it as is
                urls.add( url.getString() );
            }
        }

        // Return with an exception
        LdapReferralException lre = new LdapReferralException( urls );
        lre.setRemainingDn( childDn );
        lre.setResolvedDn( parentEntry.getDn() );
        lre.setResolvedObject( parentEntry );

        return lre;
    }


    private LdapPartialResultException buildLdapPartialResultException( Dn childDn )
    {
        LdapPartialResultException lpre = new LdapPartialResultException( I18n.err( I18n.ERR_315 ) );

        lpre.setRemainingDn( childDn );
        lpre.setResolvedDn( Dn.EMPTY_DN );

        return lpre;
    }


    /**
     * {@inheritDoc}
     */
    public void add( AddOperationContext addContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> AddOperation : {}", addContext );
        }

        long addStart = 0L;

        if ( IS_TIME )
        {
            addStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the addContext Dn
        Dn dn = addContext.getDn();
        
        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            addContext.setDn( dn );
        }
        
        // Find the working partition
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        addContext.setPartition( partition );
        
        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            if ( directoryService.getReferralManager().hasParentReferral( dn ) )
            {
                Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                // Depending on the Context.REFERRAL property value, we will throw
                // a different exception.
                if ( addContext.isReferralIgnored() )
                {
                    throw buildLdapPartialResultException( childDn );
                }
                else
                {
                    throw buildReferralException( parentEntry, childDn );
                }
            }
        }
        finally
        {
            // Unlock the referral manager
            directoryService.getReferralManager().unlock();
        }

        // Call the Add method
        Interceptor head = directoryService.getInterceptor( addContext.getNextInterceptor() );

        lockWrite();

        // Start a Write transaction right away
        PartitionTxn transaction = addContext.getSession().getTransaction( partition ); 
        
        try
        {
            if ( transaction == null )
            {
                transaction = partition.beginWriteTransaction();
                
                if ( addContext.getSession().hasSessionTransaction() )
                {
                    addContext.getSession().addTransaction( partition, transaction );
                }
            }
            
            addContext.setTransaction( transaction );

            head.add( addContext );
            
            if ( !addContext.getSession().hasSessionTransaction() )
            {
                transaction.commit();
            }
        }
        catch ( LdapException le )
        {
            try
            {
                if ( transaction != null )
                {
                    transaction.abort();
                }
                
                throw le;
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        catch ( IOException ioe )
        {
            try
            {
                transaction.abort();
                
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
            catch ( IOException ioe2 )
            {
                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
            }
        }
        finally
        {
            unlockWrite();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< AddOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Add operation took {} ns", ( System.nanoTime() - addStart ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    public void bind( BindOperationContext bindContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> BindOperation : {}", bindContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Call the Delete method
        Interceptor head = directoryService.getInterceptor( bindContext.getNextInterceptor() );

        // Normalize the addContext Dn
        Dn dn = bindContext.getDn();
        
        if ( ( dn != null ) && !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            bindContext.setDn( dn );
        }

        lockRead();

        try
        {
            Partition partition = directoryService.getPartitionNexus().getPartition( dn );
            
            try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
            {
                bindContext.setPartition( partition );
                bindContext.setTransaction( partitionTxn );
                
                head.bind( bindContext );
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        finally
        {
            unlockRead();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< BindOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Bind operation took {} ns", ( System.nanoTime() - opStart )  );
        }
    }


    /**
     * {@inheritDoc}
     */
    public boolean compare( CompareOperationContext compareContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> CompareOperation : {}", compareContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();
        
        // Normalize the compareContext Dn
        Dn dn = compareContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            compareContext.setDn( dn );
        }

        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            // Check if we have an ancestor for this Dn
            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );

            if ( parentEntry != null )
            {
                // We have found a parent referral for the current Dn
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                if ( directoryService.getReferralManager().isReferral( dn ) )
                {
                    // This is a referral. We can delete it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !compareContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                {
                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( compareContext.isReferralIgnored() )
                    {
                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
            }
        }
        finally
        {
            // Unlock the ReferralManager
            directoryService.getReferralManager().unlock();
        }

        // populate the context with the old entry
        compareContext.setOriginalEntry( getOriginalEntry( compareContext ) );

        // Call the Compare method
        Interceptor head = directoryService.getInterceptor( compareContext.getNextInterceptor() );

        boolean result = false;

        lockRead();

        try
        {
            Partition partition = directoryService.getPartitionNexus().getPartition( dn );
            
            try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
            {
                compareContext.setPartition( partition );
                compareContext.setTransaction( partitionTxn );
                
                result = head.compare( compareContext );
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        finally
        {
            unlockRead();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< CompareOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Compare operation took {} ns", ( System.nanoTime() - opStart ) );
        }

        return result;
    }
    
    
    private void deleteEntry( DeleteOperationContext deleteContext , Dn dn ) throws LdapException
    {
        DeleteOperationContext entryDeleteContext = 
            new DeleteOperationContext( deleteContext.getSession(), dn );
        entryDeleteContext.setTransaction( deleteContext.getTransaction() );

        eagerlyPopulateFields( entryDeleteContext );
        
        // Call the Delete method
        Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );

        head.delete( entryDeleteContext );
    }
    
    
    private void processTreeDelete( DeleteOperationContext deleteContext, Dn dn ) throws LdapException, CursorException
    {
        objectClassAT = directoryService.getSchemaManager().getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
        nbChildrenAT = directoryService.getSchemaManager().getAttributeType( ApacheSchemaConstants.NB_CHILDREN_OID );

        // This is a depth first recursive operation
        PresenceNode filter = new PresenceNode( objectClassAT );
        SearchOperationContext searchContext = new SearchOperationContext( 
            deleteContext.getSession(), 
            dn, 
            SearchScope.ONELEVEL, filter,
            ApacheSchemaConstants.NB_CHILDREN_OID );
        searchContext.setTransaction( deleteContext.getTransaction() );

        EntryFilteringCursor cursor = search( searchContext );
        
        cursor.beforeFirst();
        
        while ( cursor.next() )
        {
            Entry entry = cursor.get();
            
            if ( Integer.parseInt( entry.get( nbChildrenAT ).getString() ) == 0 )
            {
                // We can delete the entry
                deleteEntry( deleteContext, entry.getDn() );
            }
            else
            {
                // Recurse
                processTreeDelete( deleteContext, entry.getDn() );
            }
        }
        
        // Done with the children, we can delete the entry
        // We can delete the entry
        deleteEntry( deleteContext, dn );
    }


    /**
     * {@inheritDoc}
     */
    public void delete( DeleteOperationContext deleteContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> DeleteOperation : {}", deleteContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the deleteContext Dn
        Dn dn = deleteContext.getDn();
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        deleteContext.setPartition( partition );

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            deleteContext.setDn( dn );
        }

        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );

            if ( parentEntry != null )
            {
                // We have found a parent referral for the current Dn
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                if ( directoryService.getReferralManager().isReferral( dn ) )
                {
                    // This is a referral. We can delete it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !deleteContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                {
                    // We can't delete an entry which has an ancestor referral

                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( deleteContext.isReferralIgnored() )
                    {
                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
            }
        }
        finally
        {
            // Unlock the ReferralManager
            directoryService.getReferralManager().unlock();
        }

        // populate the context with the old entry
        lockWrite();

        // Start a Write transaction right away
        PartitionTxn transaction = deleteContext.getSession().getTransaction( partition ); 
        
        try
        {
            if ( transaction == null )
            {
                transaction = partition.beginWriteTransaction();
                
                if ( deleteContext.getSession().hasSessionTransaction() )
                {
                    deleteContext.getSession().addTransaction( partition, transaction );
                }
            }
            
            deleteContext.setTransaction( transaction );

            // Check if the TreeDelete control is used
            if ( deleteContext.hasRequestControl( TreeDelete.OID ) )
            {
                try
                {
                    processTreeDelete( deleteContext, deleteContext.getDn() );

                    if ( !deleteContext.getSession().hasSessionTransaction() )
                    {
                        transaction.commit();
                    }
                }
                catch ( CursorException ce )
                {
                    try
                    {
                        if ( transaction != null )
                        {
                            transaction.abort();
                        }
                        
                        throw new LdapOtherException( ce.getMessage(), ce );
                    }
                    catch ( IOException ioe )
                    {
                        throw new LdapOtherException( ioe.getMessage(), ioe );
                    }
                }
            }
            else
            {
                eagerlyPopulateFields( deleteContext );
    
                // Call the Delete method
                Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
    
                head.delete( deleteContext );
    
                if ( !deleteContext.getSession().hasSessionTransaction() )
                {
                    transaction.commit();
                }
            }
        }
        catch ( LdapException le )
        {
            try
            {
                if ( transaction != null )
                {
                    transaction.abort();
                }
                
                throw le;
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        catch ( IOException ioe )
        {
            try
            {
                transaction.abort();
                
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
            catch ( IOException ioe2 )
            {
                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
            }
        }
        finally
        {
            unlockWrite();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< DeleteOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Delete operation took {} ns", ( System.nanoTime() - opStart ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    public Entry getRootDse( GetRootDseOperationContext getRootDseContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> GetRootDseOperation : {}", getRootDseContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        Interceptor head = directoryService.getInterceptor( getRootDseContext.getNextInterceptor() );
        Entry root;

        try
        {
            lockRead();
            
            Partition partition = directoryService.getPartitionNexus().getPartition( Dn.ROOT_DSE );
            
            try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
            {
                getRootDseContext.setPartition( partition );
                getRootDseContext.setTransaction( partitionTxn );
                
                root = head.getRootDse( getRootDseContext );
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        finally
        {
            unlockRead();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< getRootDseOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "GetRootDSE operation took {} ns", ( System.nanoTime() - opStart ) );
        }

        return root;
    }


    /**
     * {@inheritDoc}
     */
    public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> hasEntryOperation : {}", hasEntryContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        Interceptor head = directoryService.getInterceptor( hasEntryContext.getNextInterceptor() );

        boolean result = false;

        lockRead();

        // Normalize the addContext Dn
        Dn dn = hasEntryContext.getDn();
        
        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            hasEntryContext.setDn( dn );
        }

        try
        {
            Partition partition = directoryService.getPartitionNexus().getPartition( dn );

            try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
            {
                hasEntryContext.setPartition( partition );
                hasEntryContext.setTransaction( partitionTxn );

                result = head.hasEntry( hasEntryContext );
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        finally
        {
            unlockRead();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< HasEntryOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "HasEntry operation took {} ns", ( System.nanoTime() - opStart ) );
        }

        return result;
    }


    /**
     * {@inheritDoc}
     */
    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> LookupOperation : {}", lookupContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        Interceptor head = directoryService.getInterceptor( lookupContext.getNextInterceptor() );

        Entry entry = null;

        // Normalize the modifyContext Dn
        Dn dn = lookupContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            lookupContext.setDn( dn );
        }
        
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        lookupContext.setPartition( partition );
        
        // Start a read transaction right away
        try ( PartitionTxn transaction = partition.beginReadTransaction() )
        {
            lookupContext.setTransaction( transaction );

            lockRead();
    
            try
            {
                entry = head.lookup( lookupContext );
            }
            finally
            {
                unlockRead();
            }
        }
        catch ( IOException ioe )
        {
            throw new LdapOtherException( ioe.getMessage(), ioe );
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< LookupOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Lookup operation took {} ns", ( System.nanoTime() - opStart ) );
        }

        return entry;
    }


    /**
     * {@inheritDoc}
     */
    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> ModifyOperation : {}", modifyContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the modifyContext Dn
        Dn dn = modifyContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            modifyContext.setDn( dn );
        }

        ReferralManager referralManager = directoryService.getReferralManager();

        // We have to deal with the referral first
        referralManager.lockRead();

        try
        {
            // Check if we have an ancestor for this Dn
            Entry parentEntry = referralManager.getParentReferral( dn );

            if ( parentEntry != null )
            {
                if ( referralManager.isReferral( dn ) )
                {
                    // This is a referral. We can delete it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !modifyContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        // We have found a parent referral for the current Dn
                        Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                        throw buildReferralException( parentEntry, childDn );
                    }
                }
                else if ( referralManager.hasParentReferral( dn ) )
                {
                    // We can't delete an entry which has an ancestor referral

                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( modifyContext.isReferralIgnored() )
                    {
                        // We have found a parent referral for the current Dn
                        Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        // We have found a parent referral for the current Dn
                        Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                        throw buildReferralException( parentEntry, childDn );
                    }
                }
            }
        }
        finally
        {
            // Unlock the ReferralManager
            referralManager.unlock();
        }
        
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        modifyContext.setPartition( partition );
        
        lockWrite();
        
        // Start a Write transaction right away
        PartitionTxn transaction = modifyContext.getSession().getTransaction( partition ); 

        try
        {
            if ( transaction == null )
            {
                transaction = partition.beginWriteTransaction();
                
                if ( modifyContext.getSession().hasSessionTransaction() )
                {
                    modifyContext.getSession().addTransaction( partition, transaction );
                }
            }

            modifyContext.setTransaction( transaction );

            // populate the context with the old entry
            eagerlyPopulateFields( modifyContext );

            // Call the Modify method
            Interceptor head = directoryService.getInterceptor( modifyContext.getNextInterceptor() );

            head.modify( modifyContext );
            
            if ( !modifyContext.getSession().hasSessionTransaction() )
            {
                transaction.commit();
            }
        }
        catch ( LdapException le )
        {
            try 
            {
                if ( transaction != null )
                {
                    transaction.abort();
                }
                
                throw le;
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        catch ( IOException ioe )
        {
            try 
            {
                transaction.abort();
                
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
            catch ( IOException ioe2 )
            {
                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
            }
        }
        finally
        {
            unlockWrite();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< ModifyOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Modify operation took {} ns", ( System.nanoTime() - opStart ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    public void move( MoveOperationContext moveContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> MoveOperation : {}", moveContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the moveContext Dn
        Dn dn = moveContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            moveContext.setDn( dn );
        }

        // Normalize the moveContext superior Dn
        Dn newSuperiorDn = moveContext.getNewSuperior();

        if ( !newSuperiorDn.isSchemaAware() )
        {
            newSuperiorDn = new Dn( directoryService.getSchemaManager(), newSuperiorDn );
            moveContext.setNewSuperior( newSuperiorDn );
        }

        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            // Check if we have an ancestor for this Dn
            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );

            if ( parentEntry != null )
            {
                // We have found a parent referral for the current Dn
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                if ( directoryService.getReferralManager().isReferral( dn ) )
                {
                    // This is a referral. We can delete it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !moveContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                {
                    // We can't delete an entry which has an ancestor referral

                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( moveContext.isReferralIgnored() )
                    {
                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
            }

            // Now, check the destination
            // If he parent Dn is a referral, or has a referral ancestor, we have to issue a AffectMultipleDsas result
            // as stated by RFC 3296 Section 5.6.2
            if ( directoryService.getReferralManager().isReferral( newSuperiorDn )
                || directoryService.getReferralManager().hasParentReferral( newSuperiorDn ) )
            {
                throw new LdapAffectMultipleDsaException();
            }

        }
        finally
        {
            // Unlock the referral manager
            directoryService.getReferralManager().unlock();
        }

        lockWrite();
        
        // Find the working partition
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        moveContext.setPartition( partition );

        // Start a Write transaction right away
        PartitionTxn transaction = moveContext.getSession().getTransaction( partition ); 
        
        try
        {
            if ( transaction == null )
            {
                transaction = partition.beginWriteTransaction();
                
                if ( moveContext.getSession().hasSessionTransaction() )
                {
                    moveContext.getSession().addTransaction( partition, transaction );
                }
            }
        
            moveContext.setTransaction( transaction );
            Entry originalEntry = getOriginalEntry( moveContext );

            moveContext.setOriginalEntry( originalEntry );

            // Call the Move method
            Interceptor head = directoryService.getInterceptor( moveContext.getNextInterceptor() );

            head.move( moveContext );
            
            if ( !moveContext.getSession().hasSessionTransaction() )
            {
                transaction.commit();
            }
        }
        catch ( LdapException le )
        {
            try
            {
                if ( transaction != null )
                {
                    transaction.abort();
                }
                
                throw le;
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        catch ( IOException ioe )
        {
            try
            {
                if ( transaction != null )
                {
                    transaction.abort();
                }
                
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
            catch ( IOException ioe2 )
            {
                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
            }
        }
        finally
        {
            unlockWrite();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< MoveOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Move operation took {} ns", ( System.nanoTime() - opStart ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> MoveAndRenameOperation : {}", moveAndRenameContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the moveAndRenameContext Dn
        Dn dn = moveAndRenameContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            moveAndRenameContext.setDn( dn );
        }

        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            // Check if we have an ancestor for this Dn
            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );

            if ( parentEntry != null )
            {
                // We have found a parent referral for the current Dn
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                if ( directoryService.getReferralManager().isReferral( dn ) )
                {
                    // This is a referral. We can delete it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !moveAndRenameContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                {
                    // We can't delete an entry which has an ancestor referral

                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( moveAndRenameContext.isReferralIgnored() )
                    {
                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
            }

            // Now, check the destination
            // Normalize the moveAndRenameContext Dn
            Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();

            if ( !newSuperiorDn.isSchemaAware() )
            {
                newSuperiorDn = new Dn( directoryService.getSchemaManager(), newSuperiorDn );
                moveAndRenameContext.setNewSuperiorDn( newSuperiorDn );
            }

            // If he parent Dn is a referral, or has a referral ancestor, we have to issue a AffectMultipleDsas result
            // as stated by RFC 3296 Section 5.6.2
            if ( directoryService.getReferralManager().isReferral( newSuperiorDn )
                || directoryService.getReferralManager().hasParentReferral( newSuperiorDn ) )
            {
                // The parent Dn is a referral, we have to issue a AffectMultipleDsas result
                // as stated by RFC 3296 Section 5.6.2
                throw new LdapAffectMultipleDsaException();
            }
        }
        finally
        {
            // Unlock the ReferralManager
            directoryService.getReferralManager().unlock();
        }

        // Find the working partition
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        moveAndRenameContext.setPartition( partition );

        lockWrite();
        
        // Start a Write transaction right away
        PartitionTxn transaction = moveAndRenameContext.getSession().getTransaction( partition ); 
        
        try
        {
            if ( transaction == null )
            {
                transaction = partition.beginWriteTransaction();
                
                if ( moveAndRenameContext.getSession().hasSessionTransaction() )
                {
                    moveAndRenameContext.getSession().addTransaction( partition, transaction );
                }
            }

            moveAndRenameContext.setOriginalEntry( getOriginalEntry( moveAndRenameContext ) );
            moveAndRenameContext.setModifiedEntry( moveAndRenameContext.getOriginalEntry().clone() );
            moveAndRenameContext.setTransaction( transaction );

            // Call the MoveAndRename method
            Interceptor head = directoryService.getInterceptor( moveAndRenameContext.getNextInterceptor() );

            head.moveAndRename( moveAndRenameContext );

            if ( !moveAndRenameContext.getSession().hasSessionTransaction() )
            {
                transaction.commit();
            }
        }
        catch ( LdapException le )
        {
            try
            {
                if ( transaction != null )
                {
                    transaction.abort();
                }
                
                throw le;
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
        }
        catch ( IOException ioe )
        {
            try
            {
                transaction.abort();
                
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
            catch ( IOException ioe2 )
            {
                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
            }
        }
        finally
        {
            unlockWrite();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< MoveAndRenameOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "MoveAndRename operation took {} ns", ( System.nanoTime() - opStart ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    public void rename( RenameOperationContext renameContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> RenameOperation : {}", renameContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the renameContext Dn
        Dn dn = renameContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            renameContext.setDn( dn );
        }

        // Inject the newDn into the operation context
        // Inject the new Dn into the context
        if ( !dn.isEmpty() )
        {
            Dn newDn = dn.getParent();
            Rdn newRdn = renameContext.getNewRdn();
            
            if ( !newRdn.isSchemaAware() )
            {
                newRdn = new Rdn( directoryService.getSchemaManager(), newRdn );
                renameContext.setNewRdn( newRdn );
            }
            
            newDn = newDn.add( renameContext.getNewRdn() );
            renameContext.setNewDn( newDn );
        }

        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            // Check if we have an ancestor for this Dn
            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );

            if ( parentEntry != null )
            {
                // We have found a parent referral for the current Dn
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                if ( directoryService.getReferralManager().isReferral( dn ) )
                {
                    // This is a referral. We can delete it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !renameContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                {
                    // We can't delete an entry which has an ancestor referral

                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( renameContext.isReferralIgnored() )
                    {
                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        throw buildReferralException( parentEntry, childDn );
                    }
                }
            }
        }
        finally
        {
            // Unlock the ReferralManager
            directoryService.getReferralManager().unlock();
        }

        lockWrite();

        Partition partition = directoryService.getPartitionNexus().getPartition( dn );

        // Start a Write transaction right away
        PartitionTxn transaction = renameContext.getSession().getTransaction( partition ); 
        
        // Call the rename method
        try
        {
            if ( transaction == null )
            {
                transaction = partition.beginWriteTransaction();
                
                if ( renameContext.getSession().hasSessionTransaction() )
                {
                    renameContext.getSession().addTransaction( partition, transaction );
                }
            }

            renameContext.setPartition( partition );

            // populate the context with the old entry
            PartitionTxn partitionTxn = null;
            
            try
            {
                partitionTxn = partition.beginReadTransaction();
                
                renameContext.setTransaction( partitionTxn );
                
                eagerlyPopulateFields( renameContext );
            }
            finally
            {
                try
                {
                    // Nothing to do
                    if ( partitionTxn != null )
                    {
                        partitionTxn.close();
                    }
                }
                catch ( IOException ioe )
                {
                    throw new LdapOtherException( ioe.getMessage(), ioe );
                }
            }

            Entry originalEntry = getOriginalEntry( renameContext );
            renameContext.setOriginalEntry( originalEntry );
            renameContext.setModifiedEntry( originalEntry.clone() );
            Interceptor head = directoryService.getInterceptor( renameContext.getNextInterceptor() );

            // Start a Write transaction right away
            transaction = renameContext.getSession().getTransaction( partition ); 
            
            // Call the Rename method
            try
            {
                if ( transaction == null )
                {
                    transaction = partition.beginWriteTransaction();
                    
                    if ( renameContext.getSession().hasSessionTransaction() )
                    {
                        renameContext.getSession().addTransaction( partition, transaction );
                    }
                }

                renameContext.setTransaction( transaction );

                head.rename( renameContext );
                
                if ( !renameContext.getSession().hasSessionTransaction() )
                {
                    transaction.commit();
                }
            }
            catch ( LdapException le )
            {
                try
                {
                    if ( transaction != null )
                    {
                        transaction.abort();
                    }
                    
                    throw le;
                }
                catch ( IOException ioe )
                {
                    throw new LdapOtherException( ioe.getMessage(), ioe );
                }
            }
            catch ( IOException ioe )
            {
                try
                {
                    if ( transaction != null )
                    {
                        transaction.abort();
                    }
                    
                    throw new LdapOtherException( ioe.getMessage(), ioe );
                }
                catch ( IOException ioe2 )
                {
                    throw new LdapOtherException( ioe2.getMessage(), ioe2 );
                }
            }
        }
        finally
        {
            unlockWrite();
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< RenameOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Rename operation took {} ns", ( System.nanoTime() - opStart ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> SearchOperation : {}", searchContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Normalize the searchContext Dn
        Dn dn = searchContext.getDn();

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( directoryService.getSchemaManager(), dn );
            searchContext.setDn( dn );
        }

        // We have to deal with the referral first
        directoryService.getReferralManager().lockRead();

        try
        {
            // Check if we have an ancestor for this Dn
            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );

            if ( parentEntry != null )
            {
                // We have found a parent referral for the current Dn
                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );

                if ( directoryService.getReferralManager().isReferral( dn ) )
                {
                    // This is a referral. We can return it if the ManageDsaIt flag is true
                    // Otherwise, we just throw a LdapReferralException
                    if ( !searchContext.isReferralIgnored() )
                    {
                        // Throw a Referral Exception
                        throw buildReferralExceptionForSearch( parentEntry, childDn, searchContext.getScope() );
                    }
                }
                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                {
                    // We can't search an entry which has an ancestor referral

                    // Depending on the Context.REFERRAL property value, we will throw
                    // a different exception.
                    if ( searchContext.isReferralIgnored() )
                    {
                        throw buildLdapPartialResultException( childDn );
                    }
                    else
                    {
                        throw buildReferralExceptionForSearch( parentEntry, childDn, searchContext.getScope() );
                    }
                }
            }
        }
        finally
        {
            // Unlock the ReferralManager
            directoryService.getReferralManager().unlock();
        }

        // Call the Search method
        Interceptor head = directoryService.getInterceptor( searchContext.getNextInterceptor() );

        EntryFilteringCursor cursor = null;
        Partition partition = directoryService.getPartitionNexus().getPartition( dn );
        
        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            searchContext.setPartition( partition );
            searchContext.setTransaction( partitionTxn );
            lockRead();
    
            try
            {
                cursor = head.search( searchContext );
            }
            finally
            {
                unlockRead();
            }
        }
        catch ( IOException ioe )
        {
            throw new LdapOtherException( ioe.getMessage(), ioe );
        }

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< SearchOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Search operation took {} ns", ( System.nanoTime() - opStart ) );
        }

        return cursor;
    }


    /**
     * {@inheritDoc}
     */
    public void unbind( UnbindOperationContext unbindContext ) throws LdapException
    {
        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( ">> UnbindOperation : {}", unbindContext );
        }

        long opStart = 0L;

        if ( IS_TIME )
        {
            opStart = System.nanoTime();
        }

        ensureStarted();

        // Call the Unbind method
        Interceptor head = directoryService.getInterceptor( unbindContext.getNextInterceptor() );

        head.unbind( unbindContext );

        if ( IS_DEBUG )
        {
            OPERATION_LOG.debug( "<< UnbindOperation successful" );
        }

        if ( IS_TIME )
        {
            OPERATION_TIME.debug( "Unbind operation took {} ns", ( System.nanoTime() - opStart ) );
        }
    }


    private void ensureStarted() throws LdapServiceUnavailableException
    {
        if ( !directoryService.isStarted() )
        {
            throw new LdapServiceUnavailableException( ResultCodeEnum.UNAVAILABLE, I18n.err( I18n.ERR_316 ) );
        }
    }
}
