From commits-return-32313-apmail-directory-commits-archive=directory.apache.org@directory.apache.org Thu Sep 1 17:34:32 2011 Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 57E0782B0 for ; Thu, 1 Sep 2011 17:34:32 +0000 (UTC) Received: (qmail 1079 invoked by uid 500); 1 Sep 2011 17:34:32 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 1018 invoked by uid 500); 1 Sep 2011 17:34:31 -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 1011 invoked by uid 99); 1 Sep 2011 17:34:31 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Sep 2011 17:34:31 +0000 X-ASF-Spam-Status: No, hits=-1998.0 required=5.0 tests=ALL_TRUSTED,FB_GET_MEDS 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; Thu, 01 Sep 2011 17:34:27 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 60FE92388A19 for ; Thu, 1 Sep 2011 17:34:07 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1164182 [2/2] - in /directory/apacheds/trunk: core-annotations/ core-api/ core-avl/ core-constants/ core-integ/ core-integ/src/test/java/org/apache/directory/server/core/collective/ core-jndi/ core/ core/src/main/java/org/apache/directory/... Date: Thu, 01 Sep 2011 17:34:05 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110901173407.60FE92388A19@eris.apache.org> Modified: directory/apacheds/trunk/jdbm/src/main/java/jdbm/btree/BTree.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm/src/main/java/jdbm/btree/BTree.java?rev=1164182&r1=1164181&r2=1164182&view=diff ============================================================================== --- directory/apacheds/trunk/jdbm/src/main/java/jdbm/btree/BTree.java (original) +++ directory/apacheds/trunk/jdbm/src/main/java/jdbm/btree/BTree.java Thu Sep 1 17:34:03 2011 @@ -47,18 +47,27 @@ package jdbm.btree; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; +import java.io.ObjectInputStream; import java.io.ObjectOutput; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Comparator; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import jdbm.ActionRecordManager; import jdbm.RecordManager; +import jdbm.helper.ActionContext; import jdbm.helper.Serializer; import jdbm.helper.Tuple; import jdbm.helper.TupleBrowser; +import jdbm.helper.WrappedRuntimeException; import org.apache.directory.server.i18n.I18n; @@ -77,7 +86,6 @@ import org.apache.directory.server.i18n. * user is responsible to supply a serializable Comparator object * to be used for the ordering of entries, which are also called Tuple. * The B+Tree allows traversing the keys in forward and reverse order using a - * TupleBrowser obtained from the browse() methods. *

* This implementation does not directly support duplicate keys, but it is * possible to handle duplicates by inlining or referencing an object collection @@ -106,7 +114,7 @@ public class BTree implements Exte private transient long recordId; /** Comparator used to index entries. */ - private Comparator comparator; + Comparator comparator; /** Serializer used to serialize index keys (optional) */ protected Serializer keySerializer; @@ -118,7 +126,7 @@ public class BTree implements Exte * Height of the B+Tree. This is the number of BPages you have to traverse * to get to a leaf BPage, starting from the root. */ - private int bTreeHeight; + int bTreeHeight; /** Record id of the root BPage */ private long rootId; @@ -131,7 +139,16 @@ public class BTree implements Exte /** Serializer used for BPages of this tree */ private transient BPage bpageSerializer; - + + /** TRUE if underlying record manager is snapshot capable */ + private transient boolean isActionCapable; + + + /** Big lock snychronizing all actions */ + private transient Lock bigLock = new ReentrantLock(); + + /** Meta root used to access versions of Btree root */ + private transient MetaRoot metaRoot = new MetaRoot(); /** * No-argument constructor used by serialization. @@ -220,8 +237,27 @@ public class BTree implements Exte this.bpageSerializer = new BPage(); this.bpageSerializer.btree = this; this.nbEntries = new AtomicInteger( 0 ); + + this.isActionCapable = recordManager instanceof ActionRecordManager; - this.recordId = recordManager.insert( this ); + boolean abortedAction = false; + ActionContext context = this.beginAction( false, "createInstance" ); + try + { + this.recordId = recordManager.insert( this ); + updateMetaRoot( this.rootId, this.bTreeHeight ); + } + catch ( IOException e ) + { + abortedAction = true; + this.abortAction( context ); + throw e; + } + finally + { + if ( !abortedAction ) + this.endAction( context ); + } } @@ -246,11 +282,33 @@ public class BTree implements Exte */ public BTree load( RecordManager recman, long recid ) throws IOException { - BTree btree = (BTree) recman.fetch( recid ); - btree.recordId = recid; - btree.recordManager = recman; - btree.bpageSerializer = new BPage(); - btree.bpageSerializer.btree = btree; + BTree btree = null; + boolean abortedAction = false; + ActionContext context = this.beginAction( false, "load" ); + + try + { + btree = (BTree) recman.fetch( recid ); + btree.recordId = recid; + btree.recordManager = recman; + btree.bpageSerializer = new BPage(); + btree.bpageSerializer.btree = btree; + btree.updateMetaRoot( btree.rootId, btree.bTreeHeight ); + + } + catch ( IOException e ) + { + abortedAction = true; + this.abortAction( context ); + throw e; + } + finally + { + if ( !abortedAction ) + { + this.endAction( context ); + } + } return btree; } @@ -268,7 +326,7 @@ public class BTree implements Exte * @param replace Set to true to replace an existing key-value pair. * @return Existing value, if any. */ - public synchronized Object insert( K key, V value, boolean replace ) throws IOException + public Object insert( K key, V value, boolean replace ) throws IOException { if ( key == null ) { @@ -280,56 +338,95 @@ public class BTree implements Exte throw new IllegalArgumentException( I18n.err( I18n.ERR_524 ) ); } - BPage rootPage = getRoot(); + + boolean abortedAction = false; + ActionContext context = this.beginAction( false, "insert" ); + - if ( rootPage == null ) + if ( !isActionCapable ) { - // BTree is currently empty, create a new root BPage - if ( DEBUG ) - { - System.out.println( "BTree.insert() new root BPage" ); - } - - rootPage = new BPage( this, key, value ); - rootId = rootPage.getRecordId(); - bTreeHeight = 1; - nbEntries.set( 1 ); - recordManager.update( recordId, this ); - - return null; + bigLock.lock(); } - else + + try { - BPage.InsertResult insert = rootPage.insert( bTreeHeight, key, value, replace ); - boolean dirty = false; - - if ( insert.overflow != null ) + BPage rootPage = getRoot(); + + if ( rootPage == null ) { - // current root page overflowed, we replace with a new root page + // BTree is currently empty, create a new root BPage if ( DEBUG ) { - System.out.println( "BTree.insert() replace root BPage due to overflow" ); + System.out.println( "BTree.insert() new root BPage" ); } - rootPage = new BPage( this, rootPage, insert.overflow ); + rootPage = new BPage( this, key, value ); rootId = rootPage.getRecordId(); - bTreeHeight += 1; - dirty = true; + bTreeHeight = 1; + nbEntries.set( 1 ); + recordManager.update( recordId, this ); + updateMetaRoot( this.rootId, this.bTreeHeight ); + + return null; } - - if ( insert.existing == null ) + else { - nbEntries.getAndIncrement(); - dirty = true; + BPage.InsertResult insert = rootPage.insert( bTreeHeight, key, value, replace ); + + if ( insert.pageNewCopy != null ) + { + rootPage = insert.pageNewCopy; + } + + boolean dirty = false; + + if ( insert.overflow != null ) + { + // current root page overflowed, we replace with a new root page + if ( DEBUG ) + { + System.out.println( "BTree.insert() replace root BPage due to overflow" ); + } + + rootPage = new BPage( this, rootPage, insert.overflow ); + rootId = rootPage.getRecordId(); + bTreeHeight += 1; + dirty = true; + updateMetaRoot( this.rootId, this.bTreeHeight ); + } + + if ( insert.existing == null ) + { + nbEntries.getAndIncrement(); + dirty = true; + } + + if ( dirty ) + { + recordManager.update( recordId, this ); + } + + // insert might have returned an existing value + return insert.existing; } - - if ( dirty ) + } + catch ( IOException e ) + { + abortedAction = true; + this.abortAction( context ); + throw e; + } + finally + { + if ( !abortedAction ) { - recordManager.update( recordId, this ); + this.endAction( context ); } - // insert might have returned an existing value - return insert.existing; + if ( !isActionCapable ) + { + bigLock.unlock(); + } } } @@ -341,52 +438,88 @@ public class BTree implements Exte * @return Value associated with the key, or null if no entry with given * key existed in the BTree. */ - public synchronized V remove( K key ) throws IOException + public V remove( K key ) throws IOException { if ( key == null ) { throw new IllegalArgumentException( I18n.err( I18n.ERR_523 ) ); } - - BPage rootPage = getRoot(); + - if ( rootPage == null ) + boolean abortedAction = false; + ActionContext context = this.beginAction( false, "remove" ); + + if ( !isActionCapable ) { - return null; + bigLock.lock(); } - boolean dirty = false; - BPage.RemoveResult remove = rootPage.remove( bTreeHeight, key ); - - if ( remove.underflow && rootPage.isEmpty() ) + try { - bTreeHeight -= 1; - dirty = true; - - recordManager.delete( rootId ); + BPage rootPage = getRoot(); - if ( bTreeHeight == 0 ) + if ( rootPage == null ) { - rootId = 0; + return null; } - else + + boolean dirty = false; + BPage.RemoveResult remove = rootPage.remove( bTreeHeight, key ); + + if ( remove.pageNewCopy != null ) { - rootId = rootPage.childBPage( pageSize - 1 ).getRecordId(); + rootPage = remove.pageNewCopy; } + + if ( remove.underflow && rootPage.isEmpty() ) + { + bTreeHeight -= 1; + dirty = true; + + recordManager.delete( rootId ); + + if ( bTreeHeight == 0 ) + { + rootId = 0; + } + else + { + rootId = rootPage.childBPage( pageSize - 1 ).getRecordId(); + } + updateMetaRoot( this.rootId, this.bTreeHeight ); + } + + if ( remove.value != null ) + { + nbEntries.getAndDecrement(); + dirty = true; + } + + if ( dirty ) + { + recordManager.update( recordId, this ); + } + + return remove.value; } - - if ( remove.value != null ) + catch ( IOException e ) { - nbEntries.getAndDecrement(); - dirty = true; + abortedAction = true; + this.abortAction( context ); + throw e; } - - if ( dirty ) + finally { - recordManager.update( recordId, this ); + if ( !abortedAction ) + { + this.endAction( context ); + } + + if ( !isActionCapable ) + { + bigLock.unlock(); + } } - - return remove.value; } @@ -396,40 +529,58 @@ public class BTree implements Exte * @param key Lookup key. * @return Value associated with the key, or null if not found. */ - public synchronized V find( K key ) throws IOException + public V find( K key ) throws IOException { + TupleBrowser browser = null; + Tuple tuple = null; + if ( key == null ) { throw new IllegalArgumentException( I18n.err( I18n.ERR_523 ) ); } - BPage rootPage = getRoot(); - - if ( rootPage == null ) + if ( !isActionCapable ) { - return null; + bigLock.lock(); } - - Tuple tuple = new Tuple( null, null ); - TupleBrowser browser = rootPage.find( bTreeHeight, key ); - - if ( browser.getNext( tuple ) ) - { - // find returns the matching key or the next ordered key, so we must - // check if we have an exact match - if ( comparator.compare( key, tuple.getKey() ) != 0 ) + + try + { + tuple = new Tuple( null, null ); + + browser = browse( key ); + + if ( browser.getNext( tuple ) ) { - return null; + // find returns the matching key or the next ordered key, so we must + // check if we have an exact match + if ( comparator.compare( key, tuple.getKey() ) != 0 ) + { + return null; + } + else + { + return this.copyValue( tuple.getValue() ); + } } else { - return tuple.getValue(); + return null; } } - else + finally { - return null; + if ( browser != null ) + { + browser.close(); + } + + if ( !isActionCapable ) + { + bigLock.unlock(); + } } + } @@ -441,10 +592,10 @@ public class BTree implements Exte * @return Value associated with the key, or a greater entry, or null if no * greater entry was found. */ - public synchronized Tuple findGreaterOrEqual( K key ) throws IOException + public Tuple findGreaterOrEqual( K key ) throws IOException { Tuple tuple; - TupleBrowser browser; + TupleBrowser browser = null; if ( key == null ) { @@ -453,16 +604,38 @@ public class BTree implements Exte return null; } + if ( !isActionCapable ) + { + bigLock.lock(); + } + tuple = new Tuple( null, null ); - browser = browse( key ); - if ( browser.getNext( tuple ) ) + try { - return tuple; + browser = browse( key ); + + if ( browser.getNext( tuple ) ) + { + tuple.setValue( this.copyValue( tuple.getValue() ) ); + return tuple; + } + else + { + return null; + } } - else + finally { - return null; + if ( browser != null ) + { + browser.close(); + } + + if ( !isActionCapable ) + { + bigLock.unlock(); + } } } @@ -476,17 +649,31 @@ public class BTree implements Exte * * @return Browser positionned at the beginning of the BTree. */ - public synchronized TupleBrowser browse() throws IOException + public TupleBrowser browse() throws IOException { - BPage rootPage = getRoot(); + TupleBrowser browser = null; + ActionContext context = this.beginAction( true, "browse" ); - if ( rootPage == null ) + try { - return new EmptyBrowser(){}; + MetaRoot meta = this.getMetaRoot(); + BPage rootPage = this.getRoot( meta ); + + if ( rootPage == null ) + { + this.endAction( context ); + return new EmptyBrowser(){}; + } + + browser = rootPage.findFirst( context ); + } + catch( IOException e ) + { + this.abortAction( context ); + throw e; } - TupleBrowser browser = rootPage.findFirst(); - + this.unsetAsCurrentAction( context ); return browser; } @@ -503,19 +690,34 @@ public class BTree implements Exte * (Null is considered to be an "infinite" key) * @return Browser positioned just before the given key. */ - public synchronized TupleBrowser browse( K key ) throws IOException + public TupleBrowser browse( K key ) throws IOException { - BPage rootPage = getRoot(); + TupleBrowser browser = null; + ActionContext context = this.beginAction( true, "browse key" ); - if ( rootPage == null ) + try { - return new EmptyBrowser(){}; + MetaRoot meta = this.getMetaRoot(); + BPage rootPage = this.getRoot( meta ); + + if ( rootPage == null ) + { + this.endAction( context ); + return new EmptyBrowser(){}; + } + + browser = rootPage.find( meta.treeHeight, key, context ); + } + catch( IOException e ) + { + this.abortAction( context ); + throw e; } - TupleBrowser browser = rootPage.find( bTreeHeight, key ); - + this.unsetAsCurrentAction( context ); return browser; } + /** @@ -537,23 +739,65 @@ public class BTree implements Exte /** - * Return the root BPage, or null if it doesn't exist. + * @return the root BPage, or null if it doesn't exist. + */ + BPage getRoot( ) throws IOException + { + assert( this.rootId == metaRoot.rootID) : "Stale root id " + this.rootId + " "+ metaRoot.rootID; + + if ( this.rootId == 0 ) + { + return null; + } + + BPage root = ( BPage ) recordManager.fetch( this.rootId, bpageSerializer ); + root.setRecordId( this.rootId ); + root.btree = this; + + return root; + } + + + /** + * @param meta The root to search for + * + * @return the root BPage, or null if it doesn't exist. */ - private BPage getRoot() throws IOException + BPage getRoot( MetaRoot meta ) throws IOException { - if ( rootId == 0 ) + if ( meta.rootID == 0 ) { return null; } - BPage root = ( BPage ) recordManager.fetch( rootId, bpageSerializer ); - root.setRecordId( rootId ); + BPage root = ( BPage ) recordManager.fetch( meta.rootID, bpageSerializer ); + root.setRecordId( meta.rootID ); root.btree = this; return root; } - - + + + /** + * + * Returns the meta root that can be used to fetch the root page + * + * @return meta root The meta root to search for + * @throws IOException If we had an exception during the fetch operation + */ + MetaRoot getMetaRoot() throws IOException + { + if ( isActionCapable ) + { + return ( MetaRoot )recordManager.fetch( -this.recordId ); + } + else + { + return metaRoot; + } + } + + /** * Implement Externalizable interface. */ @@ -616,6 +860,151 @@ public class BTree implements Exte } + void setAsCurrentAction( ActionContext context ) + { + if ( context != null ) + { + assert( isActionCapable == true ); + ( ( ActionRecordManager )recordManager ).setCurrentActionContext( context ); + } + } + + + void unsetAsCurrentAction( ActionContext context ) + { + if ( context != null ) + { + assert( isActionCapable == true ); + ( ( ActionRecordManager )recordManager ).unsetCurrentActionContext( context ); + } + } + + + ActionContext beginAction( boolean readOnly, String whoStarted ) + { + ActionContext context = null; + + if ( isActionCapable ) + { + context = ( ( ActionRecordManager )recordManager ).beginAction( readOnly, whoStarted ); + } + + return context; + } + + + void endAction( ActionContext context ) + { + if ( context != null ) + { + assert( isActionCapable ); + ( ( ActionRecordManager )recordManager ).endAction( context ); + } + } + + + void abortAction( ActionContext context ) + { + if ( context != null ) + { + assert( isActionCapable ); + ( ( ActionRecordManager )recordManager ).abortAction( context ); + } + + } + + + BPage copyOnWrite( BPage page) throws IOException + { + return page.copyOnWrite(); + + } + + + private MetaRoot copyOnWrite( MetaRoot oldMetaRoot ) + { + MetaRoot newMetaRoot = new MetaRoot(); + newMetaRoot.rootID = oldMetaRoot.rootID; + newMetaRoot.treeHeight = oldMetaRoot.treeHeight; + + return newMetaRoot; + } + + + private void updateMetaRoot( long newRootId, int newTreeHeight ) throws IOException + { + metaRoot = this.copyOnWrite( metaRoot ); + metaRoot.rootID = newRootId; + metaRoot.treeHeight = newTreeHeight; + + if ( isActionCapable ) + { + recordManager.update( -this.recordId, metaRoot ); + } + } + + + V copyValue( V value) throws IOException + { + byte[] array; + V valueCopy = null; + + if ( this.valueSerializer != null ) + { + array = this.valueSerializer.serialize( value ); + valueCopy = (V) this.valueSerializer.deserialize( array ); + } + else + { + ObjectOutputStream out = null; + ObjectInputStream in = null; + ByteArrayOutputStream bout = null; + ByteArrayInputStream bin = null; + + try + { + bout = new ByteArrayOutputStream(); + out = new ObjectOutputStream( bout ); + out.writeObject( value ); + out.flush(); + byte[] arr = bout.toByteArray(); + bin = new ByteArrayInputStream( arr ); + in =new ObjectInputStream( bin ); + valueCopy = ( V )in.readObject(); + } + catch ( ClassNotFoundException e ) + { + throw new WrappedRuntimeException( e ); + } + finally + { + if ( bout != null ) + { + bout.close(); + } + + if ( out != null ) + { + out.close(); + } + + if ( bin != null ) + { + bin.close(); + } + + if ( in != null ) + { + in.close(); + } + } + + } + + return valueCopy; + } + + public String toString() { StringBuilder sb = new StringBuilder(); @@ -662,4 +1051,14 @@ public class BTree implements Exte return sb.toString(); } + + /** + * Used to point to the root page that the reader needs based on the reader's + * read action context. ReadWrite actions always use the latest root. + */ + class MetaRoot + { + long rootID; + int treeHeight; + } } Modified: directory/apacheds/trunk/jdbm/src/main/java/jdbm/helper/TupleBrowser.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm/src/main/java/jdbm/helper/TupleBrowser.java?rev=1164182&r1=1164181&r2=1164182&view=diff ============================================================================== --- directory/apacheds/trunk/jdbm/src/main/java/jdbm/helper/TupleBrowser.java (original) +++ directory/apacheds/trunk/jdbm/src/main/java/jdbm/helper/TupleBrowser.java Thu Sep 1 17:34:03 2011 @@ -73,4 +73,11 @@ public abstract class TupleBrowser * no previous tuple. */ public abstract boolean getPrevious( Tuple tuple ) throws IOException; + + + /** + * Closes the browser and deallocates any resources it might have allocated. + * Repeated calls of close are OK. + */ + public void close() {} } Modified: directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BaseRecordManager.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BaseRecordManager.java?rev=1164182&r1=1164181&r2=1164182&view=diff ============================================================================== --- directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BaseRecordManager.java (original) +++ directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BaseRecordManager.java Thu Sep 1 17:34:03 2011 @@ -51,6 +51,10 @@ package jdbm.recman; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import jdbm.RecordManager; import jdbm.helper.DefaultSerializer; @@ -80,8 +84,7 @@ import org.apache.directory.server.i18n. * @author Alex Boisvert * @author Cees de Groot */ -public final class BaseRecordManager - implements RecordManager +public final class BaseRecordManager implements RecordManager { /** Underlying record recordFile. */ private RecordFile recordFile; @@ -107,6 +110,102 @@ public final class BaseRecordManager * the NAME_DIRECTORY_ROOT. */ private Map nameDirectory; + + private static enum IOType + { + READ_IO, + WRITE_IO + } + + /** TODO add asserts to check internal consistency */ + private static class LockElement + { + private int readers; + private int waiters; + private boolean writer; + + private Lock lock = new ReentrantLock(); + private Condition cv = lock.newCondition(); + + + public boolean anyReaders() + { + return readers > 0; + } + + + public boolean anyWaiters() + { + return waiters > 0; + } + + + public boolean beingWritten() + { + return writer; + } + + + public boolean anyUser() + { + return ( readers > 0 || waiters > 0 || writer ); + } + + + public void bumpReaders() + { + readers++; + } + + + public void decrementReaders() + { + readers--; + } + + + public void bumpWaiters() + { + waiters++; + } + + + public void decrementWaiters() + { + waiters--; + } + + + public void setWritten() + { + writer = true; + } + + + public void unsetWritten() + { + writer = false; + } + + + public Lock getLock() + { + return lock; + } + + + public Condition getNoConflictingIOCondition() + { + return cv; + } + } + + + /** + * Map used to synchronize reads and writes on the same logical + * recid. + */ + private final ConcurrentHashMap lockElements; /** @@ -121,13 +220,14 @@ public final class BaseRecordManager pageMgr = new PageManager( recordFile ); physMgr = new PhysicalRowIdManager( pageMgr ); logMgr = new LogicalRowIdManager( pageMgr ); + lockElements = new ConcurrentHashMap(); } /** * Get the underlying Transaction Manager */ - public synchronized TransactionManager getTransactionManager() throws IOException + public TransactionManager getTransactionManager() throws IOException { checkIfClosed(); return recordFile.getTxnMgr(); @@ -143,7 +243,7 @@ public final class BaseRecordManager * Only call this method directly after opening the file, otherwise * the results will be undefined. */ - public synchronized void disableTransactions() + public void disableTransactions() { checkIfClosed(); recordFile.disableTransactions(); @@ -155,7 +255,7 @@ public final class BaseRecordManager * * @throws IOException when one of the underlying I/O operations fails. */ - public synchronized void close() throws IOException + public void close() throws IOException { checkIfClosed(); @@ -188,7 +288,7 @@ public final class BaseRecordManager * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ - public synchronized long insert( Object obj, Serializer serializer ) throws IOException + public long insert( Object obj, Serializer serializer ) throws IOException { byte[] data; long recid; @@ -215,8 +315,9 @@ public final class BaseRecordManager * @param recid the rowid for the record that should be deleted. * @throws IOException when one of the underlying I/O operations fails. */ - public synchronized void delete( long recid ) throws IOException + public void delete( long recid ) throws IOException { + LockElement element; checkIfClosed(); if ( recid <= 0 ) @@ -229,10 +330,20 @@ public final class BaseRecordManager System.out.println( "BaseRecordManager.delete() recid " + recid ) ; } - Location logRowId = new Location( recid ); - Location physRowId = logMgr.fetch( logRowId ); - physMgr.delete( physRowId ); - logMgr.delete( logRowId ); + + element = this.beginIO(recid, IOType.WRITE_IO); + + try + { + Location logRowId = new Location( recid ); + Location physRowId = logMgr.fetch( logRowId ); + physMgr.delete( physRowId ); + logMgr.delete( logRowId ); + } + finally + { + this.endIO(recid, element, IOType.WRITE_IO); + } } @@ -247,8 +358,8 @@ public final class BaseRecordManager { update( recid, obj, DefaultSerializer.INSTANCE ); } - + /** * Updates a record using a custom serializer. * @@ -257,8 +368,10 @@ public final class BaseRecordManager * @param serializer a custom serializer * @throws IOException when one of the underlying I/O operations fails. */ - public synchronized void update( long recid, Object obj, Serializer serializer ) throws IOException + public void update( long recid, Object obj, Serializer serializer ) throws IOException { + LockElement element; + checkIfClosed(); if ( recid <= 0 ) @@ -266,24 +379,33 @@ public final class BaseRecordManager throw new IllegalArgumentException( I18n.err( I18n.ERR_536, recid ) ); } - Location logRecid = new Location( recid ); - Location physRecid = logMgr.fetch( logRecid ); - - byte[] data = serializer.serialize( obj ); - - if ( DEBUG ) - { - System.out.println( "BaseRecordManager.update() recid " + recid + " length " + data.length ) ; - } - - Location newRecid = physMgr.update( physRecid, data, 0, data.length ); - - if ( ! newRecid.equals( physRecid ) ) - { - logMgr.update( logRecid, newRecid ); - } + element = this.beginIO(recid, IOType.WRITE_IO); + + try + { + Location logRecid = new Location( recid ); + Location physRecid = logMgr.fetch( logRecid ); + + byte[] data = serializer.serialize( obj ); + + if ( DEBUG ) + { + System.out.println( "BaseRecordManager.update() recid " + recid + " length " + data.length ) ; + } + + Location newRecid = physMgr.update( physRecid, data, 0, data.length ); + + if ( ! newRecid.equals( physRecid ) ) + { + logMgr.update( logRecid, newRecid ); + } + } + finally + { + this.endIO(recid, element, IOType.WRITE_IO); + } } - + /** * Fetches a record using standard java object serialization. @@ -297,7 +419,7 @@ public final class BaseRecordManager return fetch( recid, DefaultSerializer.INSTANCE ); } - + /** * Fetches a record using a custom serializer. * @@ -306,26 +428,40 @@ public final class BaseRecordManager * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ - public synchronized Object fetch( long recid, Serializer serializer ) - throws IOException + public Object fetch( long recid, Serializer serializer ) throws IOException { - byte[] data; - + Object result; + LockElement element; + checkIfClosed(); - + if ( recid <= 0 ) { throw new IllegalArgumentException( I18n.err( I18n.ERR_536, recid ) ); } - data = physMgr.fetch( logMgr.fetch( new Location( recid ) ) ); + element = this.beginIO(recid, IOType.READ_IO); - if ( DEBUG ) + try + { + byte[] data; + + data = physMgr.fetch( logMgr.fetch( new Location( recid ) ) ); + + if ( DEBUG ) + { + System.out.println( "BaseRecordManager.fetch() recid " + recid + " length " + data.length ) ; + } + + result = serializer.deserialize( data ); + } + finally { - System.out.println( "BaseRecordManager.fetch() recid " + recid + " length " + data.length ) ; + this.endIO(recid, element, IOType.READ_IO); } - return serializer.deserialize( data ); + + return result; } @@ -346,7 +482,7 @@ public final class BaseRecordManager * * @see #getRootCount */ - public synchronized long getRoot( int id ) throws IOException + public long getRoot( int id ) throws IOException { checkIfClosed(); @@ -359,7 +495,7 @@ public final class BaseRecordManager * * @see #getRootCount */ - public synchronized void setRoot( int id, long rowid ) throws IOException + public void setRoot( int id, long rowid ) throws IOException { checkIfClosed(); @@ -403,6 +539,7 @@ public final class BaseRecordManager { getNameDirectory().put( name, recid ); } + saveNameDirectory( ); } @@ -410,8 +547,7 @@ public final class BaseRecordManager /** * Commit (make persistent) all changes since beginning of transaction. */ - public synchronized void commit() - throws IOException + public void commit() throws IOException { checkIfClosed(); @@ -422,7 +558,7 @@ public final class BaseRecordManager /** * Rollback (cancel) all changes since beginning of transaction. */ - public synchronized void rollback() throws IOException + public void rollback() throws IOException { checkIfClosed(); @@ -477,4 +613,163 @@ public final class BaseRecordManager throw new IllegalStateException( I18n.err( I18n.ERR_538 ) ); } } + + + /** + * Used to serialize reads/write on a given logical rowid. Checks if there is a + * ongoing conflicting IO to the same logical rowid and waits for the ongoing + * write if there is one. + * + * @param recid the logical rowid for which the fetch will be done. + * @param io type of the IO + * @return lock element representing the logical lock gotten + */ + private LockElement beginIO( Long recid, IOType io ) + { + boolean lockVerified = false; + LockElement element = null; + + // loop until we successfully verify that there is no concurrent writer +/* + element = lockElements.get( recid ); + + do + { + if ( element == null ) + { + element = new LockElement(); + + if ( io == IOType.READ_IO ) + { + element.bumpReaders(); + } + else + { + element.setWritten(); + } + + LockElement existingElement = lockElements.putIfAbsent( recid, element ); + + if ( existingElement == null ) + { + lockVerified = true; + } + else + { + element = existingElement; + } + } + else + { + Lock lock = element.getLock(); + lock.lock(); + + if ( element.anyUser() ) + { + if ( this.conflictingIOPredicate( io, element ) ) + { + element.bumpWaiters(); + + do + { + element.getNoConflictingIOCondition() + .awaitUninterruptibly(); + } + while ( this.conflictingIOPredicate( io, element ) ); + + element.decrementWaiters(); + } + + // no conflicting IO anymore..done + if ( io == IOType.READ_IO ) + { + element.bumpReaders(); + } + else + { + element.setWritten(); + } + + lockVerified = true; + } + else + { + if ( io == IOType.READ_IO ) + { + element.bumpReaders(); + } + else + { + element.setWritten(); + } + + LockElement existingElement = lockElements.get( recid ); + + if ( element != existingElement ) + { + element = existingElement; + } + else + { + lockVerified = true; // done + } + } + + lock.unlock(); + } + } + while ( !lockVerified ); +*/ + return element; + } + + + /** + * Ends the IO by releasing the logical lock on the given recid + * + * @param recid logical recid for which the IO is being ended + * @param element logical lock to be released + * @param io type of the io + */ + private void endIO( Long recid, LockElement element, IOType io ) + { + /* + Lock lock = element.getLock(); + lock.lock(); + + if ( io == IOType.READ_IO ) + { + element.decrementReaders(); + } + else + { + element.unsetWritten(); + } + + if ( element.anyWaiters() ) + { + element.getNoConflictingIOCondition().notifyAll(); + } + + if ( !element.anyUser() ) + { + lockElements.remove( recid ); + } + + lock.unlock(); + */ + } + + + private boolean conflictingIOPredicate( IOType io, LockElement element ) + { + if ( io == IOType.READ_IO ) + { + return element.beingWritten(); + } + else + { + return ( element.anyReaders() || element.beingWritten() ); + } + } } Modified: directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BlockIo.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BlockIo.java?rev=1164182&r1=1164181&r2=1164182&view=diff ============================================================================== --- directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BlockIo.java (original) +++ directory/apacheds/trunk/jdbm/src/main/java/jdbm/recman/BlockIo.java Thu Sep 1 17:34:03 2011 @@ -52,6 +52,7 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.concurrent.atomic.AtomicInteger; + import org.apache.directory.server.i18n.I18n; Propchange: directory/apacheds/trunk/ldap-client-test/ ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -0,0 +1 @@ +/directory/apacheds/branches/apacheds-jdbm/ldap-client-test:1160768-1164092 Propchange: directory/apacheds/trunk/ldif-partition/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -1,6 +1,7 @@ /directory/apacheds/branches/apacheds-codec-merge/ldif-partition:982369-987590 /directory/apacheds/branches/apacheds-config/ldif-partition:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/ldif-partition:980138-980936 +/directory/apacheds/branches/apacheds-jdbm/ldif-partition:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/ldif-partition:1040956-1043765 /directory/apacheds/branches/milestones/ldif-partition:1072812-1075328 /directory/apacheds/trunk/ldif-partition:1066126-1067785,1068026-1072718,1072800-1075329 Propchange: directory/apacheds/trunk/protocol-ldap/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -2,6 +2,7 @@ /directory/apacheds/branches/apacheds-codec-merge/protocol-ldap:982369-987590 /directory/apacheds/branches/apacheds-config/protocol-ldap:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/protocol-ldap:980138-980936 +/directory/apacheds/branches/apacheds-jdbm/protocol-ldap:1160768-1164080 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/protocol-ldap:1040956-1043765 /directory/apacheds/branches/milestones/protocol-ldap:1072812-1075328 /directory/apacheds/trunk/protocol-ldap:1066126-1067785,1068026-1072718,1072800-1075329 Propchange: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/consumer/ReplicationConsumerImpl.java ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -2,6 +2,7 @@ /directory/apacheds/branches/apacheds-codec-merge/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConsumer.java:982369-987590 /directory/apacheds/branches/apacheds-config/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConsumer.java:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConsumer.java:980138-980936 +/directory/apacheds/branches/apacheds-jdbm/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/consumer/ReplicationConsumerImpl.java:1160768-1164080 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConsumer.java:1040956-1043765 /directory/apacheds/branches/apacheds-replication/syncrepl/src/main/java/org/apache/directory/server/syncrepl/SyncReplConsumer.java:749790-762530 /directory/apacheds/branches/apacheds-schema/syncrepl/src/main/java/org/apache/directory/server/syncrepl/SyncReplConsumer.java:806623-896441 Propchange: directory/apacheds/trunk/protocol-shared/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -1,6 +1,7 @@ /directory/apacheds/branches/apacheds-codec-merge/protocol-shared:982369-987590 /directory/apacheds/branches/apacheds-config/protocol-shared:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/protocol-shared:980138-980936 +/directory/apacheds/branches/apacheds-jdbm/protocol-shared:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/protocol-shared:1040956-1043765 /directory/apacheds/branches/milestones/protocol-shared:1072812-1075328 /directory/apacheds/trunk/protocol-shared:1066126-1067785,1068026-1072718,1072800-1075329 Propchange: directory/apacheds/trunk/server-annotations/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -1,6 +1,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-annotations:982369-987590 /directory/apacheds/branches/apacheds-config/server-annotations:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-annotations:980138-980937 +/directory/apacheds/branches/apacheds-jdbm/server-annotations:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-annotations:1040956-1043765 /directory/apacheds/branches/milestones/server-annotations:1072812-1075328 /directory/apacheds/trunk/server-annotations:1066126-1067785,1068026-1072718,1072800-1075329 Propchange: directory/apacheds/trunk/server-config/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -2,6 +2,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-config:982369-987590 /directory/apacheds/branches/apacheds-config/server-config:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-config:980138-980938 +/directory/apacheds/branches/apacheds-jdbm/server-config:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-config:1040956-1043765 /directory/apacheds/branches/milestones/server-config:1072812-1075328 /directory/apacheds/branches/server-config-annotations/server-config:1042727-1043868 Propchange: directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionReader.java ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -2,6 +2,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionReader.java:982369-987590 /directory/apacheds/branches/apacheds-config/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionReader.java:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionReader.java:980138-980938 +/directory/apacheds/branches/apacheds-jdbm/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionReader.java:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-config/src/main/java/org/apache/directory/server/config/ConfigPartitionReader.java:1040956-1043765 /directory/apacheds/branches/apacheds-replication/core-annotations/src/main/java/org/apache/directory/server/core/factory/ConfigPartitionReader.java:749790-764110 /directory/apacheds/branches/apacheds-schema/core-annotations/src/main/java/org/apache/directory/server/core/factory/ConfigPartitionReader.java:806623-896441 Propchange: directory/apacheds/trunk/server-config/src/main/resources/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -3,6 +3,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-config/src/main/resources:982369-987590 /directory/apacheds/branches/apacheds-config/server-config/src/main/resources:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-config/src/main/resources:980138-980938 +/directory/apacheds/branches/apacheds-jdbm/server-config/src/main/resources:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-config/src/main/resources:1040956-1043765 /directory/apacheds/branches/apacheds-replication/core-annotations/src/main/resources:749790-764110 /directory/apacheds/branches/apacheds-replication/default-config/src/main/resources:749790-764110 Propchange: directory/apacheds/trunk/server-config/src/test/java/org/apache/directory/server/config/ConfigPartitionReaderTest.java ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -3,6 +3,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-config/src/test/java/org/apache/directory/server/config/ConfigPartitionReaderTest.java:982369-987590 /directory/apacheds/branches/apacheds-config/server-config/src/test/java/org/apache/directory/server/config/ConfigPartitionReaderTest.java:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-config/src/test/java/org/apache/directory/server/config/ConfigPartitionReaderTest.java:980138-980938 +/directory/apacheds/branches/apacheds-jdbm/server-config/src/test/java/org/apache/directory/server/config/ConfigPartitionReaderTest.java:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-config/src/test/java/org/apache/directory/server/config/ConfigPartitionReaderTest.java:1040956-1043765 /directory/apacheds/branches/apacheds-replication/core-annotations/src/main/java/org/apache/directory/server/core/factory/CiDITDirectoryServiceFactory.java:749790-764110 /directory/apacheds/branches/apacheds-schema/core-annotations/src/main/java/org/apache/directory/server/core/factory/CiDITDirectoryServiceFactory.java:806623-896441 Propchange: directory/apacheds/trunk/server-integ/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -2,6 +2,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-integ:982369-987590 /directory/apacheds/branches/apacheds-config/server-integ:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-integ:980138-980937 +/directory/apacheds/branches/apacheds-jdbm/server-integ:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-integ:1040956-1043765 /directory/apacheds/branches/milestones/server-integ:1072812-1075328 /directory/apacheds/trunk/server-integ:1066126-1067785,1068026-1072718,1072800-1075329 Modified: directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/StoredProcedureIT.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/StoredProcedureIT.java?rev=1164182&r1=1164181&r2=1164182&view=diff ============================================================================== --- directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/StoredProcedureIT.java (original) +++ directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/StoredProcedureIT.java Thu Sep 1 17:34:03 2011 @@ -50,6 +50,7 @@ import org.apache.directory.shared.ldap. import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.Ignore; /** @@ -98,6 +99,7 @@ public class StoredProcedureIT extends A } + @Ignore @Test public void testExecuteProcedureWithReturnValue() throws Exception { @@ -109,6 +111,7 @@ public class StoredProcedureIT extends A } + @Ignore @Test public void testExecuteProcedureWithParametersAndReturnValue() throws Exception { Modified: directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/replication/ClientServerReplicationIT.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/replication/ClientServerReplicationIT.java?rev=1164182&r1=1164181&r2=1164182&view=diff ============================================================================== --- directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/replication/ClientServerReplicationIT.java (original) +++ directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/replication/ClientServerReplicationIT.java Thu Sep 1 17:34:03 2011 @@ -120,6 +120,7 @@ public class ClientServerReplicationIT if ( entry.getDn().equals( entryDn ) ) { System.out.println( "The searched entry exists !!!" ); + System.out.println( "found Entry " + entry.getDn().getNormName() + " exists, entrtyUuid = " + entry.get( "entryUuid" ) ); break; } Propchange: directory/apacheds/trunk/server-jndi/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -1,6 +1,7 @@ /directory/apacheds/branches/apacheds-codec-merge/server-jndi:982369-987590 /directory/apacheds/branches/apacheds-config/server-jndi:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/server-jndi:980138-980937 +/directory/apacheds/branches/apacheds-jdbm/server-jndi:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/server-jndi:1040956-1043765 /directory/apacheds/branches/milestones/server-jndi:1072812-1075328 /directory/apacheds/trunk/server-jndi:1066126-1067785,1068026-1072718,1072800-1075329 Propchange: directory/apacheds/trunk/service/ ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -0,0 +1 @@ +/directory/apacheds/branches/apacheds-jdbm/service:1160768-1164092 Propchange: directory/apacheds/trunk/xdbm-partition/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -1,6 +1,7 @@ /directory/apacheds/branches/apacheds-codec-merge/xdbm-partition:982369-987590 /directory/apacheds/branches/apacheds-config/xdbm-partition:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/xdbm-partition:980138-980938 +/directory/apacheds/branches/apacheds-jdbm/xdbm-partition:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/xdbm-partition:1040956-1043765 /directory/apacheds/branches/milestones/xdbm-partition:1072812-1075328 /directory/apacheds/trunk/xdbm-partition:1066126-1067785,1068026-1072718,1072800-1075329 Propchange: directory/apacheds/trunk/xdbm-tools/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Sep 1 17:34:03 2011 @@ -1,6 +1,7 @@ /directory/apacheds/branches/apacheds-codec-merge/xdbm-tools:982369-987590 /directory/apacheds/branches/apacheds-config/xdbm-tools:1023442-1029077 /directory/apacheds/branches/apacheds-dnfactory-experiment/xdbm-tools:980138-980938 +/directory/apacheds/branches/apacheds-jdbm/xdbm-tools:1160768-1164092 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/xdbm-tools:1040956-1043765 /directory/apacheds/branches/milestones/xdbm-tools:1072812-1075328 /directory/apacheds/trunk/xdbm-tools:1066126-1067785,1068026-1072718,1072800-1075329