You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by sa...@apache.org on 2011/11/30 10:53:28 UTC

svn commit: r1208350 [1/2] - in /directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared: partition/ txn/ txn/logedit/

Author: saya
Date: Wed Nov 30 09:53:21 2011
New Revision: 1208350

URL: http://svn.apache.org/viewvc?rev=1208350&view=rev
Log:
Various fixes based on the tests done for txns. 

Also added methods to merge index lookups and checks for existince of an entry in a more efficient way. Used to construct a cursor each time a lookup is done. Thought this might be too much of a overhead, so added methods to directly merge what is read from partitions with the changes in the txn log.

Added:
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/EntryCursorAdaptor.java
      - copied, changed from r1201828, directory/apacheds/branches/apacheds-txns/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/EntryCursorAdaptor.java
Modified:
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultOperationExecutionManager.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/AbstractTransaction.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/DefaultTxnLogManager.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexCursorWrapper.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexWrapper.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/MasterTableWrapper.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/ReadWriteTxn.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/Transaction.java
    directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/logedit/DataChangeContainer.java

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultOperationExecutionManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultOperationExecutionManager.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultOperationExecutionManager.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultOperationExecutionManager.java Wed Nov 30 09:53:21 2011
@@ -27,8 +27,12 @@ import java.util.UUID;
 
 import org.apache.directory.server.constants.ApacheSchemaConstants;
 import org.apache.directory.server.core.api.entry.ClonedServerEntry;
+import org.apache.directory.server.core.api.filtering.BaseEntryFilteringCursor;
+import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
 import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ListOperationContext;
 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;
@@ -41,21 +45,19 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.api.partition.index.IndexEntry;
 import org.apache.directory.server.core.api.partition.index.MasterTable;
 import org.apache.directory.server.core.api.partition.index.ParentIdAndRdn;
+import org.apache.directory.server.core.api.partition.index.UUIDComparator;
 import org.apache.directory.server.core.api.txn.TxnLogManager;
 import org.apache.directory.server.core.shared.txn.TxnManagerFactory;
 import org.apache.directory.server.core.shared.txn.logedit.DataChangeContainer;
 import org.apache.directory.server.core.shared.txn.logedit.EntryAddDelete;
-import org.apache.directory.server.core.shared.txn.logedit.EntryChange;
 import org.apache.directory.server.core.shared.txn.logedit.EntryReplace;
 import org.apache.directory.server.core.shared.txn.logedit.IndexChange;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.cursor.Cursor;
 import org.apache.directory.shared.ldap.model.entry.Attribute;
-import org.apache.directory.shared.ldap.model.entry.DefaultModification;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.entry.Modification;
-import org.apache.directory.shared.ldap.model.entry.ModificationOperation;
 import org.apache.directory.shared.ldap.model.entry.Value;
 import org.apache.directory.shared.ldap.model.exception.LdapAliasDereferencingException;
 import org.apache.directory.shared.ldap.model.exception.LdapAliasException;
@@ -265,13 +267,22 @@ public class DefaultOperationExecutionMa
 
             // Add the parentId in the entry
             entry.put( SchemaConstants.ENTRY_PARENT_ID_AT, parentId.toString() );
+            
+            // Add the dn
+            entry.setDn( entryDn );
 
             // And finally prepare the entry change
             EntryAddDelete entryAdd = new EntryAddDelete( entry, EntryAddDelete.Type.ADD );
             changeContainer.addChange( entryAdd );
+            
+            // Set the modified entry
+            addContext.setModifiedEntry( entry );
 
             // log the change
             txnLogManager.log( changeContainer, false );
+            
+            //TODO TODO TODO REMOVE THIS
+            partition.add( addContext );
         }
         catch ( LdapException le )
         {
@@ -291,9 +302,12 @@ public class DefaultOperationExecutionMa
      * {@inheritDoc}
      */
     public void delete( Partition partition, DeleteOperationContext deleteContext ) throws LdapException
-    {
+    {        
         Dn dn = deleteContext.getDn();
 
+        //TODO TODO TODO REMOVE THIS
+        partition.delete( deleteContext );
+        
         // Add write dependency on the dn
         txnLogManager.addWrite( dn, SearchScope.SUBTREE );
 
@@ -492,6 +506,10 @@ public class DefaultOperationExecutionMa
                 modifyContext.getModItems().toArray( new Modification[]
                     {} ) );
             modifyContext.setAlteredEntry( modifiedEntry );
+            
+            //TODO TODO TODO REMOVE THIS
+            partition.modify( modifyContext );
+
         }
         catch ( Exception e )
         {
@@ -508,7 +526,8 @@ public class DefaultOperationExecutionMa
         UUID id = getEntryId( partition, dn );
         MasterTable master = partition.getMasterTable();
         master = txnLogManager.wrap( partition.getSuffixDn(), master );
-        Entry entry = master.get( id );
+        Entry originalEntry = master.get( id );
+        Entry entry = originalEntry.clone();
 
         DataChangeContainer changeContainer = new DataChangeContainer( partition );
         changeContainer.setEntryID( id );
@@ -537,10 +556,14 @@ public class DefaultOperationExecutionMa
                     throw new LdapException( I18n.err( I18n.ERR_221 ) );
             }
         }
+        
+        // For now use and EntryReplace change
+        EntryReplace entryReplace = new EntryReplace( entry, originalEntry );
+        changeContainer.addChange( entryReplace );
 
         // log the changes
         txnLogManager.log( changeContainer, false );
-
+        
         return entry;
     }
 
@@ -608,17 +631,23 @@ public class DefaultOperationExecutionMa
             }
         }
 
-        // create log edit for the entry change
-        Modification undo = null;
-
-        if ( prevValueExists )
+//        // create log edit for the entry change
+//        Modification undo = null;
+//
+//        if ( prevValueExists )
+//        {
+//            undo = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, changedAttribute );
+//        }
+//
+//        EntryChange entryChange = new EntryChange( mod, null );
+//        changeContainer.addChange( entryChange );
+        
+        // add all the values in mods to the same attribute in the entry
+        for ( Value<?> value : mods )
         {
-            undo = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, changedAttribute );
+            entry.add( mods.getAttributeType(), value );
         }
 
-        EntryChange entryChange = new EntryChange( mod, null );
-        changeContainer.addChange( entryChange );
-
         if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
         {
             addAliasIndices( partition, id, entryDn, mods.getString(), changeContainer );
@@ -763,16 +792,27 @@ public class DefaultOperationExecutionMa
             dropAliasIndices( partition, entryDn, id, null, changeContainer );
         }
 
-        // create log edit for the entry change
-        Modification undo = null;
-
-        if ( prevValueExists )
+//        // create log edit for the entry change
+//        Modification undo = null;
+//
+//        if ( prevValueExists )
+//        {
+//            undo = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, replacedAttribute );
+//        }
+//
+//        EntryChange entryChange = new EntryChange( mod, undo );
+//        changeContainer.addChange( entryChange );
+        
+        // replaces old attributes with new modified ones if they exist
+        if ( mods.size() > 0 )
         {
-            undo = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, replacedAttribute );
+            entry.put( mods );
+        }
+        else
+        // removes old attributes if new replacements do not exist
+        {
+            entry.remove( mods );
         }
-
-        EntryChange entryChange = new EntryChange( mod, undo );
-        changeContainer.addChange( entryChange );
 
         if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
         {
@@ -922,16 +962,42 @@ public class DefaultOperationExecutionMa
             }
         }
 
-        // Prepare the entry change
-        Modification undo = null;
-
-        if ( prevValueExists )
+//        // Prepare the entry change
+//        Modification undo = null;
+//
+//        if ( prevValueExists )
+//        {
+//            undo = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, changedAttribute );
+//        }
+//
+//        EntryChange entryChange = new EntryChange( mod, undo );
+//        changeContainer.addChange( entryChange );
+        
+        /*
+         * If there are no attribute values in the modifications then this
+         * implies the complete removal of the attribute from the entry. Else
+         * we remove individual attribute values from the entry in mods one
+         * at a time.
+         */
+        if ( mods.size() == 0 )
         {
-            undo = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, changedAttribute );
+            entry.removeAttributes( mods.getAttributeType() );
         }
+        else
+        {
+            Attribute entryAttr = entry.get( mods.getAttributeType() );
+
+            for ( Value<?> value : mods )
+            {
+                entryAttr.remove( value );
+            }
 
-        EntryChange entryChange = new EntryChange( mod, undo );
-        changeContainer.addChange( entryChange );
+            // if nothing is left just remove empty attribute
+            if ( entryAttr.size() == 0 )
+            {
+                entry.removeAttributes( entryAttr.getId() );
+            }
+        }
 
         // Aliases->single valued comp/partial attr removal is not relevant here
         if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
@@ -954,7 +1020,7 @@ public class DefaultOperationExecutionMa
             Dn oldDn = renameContext.getDn();
             Rdn newRdn = renameContext.getNewRdn();
             boolean deleteOldRdn = renameContext.getDeleteOldRdn();
-            Entry originalEntry = renameContext.getOriginalEntry();
+            Entry originalEntry = ( ( ClonedServerEntry )renameContext.getOriginalEntry() ).getOriginalEntry();
 
             if ( renameContext.getEntry() != null )
             {
@@ -965,6 +1031,9 @@ public class DefaultOperationExecutionMa
             {
                 rename( partition, oldDn, newRdn, deleteOldRdn, null, originalEntry );
             }
+            
+            //TODO TODO TODO REMOVE THIS
+            partition.rename( renameContext );
         }
         catch ( Exception e )
         {
@@ -977,180 +1046,18 @@ public class DefaultOperationExecutionMa
      * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public void rename( Partition partition, Dn dn, Rdn newRdn, boolean deleteOldRdn, Entry entry, Entry originalEntry )
-        throws Exception
+    public void rename( Partition partition, Dn dn, Rdn newRdn, boolean deleteOldRdn, Entry entry, Entry originalEntry ) throws Exception
     {
-        UUID id = getEntryId( partition, dn );
-        SchemaManager schemaManager = partition.getSchemaManager();
-        Dn suffixDn = partition.getSuffixDn();
-
-        DataChangeContainer changeContainer = new DataChangeContainer( partition );
-        changeContainer.setEntryID( id );
-        IndexChange indexChange;
-
-        if ( entry == null )
-        {
-            entry = originalEntry.clone();
-        }
-
-        Dn updn = entry.getDn();
-
-        newRdn.apply( schemaManager );
-
-        Dn parentDn = updn.getParent();
-        Dn newDn = new Dn( newRdn, parentDn );
-        newDn.apply( schemaManager );
-
-        // Add subtree dependency to old and new dn
-        txnLogManager.addWrite( updn, SearchScope.SUBTREE );
-        txnLogManager.addWrite( newDn, SearchScope.SUBTREE );
-
-        /*
-         * H A N D L E   N E W   R D N
-         * ====================================================================
-         * Add the new Rdn attribute to the entry.  If an index exists on the
-         * new Rdn attribute we add the index for this attribute value pair.
-         * Also we make sure that the presence index shows the existence of the
-         * new Rdn attribute within this entry.
-         */
-
-        for ( Ava newAtav : newRdn )
+        if ( partition.updateEntryOnDnChange() )
         {
-            String newNormType = newAtav.getNormType();
-            Object newNormValue = newAtav.getNormValue().getValue();
-
-            AttributeType newRdnAttrType = schemaManager.lookupAttributeTypeRegistry( newNormType );
-
-            if ( partition.hasUserIndexOn( newRdnAttrType ) )
-            {
-                Index<?> index = partition.getUserIndex( newRdnAttrType );
-                index = txnLogManager.wrap( partition.getSuffixDn(), index );
-
-                if ( !( ( Index<Object> ) index ).forward( newNormValue, id ) )
-                {
-                    indexChange = new IndexChange( index, newNormType, newNormValue, id,
-                        IndexChange.Type.ADD, true );
-                    changeContainer.addChange( indexChange );
-                }
-
-                // Check the entry before modifying it below so that we can check if we need to update the presence index.
-                Attribute curAttribute = entry.get( newRdnAttrType );
-
-                if ( ( curAttribute == null ) || ( curAttribute.size() == 0 ) )
-                {
-                    Index<?> presenceIdx;
-                    presenceIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
-                    indexChange = new IndexChange( presenceIdx, ApacheSchemaConstants.APACHE_PRESENCE_AT_OID,
-                        newNormType, id,
-                        IndexChange.Type.ADD, false );
-                    changeContainer.addChange( indexChange );
-                }
-            }
-
-            // Change the entry
-            entry.add( newRdnAttrType, newAtav.getNormValue() );
-
+            UUID id = getEntryId( partition, dn );
+            Dn parentDn = dn.getParent();
+            Dn newDn = new Dn( newRdn, parentDn );
+            newDn.apply( partition.getSchemaManager() );
+            handleDnChange( partition, dn, newDn, id );
         }
-
-        /*
-         * H A N D L E   O L D   R D N
-         * ====================================================================
-         * If the old Rdn is to be removed we need to get the attribute and
-         * value for it.  Keep in mind the old Rdn need not be based on the
-         * same attr as the new one.  We remove the Rdn value from the entry
-         * and remove the value/id tuple from the index on the old Rdn attr
-         * if any.  We also test if the delete of the old Rdn index tuple
-         * removed all the attribute values of the old Rdn using a reverse
-         * lookup.  If so that means we blew away the last value of the old
-         * Rdn attribute.  In this case we need to remove the attrName/id
-         * tuple from the presence index.
-         *
-         * We only remove an ATAV of the old Rdn if it is not included in the
-         * new Rdn.
-         */
-
-        if ( deleteOldRdn )
-        {
-            Rdn oldRdn = updn.getRdn();
-
-            for ( Ava oldAtav : oldRdn )
-            {
-                // check if the new ATAV is part of the old Rdn
-                // if that is the case we do not remove the ATAV
-                boolean mustRemove = true;
-
-                for ( Ava newAtav : newRdn )
-                {
-                    if ( oldAtav.equals( newAtav ) )
-                    {
-                        mustRemove = false;
-                        break;
-                    }
-                }
-
-                if ( mustRemove )
-                {
-                    String oldNormType = oldAtav.getNormType();
-                    String oldNormValue = oldAtav.getNormValue().getString();
-                    AttributeType oldRdnAttrType = schemaManager.lookupAttributeTypeRegistry( oldNormType );
-                    entry.remove( oldRdnAttrType, oldNormValue );
-
-                    if ( partition.hasUserIndexOn( oldRdnAttrType ) )
-                    {
-                        Index<?> index = partition.getUserIndex( oldRdnAttrType );
-                        indexChange = new IndexChange( index, oldNormType, oldNormValue, id,
-                            IndexChange.Type.DELETE, false );
-                        changeContainer.addChange( indexChange );
-
-                        /*
-                         * If there is no value for id in this index due to our
-                         * drop above we remove the oldRdnAttr from the presence idx
-                         */
-                        Attribute curAttribute = entry.get( oldRdnAttrType );
-
-                        if ( ( curAttribute == null ) || ( curAttribute.size() == 0 ) )
-                        {
-                            Index<?> presenceIdx;
-                            presenceIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
-                            indexChange = new IndexChange( presenceIdx, ApacheSchemaConstants.APACHE_PRESENCE_AT_OID,
-                                oldNormType, id,
-                                IndexChange.Type.DELETE, true );
-                            changeContainer.addChange( indexChange );
-                        }
-                    }
-                }
-            }
-        }
-
-        /*
-         * H A N D L E   D N   C H A N G E
-         * ====================================================================
-         * We only need to update the Rdn index.
-         * No need to calculate the new Dn.
-         */
-
-        Index<?> rdnIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_RDN_AT_OID );
-        UUID parentId = UUID.fromString( entry.get( SchemaConstants.ENTRY_PARENT_ID_AT ).getString() );
-
-        ParentIdAndRdn oldKey = new ParentIdAndRdn( parentId, newRdn );
-        indexChange = new IndexChange( rdnIdx, ApacheSchemaConstants.APACHE_RDN_AT_OID, oldKey, id,
-            IndexChange.Type.DELETE, true );
-        changeContainer.addChange( indexChange );
-
-        ParentIdAndRdn key = new ParentIdAndRdn( parentId, newRdn );
-        indexChange = new IndexChange( rdnIdx, ApacheSchemaConstants.APACHE_RDN_AT_OID, key, id,
-            IndexChange.Type.ADD, true );
-        changeContainer.addChange( indexChange );
-
-        /*
-         * Finall prepare the log edit for the entry change
-         */
-        EntryReplace entryReplace = new EntryReplace( entry, originalEntry );
-        changeContainer.addChange( entryReplace );
-
-        // log the change
-        txnLogManager.log( changeContainer, false );
-
+        
+        renameInternal( partition, dn, newRdn, deleteOldRdn, null, originalEntry );
     }
 
 
@@ -1445,9 +1352,12 @@ public class DefaultOperationExecutionMa
             Dn newSuperior = moveContext.getNewSuperior();
             Dn newDn = moveContext.getNewDn();
             Entry modifiedEntry = moveContext.getModifiedEntry();
-            Entry originalEntry = moveContext.getOriginalEntry();
+            Entry originalEntry = ( ( ClonedServerEntry )moveContext.getOriginalEntry() ).getOriginalEntry();
 
             move( partition, oldDn, newSuperior, newDn, modifiedEntry, originalEntry );
+            
+            //TODO TODO TODO REMOVE THIS
+            partition.move( moveContext );
 
         }
         catch ( Exception e )
@@ -1511,8 +1421,13 @@ public class DefaultOperationExecutionMa
         {
             modifiedEntry = originalEntry.clone();
         }
-        moveInternal( partition, oldDn, newSuperiorDn, newDn, modifiedEntry, originalEntry, newParentId );
-
+        
+        if ( partition.updateEntryOnDnChange() )
+        {
+            handleDnChange( partition, oldDn, newDn, entryId );
+        }
+        
+        moveInternal( partition, oldDn, newSuperiorDn, newDn, modifiedEntry, originalEntry, newParentId, entryId, oldParentId, false );
     }
 
 
@@ -1538,7 +1453,7 @@ public class DefaultOperationExecutionMa
             Rdn newRdn = moveAndRenameContext.getNewRdn();
             boolean deleteOldRdn = moveAndRenameContext.getDeleteOldRdn();
             Entry modifiedEntry = moveAndRenameContext.getModifiedEntry();
-            Entry originalEntry = moveAndRenameContext.getOriginalEntry();
+            Entry originalEntry = ( ( ClonedServerEntry )moveAndRenameContext.getOriginalEntry() ).getOriginalEntry();
 
             moveAndRename( partition, oldDn, newSuperiorDn, newRdn, modifiedEntry, originalEntry, deleteOldRdn );
         }
@@ -1584,6 +1499,8 @@ public class DefaultOperationExecutionMa
         }
 
         Dn newDn = newSuperiorDn.add( newRdn );
+        
+        UUID oldParentId = getParentId( partition, oldId );
 
         // Now check that the new entry does not exist
         UUID newId = getEntryId( partition, newDn );
@@ -1610,9 +1527,19 @@ public class DefaultOperationExecutionMa
         {
             modifiedEntry = originalEntry.clone();
         }
-
-        rename( partition, oldDn, newRdn, deleteOldRdn, modifiedEntry, originalEntry );
-        moveInternal( partition, oldDn, newSuperiorDn, newDn, modifiedEntry, originalEntry, newSuperiorId );
+        
+        if ( partition.updateEntryOnDnChange() )
+        {
+            handleDnChange( partition, oldDn, newDn, oldId );
+        }
+        
+        renameInternal( partition, oldDn, newRdn, deleteOldRdn, modifiedEntry, originalEntry );
+        
+        Dn parentDn = oldDn.getParent();
+        oldDn = new Dn( newRdn, parentDn );
+        oldDn.apply( partition.getSchemaManager() );
+        
+        moveInternal( partition, oldDn, newSuperiorDn, newDn, modifiedEntry, originalEntry, newSuperiorId, oldId, oldParentId, true );
     }
 
 
@@ -1739,8 +1666,70 @@ public class DefaultOperationExecutionMa
             throw new LdapOperationErrorException( e.getMessage(), e );
         }
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasEntry( Partition partition, HasEntryOperationContext entryContext ) throws LdapException
+    {
+        try
+        {
+            UUID id = getEntryId( partition, entryContext.getDn() );
+
+            Entry entry = lookup( partition, id );
+            
+            return entry != null; 
+        }
+        catch ( LdapException e )
+        {
+            return false;
+        }
+    }
+    
+    
+    //---------------------------------------------------------------------------------------------
+    // The List operation
+    //---------------------------------------------------------------------------------------------
+    /**
+     * {@inheritDoc}
+     */
+    public EntryFilteringCursor list( Partition partition, ListOperationContext listContext ) throws LdapException
+    {
+        try
+        {
+        return new BaseEntryFilteringCursor( 
+            new EntryCursorAdaptor( partition, 
+                list( partition, getEntryId( partition, listContext.getDn() ) ) ), listContext );
+        }
+        catch ( Exception e )
+        {
+            throw new LdapOperationErrorException( e.getMessage(), e );
+        }
+    }
 
+    
+    public IndexCursor<UUID> list( Partition partition, UUID id ) throws LdapException
+    {
+        try
+        {
+            Index<UUID> oneLevelIdx = ( Index<UUID> )partition.getSystemIndex( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
+            oneLevelIdx = ( Index<UUID> )txnLogManager.wrap( partition.getSuffixDn(), oneLevelIdx );
+            
+            // We use the OneLevel index to get all the entries from a starting point
+            // and below
+            IndexCursor<UUID> cursor = oneLevelIdx.forwardCursor( id );
+            cursor.beforeFirst();
+            
+            return cursor;
+         }
+        catch ( Exception e )
+        {
+            throw new LdapOperationErrorException( e.getMessage(), e );
+        }
+    }
 
+    
     //---------------------------------------------------------------------------------------------
     // ID and DN operations
     //---------------------------------------------------------------------------------------------
@@ -1789,14 +1778,9 @@ public class DefaultOperationExecutionMa
 
 
     /**
-     * builds the Dn of the entry identified by the given id
-     *
-     * @param partition partition entry lives in
-     * @param id the entry's id
-     * @return the normalized Dn of the entry
-     * @throws Exception
+     * {@inheritDoc}
      */
-    private Dn buildEntryDn( Partition partition, UUID id ) throws Exception
+    public Dn buildEntryDn( Partition partition, UUID id ) throws Exception
     {
         UUID parentId = id;
         UUID rootId = Partition.rootID;
@@ -1839,15 +1823,10 @@ public class DefaultOperationExecutionMa
 
 
     /**
-     * Gets the parent id of the given child id.
-     *
-     * @param partition partition childId lives in.
-     * @param childId id of the entry for which we want to get the parent id.
-     * @return parent id
-     * @throws Exception
+     * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    private UUID getParentId( Partition partition, UUID childId ) throws Exception
+    public UUID getParentId( Partition partition, UUID childId ) throws Exception
     {
         Index<ParentIdAndRdn> rdnIdx;
         rdnIdx = ( Index<ParentIdAndRdn> ) partition.getSystemIndex( ApacheSchemaConstants.APACHE_RDN_AT_OID );
@@ -1861,6 +1840,49 @@ public class DefaultOperationExecutionMa
 
         return key.getParentId();
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+    public int getChildCount( Partition partition, UUID id ) throws LdapOperationErrorException
+    {
+        IndexCursor<?> cursor = null;
+        try
+        {
+            Index<?> oneLevelIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
+            oneLevelIdx = txnLogManager.wrap( partition.getSuffixDn(), oneLevelIdx );
+            cursor =  ( ( Index<Object> ) oneLevelIdx ).forwardCursor( id );
+            
+            int count = 0;
+            
+            while ( cursor.next() )
+            {
+                count++;
+            }
+            
+            return count;
+        }
+        catch ( Exception e )
+        {
+            throw new LdapOperationErrorException( e.getMessage(), e );
+        }
+        finally
+        {
+            if ( cursor != null )
+            {
+                try
+                {
+                    cursor.close();
+                }
+                catch ( Exception e )
+                {
+                    throw new LdapOperationErrorException( e.getMessage(), e );
+                }
+            }
+        }
+    }
 
 
     /**
@@ -1967,12 +1989,8 @@ public class DefaultOperationExecutionMa
 
 
     private void moveInternal( Partition partition, Dn oldDn, Dn newSuperiorDn, Dn newDn, Entry modifiedEntry,
-        Entry originalEntry, UUID newParentId ) throws Exception
+        Entry originalEntry, UUID newParentId, UUID entryId, UUID oldParentId, boolean afterRename  ) throws Exception
     {
-        // Get the entry and the old parent IDs
-        UUID entryId = getEntryId( partition, oldDn );
-        UUID oldParentId = getParentId( partition, entryId );
-
         DataChangeContainer changeContainer = new DataChangeContainer( partition );
         changeContainer.setEntryID( entryId );
         IndexChange indexChange;
@@ -2008,12 +2026,12 @@ public class DefaultOperationExecutionMa
         // Update the Rdn index
         Index<?> rdnIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_RDN_AT_OID );
 
-        ParentIdAndRdn oldKey = new ParentIdAndRdn( oldParentId, oldDn.getRdn() );
+        ParentIdAndRdn oldKey = new ParentIdAndRdn( oldParentId, newDn.getRdn() );
         indexChange = new IndexChange( rdnIdx, ApacheSchemaConstants.APACHE_RDN_AT_OID, oldKey, entryId,
             IndexChange.Type.DELETE, true );
         changeContainer.addChange( indexChange );
 
-        ParentIdAndRdn newKey = new ParentIdAndRdn( newParentId, oldDn.getRdn() );
+        ParentIdAndRdn newKey = new ParentIdAndRdn( newParentId, newDn.getRdn() );
         indexChange = new IndexChange( rdnIdx, ApacheSchemaConstants.APACHE_RDN_AT_OID, newKey, entryId,
             IndexChange.Type.ADD, true );
         changeContainer.addChange( indexChange );
@@ -2039,11 +2057,267 @@ public class DefaultOperationExecutionMa
         /*
          * Finally prepare the log edit for the entry change
          */
+        modifiedEntry.setDn( newDn );
         EntryReplace entryReplace = new EntryReplace( modifiedEntry, originalEntry );
         changeContainer.addChange( entryReplace );
 
         // log the change
         txnLogManager.log( changeContainer, false );
     }
+    
+    @SuppressWarnings("unchecked")
+    private void renameInternal( Partition partition, Dn dn, Rdn newRdn, boolean deleteOldRdn, Entry entry, Entry originalEntry )
+        throws Exception
+    {
+        UUID id = getEntryId( partition, dn );
+        SchemaManager schemaManager = partition.getSchemaManager();
+        Dn suffixDn = partition.getSuffixDn();
+
+        DataChangeContainer changeContainer = new DataChangeContainer( partition );
+        changeContainer.setEntryID( id );
+        IndexChange indexChange;
+
+        if ( originalEntry == null )
+        {
+            MasterTable master = partition.getMasterTable();
+            master = txnLogManager.wrap( partition.getSuffixDn(), master );
+
+            // First get the entry
+            originalEntry = master.get( id );
+        }
+        
+        if ( entry == null )
+        {
+            entry = originalEntry.clone();
+        }
+
+        Dn updn = entry.getDn();
+
+        newRdn.apply( schemaManager );
+
+        Dn parentDn = updn.getParent();
+        Dn newDn = new Dn( newRdn, parentDn );
+        newDn.apply( schemaManager );
+
+        // Add subtree dependency to old and new dn
+        txnLogManager.addWrite( updn, SearchScope.SUBTREE );
+        txnLogManager.addWrite( newDn, SearchScope.SUBTREE );
+
+        /*
+         * H A N D L E   N E W   R D N
+         * ====================================================================
+         * Add the new Rdn attribute to the entry.  If an index exists on the
+         * new Rdn attribute we add the index for this attribute value pair.
+         * Also we make sure that the presence index shows the existence of the
+         * new Rdn attribute within this entry.
+         */
+
+        for ( Ava newAtav : newRdn )
+        {
+            String newNormType = newAtav.getNormType();
+            Object newNormValue = newAtav.getNormValue().getValue();
+
+            AttributeType newRdnAttrType = schemaManager.lookupAttributeTypeRegistry( newNormType );
+
+            if ( partition.hasUserIndexOn( newRdnAttrType ) )
+            {
+                Index<?> index = partition.getUserIndex( newRdnAttrType );
+                index = txnLogManager.wrap( partition.getSuffixDn(), index );
+
+                if ( !( ( Index<Object> ) index ).forward( newNormValue, id ) )
+                {
+                    indexChange = new IndexChange( index, newNormType, newNormValue, id,
+                        IndexChange.Type.ADD, true );
+                    changeContainer.addChange( indexChange );
+                }
+
+                // Check the entry before modifying it below so that we can check if we need to update the presence index.
+                Attribute curAttribute = entry.get( newRdnAttrType );
+
+                if ( ( curAttribute == null ) || ( curAttribute.size() == 0 ) )
+                {
+                    Index<?> presenceIdx;
+                    presenceIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
+                    indexChange = new IndexChange( presenceIdx, ApacheSchemaConstants.APACHE_PRESENCE_AT_OID,
+                        newNormType, id,
+                        IndexChange.Type.ADD, false );
+                    changeContainer.addChange( indexChange );
+                }
+            }
+
+            // Change the entry
+            entry.add( newRdnAttrType, newAtav.getNormValue() );
+
+        }
+
+        /*
+         * H A N D L E   O L D   R D N
+         * ====================================================================
+         * If the old Rdn is to be removed we need to get the attribute and
+         * value for it.  Keep in mind the old Rdn need not be based on the
+         * same attr as the new one.  We remove the Rdn value from the entry
+         * and remove the value/id tuple from the index on the old Rdn attr
+         * if any.  We also test if the delete of the old Rdn index tuple
+         * removed all the attribute values of the old Rdn using a reverse
+         * lookup.  If so that means we blew away the last value of the old
+         * Rdn attribute.  In this case we need to remove the attrName/id
+         * tuple from the presence index.
+         *
+         * We only remove an ATAV of the old Rdn if it is not included in the
+         * new Rdn.
+         */
+
+        if ( deleteOldRdn )
+        {
+            Rdn oldRdn = updn.getRdn();
+
+            for ( Ava oldAtav : oldRdn )
+            {
+                // check if the new ATAV is part of the old Rdn
+                // if that is the case we do not remove the ATAV
+                boolean mustRemove = true;
+
+                for ( Ava newAtav : newRdn )
+                {
+                    if ( oldAtav.equals( newAtav ) )
+                    {
+                        mustRemove = false;
+                        break;
+                    }
+                }
+
+                if ( mustRemove )
+                {
+                    String oldNormType = oldAtav.getNormType();
+                    String oldNormValue = oldAtav.getNormValue().getString();
+                    AttributeType oldRdnAttrType = schemaManager.lookupAttributeTypeRegistry( oldNormType );
+                    entry.remove( oldRdnAttrType, oldNormValue );
+
+                    if ( partition.hasUserIndexOn( oldRdnAttrType ) )
+                    {
+                        Index<?> index = partition.getUserIndex( oldRdnAttrType );
+                        indexChange = new IndexChange( index, oldNormType, oldNormValue, id,
+                            IndexChange.Type.DELETE, false );
+                        changeContainer.addChange( indexChange );
+
+                        /*
+                         * If there is no value for id in this index due to our
+                         * drop above we remove the oldRdnAttr from the presence idx
+                         */
+                        Attribute curAttribute = entry.get( oldRdnAttrType );
+
+                        if ( ( curAttribute == null ) || ( curAttribute.size() == 0 ) )
+                        {
+                            Index<?> presenceIdx;
+                            presenceIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
+                            indexChange = new IndexChange( presenceIdx, ApacheSchemaConstants.APACHE_PRESENCE_AT_OID,
+                                oldNormType, id,
+                                IndexChange.Type.DELETE, true );
+                            changeContainer.addChange( indexChange );
+                        }
+                    }
+                }
+            }
+        }
+
+        /*
+         * H A N D L E   D N   C H A N G E
+         * ====================================================================
+         * We only need to update the Rdn index.
+         * No need to calculate the new Dn.
+         */
+
+        Index<?> rdnIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+        UUID parentId = UUID.fromString( entry.get( SchemaConstants.ENTRY_PARENT_ID_AT ).getString() );
+
+        ParentIdAndRdn oldKey = new ParentIdAndRdn( parentId, updn.getRdn() );
+        indexChange = new IndexChange( rdnIdx, ApacheSchemaConstants.APACHE_RDN_AT_OID, oldKey, id,
+            IndexChange.Type.DELETE, true );
+        changeContainer.addChange( indexChange );
+
+        ParentIdAndRdn key = new ParentIdAndRdn( parentId, newRdn );
+        indexChange = new IndexChange( rdnIdx, ApacheSchemaConstants.APACHE_RDN_AT_OID, key, id,
+            IndexChange.Type.ADD, true );
+        changeContainer.addChange( indexChange );
+
+        /*
+         * Finally prepare the log edit for the entry change
+         */
+        entry.setDn( newDn );
+        EntryReplace entryReplace = new EntryReplace( entry, originalEntry );
+        changeContainer.addChange( entryReplace );
+
+        // log the change
+        txnLogManager.log( changeContainer, false );
+
+    }
+    
+    
+    private void handleDnChange( Partition partition, Dn oldDn, Dn newDn, UUID baseId ) throws Exception
+    {
+        Dn  suffixDn = partition.getSuffixDn();
+        SchemaManager schemaManager = partition.getSchemaManager();
+        Index<?> subLevelIdx = partition.getSystemIndex( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID );
+        subLevelIdx = txnLogManager.wrap( suffixDn, subLevelIdx );
+        
+        MasterTable master = partition.getMasterTable();
+        master = txnLogManager.wrap( partition.getSuffixDn(), master );
+        
+        Entry childEntry;
+        Entry clonedChildEntry;
+        UUID childId;
+        Dn childDn;
+        Dn childNewDn = null;
+        IndexCursor<UUID> cursor = ( ( Index<UUID> ) subLevelIdx ).forwardCursor( baseId );
+        
+        try
+        {
+            while ( cursor.next() )
+            {
+                childId = cursor.get().getId();
+                
+                // Skip base entry
+                
+                if ( UUIDComparator.INSTANCE.compare( baseId, childId ) == 0 )
+                {
+                    continue;
+                }
+                
+                childEntry = master.get( childId );
+                clonedChildEntry = childEntry.clone();
+                
+                childDn = childEntry.getDn();                
+                int startIdx = childDn.size() - oldDn.size() - 1;
+                
+                for ( int idx = startIdx; idx >= 0; idx-- )
+                {
+                    if (  idx == startIdx )
+                    {
+                        childNewDn = new Dn( childDn.getRdn( idx ), newDn );
+                        childNewDn.apply( schemaManager );
+                    }
+                    else
+                    {
+                        childNewDn = childNewDn.add( childDn.getRdn( idx ) );
+                    }
+                }
+                
+                clonedChildEntry.setDn( childNewDn );
+                
+                /*
+                 * Prepare the log edit for the entry change
+                 */
+                DataChangeContainer changeContainer = new DataChangeContainer( partition );
+                changeContainer.setEntryID( childId );
+                EntryReplace entryReplace = new EntryReplace( clonedChildEntry, childEntry );
+                changeContainer.addChange( entryReplace );
+                txnLogManager.log( changeContainer, false );
+            }
+        }
+        finally
+        {
+            cursor.close();
+        }
+    }
 
 }

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java Wed Nov 30 09:53:21 2011
@@ -57,6 +57,7 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
 import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
 import org.apache.directory.server.core.api.partition.AbstractPartition;
+import org.apache.directory.server.core.api.partition.OperationExecutionManager;
 import org.apache.directory.server.core.api.partition.Partition;
 import org.apache.directory.server.core.api.partition.PartitionNexus;
 import org.apache.directory.server.i18n.I18n;
@@ -141,6 +142,9 @@ public class DefaultPartitionNexus exten
     
     /** The cn=schema Dn */
     private Dn subschemSubentryDn;
+    
+    /** Operation Execution Manager */
+    OperationExecutionManager operationExecutionManager;
 
 
 
@@ -200,6 +204,8 @@ public class DefaultPartitionNexus exten
         // NOTE: We ignore ContextPartitionConfiguration parameter here.
         if ( !initialized )
         {
+            operationExecutionManager = OperationExecutionManagerFactory.instance();
+            
             // Add the supported controls
             Iterator<String> ctrlOidItr = directoryService.getLdapCodecService().registeredControls();
             
@@ -449,7 +455,7 @@ public class DefaultPartitionNexus exten
     public void add( AddOperationContext addContext ) throws LdapException
     {
         Partition partition = getPartition( addContext.getDn() );
-        partition.add( addContext );
+        operationExecutionManager.add( partition, addContext );
 
         Attribute at = addContext.getEntry().get( SchemaConstants.ENTRY_CSN_AT );
         directoryService.setContextCsn( at.getString() );
@@ -515,7 +521,7 @@ public class DefaultPartitionNexus exten
     public void delete( DeleteOperationContext deleteContext ) throws LdapException
     {
         Partition partition = getPartition( deleteContext.getDn() );
-        partition.delete( deleteContext );
+        operationExecutionManager.delete( partition, deleteContext );
     }
 
 
@@ -538,7 +544,7 @@ public class DefaultPartitionNexus exten
 
         Partition partition = getPartition( dn );
         
-        return partition.hasEntry( hasEntryContext );
+        return operationExecutionManager.hasEntry( partition, hasEntryContext );
     }
 
 
@@ -549,7 +555,7 @@ public class DefaultPartitionNexus exten
     {
         Partition partition = getPartition( listContext.getDn() );
         
-        return partition.list( listContext );
+        return operationExecutionManager.list( partition, listContext );
     }
 
 
@@ -592,7 +598,7 @@ public class DefaultPartitionNexus exten
         }
 
         Partition partition = getPartition( dn );
-        Entry entry =  partition.lookup( lookupContext );
+        Entry entry =  operationExecutionManager.lookup( partition, lookupContext );
         
         if ( entry == null )
         {
@@ -619,7 +625,7 @@ public class DefaultPartitionNexus exten
 
         Partition partition = getPartition( modifyContext.getDn() );
 
-        partition.modify( modifyContext );
+        operationExecutionManager.modify( partition, modifyContext );
         
         Entry alteredEntry = modifyContext.getAlteredEntry();
         
@@ -641,7 +647,7 @@ public class DefaultPartitionNexus exten
         // We also have to get the new partition as it can be different
         //Partition newBackend = getPartition( opContext.getNewDn() );
 
-        partition.move( moveContext );
+        operationExecutionManager.move( partition, moveContext );
     }
 
 
@@ -651,7 +657,7 @@ public class DefaultPartitionNexus exten
     public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
     {
         Partition partition = getPartition( moveAndRenameContext.getDn() );
-        partition.moveAndRename( moveAndRenameContext );
+        operationExecutionManager.moveAndRename( partition, moveAndRenameContext );
     }
 
 
@@ -661,7 +667,7 @@ public class DefaultPartitionNexus exten
     public void rename( RenameOperationContext renameContext ) throws LdapException
     {
         Partition partition = getPartition( renameContext.getDn() );
-        partition.rename( renameContext );
+        operationExecutionManager.rename( partition, renameContext );
     }
 
 

Copied: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/EntryCursorAdaptor.java (from r1201828, directory/apacheds/branches/apacheds-txns/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/EntryCursorAdaptor.java)
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/EntryCursorAdaptor.java?p2=directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/EntryCursorAdaptor.java&p1=directory/apacheds/branches/apacheds-txns/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/EntryCursorAdaptor.java&r1=1201828&r2=1208350&rev=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/EntryCursorAdaptor.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/EntryCursorAdaptor.java Wed Nov 30 09:53:21 2011
@@ -17,14 +17,18 @@
  *   under the License.
  *
  */
-package org.apache.directory.server.core.partition.impl.btree;
+package org.apache.directory.server.core.shared.partition;
 
 
 import java.util.Iterator;
 import java.util.UUID;
 
+import org.apache.directory.server.core.api.partition.Partition;
 import org.apache.directory.server.core.api.partition.index.IndexCursor;
 import org.apache.directory.server.core.api.partition.index.IndexEntry;
+import org.apache.directory.server.core.api.partition.index.MasterTable;
+import org.apache.directory.server.core.api.txn.TxnLogManager;
+import org.apache.directory.server.core.shared.txn.TxnManagerFactory;
 import org.apache.directory.shared.i18n.I18n;
 import org.apache.directory.shared.ldap.model.cursor.ClosureMonitor;
 import org.apache.directory.shared.ldap.model.cursor.Cursor;
@@ -39,14 +43,21 @@ import org.apache.directory.shared.ldap.
  */
 public class EntryCursorAdaptor implements Cursor<Entry>
 {
-    private final AbstractBTreePartition db;
-    private final IndexCursor<UUID> indexCursor;
+    /** Underlying partition */
+    private  Partition db;
+    
+    /** Wrapped cursor */
+    private  IndexCursor<UUID> indexCursor;
 
+    /** Master table of the partition */
+    MasterTable masterTable;
 
-    public EntryCursorAdaptor( AbstractBTreePartition db, IndexCursor<UUID> indexCursor )
+    public EntryCursorAdaptor( Partition db, IndexCursor<UUID> indexCursor ) throws Exception
     {
         this.db = db;
         this.indexCursor = indexCursor;
+        TxnLogManager txnLogManager = TxnManagerFactory.txnLogManagerInstance();
+        masterTable = txnLogManager.wrap( db.getSuffixDn(), db.getMasterTable() );
     }
 
 
@@ -137,7 +148,7 @@ public class EntryCursorAdaptor implemen
 
         if ( indexEntry.getEntry() == null )
         {
-            indexEntry.setEntry( db.lookup( indexEntry.getId() ) );
+            indexEntry.setEntry( masterTable.get( indexEntry.getId() ) );
         }
 
         return indexEntry.getEntry();

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/AbstractTransaction.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/AbstractTransaction.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/AbstractTransaction.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/AbstractTransaction.java Wed Nov 30 09:53:21 2011
@@ -19,11 +19,15 @@
  */
 package org.apache.directory.server.core.shared.txn;
 
+import java.util.Comparator;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.UUID;
 
+import org.apache.directory.server.core.api.partition.index.ForwardIndexEntry;
+import org.apache.directory.server.core.api.partition.index.IndexEntry;
+import org.apache.directory.server.core.api.partition.index.ReverseIndexEntry;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.name.Dn;
 
@@ -129,6 +133,9 @@ abstract class AbstractTransaction imple
     }
     
     
+    /**
+     * {@inheritDoc}
+     */
     public Entry mergeUpdates( Dn partitionDn, UUID entryID, Entry entry )
     {
         Entry prevEntry  = entry;
@@ -151,4 +158,69 @@ abstract class AbstractTransaction imple
         
         return curEntry;
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public UUID mergeForwardLookup(Dn partitionDn, String attributeOid,  Object key, UUID curId, Comparator<Object> valueComparator )
+    {
+        ForwardIndexEntry<Object> indexEntry = new ForwardIndexEntry<Object>();
+        indexEntry.setId( curId );
+        indexEntry.setValue( key );
+        
+        ReadWriteTxn curTxn;
+        Iterator<ReadWriteTxn> it = txnsToCheck.iterator();
+        
+        while ( it.hasNext() )
+        {
+            curTxn = it.next();
+            curTxn.updateForwardLookup( partitionDn, attributeOid, indexEntry, valueComparator );   
+        }
+        
+        return indexEntry.getId();
+    }
+   
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Object mergeReverseLookup(Dn partitionDn, String attributeOid,  UUID id, Object curValue )
+    {
+        ReverseIndexEntry<Object> indexEntry = new ReverseIndexEntry<Object>();
+        indexEntry.setId( id );
+        indexEntry.setValue( curValue );
+        
+        ReadWriteTxn curTxn;
+        Iterator<ReadWriteTxn> it = txnsToCheck.iterator();
+        
+        while ( it.hasNext() )
+        {
+            curTxn = it.next();
+            curTxn.updateReverseLookup( partitionDn, attributeOid, indexEntry );
+        }
+        
+        return indexEntry.getValue();
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public boolean mergeExistence(Dn partitionDN, String attributeOid,  IndexEntry<?> indexEntry, boolean currentlyExists )
+    {
+        ReadWriteTxn curTxn;
+        boolean forward = ( indexEntry instanceof ForwardIndexEntry );
+        
+        Iterator<ReadWriteTxn> it = txnsToCheck.iterator();
+        
+        while ( it.hasNext() )
+        {
+            curTxn = it.next();
+            currentlyExists = curTxn.updateExistence( partitionDN, attributeOid, indexEntry, currentlyExists, forward );
+          
+        }
+        
+        return currentlyExists;
+    }
 }
\ No newline at end of file

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/DefaultTxnLogManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/DefaultTxnLogManager.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/DefaultTxnLogManager.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/DefaultTxnLogManager.java Wed Nov 30 09:53:21 2011
@@ -22,6 +22,7 @@ package org.apache.directory.server.core
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectOutputStream;
+import java.util.Comparator;
 import java.util.UUID;
 
 import org.apache.directory.server.core.api.log.UserLogRecord;
@@ -30,6 +31,7 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.api.partition.index.Index;
 import org.apache.directory.server.core.api.partition.index.IndexCursor;
 import org.apache.directory.server.core.api.partition.index.IndexComparator;
+import org.apache.directory.server.core.api.partition.index.IndexEntry;
 import org.apache.directory.server.core.api.partition.index.MasterTable;
 
 import org.apache.directory.shared.ldap.model.entry.Entry;
@@ -82,6 +84,8 @@ public class DefaultTxnLogManager implem
              *  partitions directly
              */
             logEdit.apply( false );
+            
+            return;
         }
        
         if ( ! ( curTxn instanceof ReadWriteTxn ) )
@@ -157,6 +161,55 @@ public class DefaultTxnLogManager implem
         return curTxn.mergeUpdates( partitionDn, entryID, entry );
     }
     
+    
+    /**
+     * {@inheritDoc}
+     */
+    public UUID mergeForwardLookup(Dn partitionDN, String attributeOid,  Object key, UUID curId, Comparator<Object> valueComparator )
+    {
+        Transaction curTxn = txnManager.getCurTxn();
+        
+        if ( ( curTxn == null ) )
+        {
+            throw new IllegalStateException( "Trying to merge with log wihout txn" );
+        }
+        
+        return curTxn.mergeForwardLookup( partitionDN, attributeOid, key, curId, valueComparator );
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public Object mergeReversLookup(Dn partitionDN, String attributeOid,  UUID id, Object curValue )
+    {
+        Transaction curTxn = txnManager.getCurTxn();
+        
+        if ( ( curTxn == null ) )
+        {
+            throw new IllegalStateException( "Trying to merge with log wihout txn" );
+        }
+        
+        return curTxn.mergeReverseLookup( partitionDN, attributeOid, id, curValue );
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    public boolean mergeExistence(Dn partitionDN, String attributeOid,  IndexEntry<?> indexEntry, boolean currentlyExists )
+    {
+        Transaction curTxn = txnManager.getCurTxn();
+        
+        if ( ( curTxn == null ) )
+        {
+            throw new IllegalStateException( "Trying to merge with log wihout txn" );
+        }
+        
+      
+        return curTxn.mergeExistence( partitionDN, attributeOid, indexEntry, currentlyExists );
+    }
+    
    
     /**
      * {@inheritDoc}

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexCursorWrapper.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexCursorWrapper.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexCursorWrapper.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexCursorWrapper.java Wed Nov 30 09:53:21 2011
@@ -21,12 +21,17 @@ package org.apache.directory.server.core
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.TreeSet;
 import java.util.UUID;
 
 import org.apache.directory.server.core.api.partition.index.AbstractIndexCursor;
+import org.apache.directory.server.core.api.partition.index.ForwardIndexEntry;
 import org.apache.directory.server.core.api.partition.index.IndexCursor;
 import org.apache.directory.server.core.api.partition.index.IndexEntry;
 import org.apache.directory.server.core.api.partition.index.IndexComparator;
+import org.apache.directory.server.core.api.partition.index.ReverseIndexEntry;
 import org.apache.directory.server.i18n.I18n;
 
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
@@ -70,14 +75,14 @@ public class IndexCursorWrapper extends 
     /** whether this is a cursor on forward or reverse index */
     private boolean forwardIndex;
     
-    /** List of txns that this cursor depends on */
-    private ArrayList<ReadWriteTxn> txns;
+    /** Index deletes by txns that this cursor depends on */
+    private ArrayList<NavigableSet<IndexEntry<Object>>> deletes;
     
     /** True if cursor is positioned */
     private boolean positioned;
     
     /** direction of the move */
-    boolean movingNext = true;
+    private boolean movingNext = true;
     
     /** Comparator used to order the index entries */
     private IndexComparator<Object> comparator;
@@ -85,6 +90,9 @@ public class IndexCursorWrapper extends 
     /** unsupported operation message */
     private static final String UNSUPPORTED_MSG = I18n.err( I18n.ERR_722 );
     
+    /** Last value returned: here to keep memory overhead low */
+    private ForwardIndexEntry<Object> lastValue = new ForwardIndexEntry<Object>();
+     
     public IndexCursorWrapper( Dn partitionDn, IndexCursor<Object> wrappedCursor, IndexComparator<Object> comparator, String attributeOid, boolean forwardIndex, Object onlyValueKey, UUID onlyIDKey )
     {
         this.partitionDn = partitionDn;
@@ -103,7 +111,7 @@ public class IndexCursorWrapper extends 
         
         if ( toCheck.size() > 0 )
         {
-            txns = new ArrayList<ReadWriteTxn>( toCheck.size() );
+            deletes = new ArrayList<NavigableSet<IndexEntry<Object>>>( toCheck.size() );
             
             ReadWriteTxn dependentTxn;
             
@@ -111,19 +119,30 @@ public class IndexCursorWrapper extends 
             {
                 dependentTxn = toCheck.get( idx );
                 
-                if ( dependentTxn.hasDeletesFor( partitionDn, attributeOid ) )
+                if ( curTxn == dependentTxn )
                 {
-                    txns.add( dependentTxn );
+                    NavigableSet<IndexEntry<Object>> txnDeletes = dependentTxn.getDeletesFor( partitionDn, attributeOid );
+                    
+                    if ( txnDeletes != null )
+                    {
+                        TreeSet<IndexEntry<Object>> clonedDeletes = new TreeSet<IndexEntry<Object>>( comparator );
+                        clonedDeletes.addAll( txnDeletes );
+                        deletes.add( clonedDeletes );
+                    }
+                    else
+                    {
+                        deletes.add( null );
+                    }
                 }
                 else
                 {
-                    txns.add( null );
+                    deletes.add( dependentTxn.getDeletesFor( partitionDn, attributeOid ) );
                 }
                 
                 values.add( null );
                 
                 // This adds a null to the array if the txn does not have any changes for the index
-                cursors.add( dependentTxn.getCursorFor( partitionDn, attributeOid, forwardIndex, onlyValueKey, onlyIDKey, comparator ) );
+                cursors.add( getCursorFor( dependentTxn, partitionDn, attributeOid, forwardIndex, onlyValueKey, onlyIDKey, comparator ) );
             }
         }
     }
@@ -324,11 +343,12 @@ public class IndexCursorWrapper extends 
         
         checkNotClosed( "next()" );
         
-        IndexEntry<Object> lastValue = null;
         
         if ( getIndex >= 0 )
         {
-            lastValue = values.get( getIndex );
+            IndexEntry<Object> indexEntry = values.get( getIndex );
+            lastValue.setId( indexEntry.getId() );
+            lastValue.setValue( indexEntry.getValue() );
         }
         
         int idx;
@@ -377,7 +397,7 @@ public class IndexCursorWrapper extends 
         }
         
         int txnIdx;
-        ReadWriteTxn curTxn;
+        NavigableSet<IndexEntry<Object>> txnDeletes;
         boolean valueDeleted;
         
         do
@@ -398,11 +418,11 @@ public class IndexCursorWrapper extends 
             
             valueDeleted = false;
             
-            for ( ; txnIdx < txns.size(); txnIdx++ )
+            for ( ; txnIdx < deletes.size(); txnIdx++ )
             {
-                curTxn = txns.get( txnIdx );
+                txnDeletes = deletes.get( txnIdx );
                 
-                if ( ( curTxn != null ) && ( curTxn.isIndexEntryDeleted( partitionDn, attributeOid, value ) ) )
+                if ( ( txnDeletes != null ) && ( txnDeletes.contains( value ) ) )
                 {
                     valueDeleted = true;
                     break;
@@ -410,7 +430,7 @@ public class IndexCursorWrapper extends 
             }
             
             // If the value we get is not deleted and greater than the last value we returned, then we are done
-            if ( ( valueDeleted == false ) && ( ( lastValue == null ) || ( comparator.compare( value, lastValue ) > 0 ) ) )
+            if ( ( valueDeleted == false ) && ( ( lastValue.getId() == null ) || ( comparator.compare( value, lastValue ) > 0 ) ) )
             {
                 break;
             }
@@ -435,11 +455,11 @@ public class IndexCursorWrapper extends 
         
         checkNotClosed( "previous()" );
         
-        IndexEntry<Object> lastValue = null;
-        
         if ( getIndex >= 0 )
         {
-            lastValue = values.get( getIndex );
+            IndexEntry<Object> indexEntry = values.get( getIndex );
+            lastValue.setId( indexEntry.getId() );
+            lastValue.setValue( indexEntry.getValue() );
         }
         
         int idx;
@@ -489,7 +509,7 @@ public class IndexCursorWrapper extends 
         }
         
         int txnIdx;
-        ReadWriteTxn curTxn;
+        NavigableSet<IndexEntry<Object>> txnDeletes;
         boolean valueDeleted;
         
         do
@@ -510,11 +530,11 @@ public class IndexCursorWrapper extends 
             
             valueDeleted = false;
             
-            for ( ; txnIdx < txns.size(); txnIdx++ )
+            for ( ; txnIdx < deletes.size(); txnIdx++ )
             {
-                curTxn = txns.get( txnIdx );
+                txnDeletes = deletes.get( txnIdx );
                 
-                if ( curTxn!= null && curTxn.isIndexEntryDeleted( partitionDn, attributeOid, value ) )
+                if ( txnDeletes!= null && txnDeletes.contains( value ) )
                 {
                     valueDeleted = true;
                     break;
@@ -522,7 +542,7 @@ public class IndexCursorWrapper extends 
             }
             
             // If the value we get is not deleted and less than the last value we returned, then we are done
-            if ( ( valueDeleted == false ) && ( ( lastValue == null ) || ( comparator.compare( value, lastValue ) < 0 ) ) )
+            if ( ( valueDeleted == false ) && ( ( lastValue.getId() == null ) || ( comparator.compare( value, lastValue ) < 0 ) ) )
             {
                 break;
             }
@@ -552,7 +572,27 @@ public class IndexCursorWrapper extends 
                 throw new IllegalStateException( "getIndex points to a null value" );
             }
             
-            return value;
+            /*
+             * TODO fixme:
+             * Upper layers might change the index entry we return. To work around this.
+             * we create a new idex entry here. This code should be removed when
+             * search engine is changed to avoid modifying index entries.
+             */
+            IndexEntry<Object> indexEntry;
+            
+            if ( forwardIndex )
+            {
+                indexEntry = new ForwardIndexEntry<Object>();
+            }
+            else
+            {
+                indexEntry = new ReverseIndexEntry<Object>();
+            }
+            
+            indexEntry.setId( value.getId() );
+            indexEntry.setValue( value.getValue() );
+            
+            return indexEntry;
         }
 
         throw new InvalidCursorPositionException();
@@ -697,4 +737,49 @@ public class IndexCursorWrapper extends 
             }
         }
     }
+    
+    /**
+     * Returns a cursor over the changes made by the given txn on the index identified by partitionDn+attributeOid. 
+     *
+     * @param txn for which the cursor will be built.
+     * @param partitionDn dn of the partition
+     * @param attributeOid oid of the indexed attribute
+     * @param forwardIndex true if forward index and reverse if reverse index
+     * @param onlyValueKey set if the cursor should be locked down by a key ( should be non null only for forward indices )
+     * @param onlyIDKey  set if the cursor should be locked down by a key ( should be non null only for reverse indices )
+     * @param comparator comparator that will be used to order index entries.
+     * @return
+     */
+    private IndexCursor<Object> getCursorFor( ReadWriteTxn txn, Dn partitionDn, String attributeOid, boolean forwardIndex,
+        Object onlyValueKey, UUID onlyIDKey, IndexComparator<Object> comparator )
+    {
+        NavigableSet<IndexEntry<Object>> changes; 
+        TxnIndexCursor txnIndexCursor = null;
+
+        if ( forwardIndex )
+        {
+            changes = txn.getForwardIndexChanges( partitionDn, attributeOid );
+        }
+        else
+        {
+            changes = txn.getReverseIndexChanges( partitionDn, attributeOid );
+        }
+        
+        if ( changes == null || ( changes.size() == 0 ) )
+        {
+            return null;
+        }
+        
+        Transaction curTxn = TxnManagerFactory.txnManagerInternalInstance().getCurTxn();
+        
+        if ( txn == curTxn )
+        {
+            NavigableSet<IndexEntry<Object>> originalChanges = changes;
+            changes = new TreeSet<IndexEntry<Object>>( comparator );
+            changes.addAll( originalChanges );
+        }
+        
+        return new TxnIndexCursor( changes, forwardIndex, onlyValueKey, onlyIDKey, comparator );
+    }
+
 }

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexWrapper.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexWrapper.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexWrapper.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/IndexWrapper.java Wed Nov 30 09:53:21 2011
@@ -25,9 +25,11 @@ import java.util.Comparator;
 import java.util.UUID;
 
 import org.apache.directory.server.core.api.partition.index.ForwardIndexComparator;
+import org.apache.directory.server.core.api.partition.index.ForwardIndexEntry;
 import org.apache.directory.server.core.api.partition.index.Index;
 import org.apache.directory.server.core.api.partition.index.IndexCursor;
 import org.apache.directory.server.core.api.partition.index.ReverseIndexComparator;
+import org.apache.directory.server.core.api.partition.index.ReverseIndexEntry;
 import org.apache.directory.server.core.api.partition.index.UUIDComparator;
 import org.apache.directory.server.core.api.txn.TxnLogManager;
 
@@ -47,12 +49,15 @@ public class IndexWrapper implements Ind
     
     /** partition the table belongs to */
     private Dn partitionDn;
-   
+    
+    /** Txn log manager */
+   private TxnLogManager txnLogManager;
     
     public IndexWrapper( Dn partitionDn, Index<Object> wrappedIndex )
     {
         this.partitionDn = partitionDn;
         this.wrappedIndex = wrappedIndex;
+        txnLogManager = TxnManagerFactory.txnLogManagerInstance();
     }
 
     
@@ -167,23 +172,28 @@ public class IndexWrapper implements Ind
      */
     public UUID forwardLookup( Object attrVal ) throws Exception
     {
-        IndexCursor<Object> cursor = forwardCursor( attrVal );
-        
-        try
-        {
-            cursor.beforeValue( null, attrVal );
-            
-            if ( cursor.next() )
-            {
-                return cursor.get().getId();
-            }
-            
-            return null;
-        }
-        finally
-        {
-            cursor.close();
-        }
+//        IndexCursor<Object> cursor = forwardCursor( attrVal );
+//
+//        try
+//        {
+//
+//            if ( cursor.next() )
+//            {
+//                return cursor.get().getId();
+//            }
+//
+//            return null;
+//        }
+//        finally
+//        {
+//            cursor.close();
+//        }
+        
+        UUID curId = wrappedIndex.forwardLookup( attrVal );
+        
+        curId = txnLogManager.mergeForwardLookup( partitionDn, wrappedIndex.getAttribute().getOid(), attrVal, curId, wrappedIndex.getForwardIndexEntryComparator().getValueComparator() );
+       
+        return curId;
     }
 
 
@@ -192,23 +202,28 @@ public class IndexWrapper implements Ind
      */
     public Object reverseLookup( UUID id ) throws Exception
     {
-        IndexCursor<Object> cursor = reverseCursor( id );
+//        IndexCursor<Object> cursor = reverseCursor( id );
+//        
+//        try
+//        {
+//            
+//            if ( cursor.next() )
+//            {
+//                return cursor.get().getValue();
+//            }
+//            
+//            return null;
+//        }
+//        finally
+//        {
+//            cursor.close();
+//        }
         
-        try
-        {
-            cursor.beforeValue( id, null );
-            
-            if ( cursor.next() )
-            {
-                return cursor.get().getValue();
-            }
-            
-            return null;
-        }
-        finally
-        {
-            cursor.close();
-        }
+        Object curVal = wrappedIndex.reverseLookup( id );
+        
+        curVal = txnLogManager.mergeReversLookup( partitionDn, wrappedIndex.getAttribute().getOid(), id, curVal );
+        
+        return curVal;
     }
 
 
@@ -246,11 +261,10 @@ public class IndexWrapper implements Ind
     {
         IndexCursor<Object> wrappedCursor;
         IndexCursor<Object> cursor = wrappedIndex.reverseCursor();
-        TxnLogManager logManager = TxnManagerFactory.txnLogManagerInstance();
         
         try
         {
-            wrappedCursor = ( IndexCursor<Object>) logManager.wrap( partitionDn, cursor, wrappedIndex.getReverseIndexEntryComparator(), 
+            wrappedCursor = ( IndexCursor<Object>) txnLogManager.wrap( partitionDn, cursor, wrappedIndex.getReverseIndexEntryComparator(), 
                 wrappedIndex.getAttribute().getOid(), false, null, null );
         } 
         catch (Exception e)
@@ -269,12 +283,11 @@ public class IndexWrapper implements Ind
     public IndexCursor<Object> forwardCursor() throws Exception
     {
         IndexCursor<Object> wrappedCursor;
-        IndexCursor<Object> cursor = wrappedIndex.reverseCursor();
-        TxnLogManager logManager = TxnManagerFactory.txnLogManagerInstance();
+        IndexCursor<Object> cursor = wrappedIndex.forwardCursor();
         
         try
         {
-            wrappedCursor = ( IndexCursor<Object>)logManager.wrap( partitionDn, cursor, wrappedIndex.getForwardIndexEntryComparator(), 
+            wrappedCursor = ( IndexCursor<Object>)txnLogManager.wrap( partitionDn, cursor, wrappedIndex.getForwardIndexEntryComparator(), 
                 wrappedIndex.getAttribute().getOid(), true, null, null );
         } 
         catch (Exception e)
@@ -293,12 +306,11 @@ public class IndexWrapper implements Ind
     public IndexCursor<Object> reverseCursor( UUID id ) throws Exception
     {
         IndexCursor<Object> wrappedCursor;
-        IndexCursor<Object> cursor = wrappedIndex.reverseCursor();
-        TxnLogManager logManager = TxnManagerFactory.txnLogManagerInstance();
+        IndexCursor<Object> cursor = wrappedIndex.reverseCursor( id );
         
         try
         {
-            wrappedCursor = ( IndexCursor<Object>)logManager.wrap( partitionDn, cursor, wrappedIndex.getReverseIndexEntryComparator(), 
+            wrappedCursor = ( IndexCursor<Object>)txnLogManager.wrap( partitionDn, cursor, wrappedIndex.getReverseIndexEntryComparator(), 
                 wrappedIndex.getAttribute().getOid(), false, null, id );
         } 
         catch (Exception e)
@@ -317,12 +329,11 @@ public class IndexWrapper implements Ind
     public IndexCursor<Object> forwardCursor( Object key ) throws Exception
     {
         IndexCursor<Object> wrappedCursor;
-        IndexCursor<Object> cursor = wrappedIndex.reverseCursor();
-        TxnLogManager logManager = TxnManagerFactory.txnLogManagerInstance();
+        IndexCursor<Object> cursor = wrappedIndex.forwardCursor( key );
         
         try
         {
-            wrappedCursor = ( IndexCursor<Object>)logManager.wrap( partitionDn, cursor, wrappedIndex.getForwardIndexEntryComparator(), 
+            wrappedCursor = ( IndexCursor<Object>)txnLogManager.wrap( partitionDn, cursor, wrappedIndex.getForwardIndexEntryComparator(), 
                 wrappedIndex.getAttribute().getOid(), true, key, null );
         } 
         catch (Exception e)
@@ -381,24 +392,12 @@ public class IndexWrapper implements Ind
      */
     public boolean forward( Object attrVal, UUID id ) throws Exception
     {
-        IndexCursor<Object> cursor = forwardCursor( attrVal );
-        Comparator<UUID> idComp = UUIDComparator.INSTANCE;
+        boolean currentlyExists = wrappedIndex.forward( attrVal, id );
         
-        try
-        {
-            cursor.beforeValue( id, attrVal );
-            
-            if ( cursor.next() && ( idComp.compare( cursor.get().getId(), id ) == 0 ) )
-            {
-                return true;
-            }
-            
-            return false;
-        }
-        finally
-        {
-            cursor.close();
-        }
+        ForwardIndexEntry<Object> indexEntry = new ForwardIndexEntry<Object>();
+        indexEntry.setId( id );
+        indexEntry.setValue( attrVal );
+        return txnLogManager.mergeExistence( partitionDn, wrappedIndex.getAttribute().getOid(), indexEntry, currentlyExists );
     }
     
 
@@ -430,24 +429,12 @@ public class IndexWrapper implements Ind
      */
     public boolean reverse( UUID id, Object attrVal ) throws Exception
     {
-        IndexCursor<Object> cursor = reverseCursor( id );
-        Comparator<Object> valueComp = wrappedIndex.getForwardIndexEntryComparator().getValueComparator();
+        boolean currentlyExists = wrappedIndex.reverse( id, attrVal );
         
-        try
-        {
-            cursor.beforeValue( id, attrVal );
-            
-            if ( cursor.next() && ( valueComp.compare( cursor.get().getValue(), attrVal ) == 0 ))
-            {
-                return true;
-            }
-            
-            return false;
-        }
-        finally
-        {
-            cursor.close();
-        }
+        ReverseIndexEntry<Object> indexEntry = new ReverseIndexEntry<Object>();
+        indexEntry.setId( id );
+        indexEntry.setValue( attrVal );
+        return txnLogManager.mergeExistence( partitionDn, wrappedIndex.getAttribute().getOid(), indexEntry, currentlyExists );
     }
     
 

Modified: directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/MasterTableWrapper.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/MasterTableWrapper.java?rev=1208350&r1=1208349&r2=1208350&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/MasterTableWrapper.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-shared/src/main/java/org/apache/directory/server/core/shared/txn/MasterTableWrapper.java Wed Nov 30 09:53:21 2011
@@ -171,8 +171,8 @@ public class MasterTableWrapper implemen
         }
         
         TxnLogManager logManager = TxnManagerFactory.txnLogManagerInstance();
-        Entry entry = wrappedTable.get( key );
-        entry = logManager.mergeUpdates( partitionDn, key, entry );
+        Entry originalEntry = wrappedTable.get( key );
+        Entry entry = logManager.mergeUpdates( partitionDn, key, originalEntry );
         
         return entry;
     }