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;
}