directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1334904 [2/3] - in /directory/apacheds/branches/apacheds-txns: core-api/src/main/java/org/apache/directory/server/core/api/ core-api/src/main/java/org/apache/directory/server/core/api/interceptor/ core-api/src/main/java/org/apache/director...
Date Mon, 07 May 2012 07:53:22 GMT
Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java?rev=1334904&r1=1334903&r2=1334904&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java (original)
+++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java Mon May  7 07:53:21 2012
@@ -363,6 +363,47 @@ public class DefaultOperationManager imp
             throw new LdapOtherException( e.getMessage(), e );
         }
     }
+    
+    
+    /*
+     * Reinit logical data if necessary
+     */
+    private void reinitLogicalData( TxnManager txnManager, Interceptor head )
+    {
+        try
+        {
+            if ( txnManager.prepareForLogicalDataReinit() )
+            {
+                txnManager.applyPendingTxns();
+                
+                directoryService.resetCaches();
+                directoryService.getSchemaManager().reloadAllEnabled();
+                
+                head.reinitLogicalData( directoryService );
+            }
+        }
+        catch ( Exception e )
+        {
+            // Ignore for now.
+            e.printStackTrace();
+        }
+    }
+    
+    
+    public boolean isCausedByConflictException( Throwable e )
+    {
+        while ( e != null )
+        {
+            if ( e instanceof TxnConflictException )
+            {
+                return true;
+            }
+            
+            e = e.getCause();
+        }
+        
+        return false;
+    }
 
 
     /**
@@ -375,86 +416,114 @@ public class DefaultOperationManager imp
 
         ensureStarted();
 
-        // Normalize the addContext Dn
-        Dn dn = addContext.getDn();
-
-        if ( !dn.isSchemaAware() )
-        {
-            dn.apply( directoryService.getSchemaManager() );
-        }
+        Interceptor head = directoryService.getInterceptor( addContext.getNextInterceptor() );
 
-        // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
+        boolean startedTxn = false;
+        TxnManager txnManager = directoryService.getTxnManager();
+        TxnHandle curTxn = txnManager.getCurTxn();
 
-        if ( directoryService.getReferralManager().hasParentReferral( dn ) )
+        boolean done;
+        
+        do
         {
-            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() )
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
+            
+            if ( startedTxn )
             {
-                directoryService.getReferralManager().unlock();
-
-                LdapPartialResultException exception = buildLdapPartialResultException( childDn );
-                throw exception;
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
+                
+                addContext.resetContext();
+                retryTransactionRW( txnManager );
             }
-            else
+            else if ( curTxn == null )
             {
-                // Unlock the referral manager
-                directoryService.getReferralManager().unlock();
-
-                LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                throw exception;
+                beginTransactionRW( txnManager );
+                startedTxn = true;
             }
-        }
-        else
-        {
-            // Unlock the ReferralManager
-            directoryService.getReferralManager().unlock();
 
-            // Call the Add method
-            Interceptor head = directoryService.getInterceptor( addContext.getNextInterceptor() );
+            addContext.saveOriginalContext();
+        
+            // Normalize the addContext Dn
+            Dn dn = addContext.getDn();
 
-            boolean startedTxn = false;
-            TxnManager txnManager = directoryService.getTxnManager();
-            TxnHandle curTxn = txnManager.getCurTxn();
+            if ( !dn.isSchemaAware() )
+            {
+                dn.apply( directoryService.getSchemaManager() );
+            }
 
-            boolean done = false;
-            
-            do
+            // We have to deal with the referral first
+            //directoryService.getReferralManager().lockRead();
+
+            if ( directoryService.getReferralManager().hasParentReferral( dn ) )
             {
-                if ( startedTxn )
+                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() )
                 {
-                    addContext.resetContext();
-                    retryTransactionRW( txnManager );
+                    //directoryService.getReferralManager().unlock();
+
+                    LdapPartialResultException exception = buildLdapPartialResultException( childDn );
+
+                    if ( startedTxn )
+                    {
+                        abortTransaction( txnManager, exception );
+                    }
+
+                    throw exception;
                 }
-                else if ( curTxn == null )
+                else
                 {
-                    beginTransactionRW( txnManager );
-                    startedTxn = true;
+                    // Unlock the referral manager
+                    //directoryService.getReferralManager().unlock();
+
+                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
+
+                    if ( startedTxn )
+                    {
+                        abortTransaction( txnManager, exception );
+                    }
+
+                    throw exception;
                 }
+            }
+            else
+            {
+                // Unlock the ReferralManager
+                //directoryService.getReferralManager().unlock();
+
+                // Call the Add method
 
-                addContext.saveOriginalContext();
-                
                 try
                 {
                     head.add( addContext );
                 }
                 catch ( LdapException le )
                 {
-                    if ( startedTxn )
+                    if ( startedTxn && isCausedByConflictException( le ) )
                     {
-                        abortTransaction( txnManager, le );
+                        // Retry
+                        done = false; 
                     }
+                    else
+                    {
+                        if ( startedTxn )
+                        {
+                            // Reset logical data if necessary
+                            reinitLogicalData( txnManager, head );
+                            
+                            abortTransaction( txnManager, le );
+                        }
 
-                    throw le;
+                        throw ( le );
+                    }
                 }
 
-                
-                done = true;
-                
                 if ( startedTxn )
                 {
                     try
@@ -463,14 +532,14 @@ public class DefaultOperationManager imp
                     }
                     catch ( TxnConflictException txne )
                     {
-                       done = false; // retry
+                        done = false; // retry
                     }
                 }
 
-                txnManager.applyPendingTxns();
-            }
-            while ( !done );
+                //txnManager.applyPendingTxns();
+            } 
         }
+        while ( !done );
 
         LOG.debug( "<< AddOperation successful" );
         LOG_CHANGES.debug( "<< AddOperation successful" );
@@ -495,14 +564,23 @@ public class DefaultOperationManager imp
 
         do
         {
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
+            
             if ( startedTxn )
             {
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
+                
                 bindContext.resetContext();
                 retryTransactionRW( txnManager );
             }
-            
-            beginTransactionRW( txnManager );
-            startedTxn = true;
+            else
+            {
+              beginTransactionRW( txnManager );
+              startedTxn = true;
+            }
             
             
             bindContext.saveOriginalContext();
@@ -510,37 +588,42 @@ public class DefaultOperationManager imp
             try
             {
                 head.bind( bindContext );
-                
-                // If here then we are done.
-                done = true;
             }
             catch ( LdapException le )
             {
-                /*
-                 *  TODO : Bind expects the changes to be committed even if the
-                 *  authentication fails. We should certainly skip some exceptions
-                 *  here. For now commit on every exception other than maybe
-                 *  conflict exception.
-                 */
-
-                boolean conflict = false;
-                
-                try
-                {
-                    commitTransaction( txnManager );
-                }
-                catch ( TxnConflictException txne )
+                if ( startedTxn && isCausedByConflictException( le ) )
                 {
-                   conflict = true; // retry
-                }
-
-                if ( conflict == false )
-                {
-                    throw ( le );
+                    // Retry
+                    done = false;
                 }
                 else
                 {
-                    done = false;
+                    /*
+                     *  TODO : Bind expects the changes to be committed even if the
+                     *  authentication fails. We should certainly skip some exceptions
+                     *  here. For now commit on every exception other than maybe
+                     *  conflict exception.
+                     */
+
+                    boolean conflict = false;
+
+                    try
+                    {
+                        commitTransaction( txnManager );
+                    }
+                    catch ( TxnConflictException txne )
+                    {
+                        conflict = true; // retry
+                    }
+
+                    if ( conflict == false )
+                    {
+                        throw ( le );
+                    }
+                    else
+                    {
+                        done = false;
+                    }
                 }
             }
 
@@ -569,12 +652,18 @@ public class DefaultOperationManager imp
         LOG.debug( ">> CompareOperation : {}", compareContext );
 
         ensureStarted();
+        
+        TxnManager txnManager = directoryService.getTxnManager();
+
+        beginTransactionR( txnManager );
+        boolean result = false;
+        
         // Normalize the compareContext Dn
         Dn dn = compareContext.getDn();
         dn.apply( directoryService.getSchemaManager() );
 
         // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
+        //directoryService.getReferralManager().lockRead();
 
         // Check if we have an ancestor for this Dn
         Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
@@ -592,9 +681,11 @@ public class DefaultOperationManager imp
                 {
                     // Throw a Referral Exception
                     // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                    //directoryService.getReferralManager().unlock();
 
                     LdapReferralException exception = buildReferralException( parentEntry, childDn );
+                    
+                    abortTransaction( txnManager, exception );
                     throw exception;
                 }
             }
@@ -604,29 +695,28 @@ public class DefaultOperationManager imp
                 // a different exception.
                 if ( compareContext.isReferralIgnored() )
                 {
-                    directoryService.getReferralManager().unlock();
+                    //directoryService.getReferralManager().unlock();
 
                     LdapPartialResultException exception = buildLdapPartialResultException( childDn );
+                    
+                    abortTransaction( txnManager, exception );
                     throw exception;
                 }
                 else
                 {
                     // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                    //directoryService.getReferralManager().unlock();
 
                     LdapReferralException exception = buildReferralException( parentEntry, childDn );
+                    
+                    abortTransaction( txnManager, exception );
                     throw exception;
                 }
             }
         }
 
         // Unlock the ReferralManager
-        directoryService.getReferralManager().unlock();
-
-        TxnManager txnManager = directoryService.getTxnManager();
-
-        beginTransactionR( txnManager );
-        boolean result = false;
+        //directoryService.getReferralManager().unlock();
 
         try
         {
@@ -669,105 +759,139 @@ public class DefaultOperationManager imp
         LOG_CHANGES.debug( ">> DeleteOperation : {}", deleteContext );
 
         ensureStarted();
+        
+        boolean startedTxn = false;
+        TxnManager txnManager = directoryService.getTxnManager();
+        TxnHandle curTxn = txnManager.getCurTxn();
 
-        // Normalize the deleteContext Dn
-        Dn dn = deleteContext.getDn();
-        dn.apply( directoryService.getSchemaManager() );
-
-        // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
-
-        Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
+        boolean done;
+        
+        // Save the head
+        Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
 
-        if ( parentEntry != null )
+        do
         {
-            // We have found a parent referral for the current Dn
-            Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
 
-            if ( directoryService.getReferralManager().isReferral( dn ) )
+            if ( startedTxn )
             {
-                // 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
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
 
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
+                deleteContext.resetContext();
+                retryTransactionRW( txnManager );
             }
-            else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
+            else if ( curTxn == null )
             {
-                // We can't delete an entry which has an ancestor referral
+                beginTransactionRW( txnManager );
+                startedTxn = true;
+            }
 
-                // Depending on the Context.REFERRAL property value, we will throw
-                // a different exception.
-                if ( deleteContext.isReferralIgnored() )
+            deleteContext.saveOriginalContext();
+
+            // Normalize the deleteContext Dn
+            Dn dn = deleteContext.getDn();
+            dn.apply( directoryService.getSchemaManager() );
+
+            // We have to deal with the referral first
+            //directoryService.getReferralManager().lockRead();
+
+            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 ) )
                 {
-                    directoryService.getReferralManager().unlock();
+                    // 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
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
 
-                    LdapPartialResultException exception = buildLdapPartialResultException( childDn );
-                    throw exception;
+                        throw exception;
+                    }
                 }
-                else
+                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                 {
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                    // We can't delete an entry which has an ancestor referral
 
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-        }
+                    // Depending on the Context.REFERRAL property value, we will throw
+                    // a different exception.
+                    if ( deleteContext.isReferralIgnored() )
+                    {
+                        //directoryService.getReferralManager().unlock();
 
-        // Unlock the ReferralManager
-        directoryService.getReferralManager().unlock();
+                        LdapPartialResultException exception = buildLdapPartialResultException( childDn );
 
-        boolean startedTxn = false;
-        TxnManager txnManager = directoryService.getTxnManager();
-        TxnHandle curTxn = txnManager.getCurTxn();
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
 
-        boolean done = false;
+                        throw exception;
+                    }
+                    else
+                    {
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
 
-        do
-        {
-            if ( startedTxn )
-            {
-                deleteContext.resetContext();
-                retryTransactionRW( txnManager );
-            }
-            else if ( curTxn == null )
-            {
-                beginTransactionRW( txnManager );
-                startedTxn = true;
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+
+                        throw exception;
+                    }
+                }
             }
 
-            deleteContext.saveOriginalContext();
+            // Unlock the ReferralManager
+            //directoryService.getReferralManager().unlock();
             
             try
             {
                 // populate the context with the old entry
                 eagerlyPopulateFields( deleteContext );
 
-                // Call the Delete method
-                Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
-
                 head.delete( deleteContext );
             }
             catch ( LdapException le )
             {
-                if ( startedTxn )
+                if ( startedTxn && isCausedByConflictException( le ) )
                 {
-                    abortTransaction( txnManager, le );
+                    // Retry
+                    done = false; 
                 }
+                else
+                {
+                    if ( startedTxn )
+                    {
+                        // Reset logical data if necessary
+                        reinitLogicalData( txnManager, head );
+                        
+                        abortTransaction( txnManager, le );
+                    }
 
-                throw le;
+                    throw ( le );
+                }
             }
 
-            // If here then we are done.
-            done = true;
             
             if ( startedTxn )
             {
@@ -780,7 +904,7 @@ public class DefaultOperationManager imp
                    done = false; // retry
                 }
             }
-            txnManager.applyPendingTxns();
+            //txnManager.applyPendingTxns();
         }
         while ( !done );
 
@@ -874,6 +998,8 @@ public class DefaultOperationManager imp
             cursor = head.list( listContext );
 
             cursor.setTxnManager( txnManager );
+            
+            txnManager.endLogicalDataRead();
             txnManager.setCurTxn( null );
         }
         catch ( LdapException le )
@@ -942,113 +1068,147 @@ public class DefaultOperationManager imp
 
         ensureStarted();
 
-        // Normalize the modifyContext Dn
-        Dn dn = modifyContext.getDn();
-        dn.apply( directoryService.getSchemaManager() );
-
-        ReferralManager referralManager = directoryService.getReferralManager();
-
-        // We have to deal with the referral first
-        referralManager.lockRead();
-
-        // Check if we have an ancestor for this Dn
-        Entry parentEntry = referralManager.getParentReferral( dn );
+        boolean done;
+        boolean startedTxn = false;
+        TxnManager txnManager = directoryService.getTxnManager();
+        TxnHandle curTxn = txnManager.getCurTxn();
+        
+        // Save the head
+        Interceptor head = directoryService.getInterceptor( modifyContext.getNextInterceptor() );
 
-        if ( parentEntry != null )
+        do
         {
-            if ( referralManager.isReferral( dn ) )
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
+            
+            if ( startedTxn )
             {
-                // 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
-                    // Unlock the referral manager
-                    referralManager.unlock();
-
-                    // We have found a parent referral for the current Dn
-                    Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
-
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
+                
+                modifyContext.resetContext();
+                retryTransactionRW( txnManager );
             }
-            else if ( referralManager.hasParentReferral( dn ) )
+            else if ( curTxn == null )
             {
-                // We can't delete an entry which has an ancestor referral
+                beginTransactionRW( txnManager );
+                startedTxn = true;
+            }
 
-                // Depending on the Context.REFERRAL property value, we will throw
-                // a different exception.
-                if ( modifyContext.isReferralIgnored() )
-                {
-                    referralManager.unlock();
+            modifyContext.saveOriginalContext();
+            
+            // Normalize the modifyContext Dn
+            Dn dn = modifyContext.getDn();
+            dn.apply( directoryService.getSchemaManager() );
 
-                    // We have found a parent referral for the current Dn
-                    Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
+            ReferralManager referralManager = directoryService.getReferralManager();
 
-                    LdapPartialResultException exception = buildLdapPartialResultException( childDn );
-                    throw exception;
+            // We have to deal with the referral first
+            // referralManager.lockRead();
+
+            // 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
+                        // Unlock the referral manager
+                       // referralManager.unlock();
+
+                        // We have found a parent referral for the current Dn
+                        Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
+                        
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+                        
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+                        
+                        throw exception;
+                    }
                 }
-                else
+                else if ( referralManager.hasParentReferral( dn ) )
                 {
-                    // Unlock the referral manager
-                    referralManager.unlock();
+                    // We can't delete an entry which has an ancestor referral
 
-                    // We have found a parent referral for the current Dn
-                    Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
+                    // Depending on the Context.REFERRAL property value, we will throw
+                    // a different exception.
+                    if ( modifyContext.isReferralIgnored() )
+                    {
+                        //referralManager.unlock();
 
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-        }
+                        // We have found a parent referral for the current Dn
+                        Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
 
-        // Unlock the ReferralManager
-        referralManager.unlock();
+                        LdapPartialResultException exception = buildLdapPartialResultException( childDn );
+                        
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+                        
+                        throw exception;
+                    }
+                    else
+                    {
+                        // Unlock the referral manager
+                        //referralManager.unlock();
 
-        boolean done = false;
-        boolean startedTxn = false;
-        TxnManager txnManager = directoryService.getTxnManager();
-        TxnHandle curTxn = txnManager.getCurTxn();
+                        // We have found a parent referral for the current Dn
+                        Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
 
-        do
-        {
-            if ( startedTxn )
-            {
-                modifyContext.resetContext();
-                retryTransactionRW( txnManager );
-            }
-            else if ( curTxn == null )
-            {
-                beginTransactionRW( txnManager );
-                startedTxn = true;
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+                        
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+                        
+                        throw exception;
+                    }
+                }
             }
 
-            modifyContext.saveOriginalContext();
+            // Unlock the ReferralManager
+            //referralManager.unlock();
             
             try
             {
                 // populate the context with the old entry
                 eagerlyPopulateFields( modifyContext );
 
-                // Call the Modify method
-                Interceptor head = directoryService.getInterceptor( modifyContext.getNextInterceptor() );
-
+                // Call the Modify method 
                 head.modify( modifyContext );
             }
             catch ( LdapException le )
             {
-                if ( startedTxn )
+                if ( startedTxn && isCausedByConflictException( le ) )
                 {
-                    abortTransaction( txnManager, le );
+                    // Retry
+                    done = false; 
                 }
+                else
+                {
+                    if ( startedTxn )
+                    {
+                        // Reset logical data if necessary
+                        reinitLogicalData( txnManager, head );
+                        
+                        abortTransaction( txnManager, le );
+                    }
 
-                throw ( le );
+                    throw ( le );
+                }
             }
 
-            // If here then we are done.
-            done = true;
-
             if ( startedTxn )
             {
                 try
@@ -1060,7 +1220,7 @@ public class DefaultOperationManager imp
                    done = false; // retry
                 }
             }
-            txnManager.applyPendingTxns();
+            //txnManager.applyPendingTxns();
         }
         while ( !done );
 
@@ -1079,90 +1239,25 @@ public class DefaultOperationManager imp
 
         ensureStarted();
 
-        // Normalize the moveContext Dn
-        Dn dn = moveContext.getDn();
-        dn.apply( directoryService.getSchemaManager() );
-
-        // Normalize the moveContext superior Dn
-        Dn newSuperiorDn = moveContext.getNewSuperior();
-        newSuperiorDn.apply( directoryService.getSchemaManager() );
-
-        // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
-
-        // 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
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
-
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-            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() )
-                {
-                    directoryService.getReferralManager().unlock();
-
-                    LdapPartialResultException exception = buildLdapPartialResultException( childDn );
-                    throw exception;
-                }
-                else
-                {
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
-
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-        }
-
-        // 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 ) )
-        {
-            // Unlock the referral manager
-            directoryService.getReferralManager().unlock();
-
-            LdapAffectMultipleDsaException exception = new LdapAffectMultipleDsaException();
-            //exception.setRemainingName( dn );
-
-            throw exception;
-        }
-
-        // Unlock the ReferralManager
-        directoryService.getReferralManager().unlock();
-
         boolean done = false;
         boolean startedTxn = false;
         TxnManager txnManager = directoryService.getTxnManager();
         TxnHandle curTxn = txnManager.getCurTxn();
 
+        // Save the head
+        Interceptor head = directoryService.getInterceptor( moveContext.getNextInterceptor() );
+        
         do
         {
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
+            
             if ( startedTxn )
             {
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
+                
                 moveContext.resetContext();
                 retryTransactionRW( txnManager );
             }
@@ -1173,6 +1268,104 @@ public class DefaultOperationManager imp
             }
 
             moveContext.saveOriginalContext();
+
+            // Normalize the moveContext Dn
+            Dn dn = moveContext.getDn();
+            dn.apply( directoryService.getSchemaManager() );
+
+            // Normalize the moveContext superior Dn
+            Dn newSuperiorDn = moveContext.getNewSuperior();
+            newSuperiorDn.apply( directoryService.getSchemaManager() );
+
+            // We have to deal with the referral first
+            //directoryService.getReferralManager().lockRead();
+
+            // 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
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+                        
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+                        
+                        throw exception;
+                    }
+                }
+                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() )
+                    {
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapPartialResultException exception = buildLdapPartialResultException( childDn );
+                        
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+                        
+                        throw exception;
+                    }
+                    else
+                    {
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+                        
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+                        
+                        throw exception;
+                    }
+                }
+            }
+
+            // 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 ) )
+            {
+                // Unlock the referral manager
+                //directoryService.getReferralManager().unlock();
+
+                LdapAffectMultipleDsaException exception = new LdapAffectMultipleDsaException();
+                //exception.setRemainingName( dn );
+
+                if ( startedTxn )
+                {
+                    abortTransaction( txnManager, exception );
+                }
+                
+                throw exception;
+            }
+
+            // Unlock the ReferralManager
+            //directoryService.getReferralManager().unlock();
             
             try
             {
@@ -1180,24 +1373,29 @@ public class DefaultOperationManager imp
 
                 moveContext.setOriginalEntry( originalEntry );
 
-                // Call the Move method
-                Interceptor head = directoryService.getInterceptor( moveContext.getNextInterceptor() );
-
                 head.move( moveContext );
             }
             catch ( LdapException le )
             {
-                if ( startedTxn )
+                if ( startedTxn && isCausedByConflictException( le ) )
                 {
-                    abortTransaction( txnManager, le );
+                    // Retry
+                    done = false; 
                 }
+                else
+                {
+                    if ( startedTxn )
+                    {
+                        // Reset logical data if necessary
+                        reinitLogicalData( txnManager, head );
+                        
+                        abortTransaction( txnManager, le );
+                    }
 
-                throw ( le );
+                    throw ( le );
+                }
             }
 
-            // If here then we are done.
-            done = true;
-
             if ( startedTxn )
             {
                 try
@@ -1209,7 +1407,7 @@ public class DefaultOperationManager imp
                    done = false; // retry
                 }
             }
-            txnManager.applyPendingTxns();
+            //txnManager.applyPendingTxns();
         }
         while ( !done );
 
@@ -1227,127 +1425,165 @@ public class DefaultOperationManager imp
         LOG_CHANGES.debug( ">> MoveAndRenameOperation : {}", moveAndRenameContext );
 
         ensureStarted();
+        
+        boolean done = false;
+        boolean startedTxn = false;
+        TxnManager txnManager = directoryService.getTxnManager();
+        TxnHandle curTxn = txnManager.getCurTxn();
 
-        // Normalize the moveAndRenameContext Dn
-        Dn dn = moveAndRenameContext.getDn();
-        dn.apply( directoryService.getSchemaManager() );
+        // Save the head
+        Interceptor head = directoryService.getInterceptor( moveAndRenameContext.getNextInterceptor() );
+        
+        do
+        {
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
+            
+            if ( startedTxn )
+            {
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
+                
+                moveAndRenameContext.resetContext();
+                retryTransactionRW( txnManager );
+            }
+            else if ( curTxn == null )
+            {
+                beginTransactionRW( txnManager );
+                startedTxn = true;
+            }
 
-        // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
+            moveAndRenameContext.saveOriginalContext();
 
-        // Check if we have an ancestor for this Dn
-        Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
+            // Normalize the moveAndRenameContext Dn
+            Dn dn = moveAndRenameContext.getDn();
+            dn.apply( directoryService.getSchemaManager() );
 
-        if ( parentEntry != null )
-        {
-            // We have found a parent referral for the current Dn
-            Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
+            // We have to deal with the referral first
+            //directoryService.getReferralManager().lockRead();
 
-            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
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+            // Check if we have an ancestor for this Dn
+            Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
 
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-            else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
+            if ( parentEntry != null )
             {
-                // We can't delete an entry which has an ancestor referral
+                // We have found a parent referral for the current Dn
+                Dn childDn = dn.getDescendantOf( parentEntry.getDn() );
 
-                // Depending on the Context.REFERRAL property value, we will throw
-                // a different exception.
-                if ( moveAndRenameContext.isReferralIgnored() )
+                if ( directoryService.getReferralManager().isReferral( dn ) )
                 {
-                    directoryService.getReferralManager().unlock();
+                    // 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
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
 
-                    LdapPartialResultException exception = buildLdapPartialResultException( childDn );
-                    throw exception;
+                        throw exception;
+                    }
                 }
-                else
+                else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
                 {
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                    // We can't delete an entry which has an ancestor referral
 
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-        }
+                    // Depending on the Context.REFERRAL property value, we will throw
+                    // a different exception.
+                    if ( moveAndRenameContext.isReferralIgnored() )
+                    {
+                        //directoryService.getReferralManager().unlock();
 
-        // Now, check the destination
-        // Normalize the moveAndRenameContext Dn
-        Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
-        newSuperiorDn.apply( directoryService.getSchemaManager() );
-
-        // 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 ) )
-        {
-            // Unlock the referral manager
-            directoryService.getReferralManager().unlock();
+                        LdapPartialResultException exception = buildLdapPartialResultException( childDn );
 
-            // The parent Dn is a referral, we have to issue a AffectMultipleDsas result
-            // as stated by RFC 3296 Section 5.6.2
-            LdapAffectMultipleDsaException exception = new LdapAffectMultipleDsaException();
-            //exception.setRemainingName( dn );
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
 
-            throw exception;
-        }
+                        throw exception;
+                    }
+                    else
+                    {
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
 
-        // Unlock the ReferralManager
-        directoryService.getReferralManager().unlock();
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
 
-        boolean done = false;
-        boolean startedTxn = false;
-        TxnManager txnManager = directoryService.getTxnManager();
-        TxnHandle curTxn = txnManager.getCurTxn();
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
 
-        do
-        {
-            if ( startedTxn )
-            {
-                moveAndRenameContext.resetContext();
-                retryTransactionRW( txnManager );
+                        throw exception;
+                    }
+                }
             }
-            else if ( curTxn == null )
+
+            // Now, check the destination
+            // Normalize the moveAndRenameContext Dn
+            Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
+            newSuperiorDn.apply( directoryService.getSchemaManager() );
+
+            // 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 ) )
             {
-                beginTransactionRW( txnManager );
-                startedTxn = true;
+                // Unlock the referral manager
+                //directoryService.getReferralManager().unlock();
+
+                // The parent Dn is a referral, we have to issue a AffectMultipleDsas result
+                // as stated by RFC 3296 Section 5.6.2
+                LdapAffectMultipleDsaException exception = new LdapAffectMultipleDsaException();
+                //exception.setRemainingName( dn );
+
+                if ( startedTxn )
+                {
+                    abortTransaction( txnManager, exception );
+                }
+
+                throw exception;
             }
 
-            moveAndRenameContext.saveOriginalContext();
+            // Unlock the ReferralManager
+            //directoryService.getReferralManager().unlock();
             
             try
             {
                 moveAndRenameContext.setOriginalEntry( getOriginalEntry( moveAndRenameContext ) );
                 moveAndRenameContext.setModifiedEntry( moveAndRenameContext.getOriginalEntry().clone() );
 
-                // Call the MoveAndRename method
-                Interceptor head = directoryService.getInterceptor( moveAndRenameContext.getNextInterceptor() );
-
                 head.moveAndRename( moveAndRenameContext );
             }
             catch ( LdapException le )
             {
-                if ( startedTxn )
+                if ( startedTxn && isCausedByConflictException( le ) )
                 {
-                    abortTransaction( txnManager, le );
+                    // Retry
+                    done = false; 
                 }
+                else
+                {
+                    if ( startedTxn )
+                    {
+                        // Reset logical data if necessary
+                        reinitLogicalData( txnManager, head );
+                        
+                        abortTransaction( txnManager, le );
+                    }
 
-                throw ( le );
+                    throw ( le );
+                }
             }
 
-            // If here then we are done.
-            done = true;
-
             if ( startedTxn )
             {
                 try
@@ -1359,7 +1595,7 @@ public class DefaultOperationManager imp
                    done = false; // retry
                 }
             }
-            txnManager.applyPendingTxns();
+            //txnManager.applyPendingTxns();
         }
         while ( !done );
 
@@ -1377,81 +1613,25 @@ public class DefaultOperationManager imp
         LOG_CHANGES.debug( ">> RenameOperation : {}", renameContext );
 
         ensureStarted();
-
-        // Normalize the renameContext Dn
-        Dn dn = renameContext.getDn();
-        dn.apply( directoryService.getSchemaManager() );
-
-        // Inject the newDn into the operation context
-        // Inject the new Dn into the context
-        if ( !dn.isEmpty() )
-        {
-            Dn newDn = dn.getParent();
-            newDn = newDn.add( renameContext.getNewRdn() );
-            renameContext.setNewDn( newDn );
-        }
-
-        // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
-
-        // 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
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
-
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-            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() )
-                {
-                    directoryService.getReferralManager().unlock();
-
-                    LdapPartialResultException exception = buildLdapPartialResultException( childDn );
-                    throw exception;
-                }
-                else
-                {
-                    // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
-
-                    LdapReferralException exception = buildReferralException( parentEntry, childDn );
-                    throw exception;
-                }
-            }
-        }
-
-        // Unlock the ReferralManager
-        directoryService.getReferralManager().unlock();
-
         boolean done = false;
         boolean startedTxn = false;
         TxnManager txnManager = directoryService.getTxnManager();
         TxnHandle curTxn = txnManager.getCurTxn();
 
+        // Save the head
+        Interceptor head = directoryService.getInterceptor( renameContext.getNextInterceptor() );
+        
         do
         {
+            // Assume we are done, will be set to false
+            // if retry is needed
+            done = true;
+            
             if ( startedTxn )
             {
+                // Reset logical data if necessary
+                reinitLogicalData( txnManager, head );
+                
                 renameContext.resetContext();
                 retryTransactionRW( txnManager );
             }
@@ -1462,6 +1642,88 @@ public class DefaultOperationManager imp
             }
 
             renameContext.saveOriginalContext();
+            // Normalize the renameContext Dn
+            Dn dn = renameContext.getDn();
+            dn.apply( directoryService.getSchemaManager() );
+
+            // Inject the newDn into the operation context
+            // Inject the new Dn into the context
+            if ( !dn.isEmpty() )
+            {
+                Dn newDn = dn.getParent();
+                newDn = newDn.add( renameContext.getNewRdn() );
+                renameContext.setNewDn( newDn );
+            }
+
+            // We have to deal with the referral first
+            //directoryService.getReferralManager().lockRead();
+
+            // 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
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+
+                        throw exception;
+                    }
+                }
+                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() )
+                    {
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapPartialResultException exception = buildLdapPartialResultException( childDn );
+
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+
+                        throw exception;
+                    }
+                    else
+                    {
+                        // Unlock the referral manager
+                        //directoryService.getReferralManager().unlock();
+
+                        LdapReferralException exception = buildReferralException( parentEntry, childDn );
+
+                        if ( startedTxn )
+                        {
+                            abortTransaction( txnManager, exception );
+                        }
+
+                        throw exception;
+                    }
+                }
+            }
+
+            // Unlock the ReferralManager
+            //directoryService.getReferralManager().unlock();    
             
             try
             {
@@ -1472,24 +1734,29 @@ public class DefaultOperationManager imp
                 renameContext.setOriginalEntry( originalEntry );
                 renameContext.setModifiedEntry( originalEntry.clone() );
 
-                // Call the Rename method
-                Interceptor head = directoryService.getInterceptor( renameContext.getNextInterceptor() );
-
                 head.rename( renameContext );
             }
             catch ( LdapException le )
             {
-                if ( startedTxn )
+                if ( startedTxn && isCausedByConflictException( le ) )
                 {
-                    abortTransaction( txnManager, le );
+                    // Retry
+                    done = false; 
                 }
+                else
+                {
+                    if ( startedTxn )
+                    {
+                        // Reset logical data if necessary
+                        reinitLogicalData( txnManager, head );
+                        
+                        abortTransaction( txnManager, le );
+                    }
 
-                throw ( le );
+                    throw ( le );
+                }
             }
 
-            // If here then we are done.
-            done = true;
-
             if ( startedTxn )
             {
                 try
@@ -1501,7 +1768,7 @@ public class DefaultOperationManager imp
                    done = false; // retry
                 }
             }
-            txnManager.applyPendingTxns();
+            //txnManager.applyPendingTxns();
         }
         while ( !done );
 
@@ -1518,13 +1785,20 @@ public class DefaultOperationManager imp
         LOG.debug( ">> SearchOperation : {}", searchContext );
 
         ensureStarted();
+        
+        Interceptor head = directoryService.getInterceptor( searchContext.getNextInterceptor() );
+
+        TxnManager txnManager = directoryService.getTxnManager();
+
+        beginTransactionR( txnManager );
+        EntryFilteringCursor cursor = null;
 
         // Normalize the searchContext Dn
         Dn dn = searchContext.getDn();
         dn.apply( directoryService.getSchemaManager() );
 
         // We have to deal with the referral first
-        directoryService.getReferralManager().lockRead();
+        //directoryService.getReferralManager().lockRead();
 
         // Check if we have an ancestor for this Dn
         Entry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
@@ -1542,10 +1816,12 @@ public class DefaultOperationManager imp
                 {
                     // Throw a Referral Exception
                     // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                    //directoryService.getReferralManager().unlock();
 
                     LdapReferralException exception = buildReferralExceptionForSearch( parentEntry, childDn,
                         searchContext.getScope() );
+                    
+                    abortTransaction( txnManager, exception );
                     throw exception;
                 }
             }
@@ -1557,39 +1833,38 @@ public class DefaultOperationManager imp
                 // a different exception.
                 if ( searchContext.isReferralIgnored() )
                 {
-                    directoryService.getReferralManager().unlock();
+                    //directoryService.getReferralManager().unlock();
 
                     LdapPartialResultException exception = buildLdapPartialResultException( childDn );
+                    
+                    abortTransaction( txnManager, exception );
                     throw exception;
                 }
                 else
                 {
                     // Unlock the referral manager
-                    directoryService.getReferralManager().unlock();
+                    //directoryService.getReferralManager().unlock();
 
                     LdapReferralException exception = buildReferralExceptionForSearch( parentEntry, childDn,
                         searchContext.getScope() );
+                    
+                    abortTransaction( txnManager, exception );
                     throw exception;
                 }
             }
         }
 
         // Unlock the ReferralManager
-        directoryService.getReferralManager().unlock();
+        //directoryService.getReferralManager().unlock();
 
         // Call the Search method
-        Interceptor head = directoryService.getInterceptor( searchContext.getNextInterceptor() );
-
-        TxnManager txnManager = directoryService.getTxnManager();
-
-        beginTransactionR( txnManager );
-        EntryFilteringCursor cursor = null;
-
         try
         {
             cursor = head.search( searchContext );
 
             cursor.setTxnManager( txnManager );
+            
+            txnManager.endLogicalDataRead();
             txnManager.setCurTxn( null );
         }
         catch ( LdapException le )

Modified: directory/apacheds/branches/apacheds-txns/interceptors/admin/src/main/java/org/apache/directory/server/core/admin/AdministrativePointInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/admin/src/main/java/org/apache/directory/server/core/admin/AdministrativePointInterceptor.java?rev=1334904&r1=1334903&r2=1334904&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/admin/src/main/java/org/apache/directory/server/core/admin/AdministrativePointInterceptor.java (original)
+++ directory/apacheds/branches/apacheds-txns/interceptors/admin/src/main/java/org/apache/directory/server/core/admin/AdministrativePointInterceptor.java Mon May  7 07:53:21 2012
@@ -180,8 +180,8 @@ public class AdministrativePointIntercep
         SPECIFIC_AREA_ROLES.add( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA_OID );
     }
 
-    /** A lock to guarantee the AP cache consistency */
-    private ReentrantReadWriteLock mutex = new ReentrantReadWriteLock();
+//    /** A lock to guarantee the AP cache consistency */
+//    private ReentrantReadWriteLock mutex = new ReentrantReadWriteLock();
 
 
     /**
@@ -192,45 +192,45 @@ public class AdministrativePointIntercep
         super( InterceptorEnum.ADMINISTRATIVE_POINT_INTERCEPTOR );
     }
 
-    
-    /**
-     * Get a read-lock on the AP cache.
-     * No read operation can be done on the AP cache if this
-     * method is not called before.
-     */
-    public void lockRead()
-    {
-        mutex.readLock().lock();
-    }
-
-
-    /**
-     * Get a write-lock on the AP cache.
-     * No write operation can be done on the apCache if this
-     * method is not called before.
-     */
-    public void lockWrite()
-    {
-        mutex.writeLock().lock();
-    }
-
-
-    /**
-     * Release the read-write lock on the AP cache.
-     * This method must be called after having read or modified the
-     * AP cache
-     */
-    public void unlock()
-    {
-        if ( mutex.isWriteLockedByCurrentThread() )
-        {
-            mutex.writeLock().unlock();
-        }
-        else
-        {
-            mutex.readLock().unlock();
-        }
-    }
+//    
+//    /**
+//     * Get a read-lock on the AP cache.
+//     * No read operation can be done on the AP cache if this
+//     * method is not called before.
+//     */
+//    public void lockRead()
+//    {
+//        mutex.readLock().lock();
+//    }
+//
+//
+//    /**
+//     * Get a write-lock on the AP cache.
+//     * No write operation can be done on the apCache if this
+//     * method is not called before.
+//     */
+//    public void lockWrite()
+//    {
+//        mutex.writeLock().lock();
+//    }
+//
+//
+//    /**
+//     * Release the read-write lock on the AP cache.
+//     * This method must be called after having read or modified the
+//     * AP cache
+//     */
+//    public void unlock()
+//    {
+//        if ( mutex.isWriteLockedByCurrentThread() )
+//        {
+//            mutex.writeLock().unlock();
+//        }
+//        else
+//        {
+//            mutex.readLock().unlock();
+//        }
+//    }
 
 
     /**
@@ -347,10 +347,14 @@ public class AdministrativePointIntercep
     /**
      * Update the cache clones with the added roles
      */
-    private void addRole( String role, Dn dn, String uuid, DnNode<AccessControlAdministrativePoint> acapCache,
-        DnNode<CollectiveAttributeAdministrativePoint> caapCache, DnNode<TriggerExecutionAdministrativePoint> teapCache,
-        DnNode<SubschemaAdministrativePoint> ssapCache ) throws LdapException
+    private void addRole( String role, Dn dn, String uuid) throws LdapException
     {
+        DnNode<AccessControlAdministrativePoint> acapCache = directoryService.getAccessControlAPCache();
+        DnNode<CollectiveAttributeAdministrativePoint> caapCache = directoryService.getCollectiveAttributeAPCache();
+        DnNode<TriggerExecutionAdministrativePoint> teapCache = directoryService.getTriggerExecutionAPCache();
+        DnNode<SubschemaAdministrativePoint> ssapCache = directoryService.getSubschemaAPCache();
+        
+        
         // Deal with Autonomous AP : create the 4 associated SAP/AAP
         if ( isAutonomousAreaRole( role ) )
         {
@@ -441,10 +445,13 @@ public class AdministrativePointIntercep
     /**
      * Update the cache clones with the added roles
      */
-    private void delRole( String role, Dn dn, String uuid, DnNode<AccessControlAdministrativePoint> acapCache,
-        DnNode<CollectiveAttributeAdministrativePoint> caapCache, DnNode<TriggerExecutionAdministrativePoint> teapCache,
-        DnNode<SubschemaAdministrativePoint> ssapCache ) throws LdapException
+    private void delRole( String role, Dn dn, String uuid ) throws LdapException
     {
+        DnNode<AccessControlAdministrativePoint> acapCache = directoryService.getAccessControlAPCache();
+        DnNode<CollectiveAttributeAdministrativePoint> caapCache = directoryService.getCollectiveAttributeAPCache();
+        DnNode<TriggerExecutionAdministrativePoint> teapCache = directoryService.getTriggerExecutionAPCache();
+        DnNode<SubschemaAdministrativePoint> ssapCache = directoryService.getSubschemaAPCache();
+        
         // Deal with Autonomous AP : remove the 4 associated SAP/AAP
         if ( isAutonomousAreaRole( role ) )
         {
@@ -1148,9 +1155,9 @@ public class AdministrativePointIntercep
         // get the list of all the AAPs
         List<Entry> administrativePoints = getAdministrativePoints();
 
-        lockWrite();
+//        lockWrite();
         addAdminPointCache( administrativePoints );
-        unlock();
+//        unlock();
     }
 
 
@@ -1160,6 +1167,19 @@ public class AdministrativePointIntercep
     public void destroy()
     {
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void reinitLogicalData(  DirectoryService directoryService  ) throws LdapException
+    {
+        directoryService.resetCaches();
+        
+        // get the list of all the AAPs
+        List<Entry> administrativePoints = getAdministrativePoints();
+        addAdminPointCache( administrativePoints );
+    }
 
 
     private void updateAPEntries( Attribute adminPoint, String apUuid )
@@ -1206,7 +1226,7 @@ public class AdministrativePointIntercep
         LOG.debug( "Addition of an administrative point at {} for the role {}", dn, adminPoint );
 
         // Protect the AP caches against concurrent access
-        lockWrite();
+        directoryService.getTxnManager().startLogicalDataChange();
 
         // Loop on all the added roles to check if they are valid
         for ( Value<?> role : adminPoint )
@@ -1222,8 +1242,8 @@ public class AdministrativePointIntercep
         // Now, update the AdminPoint cache
         createAdministrativePoints( adminPoint, dn, apUuid );
 
-        // Release the APCaches lock
-        unlock();
+//        // Release the APCaches lock
+//        unlock();
 
         LOG.debug( "Added an Administrative Point at {}", dn );
 
@@ -1261,7 +1281,7 @@ public class AdministrativePointIntercep
         LOG.debug( "Deletion of an administrative point at {} for the role {}", dn, adminPoint );
 
         // Protect the AP caches against concurrent access
-        lockWrite();
+        directoryService.getTxnManager().startLogicalDataChange();
 
         // Check that the removed AdministrativeRoles are valid. We don't have to do
         // any other check, as the deleted entry has no children.
@@ -1281,8 +1301,8 @@ public class AdministrativePointIntercep
         // Now, update the AdminPoint cache
         deleteAdminPointCache( adminPoint, deleteContext );
 
-        // Release the APCaches lock
-        unlock();
+//        // Release the APCaches lock
+//        unlock();
 
         LOG.debug( "Deleted an Administrative Point at {}", dn );
 
@@ -1321,12 +1341,7 @@ public class AdministrativePointIntercep
         {
             modifiedAdminRole = modifiedAdminRole.clone();
         }
-
-        // Clone the AP caches before applying modifications to them modify it
-        DnNode<AccessControlAdministrativePoint> acapCacheCopy = directoryService.getAccessControlAPCache().clone();
-        DnNode<CollectiveAttributeAdministrativePoint> caapCacheCopy = directoryService.getCollectiveAttributeAPCache().clone();
-        DnNode<TriggerExecutionAdministrativePoint> teapCacheCopy = directoryService.getTriggerExecutionAPCache().clone();
-        DnNode<SubschemaAdministrativePoint> ssapCacheCopy = directoryService.getSubschemaAPCache().clone();
+      
 
         // Loop on the modification to select the AdministrativeRole and process it :
         // we will create a new AT containing all the roles after having applied the modifications
@@ -1340,6 +1355,10 @@ public class AdministrativePointIntercep
             {
                 // Ok, we have a modification impacting the administrative role
                 // Apply it to a virtual AdministrativeRole attribute
+                
+                // Protect the AP caches against concurrent access
+                directoryService.getTxnManager().startLogicalDataChange();
+                
                 switch ( modification.getOperation() )
                 {
                     case ADD_ATTRIBUTE:
@@ -1351,7 +1370,7 @@ public class AdministrativePointIntercep
 
                         for ( Value<?> role : attribute )
                         {
-                            addRole( role.getString(), dn, uuid, acapCacheCopy, caapCacheCopy, teapCacheCopy, ssapCacheCopy );
+                            addRole( role.getString(), dn, uuid );
 
                             // Add the role to the modified attribute
                             modifiedAdminRole.add( role );
@@ -1375,7 +1394,7 @@ public class AdministrativePointIntercep
                             for ( Value<?> role : modifiedAdminRole )
                             {
                                 //checkDelRole( role, modifiedAdminRole, dn, directoryService.getAdministrativePoints() );
-                                delRole( role.getString(), dn, uuid, acapCacheCopy, caapCacheCopy, teapCacheCopy, ssapCacheCopy );
+                                delRole( role.getString(), dn, uuid );
                             }
 
                             modifiedAdminRole.clear();
@@ -1404,8 +1423,7 @@ public class AdministrativePointIntercep
                             }
 
                             modifiedAdminRole.remove( value );
-                            delRole( value.getString(), dn, uuid, acapCacheCopy, caapCacheCopy, teapCacheCopy,
-                                ssapCacheCopy );
+                            delRole( value.getString(), dn, uuid );
 
                         }
 

Modified: directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java?rev=1334904&r1=1334903&r2=1334904&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java (original)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java Mon May  7 07:53:21 2012
@@ -309,6 +309,19 @@ public class AciAuthorizationInterceptor
         // Init the SubentryUtils instance
         subentryUtils = new SubentryUtils( directoryService );
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void reinitLogicalData(  DirectoryService directoryService  ) throws LdapException
+    {
+        tupleCache.reinitialize();
+        groupCache.reinitialize();
+        
+        initTupleCache();
+        initGroupCache();
+    }
 
 
     private void protectCriticalEntries( OperationContext opCtx, Dn dn ) throws LdapException

Modified: directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/GroupCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/GroupCache.java?rev=1334904&r1=1334903&r2=1334904&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/GroupCache.java (original)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/GroupCache.java Mon May  7 07:53:21 2012
@@ -97,6 +97,10 @@ public class GroupCache
 
     /** String key for the Dn of a group to a Set (HashSet) for the Strings of member DNs */
     private Cache ehCache;
+    
+    /** Directory service */
+    private DirectoryService directoryService;
+
 
     /**
      * Creates a static group cache.
@@ -117,10 +121,16 @@ public class GroupCache
         administratorsGroupDn = parseNormalized( ServerDNConstants.ADMINISTRATORS_GROUP_DN );
 
         this.ehCache = dirService.getCacheService().getCache( "groupCache" );
-        
+        directoryService = dirService;
         initialize( dirService.getAdminSession() );
     }
 
+    
+    public void reinitialize() throws LdapException
+    {
+        ehCache.removeAll();
+        initialize( directoryService.getAdminSession() );
+    }
 
     private Dn parseNormalized( String name ) throws LdapException
     {
@@ -296,6 +306,9 @@ public class GroupCache
         {
             return;
         }
+        
+        // Ensure cache consistency
+        directoryService.getTxnManager().startLogicalDataChange();
 
         Set<String> memberSet = new HashSet<String>( members.size() );
         addMembers( memberSet, members );
@@ -325,6 +338,9 @@ public class GroupCache
         {
             return;
         }
+        
+        // Ensure cache consistency
+        directoryService.getTxnManager().startLogicalDataChange();
 
         ehCache.remove( name.getNormName() );
 
@@ -414,6 +430,9 @@ public class GroupCache
                 
                 if ( memSetElement != null )
                 {
+                    // Ensure cache consistency
+                    directoryService.getTxnManager().startLogicalDataChange();
+                    
                     Set<String> memberSet = ( Set<String> ) memSetElement.getValue();
                     modify( memberSet, modification.getOperation(), modification.getAttribute() );
                 }
@@ -451,6 +470,9 @@ public class GroupCache
 
         if ( memSetElement != null )
         {
+            // Ensure cache consistency
+            directoryService.getTxnManager().startLogicalDataChange();
+            
             Set<String> memberSet = ( Set<String> ) memSetElement.getValue();
             modify( memberSet, modOp, members );
         }
@@ -555,7 +577,7 @@ public class GroupCache
     }
 
 
-    public boolean groupRenamed( Dn oldName, Dn newName )
+    public boolean groupRenamed( Dn oldName, Dn newName ) throws LdapException
     {
         Element membersElement = ehCache.get( oldName.getNormName() );
         
@@ -563,6 +585,9 @@ public class GroupCache
         {
             Set<String> members = ( Set<String> ) membersElement.getValue();
             
+            // Ensure cache consistency
+            directoryService.getTxnManager().startLogicalDataChange();
+            
             ehCache.remove( oldName.getNormName() );
             
             Element cacheElement = new Element( newName.getNormName(), members );

Modified: directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/TupleCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/TupleCache.java?rev=1334904&r1=1334903&r2=1334904&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/TupleCache.java (original)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authz/src/main/java/org/apache/directory/server/core/authz/TupleCache.java Mon May  7 07:53:21 2012
@@ -31,6 +31,7 @@ import java.util.Set;
 import javax.naming.directory.SearchControls;
 
 import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.core.api.DnFactory;
 import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
 import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
@@ -90,6 +91,9 @@ public class TupleCache
 
     /** A storage for the ObjectClass attributeType */
     private static AttributeType OBJECT_CLASS_AT;
+    
+    /** Directory service */
+    private DirectoryService directoryService;
 
 
     /**
@@ -107,9 +111,16 @@ public class TupleCache
         aciParser = new ACIItemParser( ncn, schemaManager );
         PRESCRIPTIVE_ACI_AT = schemaManager.getAttributeType( SchemaConstants.PRESCRIPTIVE_ACI_AT );
         OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+        directoryService = session.getDirectoryService();
         initialize( session );
     }
 
+    public void reinitialize() throws LdapException
+    {
+        tuples.clear();
+        initialize( directoryService.getAdminSession() );
+    }
+    
 
     private Dn parseNormalized( String name ) throws LdapException
     {
@@ -202,6 +213,9 @@ public class TupleCache
         {
             return;
         }
+        
+        // Ensure cache consistency
+        directoryService.getTxnManager().startLogicalDataChange();
 
         // Get the prescriptiveACI
         Attribute prescriptiveAci = entry.get( PRESCRIPTIVE_ACI_AT );
@@ -241,6 +255,9 @@ public class TupleCache
             return;
         }
 
+        // Ensure cache consistency
+        directoryService.getTxnManager().startLogicalDataChange();
+        
         tuples.remove( normName.toString() );
     }
 
@@ -292,8 +309,11 @@ public class TupleCache
     }
 
 
-    public void subentryRenamed( Dn oldName, Dn newName )
+    public void subentryRenamed( Dn oldName, Dn newName ) throws LdapException
     {
+        // Ensure cache consistency
+        directoryService.getTxnManager().startLogicalDataChange();
+        
         tuples.put( newName.getNormName(), tuples.remove( oldName.getNormName() ) );
     }
 }

Modified: directory/apacheds/branches/apacheds-txns/interceptors/exception/src/main/java/org/apache/directory/server/core/exception/ExceptionInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/exception/src/main/java/org/apache/directory/server/core/exception/ExceptionInterceptor.java?rev=1334904&r1=1334903&r2=1334904&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/exception/src/main/java/org/apache/directory/server/core/exception/ExceptionInterceptor.java (original)
+++ directory/apacheds/branches/apacheds-txns/interceptors/exception/src/main/java/org/apache/directory/server/core/exception/ExceptionInterceptor.java Mon May  7 07:53:21 2012
@@ -116,6 +116,16 @@ public class ExceptionInterceptor extend
     public void destroy()
     {
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void reinitLogicalData( DirectoryService directoryService ) throws LdapException
+    {
+        notAliasCache.clear();
+    }
+    
 
 
     /**
@@ -145,11 +155,9 @@ public class ExceptionInterceptor extend
         // check if we're trying to add to a parent that is an alias
         boolean notAnAlias;
 
-        synchronized ( notAliasCache )
-        {
-            notAnAlias = notAliasCache.containsKey( parentDn.getNormName() );
-        }
-
+ 
+        notAnAlias = notAliasCache.containsKey( parentDn.getNormName() );
+        
         if ( !notAnAlias )
         {
             // We don't know if the parent is an alias or not, so we will launch a
@@ -183,10 +191,9 @@ public class ExceptionInterceptor extend
             }
             else
             {
-                synchronized ( notAliasCache )
-                {
-                    notAliasCache.put( parentDn.getNormName(), parentDn );
-                }
+                // Ensure logical data consistency
+                directoryService.getTxnManager().startLogicalDataChange();
+                notAliasCache.put( parentDn.getNormName(), parentDn );
             }
         }
 
@@ -211,12 +218,12 @@ public class ExceptionInterceptor extend
         next( deleteContext );
 
         // Update the alias cache
-        synchronized ( notAliasCache )
+        if ( notAliasCache.containsKey( dn.getNormName() ) )
         {
-            if ( notAliasCache.containsKey( dn.getNormName() ) )
-            {
-                notAliasCache.remove( dn.getNormName() );
-            }
+            // Ensure logical data consistency
+            directoryService.getTxnManager().startLogicalDataChange();
+            
+            notAliasCache.remove( dn.getNormName() );
         }
     }
 
@@ -286,13 +293,13 @@ public class ExceptionInterceptor extend
         // We will simply remove the Dn from the NotAlias cache.
         // It would be smarter to check the modified attributes, but
         // it would also be more complex.
-        synchronized ( notAliasCache )
-        {
-            if ( notAliasCache.containsKey( modifyContext.getDn().getNormName() ) )
-            {
-                notAliasCache.remove( modifyContext.getDn().getNormName() );
-            }
-        }
+         if ( notAliasCache.containsKey( modifyContext.getDn().getNormName() ) )
+         {
+             // Ensure logical data consistency
+             directoryService.getTxnManager().startLogicalDataChange();
+             
+             notAliasCache.remove( modifyContext.getDn().getNormName() );
+         }
 
         next( modifyContext );
     }
@@ -314,12 +321,12 @@ public class ExceptionInterceptor extend
         next( moveContext );
 
         // Remove the original entry from the NotAlias cache, if needed
-        synchronized ( notAliasCache )
+        if ( notAliasCache.containsKey( oriChildName.getNormName() ) )
         {
-            if ( notAliasCache.containsKey( oriChildName.getNormName() ) )
-            {
-                notAliasCache.remove( oriChildName.getNormName() );
-            }
+            // Ensure logical data consistency
+            directoryService.getTxnManager().startLogicalDataChange();
+            
+            notAliasCache.remove( oriChildName.getNormName() );
         }
     }
 
@@ -339,12 +346,12 @@ public class ExceptionInterceptor extend
         }
 
         // Remove the original entry from the NotAlias cache, if needed
-        synchronized ( notAliasCache )
+        if ( notAliasCache.containsKey( oldDn.getNormName() ) )
         {
-            if ( notAliasCache.containsKey( oldDn.getNormName() ) )
-            {
-                notAliasCache.remove( oldDn.getNormName() );
-            }
+            // Ensure logical data consistency
+            directoryService.getTxnManager().startLogicalDataChange();
+            
+            notAliasCache.remove( oldDn.getNormName() );
         }
 
         next( moveAndRenameContext );
@@ -376,12 +383,12 @@ public class ExceptionInterceptor extend
         }
 
         // Remove the previous entry from the notAnAlias cache
-        synchronized ( notAliasCache )
+        if ( notAliasCache.containsKey( dn.getNormName() ) )
         {
-            if ( notAliasCache.containsKey( dn.getNormName() ) )
-            {
-                notAliasCache.remove( dn.getNormName() );
-            }
+            // Ensure logical data consistency
+            directoryService.getTxnManager().startLogicalDataChange();
+            
+            notAliasCache.remove( dn.getNormName() );
         }
 
         next( renameContext );



Mime
View raw message