You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2010/05/01 12:50:09 UTC
svn commit: r939973 [1/2] - in /directory/apacheds/trunk:
avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/
avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/
jdbm-store/src/main/java/org/apache/direct...
Author: seelmann
Date: Sat May 1 10:50:08 2010
New Revision: 939973
URL: http://svn.apache.org/viewvc?rev=939973&view=rev
Log:
o moved common methods from JdbmStore and AvlStore to super class, more to come
o added rdnIndex to AbstractStore
o removed getEntryUpDn() methods from Store interface and BTreePartition
Modified:
directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java
directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java
directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java
directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java
directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java
directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java
directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractXdbmPartition.java
directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/Store.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/AllEntriesCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/ApproximateCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/ApproximateEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/CursorBuilder.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultOptimizer.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultSearchEngine.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/EqualityCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/EqualityEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/EvaluatorBuilder.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/GreaterEqCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/GreaterEqEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/LessEqCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/LessEqEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/NotCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/PresenceCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/PresenceEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubstringCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubstringEvaluator.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeCursor.java
directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeEvaluator.java
directory/apacheds/trunk/xdbm-tools/src/main/java/org/apache/directory/server/core/partition/impl/btree/gui/EntryNode.java
directory/apacheds/trunk/xdbm-tools/src/main/java/org/apache/directory/server/core/partition/impl/btree/gui/PartitionFrame.java
directory/apacheds/trunk/xdbm-tools/src/main/java/org/apache/directory/server/xdbm/tools/StoreUtils.java
Modified: directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java (original)
+++ directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java Sat May 1 10:50:08 2010
@@ -33,11 +33,10 @@ import org.apache.directory.server.xdbm.
import org.apache.directory.server.xdbm.IndexEntry;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.cursor.Cursor;
+import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;
-import org.apache.directory.shared.ldap.entry.Entry;
-import org.apache.directory.shared.ldap.entry.StringValue;
import org.apache.directory.shared.ldap.entry.Value;
import org.apache.directory.shared.ldap.exception.LdapNoSuchObjectException;
import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
@@ -47,7 +46,6 @@ import org.apache.directory.shared.ldap.
import org.apache.directory.shared.ldap.name.RDN;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.SchemaManager;
-import org.apache.directory.shared.ldap.util.NamespaceTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -296,9 +294,12 @@ public class AvlStore<E> extends Abstrac
/**
* {@inheritDoc}
*/
- public String getEntryDn( Long id ) throws Exception
+ public DN getEntryDn( Long id ) throws Exception
{
- return ndnIdx.reverseLookup( id );
+ DN dn = new DN( ndnIdx.reverseLookup( id ) );
+ dn.normalize( schemaManager.getNormalizerMapping() );
+ return dn;
+// return ((DN)lookup( id ).getDn().clone()).normalize( schemaManager.getNormalizerMapping() );
}
@@ -314,25 +315,6 @@ public class AvlStore<E> extends Abstrac
/**
* {@inheritDoc}
*/
- public String getEntryUpdn( Long id ) throws Exception
- {
- return lookup( id ).getDn().getName();
- }
-
-
- /**
- * {@inheritDoc}
- */
- public String getEntryUpdn( String dn ) throws Exception
- {
- Long id = ndnIdx.forwardLookup( dn );
- return getEntryUpdn( id );
- }
-
-
- /**
- * {@inheritDoc}
- */
public Long getParentId( Long childId ) throws Exception
{
return oneLevelIdx.reverseLookup( childId );
@@ -433,7 +415,7 @@ public class AvlStore<E> extends Abstrac
if ( null != aliasTarget )
{
- addAliasIndices( id, new DN( getEntryDn( id ) ), aliasTarget );
+ addAliasIndices( id, getEntryDn( id ), aliasTarget );
}
}
@@ -450,7 +432,8 @@ public class AvlStore<E> extends Abstrac
* new name and adding the child's old upRdn to new name as its RDN
*/
DN childUpdn = ( DN ) updn.clone();
- DN oldUpdn = new DN( getEntryUpdn( childId ) );
+// DN oldUpdn = new DN( getEntryUpdn( childId ) );
+ DN oldUpdn = getEntryDn( childId );
String rdn = oldUpdn.get( oldUpdn.size() - 1 );
DN rdnDN = new DN( rdn );
@@ -470,246 +453,6 @@ public class AvlStore<E> extends Abstrac
}
- /**
- * Adds a set of attribute values while affecting the appropriate userIndices.
- * The entry is not persisted: it is only changed in anticipation for a put
- * into the master table.
- *
- * @param id the primary key of the entry
- * @param entry the entry to alter
- * @param mods the attribute and values to add
- * @throws Exception if index alteration or attribute addition fails
- */
- @SuppressWarnings("unchecked")
- private void add( Long id, Entry entry, EntryAttribute mods ) throws Exception
- {
- if ( entry instanceof ClonedServerEntry )
- {
- throw new Exception( I18n.err( I18n.ERR_215 ) );
- }
-
- String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
- // Special case for the ObjectClass index
- if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- for ( Value<?> value : mods )
- {
- objectClassIdx.drop( value.getString(), id );
- }
- }
- else if ( hasUserIndexOn( modsOid ) )
- {
- Index<?, E, Long> index = getUserIndex( modsOid );
-
- for ( Value<?> value : mods )
- {
- ( ( AvlIndex ) index ).add( value.get(), id );
- }
-
- // If the attr didn't exist for this id add it to existence index
- if ( !presenceIdx.forward( modsOid, id ) )
- {
- presenceIdx.add( modsOid, id );
- }
- }
-
- // add all the values in mods to the same attribute in the entry
- AttributeType type = schemaManager.lookupAttributeTypeRegistry( modsOid );
-
- for ( Value<?> value : mods )
- {
- entry.add( type, value );
- }
-
- if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
- {
- String ndnStr = ndnIdx.reverseLookup( id );
- addAliasIndices( id, new DN( ndnStr ), mods.getString() );
- }
- }
-
-
- /**
- * Completely removes the set of values for an attribute having the values
- * supplied while affecting the appropriate userIndices. The entry is not
- * persisted: it is only changed in anticipation for a put into the master
- * table. Note that an empty attribute w/o values will remove all the
- * values within the entry where as an attribute w/ values will remove those
- * attribute values it contains.
- *
- * @param id the primary key of the entry
- * @param entry the entry to alter
- * @param mods the attribute and its values to delete
- * @throws Exception if index alteration or attribute modification fails.
- */
- @SuppressWarnings("unchecked")
- private void remove( Long id, Entry entry, EntryAttribute mods ) throws Exception
- {
- if ( entry instanceof ClonedServerEntry )
- {
- throw new Exception( I18n.err( I18n.ERR_215 ) );
- }
-
- String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
- // Special case for the ObjectClass index
- if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- for ( Value<?> value : mods )
- {
- objectClassIdx.drop( value.getString(), id );
- }
- }
- else if ( hasUserIndexOn( modsOid ) )
- {
- Index<?, E, Long> index = getUserIndex( modsOid );
-
- for ( Value<?> value : mods )
- {
- ( ( AvlIndex ) index ).drop( value.get(), id );
- }
-
- /*
- * If no attribute values exist for this entryId in the index then
- * we remove the existance index entry for the removed attribute.
- */
- if ( null == index.reverseLookup( id ) )
- {
- presenceIdx.drop( modsOid, id );
- }
- }
-
- AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( modsOid );
- /*
- * If there are no attribute values in the modifications then this
- * implies the compelete removal of the attribute from the entry. Else
- * we remove individual attribute values from the entry in mods one
- * at a time.
- */
- if ( mods.size() == 0 )
- {
- entry.removeAttributes( attrType );
- }
- else
- {
- EntryAttribute entryAttr = entry.get( attrType );
-
- for ( Value<?> value : mods )
- {
- if ( value instanceof StringValue )
- {
- entryAttr.remove( ( String ) value.get() );
- }
- else
- {
- entryAttr.remove( ( byte[] ) value.get() );
- }
- }
-
- // 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 ) )
- {
- dropAliasIndices( id );
- }
- }
-
-
- /**
- * Completely replaces the existing set of values for an attribute with the
- * modified values supplied affecting the appropriate userIndices. The entry
- * is not persisted: it is only changed in anticipation for a put into the
- * master table.
- *
- * @param id the primary key of the entry
- * @param entry the entry to alter
- * @param mods the replacement attribute and values
- * @throws Exception if index alteration or attribute modification
- * fails.
- */
- @SuppressWarnings("unchecked")
- private void replace( Long id, Entry entry, EntryAttribute mods ) throws Exception
- {
- if ( entry instanceof ClonedServerEntry )
- {
- throw new Exception( I18n.err( I18n.ERR_215 ) );
- }
-
- String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
- // Special case for the ObjectClass index
- if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- // if the id exists in the index drop all existing attribute
- // value index entries and add new ones
- if ( objectClassIdx.reverse( id ) )
- {
- objectClassIdx.drop( id );
- }
-
- for ( Value<?> value : mods )
- {
- objectClassIdx.add( value.getString(), id );
- }
- }
- else if ( hasUserIndexOn( modsOid ) )
- {
- Index<?, E, Long> index = getUserIndex( modsOid );
-
- // if the id exists in the index drop all existing attribute value index entries and add new ones
- if ( index.reverse( id ) )
- {
- ( ( AvlIndex<?, E> ) index ).drop( id );
- }
-
- for ( Value<?> value : mods )
- {
- ( ( AvlIndex<Object, E> ) index ).add( value.get(), id );
- }
-
- /*
- * If no attribute values exist for this entryId in the index then
- * we remove the existance index entry for the removed attribute.
- */
- if ( null == index.reverseLookup( id ) )
- {
- presenceIdx.drop( modsOid, id );
- }
- }
-
- String aliasAttributeOid = SchemaConstants.ALIASED_OBJECT_NAME_AT_OID;
-
- if ( modsOid.equals( aliasAttributeOid ) )
- {
- dropAliasIndices( id );
- }
-
- // replaces old attributes with new modified ones if they exist
- if ( mods.size() > 0 )
- {
- entry.put( mods );
- }
- else
- // removes old attributes if new replacements do not exist
- {
- entry.remove( mods );
- }
-
- if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
- {
- String ndnStr = ndnIdx.reverseLookup( id );
- addAliasIndices( id, new DN( ndnStr ), mods.getString() );
- }
- }
-
-
public void modify( DN dn, ModificationOperation modOp, Entry mods ) throws Exception
{
if ( mods instanceof ClonedServerEntry )
@@ -855,9 +598,12 @@ public class AvlStore<E> extends Abstrac
* user provided RDN & the new parent's UPDN. Basically add the child's
* UpRdn String to the tail of the new parent's Updn Name.
*/
- DN childUpdn = new DN( getEntryUpdn( childId ) );
+// DN childUpdn = new DN( getEntryUpdn( childId ) );
+// String childRdn = childUpdn.get( childUpdn.size() - 1 );
+// DN newUpdn = new DN( getEntryUpdn( newParentId ) );
+ DN childUpdn = getEntryDn( childId );
String childRdn = childUpdn.get( childUpdn.size() - 1 );
- DN newUpdn = new DN( getEntryUpdn( newParentId ) );
+ DN newUpdn = getEntryDn( newParentId );
newUpdn.add( newUpdn.size(), childRdn );
// Call the modifyDn operation with the new updn
@@ -1036,185 +782,6 @@ public class AvlStore<E> extends Abstrac
/**
- * Adds userIndices for an aliasEntry to be added to the database while checking
- * for constrained alias constructs like alias cycles and chaining.
- *
- * @param aliasDn normalized distinguished name for the alias entry
- * @param aliasTarget the user provided aliased entry dn as a string
- * @param aliasId the id of alias entry to add
- * @throws Exception if index addition fails, and if the alias is
- * not allowed due to chaining or cycle formation.
- * @throws Exception if the wrappedCursor btrees cannot be altered
- */
- private void addAliasIndices( Long aliasId, DN aliasDn, String aliasTarget ) throws Exception
- {
- DN normalizedAliasTargetDn; // Name value of aliasedObjectName
- Long targetId; // Id of the aliasedObjectName
- DN ancestorDn; // Name of an alias entry relative
- Long ancestorId; // Id of an alias entry relative
-
- // Access aliasedObjectName, normalize it and generate the Name
- normalizedAliasTargetDn = new DN( aliasTarget );
- normalizedAliasTargetDn.normalize( schemaManager.getNormalizerMapping() );
-
- /*
- * Check For Cycles
- *
- * Before wasting time to lookup more values we check using the target
- * dn to see if we have the possible formation of an alias cycle. This
- * happens when the alias refers back to a target that is also a
- * relative of the alias entry. For detection we test if the aliased
- * entry Dn starts with the target Dn. If it does then we know the
- * aliased target is a relative and we have a perspecitive cycle.
- */
- if ( aliasDn.isChildOf( normalizedAliasTargetDn ) )
- {
- if ( aliasDn.equals( normalizedAliasTargetDn ) )
- {
- throw new Exception( I18n.err( I18n.ERR_223 ) );
- }
-
- throw new Exception( I18n.err( I18n.ERR_224, aliasTarget, aliasDn ) );
- }
-
- /*
- * Check For Aliases External To Naming Context
- *
- * id may be null but the alias may be to a valid entry in
- * another namingContext. Such aliases are not allowed and we
- * need to point it out to the user instead of saying the target
- * does not exist when it potentially could outside of this upSuffix.
- */
- if ( !normalizedAliasTargetDn.isChildOf( suffixDn ) )
- {
- // Complain specifically about aliases to outside naming contexts
- throw new Exception( I18n.err( I18n.ERR_225, suffixDn.getName() ) );
- }
-
- // L O O K U P T A R G E T I D
- targetId = ndnIdx.forwardLookup( normalizedAliasTargetDn.getNormName() );
-
- /*
- * Check For Target Existance
- *
- * We do not allow the creation of inconsistant aliases. Aliases should
- * not be broken links. If the target does not exist we start screaming
- */
- if ( null == targetId )
- {
- // Complain about target not existing
- throw new Exception( I18n.err( I18n.ERR_226 ) );
- }
-
- /*
- * Detect Direct Alias Chain Creation
- *
- * Rather than resusitate the target to test if it is an alias and fail
- * due to chaing creation we use the alias index to determine if the
- * target is an alias. Hence if the alias we are about to create points
- * to another alias as its target in the aliasedObjectName attribute,
- * then we have a situation where an alias chain is being created.
- * Alias chaining is not allowed so we throw and exception.
- */
- if ( null != aliasIdx.reverseLookup( targetId ) )
- {
- // Complain about illegal alias chain
- throw new Exception( I18n.err( I18n.ERR_227 ) );
- }
-
- // Add the alias to the simple alias index
- aliasIdx.add( normalizedAliasTargetDn.getNormName(), aliasId );
-
- /*
- * Handle One Level Scope Alias Index
- *
- * The first relative is special with respect to the one level alias
- * index. If the target is not a sibling of the alias then we add the
- * index entry maping the parent's id to the aliased target id.
- */
- ancestorDn = ( DN ) aliasDn.clone();
- ancestorDn.remove( aliasDn.size() - 1 );
- ancestorId = getEntryId( ancestorDn );
-
- // check if alias parent and aliased entry are the same
- DN normalizedAliasTargetParentDn = ( DN ) normalizedAliasTargetDn.clone();
- normalizedAliasTargetParentDn.remove( normalizedAliasTargetDn.size() - 1 );
- if ( !aliasDn.isChildOf( normalizedAliasTargetParentDn ) )
- {
- oneAliasIdx.add( ancestorId, targetId );
- }
-
- /*
- * Handle Sub Level Scope Alias Index
- *
- * Walk the list of relatives from the parents up to the upSuffix, testing
- * to see if the alias' target is a descendant of the relative. If the
- * alias target is not a descentant of the relative it extends the scope
- * and is added to the sub tree scope alias index. The upSuffix node is
- * ignored since everything is under its scope. The first loop
- * iteration shall handle the parents.
- */
- while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
- {
- if ( !NamespaceTools.isDescendant( ancestorDn, normalizedAliasTargetDn ) )
- {
- subAliasIdx.add( ancestorId, targetId );
- }
-
- ancestorDn.remove( ancestorDn.size() - 1 );
- ancestorId = getEntryId( ancestorDn );
- }
- }
-
-
- /**
- * Removes the index entries for an alias before the entry is deleted from
- * the master table.
- *
- * @todo Optimize this by walking the hierarchy index instead of the name
- * @param aliasId the id of the alias entry in the master table
- * @throws Exception if we cannot parse ldap names
- * @throws Exception if we cannot delete index values in the database
- */
- private void dropAliasIndices( Long aliasId ) throws Exception
- {
- String targetDn = aliasIdx.reverseLookup( aliasId );
- Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
- String aliasDn = getEntryDn( aliasId );
- DN aliasDN = ( DN ) new DN( aliasDn );
-
- DN ancestorDn = ( DN ) aliasDN.clone();
- ancestorDn.remove( aliasDN.size() - 1 );
- Long ancestorId = getEntryId( ancestorDn );
-
- /*
- * We cannot just drop all tuples in the one level and subtree userIndices
- * linking baseIds to the targetId. If more than one alias refers to
- * the target then droping all tuples with a value of targetId would
- * make all other aliases to the target inconsistent.
- *
- * We need to walk up the path of alias ancestors until we reach the
- * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
- * subtree scope alias. We only need to do this for the direct parent
- * of the alias on the one level subtree.
- */
- oneAliasIdx.drop( ancestorId, targetId );
- subAliasIdx.drop( ancestorId, targetId );
-
- while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
- {
- ancestorDn = ( DN ) ancestorDn.getPrefix( ancestorDn.size() - 1 );
- ancestorId = getEntryId( ancestorDn );
-
- subAliasIdx.drop( ancestorId, targetId );
- }
-
- // Drops all alias tuples pointing to the id of the alias to be deleted
- aliasIdx.drop( aliasId );
- }
-
-
- /**
*
* updates the SubLevel Index as part of a move operation.
*
@@ -1277,96 +844,6 @@ public class AvlStore<E> extends Abstrac
/**
- * For all aliases including and under the moved base, this method removes
- * one and subtree alias index tuples for old ancestors above the moved base
- * that will no longer be ancestors after the move.
- *
- * @param movedBase the base at which the move occured - the moved node
- * @throws Exception if system userIndices fail
- */
- private void dropMovedAliasIndices( final DN movedBase ) throws Exception
- {
- // // Find all the aliases from movedBase down
- // IndexAssertion<Object,E> isBaseDescendant = new IndexAssertion<Object,E>()
- // {
- // public boolean assertCandidate( IndexEntry<Object,E> rec ) throws Exception
- // {
- // String dn = getEntryDn( rec.getId() );
- // return dn.endsWith( movedBase.toString() );
- // }
- // };
-
- Long movedBaseId = getEntryId( movedBase );
-
- if ( aliasIdx.reverseLookup( movedBaseId ) != null )
- {
- dropAliasIndices( movedBaseId, movedBase );
- }
-
- // throw new NotImplementedException( "Fix the code below this line" );
-
- // NamingEnumeration<ForwardIndexEntry> aliases =
- // new IndexAssertionEnumeration( aliasIdx.listIndices( movedBase.toString(), true ), isBaseDescendant );
- //
- // while ( aliases.hasMore() )
- // {
- // ForwardIndexEntry entry = aliases.next();
- // dropAliasIndices( (Long)entry.getId(), movedBase );
- // }
- }
-
-
- /**
- * For the alias id all ancestor one and subtree alias tuples are moved
- * above the moved base.
- *
- * @param aliasId the id of the alias
- * @param movedBase the base where the move occured
- * @throws Exception if userIndices fail
- */
- private void dropAliasIndices( Long aliasId, DN movedBase ) throws Exception
- {
- String targetDn = aliasIdx.reverseLookup( aliasId );
- Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
- String aliasDn = getEntryDn( aliasId );
-
- /*
- * Start droping index tuples with the first ancestor right above the
- * moved base. This is the first ancestor effected by the move.
- */
- DN ancestorDn = ( DN ) movedBase.getPrefix( 1 );
- Long ancestorId = getEntryId( ancestorDn );
-
- /*
- * We cannot just drop all tuples in the one level and subtree userIndices
- * linking baseIds to the targetId. If more than one alias refers to
- * the target then droping all tuples with a value of targetId would
- * make all other aliases to the target inconsistent.
- *
- * We need to walk up the path of alias ancestors right above the moved
- * base until we reach the upSuffix, deleting each ( ancestorId,
- * targetId ) tuple in the subtree scope alias. We only need to do
- * this for the direct parent of the alias on the one level subtree if
- * the moved base is the alias.
- */
- if ( aliasDn.equals( movedBase.toString() ) )
- {
- oneAliasIdx.drop( ancestorId, targetId );
- }
-
- subAliasIdx.drop( ancestorId, targetId );
-
- while ( !ancestorDn.equals( suffixDn ) )
- {
- ancestorDn = ( DN ) ancestorDn.getPrefix( 1 );
- ancestorId = getEntryId( ancestorDn );
-
- subAliasIdx.drop( ancestorId, targetId );
- }
- }
-
-
- /**
* Always returns 0 (zero), cause this is a in-memory store
*/
@Override
Modified: directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java (original)
+++ directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java Sat May 1 10:50:08 2010
@@ -308,7 +308,7 @@ public class AvlStoreTest
Iterator<String> systemIndices = store.systemIndices();
- for ( int ii = 0; ii < 10; ii++ )
+ for ( int ii = 0; ii < 11; ii++ )
{
assertTrue( systemIndices.hasNext() );
assertNotNull( systemIndices.next() );
@@ -388,9 +388,9 @@ public class AvlStoreTest
dn.normalize( schemaManager.getNormalizerMapping() );
assertEquals( 1L, ( long ) store.getEntryId( dn ) );
assertEquals( 11, store.count() );
- assertEquals( "o=Good Times Co.", store.getEntryUpdn( dn.getNormName() ) );
- assertEquals( dn.getNormName(), store.getEntryDn( 1L ) );
- assertEquals( dn.getName(), store.getEntryUpdn( 1L ) );
+// assertEquals( "o=Good Times Co.", store.getEntryDn( 1L ).getName() );
+// assertEquals( dn.getNormName(), store.getEntryDn( 1L ).getNormName() );
+// assertEquals( dn.getName(), store.getEntryDn( 1L ).getName() );
// note that the suffix entry returns 0 for it's parent which does not exist
assertEquals( 0L, ( long ) store.getParentId( store.getEntryId( dn ) ) );
Modified: directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java Sat May 1 10:50:08 2010
@@ -48,7 +48,7 @@ import org.slf4j.LoggerFactory;
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
-public class JdbmRdnIndex extends JdbmIndex<ParentIdAndRdn<Long>, Long>
+public class JdbmRdnIndex<E> extends JdbmIndex<ParentIdAndRdn<Long>, E>
{
/** A logger for this class */
Modified: directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java Sat May 1 10:50:08 2010
@@ -40,13 +40,11 @@ import org.apache.directory.server.xdbm.
import org.apache.directory.shared.ldap.MultiException;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.cursor.Cursor;
+import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;
-import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.Value;
-import org.apache.directory.shared.ldap.exception.LdapAliasDereferencingException;
-import org.apache.directory.shared.ldap.exception.LdapAliasException;
import org.apache.directory.shared.ldap.exception.LdapException;
import org.apache.directory.shared.ldap.exception.LdapNoSuchObjectException;
import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
@@ -56,7 +54,6 @@ import org.apache.directory.shared.ldap.
import org.apache.directory.shared.ldap.name.RDN;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.SchemaManager;
-import org.apache.directory.shared.ldap.util.NamespaceTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -72,17 +69,12 @@ public class JdbmStore<E> extends Abstra
/** the master table storing entries by primary key */
private JdbmMasterTable<Entry> master;
- /** the relative distinguished name index */
- private JdbmRdnIndex rdnIdx;
-
/** Static declarations to avoid lookup all over the code */
private static AttributeType OBJECT_CLASS_AT;
private static AttributeType ENTRY_CSN_AT;
private static AttributeType ENTRY_UUID_AT;
private static AttributeType ALIASED_OBJECT_NAME_AT;
- private DN contextEntryDn;
-
// ------------------------------------------------------------------------
// C O N S T R U C T O R S
@@ -154,20 +146,6 @@ public class JdbmStore<E> extends Abstra
}
- @SuppressWarnings("unchecked")
- protected void setupSystemIndices() throws Exception
- {
- if ( rdnIdx == null )
- {
- rdnIdx = new JdbmRdnIndex();
- rdnIdx.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
- systemIndices.put( ApacheSchemaConstants.APACHE_RDN_AT_OID, ( JdbmIndex ) rdnIdx );
- }
-
- super.setupSystemIndices();
- }
-
-
/**
* Close the partition : we have to close all the userIndices and the master table.
*
@@ -278,7 +256,15 @@ public class JdbmStore<E> extends Abstra
protected Index<?, E, Long> convertAndInit( Index<?, E, Long> index ) throws Exception
{
JdbmIndex<?, E> jdbmIndex;
- if ( index instanceof JdbmIndex<?, ?> )
+ if( index.getAttributeId().equals( ApacheSchemaConstants.APACHE_RDN_AT_OID ) )
+ {
+ jdbmIndex = new JdbmRdnIndex();
+ jdbmIndex.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+ jdbmIndex.setCacheSize( index.getCacheSize() );
+ jdbmIndex.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
+ jdbmIndex.setWkDirPath( index.getWkDirPath() );
+ }
+ else if ( index instanceof JdbmIndex<?, ?> )
{
jdbmIndex = ( JdbmIndex<?, E> ) index;
}
@@ -344,9 +330,9 @@ public class JdbmStore<E> extends Abstra
* gives the normalized name of the DN of the entry identified by the given id
* @param id the entry's id
*/
- public String getEntryDn( Long id ) throws Exception
+ public DN getEntryDn( Long id ) throws Exception
{
- return buildEntryDn( id ).getNormName();
+ return buildEntryDn( id );
}
@@ -424,18 +410,6 @@ public class JdbmStore<E> extends Abstra
}
- public String getEntryUpdn( Long id ) throws Exception
- {
- return buildEntryDn( id ).getName();
- }
-
-
- public String getEntryUpdn( String dn ) throws Exception
- {
- return buildEntryDn( dn ).getName();
- }
-
-
public int count() throws Exception
{
return master.count();
@@ -443,200 +417,6 @@ public class JdbmStore<E> extends Abstra
/**
- * Removes the index entries for an alias before the entry is deleted from
- * the master table.
- *
- * @todo Optimize this by walking the hierarchy index instead of the name
- * @param aliasId the id of the alias entry in the master table
- * @throws LdapException if we cannot parse ldap names
- * @throws Exception if we cannot delete index values in the database
- */
- private void dropAliasIndices( Long aliasId ) throws Exception
- {
- String targetDn = aliasIdx.reverseLookup( aliasId );
- Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
- String aliasDn = getEntryDn( aliasId );
- DN aliasDN = ( DN ) new DN( aliasDn );
-
- DN ancestorDn = ( DN ) aliasDN.clone();
- ancestorDn.remove( aliasDN.size() - 1 );
- Long ancestorId = getEntryId( ancestorDn );
-
- /*
- * We cannot just drop all tuples in the one level and subtree userIndices
- * linking baseIds to the targetId. If more than one alias refers to
- * the target then droping all tuples with a value of targetId would
- * make all other aliases to the target inconsistent.
- *
- * We need to walk up the path of alias ancestors until we reach the
- * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
- * subtree scope alias. We only need to do this for the direct parent
- * of the alias on the one level subtree.
- */
- oneAliasIdx.drop( ancestorId, targetId );
- subAliasIdx.drop( ancestorId, targetId );
-
- while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
- {
- ancestorDn = ( DN ) ancestorDn.getPrefix( ancestorDn.size() - 1 );
- ancestorId = getEntryId( ancestorDn );
-
- subAliasIdx.drop( ancestorId, targetId );
- }
-
- // Drops all alias tuples pointing to the id of the alias to be deleted
- aliasIdx.drop( aliasId );
- }
-
-
- /**
- * Adds userIndices for an aliasEntry to be added to the database while checking
- * for constrained alias constructs like alias cycles and chaining.
- *
- * @param aliasDn normalized distinguished name for the alias entry
- * @param aliasTarget the user provided aliased entry dn as a string
- * @param aliasId the id of alias entry to add
- * @throws LdapException if index addition fails, and if the alias is
- * not allowed due to chaining or cycle formation.
- * @throws Exception if the wrappedCursor btrees cannot be altered
- */
- private void addAliasIndices( Long aliasId, DN aliasDn, String aliasTarget ) throws Exception
- {
- DN normalizedAliasTargetDn; // Name value of aliasedObjectName
- Long targetId; // Id of the aliasedObjectName
- DN ancestorDn; // Name of an alias entry relative
- Long ancestorId; // Id of an alias entry relative
-
- // Access aliasedObjectName, normalize it and generate the Name
- normalizedAliasTargetDn = buildEntryDn( aliasTarget );//new DN( aliasTarget );
- //normalizedAliasTargetDn.normalize( schemaManager.getNormalizerMapping() );
-
- /*
- * Check For Cycles
- *
- * Before wasting time to lookup more values we check using the target
- * dn to see if we have the possible formation of an alias cycle. This
- * happens when the alias refers back to a target that is also a
- * relative of the alias entry. For detection we test if the aliased
- * entry Dn starts with the target Dn. If it does then we know the
- * aliased target is a relative and we have a perspecitive cycle.
- */
- if ( aliasDn.isChildOf( normalizedAliasTargetDn ) )
- {
- if ( aliasDn.equals( normalizedAliasTargetDn ) )
- {
- String msg = I18n.err( I18n.ERR_223 );
- LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
- //e.setResolvedName( aliasDn );
- throw e;
- }
-
- String msg = I18n.err( I18n.ERR_224, aliasTarget, aliasDn );
- LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
- //e.setResolvedName( aliasDn );
- throw e;
- }
-
- /*
- * Check For Aliases External To Naming Context
- *
- * id may be null but the alias may be to a valid entry in
- * another namingContext. Such aliases are not allowed and we
- * need to point it out to the user instead of saying the target
- * does not exist when it potentially could outside of this upSuffix.
- */
- if ( !normalizedAliasTargetDn.isChildOf( suffixDn ) )
- {
- String msg = I18n.err( I18n.ERR_225, suffixDn.getName() );
- LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
- //e.setResolvedName( aliasDn );
- throw e;
- }
-
- // L O O K U P T A R G E T I D
- ParentIdAndRdn<Long> key = new ParentIdAndRdn<Long>( getParentId( getEntryId( normalizedAliasTargetDn ) ),
- normalizedAliasTargetDn.getRdn() );
- targetId = rdnIdx.forwardLookup( key );
-
- /*
- * Check For Target Existence
- *
- * We do not allow the creation of inconsistent aliases. Aliases should
- * not be broken links. If the target does not exist we start screaming
- */
- if ( null == targetId )
- {
- // Complain about target not existing
- String msg = I18n.err( I18n.ERR_581, aliasDn.getName(), aliasTarget );
- LdapAliasException e = new LdapAliasException( msg );
- //e.setResolvedName( aliasDn );
- throw e;
- }
-
- /*
- * Detect Direct Alias Chain Creation
- *
- * Rather than resusitate the target to test if it is an alias and fail
- * due to chaing creation we use the alias index to determine if the
- * target is an alias. Hence if the alias we are about to create points
- * to another alias as its target in the aliasedObjectName attribute,
- * then we have a situation where an alias chain is being created.
- * Alias chaining is not allowed so we throw and exception.
- */
- if ( null != aliasIdx.reverseLookup( targetId ) )
- {
- String msg = I18n.err( I18n.ERR_227 );
- LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
- //e.setResolvedName( aliasDn );
- throw e;
- }
-
- // Add the alias to the simple alias index
- aliasIdx.add( normalizedAliasTargetDn.getNormName(), aliasId );
-
- /*
- * Handle One Level Scope Alias Index
- *
- * The first relative is special with respect to the one level alias
- * index. If the target is not a sibling of the alias then we add the
- * index entry maping the parent's id to the aliased target id.
- */
- ancestorDn = ( DN ) aliasDn.clone();
- ancestorDn.remove( aliasDn.size() - 1 );
- ancestorId = getEntryId( ancestorDn );
-
- // check if alias parent and aliased entry are the same
- DN normalizedAliasTargetParentDn = ( DN ) normalizedAliasTargetDn.clone();
- normalizedAliasTargetParentDn.remove( normalizedAliasTargetDn.size() - 1 );
- if ( !aliasDn.isChildOf( normalizedAliasTargetParentDn ) )
- {
- oneAliasIdx.add( ancestorId, targetId );
- }
-
- /*
- * Handle Sub Level Scope Alias Index
- *
- * Walk the list of relatives from the parents up to the upSuffix, testing
- * to see if the alias' target is a descendant of the relative. If the
- * alias target is not a descentant of the relative it extends the scope
- * and is added to the sub tree scope alias index. The upSuffix node is
- * ignored since everything is under its scope. The first loop
- * iteration shall handle the parents.
- */
- while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
- {
- if ( !NamespaceTools.isDescendant( ancestorDn, normalizedAliasTargetDn ) )
- {
- subAliasIdx.add( ancestorId, targetId );
- }
-
- ancestorDn.remove( ancestorDn.size() - 1 );
- ancestorId = getEntryId( ancestorDn );
- }
- }
-
-
- /**
* {@inheritDoc}
* TODO : We should be able to revert all the changes made to index
* if something went wrong. Also the index should auto-repair : if
@@ -894,241 +674,6 @@ public class JdbmStore<E> extends Abstra
}
- /**
- * Adds a set of attribute values while affecting the appropriate userIndices.
- * The entry is not persisted: it is only changed in anticipation for a put
- * into the master table.
- *
- * @param id the primary key of the entry
- * @param entry the entry to alter
- * @param mods the attribute and values to add
- * @throws Exception if index alteration or attribute addition fails
- */
- @SuppressWarnings("unchecked")
- private void add( Long id, Entry entry, EntryAttribute mods ) throws Exception
- {
- if ( entry instanceof ClonedServerEntry )
- {
- throw new Exception( I18n.err( I18n.ERR_215 ) );
- }
-
- String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
- // Special case for the ObjectClass index
- if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- for ( Value<?> value : mods )
- {
- objectClassIdx.drop( value.getString(), id );
- }
- }
- else if ( hasUserIndexOn( modsOid ) )
- {
- Index<?, E, Long> index = getUserIndex( modsOid );
-
- for ( Value<?> value : mods )
- {
- ( ( JdbmIndex ) index ).add( value.get(), id );
- }
-
- // If the attr didn't exist for this id add it to existence index
- if ( !presenceIdx.forward( modsOid, id ) )
- {
- presenceIdx.add( modsOid, id );
- }
- }
-
- // add all the values in mods to the same attribute in the entry
- AttributeType type = schemaManager.lookupAttributeTypeRegistry( modsOid );
-
- for ( Value<?> value : mods )
- {
- entry.add( type, value );
- }
-
- if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
- {
- DN ndn = buildEntryDn( id );
- addAliasIndices( id, ndn, mods.getString() );
- }
- }
-
-
- /**
- * Completely removes the set of values for an attribute having the values
- * supplied while affecting the appropriate userIndices. The entry is not
- * persisted: it is only changed in anticipation for a put into the master
- * table. Note that an empty attribute w/o values will remove all the
- * values within the entry where as an attribute w/ values will remove those
- * attribute values it contains.
- *
- * @param id the primary key of the entry
- * @param entry the entry to alter
- * @param mods the attribute and its values to delete
- * @throws Exception if index alteration or attribute modification fails.
- */
- @SuppressWarnings("unchecked")
- private void remove( Long id, Entry entry, EntryAttribute mods ) throws Exception
- {
- if ( entry instanceof ClonedServerEntry )
- {
- throw new Exception( I18n.err( I18n.ERR_215 ) );
- }
-
- String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
- // Special case for the ObjectClass index
- if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- for ( Value<?> value : mods )
- {
- objectClassIdx.drop( value.getString(), id );
- }
- }
- else if ( hasUserIndexOn( modsOid ) )
- {
- Index<?, E, Long> index = getUserIndex( modsOid );
-
- for ( Value<?> value : mods )
- {
- ( ( JdbmIndex ) index ).drop( value.get(), id );
- }
-
- /*
- * If no attribute values exist for this entryId in the index then
- * we remove the presence index entry for the removed attribute.
- */
- if ( null == index.reverseLookup( id ) )
- {
- presenceIdx.drop( modsOid, id );
- }
- }
-
- AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( modsOid );
- /*
- * If there are no attribute values in the modifications then this
- * implies the compelete removal of the attribute from the entry. Else
- * we remove individual attribute values from the entry in mods one
- * at a time.
- */
- if ( mods.size() == 0 )
- {
- entry.removeAttributes( attrType );
- }
- else
- {
- EntryAttribute entryAttr = entry.get( attrType );
-
- for ( Value<?> value : mods )
- {
- entryAttr.remove( value );
- }
-
- // if nothing is left just remove empty attribute
- if ( entryAttr.size() == 0 )
- {
- entry.removeAttributes( entryAttr.getId() );
- }
- }
-
- // Aliases->single valued comp/partial attr removal is not relevant here
- if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
- {
- dropAliasIndices( id );
- }
- }
-
-
- /**
- * Completely replaces the existing set of values for an attribute with the
- * modified values supplied affecting the appropriate userIndices. The entry
- * is not persisted: it is only changed in anticipation for a put into the
- * master table.
- *
- * @param id the primary key of the entry
- * @param entry the entry to alter
- * @param mods the replacement attribute and values
- * @throws Exception if index alteration or attribute modification
- * fails.
- */
- @SuppressWarnings("unchecked")
- private void replace( Long id, Entry entry, EntryAttribute mods ) throws Exception
- {
- if ( entry instanceof ClonedServerEntry )
- {
- throw new Exception( I18n.err( I18n.ERR_215 ) );
- }
-
- String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
- // Special case for the ObjectClass index
- if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- // if the id exists in the index drop all existing attribute
- // value index entries and add new ones
- if ( objectClassIdx.reverse( id ) )
- {
- objectClassIdx.drop( id );
- }
-
- for ( Value<?> value : mods )
- {
- objectClassIdx.add( value.getString(), id );
- }
- }
- else if ( hasUserIndexOn( modsOid ) )
- {
- Index<?, E, Long> index = getUserIndex( modsOid );
-
- // if the id exists in the index drop all existing attribute
- // value index entries and add new ones
- if ( index.reverse( id ) )
- {
- ( ( JdbmIndex<?, E> ) index ).drop( id );
- }
-
- for ( Value<?> value : mods )
- {
- ( ( JdbmIndex<Object, E> ) index ).add( value.get(), id );
- }
-
- /*
- * If no attribute values exist for this entryId in the index then
- * we remove the presence index entry for the removed attribute.
- */
- if ( null == index.reverseLookup( id ) )
- {
- presenceIdx.drop( modsOid, id );
- }
- }
-
- String aliasAttributeOid = schemaManager.getAttributeTypeRegistry().getOidByName(
- SchemaConstants.ALIASED_OBJECT_NAME_AT );
-
- if ( modsOid.equals( aliasAttributeOid ) )
- {
- dropAliasIndices( id );
- }
-
- // replaces old attributes with new modified ones if they exist
- if ( mods.size() > 0 )
- {
- entry.put( mods );
- }
- else
- // removes old attributes if new replacements do not exist
- {
- entry.remove( mods );
- }
-
- if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
- {
- DN ndn = buildEntryDn( id );
- addAliasIndices( id, ndn, mods.getString() );
- }
- }
-
-
public void modify( DN dn, ModificationOperation modOp, Entry mods ) throws Exception
{
if ( mods instanceof ClonedServerEntry )
@@ -1478,11 +1023,9 @@ public class JdbmStore<E> extends Abstra
* user provided RDN & the new parent's UPDN. Basically add the child's
* UpRdn String to the tail of the new parent's Updn Name.
*/
-
DN childUpdn = buildEntryDn( childId );
RDN childRdn = childUpdn.getRdn( childUpdn.size() - 1 );
DN newUpdn = buildEntryDn( newParentId );
-
newUpdn.add( childRdn );
// Call the modifyDn operation with the new updn
@@ -1553,94 +1096,4 @@ public class JdbmStore<E> extends Abstra
}
}
-
- /**
- * For all aliases including and under the moved base, this method removes
- * one and subtree alias index tuples for old ancestors above the moved base
- * that will no longer be ancestors after the move.
- *
- * @param movedBase the base at which the move occured - the moved node
- * @throws Exception if system userIndices fail
- */
- private void dropMovedAliasIndices( final DN movedBase ) throws Exception
- {
- // // Find all the aliases from movedBase down
- // IndexAssertion<Object,E> isBaseDescendant = new IndexAssertion<Object,E>()
- // {
- // public boolean assertCandidate( IndexEntry<Object,E> rec ) throws Exception
- // {
- // String dn = getEntryDn( rec.getId() );
- // return dn.endsWith( movedBase.toString() );
- // }
- // };
-
- Long movedBaseId = getEntryId( movedBase );
-
- if ( aliasIdx.reverseLookup( movedBaseId ) != null )
- {
- dropAliasIndices( movedBaseId, movedBase );
- }
-
- // throw new NotImplementedException( "Fix the code below this line" );
-
- // NamingEnumeration<ForwardIndexEntry> aliases =
- // new IndexAssertionEnumeration( aliasIdx.listIndices( movedBase.toString(), true ), isBaseDescendant );
- //
- // while ( aliases.hasMore() )
- // {
- // ForwardIndexEntry entry = aliases.next();
- // dropAliasIndices( (Long)entry.getId(), movedBase );
- // }
- }
-
-
- /**
- * For the alias id all ancestor one and subtree alias tuples are moved
- * above the moved base.
- *
- * @param aliasId the id of the alias
- * @param movedBase the base where the move occured
- * @throws Exception if userIndices fail
- */
- private void dropAliasIndices( Long aliasId, DN movedBase ) throws Exception
- {
- String targetDn = aliasIdx.reverseLookup( aliasId );
- Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
- String aliasDn = getEntryDn( aliasId );
-
- /*
- * Start droping index tuples with the first ancestor right above the
- * moved base. This is the first ancestor effected by the move.
- */
- DN ancestorDn = ( DN ) movedBase.getPrefix( 1 );
- Long ancestorId = getEntryId( ancestorDn );
-
- /*
- * We cannot just drop all tuples in the one level and subtree userIndices
- * linking baseIds to the targetId. If more than one alias refers to
- * the target then droping all tuples with a value of targetId would
- * make all other aliases to the target inconsistent.
- *
- * We need to walk up the path of alias ancestors right above the moved
- * base until we reach the upSuffix, deleting each ( ancestorId,
- * targetId ) tuple in the subtree scope alias. We only need to do
- * this for the direct parent of the alias on the one level subtree if
- * the moved base is the alias.
- */
- if ( aliasDn.equals( movedBase.toString() ) )
- {
- oneAliasIdx.drop( ancestorId, targetId );
- }
-
- subAliasIdx.drop( ancestorId, targetId );
-
- while ( !ancestorDn.equals( suffixDn ) )
- {
- ancestorDn = ( DN ) ancestorDn.getPrefix( 1 );
- ancestorId = getEntryId( ancestorDn );
-
- subAliasIdx.drop( ancestorId, targetId );
- }
- }
-
}
Modified: directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java Sat May 1 10:50:08 2010
@@ -456,9 +456,9 @@ public class JdbmStoreTest
dn.normalize( schemaManager.getNormalizerMapping() );
assertEquals( 1L, ( long ) store.getEntryId( dn ) );
assertEquals( 11, store.count() );
- assertEquals( "o=Good Times Co.", store.getEntryUpdn( dn.getName() ) );
- assertEquals( dn.getNormName(), store.getEntryDn( 1L ) );
- assertEquals( dn.getName(), store.getEntryUpdn( 1L ) );
+ assertEquals( "o=Good Times Co.", store.getEntryDn( 1L ).getName() );
+ assertEquals( dn.getNormName(), store.getEntryDn( 1L ).getNormName() );
+ assertEquals( dn.getName(), store.getEntryDn( 1L ).getName() );
// note that the suffix entry returns 0 for it's parent which does not exist
assertEquals( 0L, ( long ) store.getParentId( store.getEntryId( dn ) ) );
Modified: directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java (original)
+++ directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java Sat May 1 10:50:08 2010
@@ -799,7 +799,7 @@ public class LdifPartition extends BTree
@Override
- public String getEntryDn( Long id ) throws Exception
+ public DN getEntryDn( Long id ) throws Exception
{
return wrappedPartition.getEntryDn( id );
}
@@ -813,20 +813,6 @@ public class LdifPartition extends BTree
@Override
- public String getEntryUpdn( Long id ) throws Exception
- {
- return wrappedPartition.getEntryUpdn( id );
- }
-
-
- @Override
- public String getEntryUpdn( String dn ) throws Exception
- {
- return wrappedPartition.getEntryUpdn( dn );
- }
-
-
- @Override
public Index<Long, Entry, Long> getOneAliasIndex()
{
return wrappedPartition.getOneAliasIndex();
Modified: directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java (original)
+++ directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java Sat May 1 10:50:08 2010
@@ -428,27 +428,7 @@ public abstract class BTreePartition<ID>
public abstract ID getEntryId( DN dn ) throws Exception;
- public abstract String getEntryDn( ID id ) throws Exception;
-
-
- /**
- * Gets the user provided distinguished name.
- *
- * @param id the entry id
- * @return the user provided distinguished name
- * @throws Exception if the updn index cannot be accessed
- */
- public abstract String getEntryUpdn( ID id ) throws Exception;
-
-
- /**
- * Gets the user provided distinguished name.
- *
- * @param dn the normalized distinguished name
- * @return the user provided distinguished name
- * @throws Exception if the updn and ndn indices cannot be accessed
- */
- public abstract String getEntryUpdn( String dn ) throws Exception;
+ public abstract DN getEntryDn( ID id ) throws Exception;
public abstract ClonedServerEntry lookup( ID id ) throws Exception;
Modified: directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java (original)
+++ directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java Sat May 1 10:50:08 2010
@@ -28,14 +28,21 @@ import java.util.Map;
import java.util.Set;
import org.apache.directory.server.constants.ApacheSchemaConstants;
+import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.shared.asn1.primitives.OID;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.exception.LdapAliasDereferencingException;
+import org.apache.directory.shared.ldap.exception.LdapAliasException;
import org.apache.directory.shared.ldap.exception.LdapException;
import org.apache.directory.shared.ldap.name.DN;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.MatchingRule;
import org.apache.directory.shared.ldap.schema.SchemaManager;
+import org.apache.directory.shared.ldap.util.NamespaceTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,7 +53,7 @@ import org.slf4j.LoggerFactory;
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $$Rev$$
*/
-public abstract class AbstractStore<E, ID> implements Store<E, ID>
+public abstract class AbstractStore<E, ID extends Comparable<ID>> implements Store<E, ID>
{
/** static logger */
private static final Logger LOG = LoggerFactory.getLogger( AbstractStore.class );
@@ -111,6 +118,9 @@ public abstract class AbstractStore<E, I
/** a system index on entryCSN attribute */
protected Index<String, E, ID> entryCsnIdx;
+ /** the relative distinguished name index */
+ protected Index<ParentIdAndRdn<ID>, E, ID> rdnIdx;
+
protected void protect( String property )
{
@@ -247,6 +257,10 @@ public abstract class AbstractStore<E, I
{
addIndex( new GenericIndex<ID, E, ID>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID ) );
}
+ if ( getRdnIndex() == null )
+ {
+ addIndex( new GenericIndex<ParentIdAndRdn<ID>, E, ID>( ApacheSchemaConstants.APACHE_RDN_AT_OID ) );
+ }
if ( getNdnIndex() == null )
{
addIndex( new GenericIndex<String, E, ID>( ApacheSchemaConstants.APACHE_N_DN_AT_OID ) );
@@ -285,6 +299,7 @@ public abstract class AbstractStore<E, I
}
// set index shortcuts
+ rdnIdx = ( Index<ParentIdAndRdn<ID>, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
ndnIdx = ( Index<String, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_N_DN_AT_OID );
presenceIdx = ( Index<String, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_EXISTENCE_AT_OID );
oneLevelIdx = ( Index<ID, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
@@ -469,6 +484,16 @@ public abstract class AbstractStore<E, I
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
+ public Index<ParentIdAndRdn<ID>, E, ID> getRdnIndex()
+ {
+ return ( Index<ParentIdAndRdn<ID>, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
public Index<String, E, ID> getNdnIndex()
{
return ( Index<String, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_N_DN_AT_OID );
@@ -564,4 +589,522 @@ public abstract class AbstractStore<E, I
return ( Index<String, E, ID> ) systemIndices.get( SchemaConstants.ENTRY_CSN_AT_OID );
}
+
+ ////////////////////////////////////////////////7
+
+ /**
+ * Adds a set of attribute values while affecting the appropriate userIndices.
+ * The entry is not persisted: it is only changed in anticipation for a put
+ * into the master table.
+ *
+ * @param id the primary key of the entry
+ * @param entry the entry to alter
+ * @param mods the attribute and values to add
+ * @throws Exception if index alteration or attribute addition fails
+ */
+ @SuppressWarnings("unchecked")
+ protected void add( ID id, Entry entry, EntryAttribute mods ) throws Exception
+ {
+ if ( entry instanceof ClonedServerEntry )
+ {
+ throw new Exception( I18n.err( I18n.ERR_215 ) );
+ }
+
+ String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
+
+ // Special case for the ObjectClass index
+ if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+ {
+ for ( Value<?> value : mods )
+ {
+ objectClassIdx.drop( value.getString(), id );
+ }
+ }
+ else if ( hasUserIndexOn( modsOid ) )
+ {
+ Index<?, E, ID> index = getUserIndex( modsOid );
+
+ for ( Value<?> value : mods )
+ {
+ ( ( Index ) index ).add( value.get(), id );
+ }
+
+ // If the attr didn't exist for this id add it to existence index
+ if ( !presenceIdx.forward( modsOid, id ) )
+ {
+ presenceIdx.add( modsOid, id );
+ }
+ }
+
+ // add all the values in mods to the same attribute in the entry
+ AttributeType type = schemaManager.lookupAttributeTypeRegistry( modsOid );
+
+ for ( Value<?> value : mods )
+ {
+ entry.add( type, value );
+ }
+
+ if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
+ {
+ DN ndn = getEntryDn( id );
+ addAliasIndices( id, ndn, mods.getString() );
+ }
+ }
+
+
+ /**
+ * Completely replaces the existing set of values for an attribute with the
+ * modified values supplied affecting the appropriate userIndices. The entry
+ * is not persisted: it is only changed in anticipation for a put into the
+ * master table.
+ *
+ * @param id the primary key of the entry
+ * @param entry the entry to alter
+ * @param mods the replacement attribute and values
+ * @throws Exception if index alteration or attribute modification
+ * fails.
+ */
+ @SuppressWarnings("unchecked")
+ protected void replace( ID id, Entry entry, EntryAttribute mods ) throws Exception
+ {
+ if ( entry instanceof ClonedServerEntry )
+ {
+ throw new Exception( I18n.err( I18n.ERR_215 ) );
+ }
+
+ String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
+
+ // Special case for the ObjectClass index
+ if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+ {
+ // if the id exists in the index drop all existing attribute
+ // value index entries and add new ones
+ if ( objectClassIdx.reverse( id ) )
+ {
+ objectClassIdx.drop( id );
+ }
+
+ for ( Value<?> value : mods )
+ {
+ objectClassIdx.add( value.getString(), id );
+ }
+ }
+ else if ( hasUserIndexOn( modsOid ) )
+ {
+ Index<?, E, ID> index = getUserIndex( modsOid );
+
+ // if the id exists in the index drop all existing attribute
+ // value index entries and add new ones
+ if ( index.reverse( id ) )
+ {
+ ( ( Index<?, E, ID> ) index ).drop( id );
+ }
+
+ for ( Value<?> value : mods )
+ {
+ ( ( Index<Object, E, ID> ) index ).add( value.get(), id );
+ }
+
+ /*
+ * If no attribute values exist for this entryId in the index then
+ * we remove the presence index entry for the removed attribute.
+ */
+ if ( null == index.reverseLookup( id ) )
+ {
+ presenceIdx.drop( modsOid, id );
+ }
+ }
+
+ String aliasAttributeOid = schemaManager.getAttributeTypeRegistry().getOidByName(
+ SchemaConstants.ALIASED_OBJECT_NAME_AT );
+
+ if ( modsOid.equals( aliasAttributeOid ) )
+ {
+ dropAliasIndices( id );
+ }
+
+ // replaces old attributes with new modified ones if they exist
+ if ( mods.size() > 0 )
+ {
+ entry.put( mods );
+ }
+ else
+ // removes old attributes if new replacements do not exist
+ {
+ entry.remove( mods );
+ }
+
+ if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
+ {
+ DN entryDn = getEntryDn( id );
+ addAliasIndices( id, entryDn, mods.getString() );
+ }
+ }
+
+
+ /**
+ * Completely removes the set of values for an attribute having the values
+ * supplied while affecting the appropriate userIndices. The entry is not
+ * persisted: it is only changed in anticipation for a put into the master
+ * table. Note that an empty attribute w/o values will remove all the
+ * values within the entry where as an attribute w/ values will remove those
+ * attribute values it contains.
+ *
+ * @param id the primary key of the entry
+ * @param entry the entry to alter
+ * @param mods the attribute and its values to delete
+ * @throws Exception if index alteration or attribute modification fails.
+ */
+ @SuppressWarnings("unchecked")
+ protected void remove( ID id, Entry entry, EntryAttribute mods ) throws Exception
+ {
+ if ( entry instanceof ClonedServerEntry )
+ {
+ throw new Exception( I18n.err( I18n.ERR_215 ) );
+ }
+
+ String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
+
+ // Special case for the ObjectClass index
+ if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+ {
+ for ( Value<?> value : mods )
+ {
+ objectClassIdx.drop( value.getString(), id );
+ }
+ }
+ else if ( hasUserIndexOn( modsOid ) )
+ {
+ Index<?, E, ID> index = getUserIndex( modsOid );
+
+ for ( Value<?> value : mods )
+ {
+ ( ( Index ) index ).drop( value.get(), id );
+ }
+
+ /*
+ * If no attribute values exist for this entryId in the index then
+ * we remove the presence index entry for the removed attribute.
+ */
+ if ( null == index.reverseLookup( id ) )
+ {
+ presenceIdx.drop( modsOid, id );
+ }
+ }
+
+ AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( modsOid );
+ /*
+ * If there are no attribute values in the modifications then this
+ * implies the compelete removal of the attribute from the entry. Else
+ * we remove individual attribute values from the entry in mods one
+ * at a time.
+ */
+ if ( mods.size() == 0 )
+ {
+ entry.removeAttributes( attrType );
+ }
+ else
+ {
+ EntryAttribute entryAttr = entry.get( attrType );
+
+ for ( Value<?> value : mods )
+ {
+ entryAttr.remove( value );
+ }
+
+ // if nothing is left just remove empty attribute
+ if ( entryAttr.size() == 0 )
+ {
+ entry.removeAttributes( entryAttr.getId() );
+ }
+ }
+
+ // Aliases->single valued comp/partial attr removal is not relevant here
+ if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
+ {
+ dropAliasIndices( id );
+ }
+ }
+
+
+ /////////////////////////////////////////////////////////
+
+ /**
+ * Adds userIndices for an aliasEntry to be added to the database while checking
+ * for constrained alias constructs like alias cycles and chaining.
+ *
+ * @param aliasDn normalized distinguished name for the alias entry
+ * @param aliasTarget the user provided aliased entry dn as a string
+ * @param aliasId the id of alias entry to add
+ * @throws LdapException if index addition fails, and if the alias is
+ * not allowed due to chaining or cycle formation.
+ * @throws Exception if the wrappedCursor btrees cannot be altered
+ */
+ protected void addAliasIndices( ID aliasId, DN aliasDn, String aliasTarget ) throws Exception
+ {
+ DN normalizedAliasTargetDn; // Name value of aliasedObjectName
+ ID targetId; // Id of the aliasedObjectName
+ DN ancestorDn; // Name of an alias entry relative
+ ID ancestorId; // Id of an alias entry relative
+
+ // Access aliasedObjectName, normalize it and generate the Name
+ normalizedAliasTargetDn = new DN( aliasTarget );
+ normalizedAliasTargetDn.normalize( schemaManager.getNormalizerMapping() );
+
+ /*
+ * Check For Cycles
+ *
+ * Before wasting time to lookup more values we check using the target
+ * dn to see if we have the possible formation of an alias cycle. This
+ * happens when the alias refers back to a target that is also a
+ * relative of the alias entry. For detection we test if the aliased
+ * entry Dn starts with the target Dn. If it does then we know the
+ * aliased target is a relative and we have a perspecitive cycle.
+ */
+ if ( aliasDn.isChildOf( normalizedAliasTargetDn ) )
+ {
+ if ( aliasDn.equals( normalizedAliasTargetDn ) )
+ {
+ String msg = I18n.err( I18n.ERR_223 );
+ LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+ //e.setResolvedName( aliasDn );
+ throw e;
+ }
+
+ String msg = I18n.err( I18n.ERR_224, aliasTarget, aliasDn );
+ LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+ //e.setResolvedName( aliasDn );
+ throw e;
+ }
+
+ /*
+ * Check For Aliases External To Naming Context
+ *
+ * id may be null but the alias may be to a valid entry in
+ * another namingContext. Such aliases are not allowed and we
+ * need to point it out to the user instead of saying the target
+ * does not exist when it potentially could outside of this upSuffix.
+ */
+ if ( !normalizedAliasTargetDn.isChildOf( suffixDn ) )
+ {
+ String msg = I18n.err( I18n.ERR_225, suffixDn.getName() );
+ LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+ //e.setResolvedName( aliasDn );
+ throw e;
+ }
+
+ // L O O K U P T A R G E T I D
+ targetId = getEntryId( normalizedAliasTargetDn );
+
+ /*
+ * Check For Target Existence
+ *
+ * We do not allow the creation of inconsistent aliases. Aliases should
+ * not be broken links. If the target does not exist we start screaming
+ */
+ if ( null == targetId )
+ {
+ // Complain about target not existing
+ String msg = I18n.err( I18n.ERR_581, aliasDn.getName(), aliasTarget );
+ LdapAliasException e = new LdapAliasException( msg );
+ //e.setResolvedName( aliasDn );
+ throw e;
+ }
+
+ /*
+ * Detect Direct Alias Chain Creation
+ *
+ * Rather than resusitate the target to test if it is an alias and fail
+ * due to chaing creation we use the alias index to determine if the
+ * target is an alias. Hence if the alias we are about to create points
+ * to another alias as its target in the aliasedObjectName attribute,
+ * then we have a situation where an alias chain is being created.
+ * Alias chaining is not allowed so we throw and exception.
+ */
+ if ( null != aliasIdx.reverseLookup( targetId ) )
+ {
+ String msg = I18n.err( I18n.ERR_227 );
+ LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+ //e.setResolvedName( aliasDn );
+ throw e;
+ }
+
+ // Add the alias to the simple alias index
+ aliasIdx.add( normalizedAliasTargetDn.getNormName(), aliasId );
+
+ /*
+ * Handle One Level Scope Alias Index
+ *
+ * The first relative is special with respect to the one level alias
+ * index. If the target is not a sibling of the alias then we add the
+ * index entry maping the parent's id to the aliased target id.
+ */
+ ancestorDn = ( DN ) aliasDn.clone();
+ ancestorDn.remove( aliasDn.size() - 1 );
+ ancestorId = getEntryId( ancestorDn );
+
+ // check if alias parent and aliased entry are the same
+ DN normalizedAliasTargetParentDn = ( DN ) normalizedAliasTargetDn.clone();
+ normalizedAliasTargetParentDn.remove( normalizedAliasTargetDn.size() - 1 );
+ if ( !aliasDn.isChildOf( normalizedAliasTargetParentDn ) )
+ {
+ oneAliasIdx.add( ancestorId, targetId );
+ }
+
+ /*
+ * Handle Sub Level Scope Alias Index
+ *
+ * Walk the list of relatives from the parents up to the upSuffix, testing
+ * to see if the alias' target is a descendant of the relative. If the
+ * alias target is not a descentant of the relative it extends the scope
+ * and is added to the sub tree scope alias index. The upSuffix node is
+ * ignored since everything is under its scope. The first loop
+ * iteration shall handle the parents.
+ */
+ while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
+ {
+ if ( !NamespaceTools.isDescendant( ancestorDn, normalizedAliasTargetDn ) )
+ {
+ subAliasIdx.add( ancestorId, targetId );
+ }
+
+ ancestorDn.remove( ancestorDn.size() - 1 );
+ ancestorId = getEntryId( ancestorDn );
+ }
+ }
+
+
+ /**
+ * Removes the index entries for an alias before the entry is deleted from
+ * the master table.
+ *
+ * @todo Optimize this by walking the hierarchy index instead of the name
+ * @param aliasId the id of the alias entry in the master table
+ * @throws LdapException if we cannot parse ldap names
+ * @throws Exception if we cannot delete index values in the database
+ */
+ protected void dropAliasIndices( ID aliasId ) throws Exception
+ {
+ String targetDn = aliasIdx.reverseLookup( aliasId );
+ ID targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
+ DN aliasDN = getEntryDn( aliasId );
+
+ DN ancestorDn = ( DN ) aliasDN.clone();
+ ancestorDn.remove( aliasDN.size() - 1 );
+ ID ancestorId = getEntryId( ancestorDn );
+
+ /*
+ * We cannot just drop all tuples in the one level and subtree userIndices
+ * linking baseIds to the targetId. If more than one alias refers to
+ * the target then droping all tuples with a value of targetId would
+ * make all other aliases to the target inconsistent.
+ *
+ * We need to walk up the path of alias ancestors until we reach the
+ * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
+ * subtree scope alias. We only need to do this for the direct parent
+ * of the alias on the one level subtree.
+ */
+ oneAliasIdx.drop( ancestorId, targetId );
+ subAliasIdx.drop( ancestorId, targetId );
+
+ while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
+ {
+ ancestorDn = ( DN ) ancestorDn.getPrefix( ancestorDn.size() - 1 );
+ ancestorId = getEntryId( ancestorDn );
+
+ subAliasIdx.drop( ancestorId, targetId );
+ }
+
+ // Drops all alias tuples pointing to the id of the alias to be deleted
+ aliasIdx.drop( aliasId );
+ }
+
+ /**
+ * For all aliases including and under the moved base, this method removes
+ * one and subtree alias index tuples for old ancestors above the moved base
+ * that will no longer be ancestors after the move.
+ *
+ * @param movedBase the base at which the move occured - the moved node
+ * @throws Exception if system userIndices fail
+ */
+ protected void dropMovedAliasIndices( final DN movedBase ) throws Exception
+ {
+ // // Find all the aliases from movedBase down
+ // IndexAssertion<Object,E> isBaseDescendant = new IndexAssertion<Object,E>()
+ // {
+ // public boolean assertCandidate( IndexEntry<Object,E> rec ) throws Exception
+ // {
+ // String dn = getEntryDn( rec.getId() );
+ // return dn.endsWith( movedBase.toString() );
+ // }
+ // };
+
+ ID movedBaseId = getEntryId( movedBase );
+
+ if ( aliasIdx.reverseLookup( movedBaseId ) != null )
+ {
+ dropAliasIndices( movedBaseId, movedBase );
+ }
+
+ // throw new NotImplementedException( "Fix the code below this line" );
+
+ // NamingEnumeration<ForwardIndexEntry> aliases =
+ // new IndexAssertionEnumeration( aliasIdx.listIndices( movedBase.toString(), true ), isBaseDescendant );
+ //
+ // while ( aliases.hasMore() )
+ // {
+ // ForwardIndexEntry entry = aliases.next();
+ // dropAliasIndices( (Long)entry.getId(), movedBase );
+ // }
+ }
+
+
+ /**
+ * For the alias id all ancestor one and subtree alias tuples are moved
+ * above the moved base.
+ *
+ * @param aliasId the id of the alias
+ * @param movedBase the base where the move occured
+ * @throws Exception if userIndices fail
+ */
+ protected void dropAliasIndices( ID aliasId, DN movedBase ) throws Exception
+ {
+ String targetDn = aliasIdx.reverseLookup( aliasId );
+ ID targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
+ DN aliasDn = getEntryDn( aliasId );
+
+ /*
+ * Start droping index tuples with the first ancestor right above the
+ * moved base. This is the first ancestor effected by the move.
+ */
+ DN ancestorDn = ( DN ) movedBase.getPrefix( 1 );
+ ID ancestorId = getEntryId( ancestorDn );
+
+ /*
+ * We cannot just drop all tuples in the one level and subtree userIndices
+ * linking baseIds to the targetId. If more than one alias refers to
+ * the target then droping all tuples with a value of targetId would
+ * make all other aliases to the target inconsistent.
+ *
+ * We need to walk up the path of alias ancestors right above the moved
+ * base until we reach the upSuffix, deleting each ( ancestorId,
+ * targetId ) tuple in the subtree scope alias. We only need to do
+ * this for the direct parent of the alias on the one level subtree if
+ * the moved base is the alias.
+ */
+ if ( aliasDn.equals( movedBase ) )
+ {
+ oneAliasIdx.drop( ancestorId, targetId );
+ }
+
+ subAliasIdx.drop( ancestorId, targetId );
+
+ while ( !ancestorDn.equals( suffixDn ) )
+ {
+ ancestorDn = ( DN ) ancestorDn.getPrefix( 1 );
+ ancestorId = getEntryId( ancestorDn );
+
+ subAliasIdx.drop( ancestorId, targetId );
+ }
+ }
}