Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 17746 invoked from network); 1 Apr 2009 00:00:52 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 1 Apr 2009 00:00:52 -0000 Received: (qmail 51980 invoked by uid 500); 1 Apr 2009 00:00:52 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 51925 invoked by uid 500); 1 Apr 2009 00:00:52 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 51915 invoked by uid 99); 1 Apr 2009 00:00:52 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Apr 2009 00:00:52 +0000 X-ASF-Spam-Status: No, hits=-1999.6 required=10.0 tests=ALL_TRUSTED,SUBJECT_FUZZY_TION X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Apr 2009 00:00:49 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id ABBEA2388B54; Wed, 1 Apr 2009 00:00:27 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r760740 - in /directory: apacheds/branches/ldif-partition/core-avl/src/main/java/org/apache/directory/server/core/avltree/ apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/ apache... Date: Wed, 01 Apr 2009 00:00:27 -0000 To: commits@directory.apache.org From: akarasulu@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090401000027.ABBEA2388B54@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: akarasulu Date: Wed Apr 1 00:00:26 2009 New Revision: 760740 URL: http://svn.apache.org/viewvc?rev=760740&view=rev Log: added avl table and cursors Added: directory/apacheds/branches/ldif-partition/core-avl/src/main/java/org/apache/directory/server/core/avltree/KeyTupleAvlCursor.java directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/ directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTable.java directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTableDupsCursor.java directory/apacheds/branches/ldif-partition/ldif-partition/src/test/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/AvlUsageTest.java Modified: directory/apacheds/branches/ldif-partition/server-xml/src/test/java/org/apache/directory/server/SpringServerTest.java directory/project/trunk/resources/dictionary Added: directory/apacheds/branches/ldif-partition/core-avl/src/main/java/org/apache/directory/server/core/avltree/KeyTupleAvlCursor.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/ldif-partition/core-avl/src/main/java/org/apache/directory/server/core/avltree/KeyTupleAvlCursor.java?rev=760740&view=auto ============================================================================== --- directory/apacheds/branches/ldif-partition/core-avl/src/main/java/org/apache/directory/server/core/avltree/KeyTupleAvlCursor.java (added) +++ directory/apacheds/branches/ldif-partition/core-avl/src/main/java/org/apache/directory/server/core/avltree/KeyTupleAvlCursor.java Wed Apr 1 00:00:26 2009 @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.directory.server.core.avltree; + + +import org.apache.directory.server.core.cursor.InvalidCursorPositionException; +import org.apache.directory.server.xdbm.Tuple; +import org.apache.directory.server.xdbm.AbstractTupleCursor; +import org.apache.directory.server.core.avltree.AvlTree; +import org.apache.directory.server.core.avltree.AvlTreeCursor; + + +/** + * Cursor over a set of values for the same key which are store in an in + * memory AvlTree. This Cursor is limited to the same key and it's tuples + * will always return the same key. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class KeyTupleAvlCursor extends AbstractTupleCursor +{ + private final AvlTreeCursor wrapped; + private final K key; + + private Tuple returnedTuple = new Tuple(); + private boolean valueAvailable; + + + /** + * Creates a Cursor over the tuples of an AvlTree. + * + * @param avlTree the AvlTree to build a Tuple returning Cursor over + * @param key the constant key for which values are returned + */ + public KeyTupleAvlCursor( AvlTree avlTree, K key ) + { + this.key = key; + this.wrapped = new AvlTreeCursor( avlTree ); + } + + + private void clearValue() + { + returnedTuple.setKey( key ); + returnedTuple.setValue( null ); + valueAvailable = false; + } + + + public boolean available() + { + return valueAvailable; + } + + + public void beforeKey( K key ) throws Exception + { + throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." ); + } + + + public void afterKey( K key ) throws Exception + { + throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." ); + } + + + public void beforeValue( K key, V value ) throws Exception + { + checkNotClosed( "beforeValue()" ); + if ( key != null && ! key.equals( this.key ) ) + { + throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." ); + } + + wrapped.before( value ); + clearValue(); + } + + + public void afterValue( K key, V value ) throws Exception + { + checkNotClosed( "afterValue()" ); + if ( key != null && ! key.equals( this.key ) ) + { + throw new UnsupportedOperationException( "This cursor locks down the key so keywise advances are not allowed." ); + } + + wrapped.after( value ); + clearValue(); + } + + + /** + * Positions this Cursor over the same keys before the value of the + * supplied element Tuple. The supplied element Tuple's key is not + * considered at all. + * + * @param element the valueTuple who's value is used to position this Cursor + * @throws Exception if there are failures to position the Cursor + */ + public void before( Tuple element ) throws Exception + { + checkNotClosed( "before()" ); + wrapped.before( element.getValue() ); + clearValue(); + } + + + public void after( Tuple element ) throws Exception + { + checkNotClosed( "after()" ); + wrapped.after( element.getValue() ); + clearValue(); + } + + + public void beforeFirst() throws Exception + { + checkNotClosed( "beforeFirst()" ); + wrapped.beforeFirst(); + clearValue(); + } + + + public void afterLast() throws Exception + { + checkNotClosed( "afterLast()" ); + wrapped.afterLast(); + clearValue(); + } + + + public boolean first() throws Exception + { + beforeFirst(); + return next(); + } + + + public boolean last() throws Exception + { + afterLast(); + return previous(); + } + + + public boolean previous() throws Exception + { + checkNotClosed( "previous()" ); + if ( wrapped.previous() ) + { + returnedTuple.setKey( key ); + returnedTuple.setValue( wrapped.get() ); + return valueAvailable = true; + } + else + { + clearValue(); + return false; + } + } + + + public boolean next() throws Exception + { + checkNotClosed( "next()" ); + if ( wrapped.next() ) + { + returnedTuple.setKey( key ); + returnedTuple.setValue( wrapped.get() ); + return valueAvailable = true; + } + else + { + clearValue(); + return false; + } + } + + + public Tuple get() throws Exception + { + checkNotClosed( "get()" ); + if ( valueAvailable ) + { + return returnedTuple; + } + + throw new InvalidCursorPositionException(); + } + + + public boolean isElementReused() + { + return true; + } +} \ No newline at end of file Added: directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTable.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTable.java?rev=760740&view=auto ============================================================================== --- directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTable.java (added) +++ directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTable.java Wed Apr 1 00:00:26 2009 @@ -0,0 +1,456 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.directory.server.core.partition.ldif; + + +import java.util.Comparator; + +import org.apache.directory.server.core.avltree.AvlTree; +import org.apache.directory.server.core.avltree.AvlTreeCursor; +import org.apache.directory.server.core.avltree.AvlTreeMap; +import org.apache.directory.server.core.avltree.AvlTreeMapNoDupsCursor; +import org.apache.directory.server.core.avltree.KeyTupleAvlCursor; +import org.apache.directory.server.core.avltree.LinkedAvlMapNode; +import org.apache.directory.server.core.cursor.Cursor; +import org.apache.directory.server.core.cursor.EmptyCursor; +import org.apache.directory.server.core.cursor.SingletonCursor; +import org.apache.directory.server.xdbm.Table; +import org.apache.directory.server.xdbm.Tuple; + + +/** + * A Table implementation backed by in memory AVL tree. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class AvlTable implements Table +{ + private final AvlTreeMap avl; + private final String name; + private final Comparator keyComparator; + private final Comparator valComparator; + private int count; + + + public AvlTable( String name, Comparator keyComparator, Comparator valComparator, boolean dupsEnabled ) + { + this.name = name; + this.keyComparator = keyComparator; + this.valComparator = valComparator; + this.avl = new AvlTreeMap( keyComparator, valComparator, dupsEnabled ); + } + + + /** + * Does nothing. + * + * {@inheritDoc} + */ + public void close() throws Exception + { + } + + + /** + * {@inheritDoc} + */ + public int count() throws Exception + { + return count; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public int count( K key ) throws Exception + { + if ( key == null ) + { + return 0; + } + + LinkedAvlMapNode node = avl.find( key ); + if ( node == null ) + { + return 0; + } + + V val = node.getValue(); + if ( val instanceof AvlTree ) + { + return ( ( AvlTree ) val ).getSize(); + } + + return 1; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public V get( K key ) throws Exception + { + if ( key == null ) + { + return null; + } + + LinkedAvlMapNode node = avl.find( key ); + if ( node == null ) + { + return null; + } + + V val = node.getValue(); + if ( val instanceof AvlTree ) + { + return ( ( AvlTree ) val ).getFirst().getKey(); + } + + return val; + } + + + /** + * {@inheritDoc} + */ + public Comparator getKeyComparator() + { + return keyComparator; + } + + + /** + * {@inheritDoc} + */ + public Comparator getValueComparator() + { + return valComparator; + } + + + /** + * {@inheritDoc} + */ + public String getName() + { + return name; + } + + + /** + * {@inheritDoc} + */ + public int greaterThanCount( K key ) throws Exception + { + return avl.getSize(); + } + + + /** + * {@inheritDoc} + */ + public boolean has( K key ) throws Exception + { + if ( key == null ) + { + return false; + } + + return avl.find( key ) != null; + } + + + /** + * {@inheritDoc} + */ + public boolean has( K key, V value ) throws Exception + { + if ( key == null ) + { + return false; + } + + return avl.find( key, value ) != null; + } + + + /** + * {@inheritDoc} + */ + public boolean hasGreaterOrEqual( K key ) throws Exception + { + if ( key == null ) + { + return false; + } + + return avl.findGreaterOrEqual( key ) != null; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean hasGreaterOrEqual( K key, V val ) throws Exception + { + if ( key == null ) + { + return false; + } + + LinkedAvlMapNode node = avl.findGreaterOrEqual( key ); + if ( node == null ) + { + return false; + } + + if ( node.getValue() instanceof AvlTree ) + { + AvlTree values = ( AvlTree ) node.getValue(); + return values.findGreaterOrEqual( val ) != null; + } + + return valComparator.compare( node.getValue(), val ) >= 0; + } + + + /** + * {@inheritDoc} + */ + public boolean hasLessOrEqual( K key ) throws Exception + { + if ( key == null ) + { + return false; + } + + return avl.findLessOrEqual( key ) != null; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean hasLessOrEqual( K key, V val ) throws Exception + { + if ( key == null ) + { + return false; + } + + LinkedAvlMapNode node = avl.findLessOrEqual( key ); + if ( node == null ) + { + return false; + } + + if ( node.getValue() instanceof AvlTree ) + { + AvlTree values = ( AvlTree ) node.getValue(); + return values.findLessOrEqual( val ) != null; + } + + return valComparator.compare( node.getValue(), val ) <= 0; + } + + + /** + * {@inheritDoc} + */ + public boolean isCountExact() + { + return false; + } + + + /** + * {@inheritDoc} + */ + public boolean isDupsEnabled() + { + return avl.isDupsAllowed(); + } + + + /** + * {@inheritDoc} + */ + public int lessThanCount( K key ) throws Exception + { + return count; + } + + + /** + * {@inheritDoc} + */ + public void put( K key, V value ) throws Exception + { + if ( key == null || value == null ) + { + return; + } + + if ( avl.insert( key, value ) == null ) + { + count++; + } + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void remove( K key ) throws Exception + { + if ( key == null ) + { + return; + } + + if ( ! avl.isDupsAllowed() ) + { + if ( avl.remove( key, null ) != null ) + { + count--; + } + return; + } + + LinkedAvlMapNode node = avl.find( key ); + if ( node == null ) + { + return; + } + + V value = node.getValue(); + + if ( value instanceof AvlTree ) + { + count -= ( ( AvlTree ) value ).getSize(); + avl.remove( key, null ); + } + else + { + avl.remove( key, null ); + count --; + } + } + + + /** + * {@inheritDoc} + */ + public void remove( K key, V value ) throws Exception + { + if ( avl.remove( key, value ) != null ) + { + count--; + } + } + + + /** + * {@inheritDoc} + */ + public Cursor> cursor() throws Exception + { + if ( ! avl.isDupsAllowed() ) + { + return new AvlTreeMapNoDupsCursor( avl ); + } + + return new AvlTableDupsCursor( this ); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Cursor> cursor( K key ) throws Exception + { + if ( key == null ) + { + return new EmptyCursor>(); + } + + LinkedAvlMapNode node = avl.find( key ); + if ( node == null ) + { + return new EmptyCursor>(); + } + + V value = node.getValue(); + if ( value instanceof AvlTree ) + { + return new KeyTupleAvlCursor( ( AvlTree ) value, key ); + } + + return new SingletonCursor>( new Tuple( key, value ) ); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Cursor valueCursor( K key ) throws Exception + { + if ( key == null ) + { + return new EmptyCursor(); + } + + LinkedAvlMapNode node = avl.find( key ); + if ( node == null ) + { + return new EmptyCursor(); + } + + V value = node.getValue(); + if ( value instanceof AvlTree ) + { + return new AvlTreeCursor( ( AvlTree ) value ); + } + + return new SingletonCursor( value ); + } + + + /** + * Returns the internal AvlTreeMap so other classes like Cursors + * in the same package can access it. + * + * @return AvlTreeMap used to store Tuples + */ + AvlTreeMap getAvlTreeMap() + { + return avl; + } +} Added: directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTableDupsCursor.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTableDupsCursor.java?rev=760740&view=auto ============================================================================== --- directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTableDupsCursor.java (added) +++ directory/apacheds/branches/ldif-partition/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/AvlTableDupsCursor.java Wed Apr 1 00:00:26 2009 @@ -0,0 +1,514 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.directory.server.core.partition.ldif; + + +import org.apache.directory.server.core.avltree.AvlTree; +import org.apache.directory.server.core.avltree.AvlTreeCursor; +import org.apache.directory.server.core.avltree.AvlTreeMapNoDupsCursor; +import org.apache.directory.server.core.cursor.Cursor; +import org.apache.directory.server.core.cursor.InvalidCursorPositionException; +import org.apache.directory.server.core.cursor.SingletonCursor; +import org.apache.directory.server.xdbm.AbstractTupleCursor; +import org.apache.directory.server.xdbm.Tuple; +import org.apache.directory.server.xdbm.TupleCursor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * A Cursor which walks and advance over AvlTables that may contain duplicate + * keys with values stored in an AvlTree. All duplicate keys are traversed + * returning the key and the value in a Tuple. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class AvlTableDupsCursor extends AbstractTupleCursor +{ + private static final Logger LOG = LoggerFactory.getLogger( AvlTableDupsCursor.class.getSimpleName() ); + + /** The AVL backed table this Cursor traverses over. */ + private final AvlTable table; + + /** + * The underlying wrapped cursor which returns Tuples whose values are + * either V objects or AvlTree objects. + */ + private final TupleCursor wrappedCursor; + + /** + * A Cursor over a set of value objects for the current key held in the + * containerTuple. A new Cursor will be set for each new key as we + * traverse. The Cursor traverses over either a AvlTree object full + * of values in a multi-valued key or it traverses over a BTree which + * contains the values in the key field of it's Tuples. + */ + private Cursor dupsCursor; + + /** The current Tuple returned from the wrapped cursor. */ + private final Tuple wrappedTuple = new Tuple(); + + /** + * The Tuple that is used to return values via the get() method. This + * same Tuple instance will be returned every time. At different + * positions it may return different values for the same key. + */ + private final Tuple returnedTuple = new Tuple(); + + /** Whether or not a value is available when get() is called. */ + private boolean valueAvailable; + + + /** + * Creates a new instance of AvlTableDupsCursor. + * + * @param table the AvlTable to build a Cursor on. + */ + public AvlTableDupsCursor( AvlTable table ) + { + this.table = table; + this.wrappedCursor = new AvlTreeMapNoDupsCursor( table.getAvlTreeMap() ); + LOG.debug( "Created on table {}", table.getName() ); + } + + + /** + * {@inheritDoc} + */ + public boolean available() + { + return valueAvailable; + } + + + /** + * {@inheritDoc} + */ + public void beforeKey( K key ) throws Exception + { + beforeValue( key, null ); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void beforeValue( K key, V value ) throws Exception + { + checkNotClosed( "beforeValue()" ); + wrappedCursor.before( new Tuple( key, null ) ); + + if ( wrappedCursor.next() ) + { + wrappedTuple.setBoth( wrappedCursor.get() ); + + if ( wrappedTuple.getValue() instanceof AvlTree ) + { + AvlTree avlTree = ( AvlTree ) wrappedTuple.getValue(); + dupsCursor = new AvlTreeCursor( avlTree ); + } + else + { + dupsCursor = new SingletonCursor( wrappedTuple.getValue() ); + } + + if ( value == null ) + { + return; + } + + /* + * The cursor over the values is only advanced if we're on the + * same key as the primary cursor. This is because we want this + * method to really position us within a set of duplicate key + * entries at the proper value. + */ + if ( table.getKeyComparator().compare( wrappedTuple.getKey(), key ) == 0 ) + { + dupsCursor.before( value ); + } + + return; + } + + clearValue(); + wrappedTuple.setKey( null ); + wrappedTuple.setValue( null ); + } + + + /** + * {@inheritDoc} + */ + public void afterKey( K key ) throws Exception + { + afterValue( key, null ); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void afterValue( K key, V value ) throws Exception + { + checkNotClosed( "afterValue()" ); + /* + * There is a subtle difference between after and before handling + * with dupicate key values. Say we have the following tuples: + * + * (0, 0) + * (1, 1) + * (1, 2) + * (1, 3) + * (2, 2) + * + * If we request an after cursor on (1, 2). We must make sure that + * the container cursor does not advance after the entry with key 1 + * since this would result in us skip returning (1. 3) on the call to + * next which will incorrectly return (2, 2) instead. + * + * So if the value is null in the element then we don't care about + * this obviously since we just want to advance past the duplicate key + * values all together. But when it is not null, then we want to + * go right before this key instead of after it. + */ + + if ( value == null ) + { + wrappedCursor.after( new Tuple( key, null ) ); + } + else + { + wrappedCursor.before( new Tuple( key, null ) ); + } + + if ( wrappedCursor.next() ) + { + wrappedTuple.setBoth( wrappedCursor.get() ); + V values = wrappedTuple.getValue(); + + if ( values instanceof AvlTree ) + { + AvlTree set = ( AvlTree ) values; + dupsCursor = new AvlTreeCursor( set ); + } + else + { + dupsCursor = new SingletonCursor( values ); + } + + if ( value == null ) + { + return; + } + + // only advance the dupsCursor if we're on same key + if ( table.getKeyComparator().compare( wrappedTuple.getKey(), key ) == 0 ) + { + dupsCursor.after( value ); + } + + return; + } + + clearValue(); + wrappedTuple.setKey( null ); + wrappedTuple.setValue( null ); + } + + + /** + * {@inheritDoc} + */ + public void after( Tuple element ) throws Exception + { + afterValue( element.getKey(), element.getValue() ); + } + + + /** + * {@inheritDoc} + */ + public void afterLast() throws Exception + { + checkNotClosed( "afterLast()" ); + clearValue(); + wrappedCursor.afterLast(); + wrappedTuple.setKey( null ); + wrappedTuple.setValue( null ); + dupsCursor = null; + } + + + /** + * {@inheritDoc} + */ + public void before( Tuple element ) throws Exception + { + beforeValue( element.getKey(), element.getValue() ); + } + + + /** + * {@inheritDoc} + */ + public void beforeFirst() throws Exception + { + checkNotClosed( "beforeFirst()" ); + clearValue(); + wrappedCursor.beforeFirst(); + wrappedTuple.setKey( null ); + wrappedTuple.setValue( null ); + dupsCursor = null; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean first() throws Exception + { + checkNotClosed( "first()" ); + clearValue(); + dupsCursor = null; + + if ( wrappedCursor.first() ) + { + wrappedTuple.setBoth( wrappedCursor.get() ); + V values = wrappedTuple.getValue(); + + if ( values instanceof AvlTree ) + { + dupsCursor = new AvlTreeCursor( ( AvlTree ) values ); + } + else + { + dupsCursor = new SingletonCursor( values ); + } + + /* + * Since only tables with duplicate keys enabled use this + * cursor, entries must have at least one value, and therefore + * call to last() will always return true. + */ + dupsCursor.first(); + valueAvailable = true; + returnedTuple.setKey( wrappedTuple.getKey() ); + returnedTuple.setValue( dupsCursor.get() ); + return true; + } + + return false; + } + + + /** + * {@inheritDoc} + */ + public Tuple get() throws Exception + { + checkNotClosed( "get()" ); + + if ( ! valueAvailable ) + { + throw new InvalidCursorPositionException(); + } + + return returnedTuple; + } + + + /** + * {@inheritDoc} + */ + public boolean isElementReused() + { + return true; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean last() throws Exception + { + checkNotClosed( "last()" ); + clearValue(); + dupsCursor = null; + + if ( wrappedCursor.last() ) + { + wrappedTuple.setBoth( wrappedCursor.get() ); + V values = wrappedTuple.getValue(); + + if ( values instanceof AvlTree ) + { + dupsCursor = new AvlTreeCursor( ( AvlTree ) values ); + } + else + { + dupsCursor = new SingletonCursor( values ); + } + + /* + * Since only tables with duplicate keys enabled use this + * cursor, entries must have at least one value, and therefore + * call to last() will always return true. + */ + dupsCursor.last(); + valueAvailable = true; + returnedTuple.setKey( wrappedTuple.getKey() ); + returnedTuple.setValue( dupsCursor.get() ); + return true; + } + + return false; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean next() throws Exception + { + checkNotClosed( "next()" ); + /* + * If the cursor over the values of the current key is null or is + * extinguished then we need to advance to the next key. + */ + if ( null == dupsCursor || ! dupsCursor.next() ) + { + /* + * If the wrappedCursor cursor has more elements we get the next + * key/AvlTree Tuple to work with and get a cursor over it. + */ + if ( wrappedCursor.next() ) + { + wrappedTuple.setBoth( wrappedCursor.get() ); + V values = wrappedTuple.getValue(); + + if ( values instanceof AvlTree ) + { + dupsCursor = new AvlTreeCursor( ( AvlTree ) values ); + } + else + { + dupsCursor = new SingletonCursor( values ); + } + + /* + * Since only tables with duplicate keys enabled use this + * cursor, entries must have at least one value, and therefore + * call to next() after bringing the cursor to beforeFirst() + * will always return true. + */ + dupsCursor.beforeFirst(); + dupsCursor.next(); + } + else + { + dupsCursor = null; + return false; + } + } + + /* + * If we get to this point then cursor has more elements and + * wrappedTuple holds the Tuple containing the key and the + * AvlTree of values for that key which the Cursor traverses. All we + * need to do is populate our tuple object with the key and the value + * in the cursor. + */ + returnedTuple.setKey( wrappedTuple.getKey() ); + returnedTuple.setValue( dupsCursor.get() ); + return valueAvailable = true; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean previous() throws Exception + { + checkNotClosed( "previous()" ); + /* + * If the cursor over the values of the current key is null or is + * extinguished then we need to advance to the previous key. + */ + if ( null == dupsCursor || ! dupsCursor.previous() ) + { + /* + * If the wrappedCursor cursor has more elements we get the previous + * key/AvlTree Tuple to work with and get a cursor over it's + * values. + */ + if ( wrappedCursor.previous() ) + { + wrappedTuple.setBoth( wrappedCursor.get() ); + V values = wrappedTuple.getValue(); + + if ( values instanceof AvlTree ) + { + dupsCursor = new AvlTreeCursor( ( AvlTree ) values ); + } + else + { + dupsCursor = new SingletonCursor( values ); + } + + /* + * Since only tables with duplicate keys enabled use this + * cursor, entries must have at least one value, and therefore + * call to previous() after bringing the cursor to afterLast() + * will always return true. + */ + dupsCursor.afterLast(); + dupsCursor.previous(); + } + else + { + dupsCursor = null; + return false; + } + } + + returnedTuple.setKey( wrappedTuple.getKey() ); + returnedTuple.setValue( dupsCursor.get() ); + return valueAvailable = true; + } + + + /** + * Clears the returned Tuple and makes sure valueAvailable returns false. + */ + private void clearValue() + { + returnedTuple.setKey( null ); + returnedTuple.setValue( null ); + valueAvailable = false; + } +} Added: directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/AvlUsageTest.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/AvlUsageTest.java?rev=760740&view=auto ============================================================================== --- directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/AvlUsageTest.java (added) +++ directory/apacheds/branches/ldif-partition/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/AvlUsageTest.java Wed Apr 1 00:00:26 2009 @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.directory.server.core.partition.ldif; + + +import java.util.Comparator; + +import org.apache.directory.server.core.avltree.AvlTree; +import org.apache.directory.server.xdbm.Tuple; + +import junit.framework.TestCase; + + +/** + * TODO AvlUsageTest. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class AvlUsageTest extends TestCase +{ + public void testWithTuple() + { + //AvlTree> avlTree = new AvlTree>(); + } + + + class AvlTupleComparator implements Comparator> + { + public int compare( Tuple arg0, Tuple arg1 ) + { + // TODO Auto-generated method stub + return 0; + } + } +} Modified: directory/apacheds/branches/ldif-partition/server-xml/src/test/java/org/apache/directory/server/SpringServerTest.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/ldif-partition/server-xml/src/test/java/org/apache/directory/server/SpringServerTest.java?rev=760740&r1=760739&r2=760740&view=diff ============================================================================== --- directory/apacheds/branches/ldif-partition/server-xml/src/test/java/org/apache/directory/server/SpringServerTest.java (original) +++ directory/apacheds/branches/ldif-partition/server-xml/src/test/java/org/apache/directory/server/SpringServerTest.java Wed Apr 1 00:00:26 2009 @@ -26,7 +26,6 @@ import org.apache.directory.server.core.authn.Authenticator; import org.apache.directory.server.core.authn.SimpleAuthenticator; import org.apache.directory.server.core.authn.StrongAuthenticator; -import org.apache.directory.server.core.interceptor.Interceptor; import org.apache.xbean.spring.context.FileSystemXmlApplicationContext; import org.junit.Test; import org.springframework.context.ApplicationContext; Modified: directory/project/trunk/resources/dictionary URL: http://svn.apache.org/viewvc/directory/project/trunk/resources/dictionary?rev=760740&r1=760739&r2=760740&view=diff ============================================================================== --- directory/project/trunk/resources/dictionary (original) +++ directory/project/trunk/resources/dictionary Wed Apr 1 00:00:26 2009 @@ -26,3 +26,4 @@ Rev interceptors resusitated +multi