[maven-release-plugin]  copy for tag 2.0.0-M3

git-svn-id: https://svn.apache.org/repos/asf/directory/apacheds/tags/2.0.0-M3@1167194 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
index 7476c4c..eb7822f 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -24,7 +24,7 @@
   <parent>
     <groupId>org.apache.directory.server</groupId>
     <artifactId>apacheds-parent</artifactId>
-    <version>1.5.8-SNAPSHOT</version>
+    <version>2.0.0-M3-SNAPSHOT</version>
   </parent>
   <artifactId>apacheds-benchmarks</artifactId>
   <name>ApacheDS Benchmarks</name>
diff --git a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.bat b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.bat
index 2273ae6..c793744 100644
--- a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.bat
+++ b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.bat
@@ -35,7 +35,7 @@
 

 DEF_CTRLS="-Ddefault.controls=org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory"

 

-EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncModifyDnFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"

+EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"

 

 DEF_EXT_OP_REQ="-Ddefault.extendedOperation.requests=org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory"

 

diff --git a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh
index 962b721..2232d39 100644
--- a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh
+++ b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh
@@ -62,7 +62,7 @@
 
 DEF_CTRLS="-Ddefault.controls=org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory"
 
-EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncModifyDnFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"
+EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"
 
 DEF_EXT_OP_REQ="-Ddefault.extendedOperation.requests=org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory"
 
diff --git a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/wrapper-installation.conf b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/wrapper-installation.conf
index 89e1a21..1821890 100644
--- a/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/wrapper-installation.conf
+++ b/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/wrapper-installation.conf
@@ -36,7 +36,7 @@
 wrapper.java.additional.4=-Dapacheds.run.dir=${double.quote}%INSTANCE_DIRECTORY%/run${double.quote}
 wrapper.java.additional.5=-Dapacheds.instance=${double.quote}%INSTANCE%${double.quote}
 wrapper.java.additional.6=-Ddefault.controls=${double.quote}org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory${double.quote}
-wrapper.java.additional.7=-Dextra.controls=${double.quote}org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncModifyDnFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory${double.quote}
+wrapper.java.additional.7=-Dextra.controls=${double.quote}org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory${double.quote}
 wrapper.java.additional.8=-Ddefault.extendedOperation.requests=${double.quote}org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory${double.quote}
 wrapper.java.additional.9=-Ddefault.extendedOperation.responses=${double.quote}org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory${double.quote}
 
diff --git a/jdbm/src/main/java/jdbm/btree/BPage.java b/jdbm/src/main/java/jdbm/btree/BPage.java
index 2af8474..2be2f2a 100644
--- a/jdbm/src/main/java/jdbm/btree/BPage.java
+++ b/jdbm/src/main/java/jdbm/btree/BPage.java
@@ -221,10 +221,14 @@
         newPage.recordId = this.recordId;
         
         if ( this.children != null )
+        {
             this.copyChildren( this, 0, newPage, 0, btree.pageSize ); // this copies keys as well
+        }
         
-        if (this.values != null ) 
+        if (this.values != null )
+        {
             this.copyEntries( this, 0, newPage, 0, btree.pageSize ); // this copies keys as well
+        }
         
         return newPage;
     }
@@ -401,7 +405,7 @@
                 
                 if ( replace )
                 {
-                    pageNewCopy.values[index] = value;
+                    pageNewCopy.values[index] = btree.copyValue( value );
                     btree.recordManager.update( recordId, pageNewCopy, this );
                 }
                 
@@ -956,10 +960,10 @@
     /**
      * Set the entry at the given index.
      */
-    private void setEntry( BPage<K, V> page, int index, K key, V value )
+    private void setEntry( BPage<K, V> page, int index, K key, V value ) throws IOException
     {
         page.keys[index] = key;
-        page.values[index] = value;
+        page.values[index] = btree.copyValue( value );
     }
 
 
@@ -1494,7 +1498,9 @@
             finally
             {
                 if ( context != null )
+                {
                     btree.unsetAsCurrentAction( context );
+                }
             }
           
             return true;
@@ -1502,7 +1508,8 @@
 
         public boolean getPrevious( Tuple<K, V> tuple ) throws IOException
         {
-            btree.setAsCurrentAction( context );           
+            btree.setAsCurrentAction( context );
+            
             try
             {
                 if ( index == page.first )
@@ -1514,7 +1521,7 @@
                     }
                     else
                     {
-                        // reached beginning of the tree                                                             
+                        // reached beginning of the tree
                         return false;
                     }
                 }
@@ -1533,8 +1540,10 @@
             finally
             {
                 if ( context != null )
+                {
                     btree.unsetAsCurrentAction( context );
-            }          
+                }
+            }
 
             return true;
         }
@@ -1552,6 +1561,7 @@
             }
             
             int browserCount = outstandingBrowsers.decrementAndGet();
+            
             if ( browserCount > 0 )
             {
                 //System.out.println( "JDBM btree browsers are outstanding after close: " + browserCount );
diff --git a/jdbm/src/main/java/jdbm/btree/BTree.java b/jdbm/src/main/java/jdbm/btree/BTree.java
index b498e6a..c51ef6a 100644
--- a/jdbm/src/main/java/jdbm/btree/BTree.java
+++ b/jdbm/src/main/java/jdbm/btree/BTree.java
@@ -949,6 +949,12 @@
         byte[] array;
         V valueCopy = null;
         
+        
+        if ( value == null )
+        {
+            return null;
+        }
+        
         if ( this.valueSerializer != null )
         {
             array = this.valueSerializer.serialize( value );
@@ -969,7 +975,7 @@
                 out.flush();
                 byte[]  arr = bout.toByteArray();
                 bin = new ByteArrayInputStream( arr );
-                in =new ObjectInputStream( bin );
+                in = new ObjectInputStream( bin );
                 valueCopy = ( V )in.readObject();
             }
             catch ( ClassNotFoundException e )
diff --git a/jdbm/src/main/java/jdbm/helper/ActionContext.java b/jdbm/src/main/java/jdbm/helper/ActionContext.java
index a59406d..8e2177a 100644
--- a/jdbm/src/main/java/jdbm/helper/ActionContext.java
+++ b/jdbm/src/main/java/jdbm/helper/ActionContext.java
@@ -45,7 +45,7 @@
     
     public void endAction()
     {
-        assert( version != null );
+        assert( version != null ) : "Unexpected action state during endAction: " + this;
         version = null;
     }
     
@@ -78,4 +78,17 @@
     {
         return whoStarted;
     }
+    
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append( "ActionContext: " );
+        sb.append( "(readOnly: " ).append( readOnly );
+        sb.append( ", version: " ).append( version );
+        sb.append( ", whoStarted: " ).append( whoStarted );
+        sb.append( ")\n" );
+        
+        return sb.toString();
+    }
 }
diff --git a/jdbm/src/main/java/jdbm/helper/ActionVersioning.java b/jdbm/src/main/java/jdbm/helper/ActionVersioning.java
index f50bcc6..6899c6f 100644
--- a/jdbm/src/main/java/jdbm/helper/ActionVersioning.java
+++ b/jdbm/src/main/java/jdbm/helper/ActionVersioning.java
@@ -153,7 +153,7 @@
     {
         long numActions = version.getNumActions().decrementAndGet();
         
-        assert( numActions >= 0 );
+        assert( numActions >= 0 ) : "NumActions zero when read action is ended : " + version;
         
         if ( ( numActions > 0 ) || ( version == readReference.get() ) )
         {
@@ -216,5 +216,17 @@
         {
             return version;
         }
+        
+        @Override
+        public String toString()
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append( "Version: ");
+            sb.append( "(vesion: " ).append( version );
+            sb.append( ", numActions: " ).append( numActions );
+            sb.append( ")\n" );
+            
+            return sb.toString();
+        }
     }
 }
\ No newline at end of file
diff --git a/jdbm/src/main/java/jdbm/helper/ExplicitList.java b/jdbm/src/main/java/jdbm/helper/ExplicitList.java
index bd60dc8..bc92c21 100644
--- a/jdbm/src/main/java/jdbm/helper/ExplicitList.java
+++ b/jdbm/src/main/java/jdbm/helper/ExplicitList.java
@@ -31,8 +31,10 @@
 public class ExplicitList<T>
 {
 
-    Link<T> head = new Link<T>( null );
+    private Link<T> head = new Link<T>( null );
 
+    private int listSize = 0;
+    
     public static class Link<V>
     {
         private V element;
@@ -73,7 +75,7 @@
 
         public void remove()
         {
-            assert ( isLinked() );
+            assert( isLinked() ) : "Trying to remove from list an unlinked link";
             this.getPrev().setNext( this.getNext() );
             this.getNext().setPrev( this.getPrev() );
             this.reset();
@@ -82,6 +84,7 @@
 
         public void addAfter( Link<V> after )
         {
+            assert( this.isUnLinked() ) : "Trying to add to list already linked link: " + this;
             after.getNext().setPrev( this );
             this.setNext( after.getNext() );
             after.setNext( this );
@@ -91,6 +94,7 @@
 
         public void addBefore( Link<V> before )
         {
+            assert( this.isUnLinked() ) : "Trying to add to list already linked link: " + this;
             before.getPrev().setNext( this );
             this.setPrev( before.getPrev() );
             before.setPrev( this );
@@ -98,6 +102,11 @@
         }
 
 
+        /**
+         * Splices the given list by making this link as the new head.
+         *
+         * @param listHead head of the existing list
+         */
         public void splice( Link<V> listHead )
         {
             Link<V> prevLink = listHead.getPrev();
@@ -110,7 +119,7 @@
 
         public boolean isUnLinked()
         {
-            return ( prev == this && next == this );
+            return ( ( prev == this ) && ( next == this ) );
         }
 
 
@@ -129,7 +138,7 @@
 
         public void uninit()
         {
-            assert ( this.isUnLinked() );
+            assert ( this.isUnLinked() ) :  " Unitializing a still linked entry" + this;
             element = null;
         }
 
@@ -138,23 +147,39 @@
         {
             return this.element;
         }
+        
+        @Override
+        public String toString()
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append( "Link: " ).append( this ).append( " " );
+            sb.append( "(next: " ).append( next );
+            sb.append( ",prev: " ).append( prev ).append(")");            
+            sb.append( "\n" );
+            
+            return sb.toString();
+        }
     }
 
 
     public void remove( Link<T> link )
     {
+        assert( listSize > 0 ) : "Trying to remove link " + link + " from a list with no elements";
+        listSize--;
         link.remove();
     }
 
 
     public void addFirst( Link<T> link )
     {
+        listSize++;
         link.addAfter( head );
     }
 
 
     public void addLast( Link<T> link )
     {
+        listSize++;
         link.addBefore( head );
     }
 
@@ -169,5 +194,21 @@
     {
         return head;
     }
+    
+    public int size()
+    {
+        return listSize;
+    }
+    
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append( "List: " );
+        sb.append( "(size: " ).append( listSize ).append( ")" );
+        sb.append( "\n" );
+        
+        return sb.toString();
+    }
 
 }
\ No newline at end of file
diff --git a/jdbm/src/main/java/jdbm/helper/LRUCache.java b/jdbm/src/main/java/jdbm/helper/LRUCache.java
index 522637c..79d8b9d 100644
--- a/jdbm/src/main/java/jdbm/helper/LRUCache.java
+++ b/jdbm/src/main/java/jdbm/helper/LRUCache.java
@@ -1,4 +1,4 @@
-/*
+    /*
  *  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
@@ -65,7 +65,7 @@
     private final int numBuckets;
     
     /** Log of number of hash buckets each latch protects */
-    private final static int LOG_BUCKET_PER_LATCH = 3;
+    private final static int LOG_BUCKET_PER_LATCH = 0;
     
     /** Number of lrus */
     private final static int NUM_LRUS = 16;
@@ -74,7 +74,7 @@
     private final static int MIN_ENTRIES = 1 << 10;
     
     /** Max sleep time(in ms) for writes in case of cache eviction failure */
-    private final static long MAX_WRITE_SLEEP_TIME = 10000;
+    private final static long MAX_WRITE_SLEEP_TIME = 600000;
     
     /** lru list */
     LRU lrus[];
@@ -94,8 +94,18 @@
     /** minimum version cache has to satisfy during reads */
     private long minReadVersion;
     
-
-
+    /** Stats to keep track of cache gets */
+    private long cacheGets;
+    
+    /** Stats to keep track of cache hits for cache gets */
+    private long cacheMisses;
+    
+    /** Stats to keep track of cache puts */
+    private long cachePuts;
+    
+    /** Stats to keep track of # of times writes sleep for free cache entry */
+    private long cachePutSleeps;
+    
     @SuppressWarnings("unchecked") 
     public LRUCache( EntryIO<K, V> entryIO, int cacheSize )
     {
@@ -196,6 +206,8 @@
          * While reading or waiting, latch is released.
          */
         
+        this.cachePuts++;
+        
         while ( true )
         {
             latches[latchIndex].lock();
@@ -226,7 +238,19 @@
                             
                             if ( !entry.isCurrentVersion() )
                             {
-                                CacheEntry newEntry = this.findNewEntry( key, latchIndex );
+                                assert( entry.isNeverReplace() == false ) : " Non current entry should not have neverReplace set " + entry; 
+                                
+                                entry.setNeverReplace();
+                                CacheEntry newEntry = null;
+                                
+                                try
+                                {
+                                    newEntry = this.findNewEntry( key, hashIndex >> LOG_BUCKET_PER_LATCH );
+                                }
+                                finally
+                                {
+                                    entry.clearNeverReplace();
+                                }
                                 
                                 /*
                                  * Remove existing entry, chain as a snapshot
@@ -269,7 +293,7 @@
                             // FALLTHROUGH
                             
                         default:
-                            assert ( false );
+                            assert ( false ): "Unknown cache entry state: " + entry ;
                     }
                 }
                 else
@@ -287,6 +311,7 @@
                 
                 if ( sleepForFreeEntry == false )
                 {
+                    System.out.println(" NO cache entry for write " + totalSleepTime );
                     throw e;
                 }
             }
@@ -314,6 +339,11 @@
                 break;
             }
         }
+        
+        if ( totalSleepTime != 0 )
+        {  
+            this.cachePutSleeps++;
+        }
     }
     
     
@@ -346,6 +376,9 @@
          * 
          * While reading or waiting, latch is released.
          */
+        
+        this.cacheGets++;
+        
         latches[latchIndex].lock();
         boolean chainExists = false;
         
@@ -374,10 +407,26 @@
                         {
                             value = this.searchChainForVersion( entry, version );
                             
-                            if (value != null)
+                            if ( value != null )
+                            {
                                 break;
-                             
-                            CacheEntry newEntry = this.findNewEntry( key, latchIndex );
+                            }
+                            
+                            this.cacheMisses++;
+                            
+                            assert( entry.isNeverReplace() == false ) : "Non Current Entry has neverReplace set to true:" + entry;
+                            
+                            entry.setNeverReplace();
+                            CacheEntry newEntry = null;
+                            
+                            try
+                            {
+                                newEntry = this.findNewEntry( key, hashIndex >> LOG_BUCKET_PER_LATCH );
+                            }
+                            finally
+                            {
+                                entry.clearNeverReplace();
+                            }
     
                             /*
                              * Remove existing entry, chain as a snapshot
@@ -411,16 +460,18 @@
                     case ENTRY_INITIAL:
                         
                         LOG.warn( "Entry with key {} is at intial while trying to read from it", entry.getKey() );
+                        this.cacheMisses++;
                         this.doRead( entry, latches[latchIndex], serializer );
                         value = this.searchChainForVersion( entry, version );
                         break;
 
                     default:
-                        assert ( false );
+                        assert ( false ) : "Unknown cache entry state: " + entry;
                 }
             }
             else
             {
+                this.cacheMisses++;
                 entry = this.findNewEntry( key, latchIndex );
                 buckets[hashIndex].add( entry );
                 this.doRead( entry, latches[latchIndex], serializer );
@@ -444,6 +495,21 @@
         return value;
     }
     
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append( "LRUCache: " );
+        sb.append( "(numEntries:" ).append( this.numEntries );
+        sb.append( ",maxEntries:" ).append( this.maxEntries );
+        sb.append( ",cacheGets:" ).append( this.cacheGets );
+        sb.append( ",cacheMisses:" ).append( this.cacheMisses );
+        sb.append( ",cachePuts:" ).append( this.cachePuts );
+        sb.append( ",cachePutSleeps:" ).append( this.cachePutSleeps );
+        sb.append( ")\n" );
+        
+        return sb.toString();
+    }
      
     /**
      * Creates a new version of the given entry with the given new version.
@@ -461,12 +527,33 @@
     private void putNewVersion( CacheEntry entry, K key, V value, long newVersion, int hashIndex, 
         Lock latch, Serializer serializer, boolean neverReplace ) throws IOException, CacheEvictionException
     {
+        
         if ( entry.getStartVersion() != newVersion  )
         {
-            CacheEntry newEntry = this.findNewEntry( key, hashIndex >> LOG_BUCKET_PER_LATCH );
-
-            // Initialize and set to new version 
-            newEntry.initialize( key );
+            
+            boolean resetNeverReplace = true;
+            
+            if ( entry.isNeverReplace() )
+            {  
+                resetNeverReplace = false;
+            }
+            
+            entry.setNeverReplace();
+            CacheEntry newEntry = null;
+            
+            try
+            {
+                newEntry = this.findNewEntry( key, hashIndex >> LOG_BUCKET_PER_LATCH );
+            }
+            finally
+            {
+                if ( resetNeverReplace )
+                {
+                    entry.clearNeverReplace();
+                }
+            }
+            
+            // Set to new version 
             newEntry.setAsCurrentVersion( value, newVersion );
 
             /*
@@ -482,7 +569,7 @@
         }
         else
         {
-            assert( entry.isCurrentVersion() );
+            assert( entry.isCurrentVersion() ) : "Entry not at expected version: " + entry ;
             
             // Entry already at current version. Just update the value
             entry.setAsCurrentVersion( value, newVersion );
@@ -506,7 +593,11 @@
              * Not much we can do here, just leave the entry in an
              * inconsistent state.
              */
+            latch.lock();
+            
+            
             entry.setState( EntryState.ENTRY_INITIAL );
+            entry.clearNeverReplace();
             
             if ( entry.anyWaiters() )
             {
@@ -559,14 +650,15 @@
             
             if ( curEntry.getState() != EntryState.ENTRY_READY )
             {
-                assert( curEntry == head );
+                assert( curEntry == head ) : "Unexpected state for entry: " + curEntry;
                 curLink = curLink.getNext();
                 continue;
             }
         
             if ( curStartVersion != 0 && ( curEntry.getEndVersion() > curStartVersion ) )
             {
-                assert( false );
+                assert( false ) : "Unexpected version number for entry. curStartVersion: " 
+                        + curStartVersion + " entry: " + curEntry;
             }
             
             curStartVersion = curEntry.getStartVersion();
@@ -594,7 +686,7 @@
         
         if ( value == null && mustFind == true )
         {
-            assert( false );
+            assert( false ) : "Traversed all versions and could not find cache entry";
         }
         
         return value;
@@ -711,18 +803,17 @@
             numEntries.incrementAndGet();
             CacheEntry newEntry  = new CacheEntry( index );
             lru = lrus[index];
+            newEntry.initialize( key );
             lru.getLock().lock();
             lru.addToLRU( newEntry );
             lru.getLock().unlock();
-            newEntry.initialize( key );
             
             return newEntry;
         }
         
         /*
          * We start with a lru determined by the lru randomizer and try to lock the lru without waiting. 
-         * If this doesnt work, we wait on the first lru lock. Once we get the lru, we walk over each lru
-         * (this time waiting on the lock when we switch to a new lru) and try to find a victim. 
+         * If this doesnt work, we wait on the first lru lock. 
          */
         CacheEntry victimEntry = null;
         lru = null;
@@ -747,37 +838,23 @@
             lru.getLock().lock();
         }
         
-        int startingIndex = curIndex;
+        victimEntry = lru.findVictim( latchIndex );
         
-        do
-        {
-            victimEntry = lru.findVictim( latchIndex );
-            lru.getLock().unlock();
-            
-            if ( victimEntry != null )
-            {
-                break;
-            }
-                
-            curIndex = (curIndex + 1) % NUM_LRUS;
-            if ( curIndex == startingIndex )
-                break;
-            
-            lru = lrus[curIndex];
-            lru.getLock().lock();
-        } 
-        while ( true );
         
         if ( victimEntry != null )
         { 
             victimEntry.initialize( key );
+            lru.getLock().unlock();
         }
         else
         {
+            lru.getLock().unlock();
+            
             LOG.warn( "Cache eviction failure: " + this.minReadVersion );
             throw new CacheEvictionException( null );
         }
         
+        
         return victimEntry;
     }
     
@@ -856,17 +933,18 @@
         {
             this.key = key;
             value = null;
-            startVersion = endVersion = 0;
+            startVersion = 0;
+            endVersion = Long.MAX_VALUE;
 
             stateCondition = null;
-            assert ( numWaiters == 0 );
+            assert ( numWaiters == 0 ) : "Numwaiters is not zero when entry is newly initialized: " + this;
             state = EntryState.ENTRY_INITIAL;
 
             assert ( versionsLink.isUnLinked() == true );
             
             hashIndex = hash( key ) & ( numBuckets - 1 );
             
-            assert( neverReplace == false );
+            assert( neverReplace == false ) : "Neverreplace is true when entry is newly intialized:" + this;
         }
 
         public void setNeverReplace()
@@ -874,6 +952,16 @@
             neverReplace = true;
         }
         
+        public void clearNeverReplace()
+        {
+            neverReplace = false;
+        }
+        
+        public boolean isNeverReplace()
+        {
+            return neverReplace;
+        }
+        
         
         public K getKey()
         {
@@ -918,7 +1006,7 @@
 
         public void decrementWaiters()
         {
-            assert ( numWaiters > 0 );
+            assert ( numWaiters > 0 ) : "Unexpected num waiters for entry:" + this;
             numWaiters--;
         }
 
@@ -1000,10 +1088,10 @@
         
         public void setAsSnapshotVersion( long newEndVersion )
         {
-            this.endVersion = newEndVersion;
-            neverReplace = false;
+            this.clearNeverReplace();
             LRU lru = this.getLru();
             lru.getLock().lock();
+            this.endVersion = newEndVersion;
             lru.addToSnapshots( this );
             lru.getLock().unlock();
         }
@@ -1014,6 +1102,23 @@
             return ( this.state != EntryState.ENTRY_READING && this.numWaiters == 0 && 
                 this.state != EntryState.ENTRY_WRITING && !neverReplace);
         }
+        
+        @Override
+        public String toString()
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append( "Entry: " );
+            sb.append("(state: ").append( this.state );
+            sb.append(",numWaiters:").append( this.numWaiters );
+            sb.append(",startVersion:").append( this.startVersion );
+            sb.append(",endVersion:").append( this.endVersion );
+            sb.append(",key:").append( this.key );
+            sb.append(",value:").append( this.value ).append( ")" );
+            sb.append( "\n" );
+            
+            return sb.toString();
+            
+        }
     }
     
         
@@ -1023,11 +1128,17 @@
         private ExplicitList<CacheEntry> mostRecentVersions = new ExplicitList<CacheEntry>();
         
         /** List of snapshot entries */
-        private LinkedList<CacheEntry> snapshotVersions = new LinkedList<CacheEntry>(); 
+        private ExplicitList<CacheEntry> snapshotVersions = new ExplicitList<CacheEntry>(); 
         
         /** Lock protecting the list */
         private Lock lock = new ReentrantLock();
         
+        /** Number of snaphot versions created */
+        private int numSnapshotsCreated;
+        
+        /** True if lru needs to be purged of unusable snapshot versions */
+        private boolean snapshotPurgeNeeded;
+        
         public Lock getLock()
         {
             return lock;
@@ -1054,7 +1165,9 @@
         public void addToSnapshots( CacheEntry entry )
         {
             mostRecentVersions.remove( entry.getLruLink() );
-            snapshotVersions.addLast( entry );
+            snapshotVersions.addLast( entry.getLruLink() );
+            
+            numSnapshotsCreated++;
         }
         
         
@@ -1102,28 +1215,40 @@
              * gotten from the tail of the lru.
              */
             
-            Iterator<CacheEntry> it = snapshotVersions.listIterator();
+            ExplicitList.Link<CacheEntry> curLink;
+              
+            curLink = snapshotVersions.begin();
             
-            while ( it.hasNext() )
+            while ( curLink != snapshotVersions.end() )
             {
-                victimEntry = it.next();
+                victimEntry = curLink.getElement();
                 
                 if ( victimEntry.getEndVersion() > minReadVersion )
                 {
                     break;
                 }
+                               
+                assert( victimEntry.getKey() != null ) : 
+                    "Snapshot victimEntry doesnt have key set:" + victimEntry ;
                 
-                assert ( victimEntry.isEntryFreeable() == true );
-                
+                if ( victimEntry.isNeverReplace() )
+                {
+                    curLink = curLink.getNext();    
+                    continue;
+                }
                 
                 victimBucketIndex = victimEntry.getHashIndex();
                 victimLatchIndex = (victimBucketIndex >> LOG_BUCKET_PER_LATCH );
                 
                 if ( ( latchIndex != victimLatchIndex ) && ( latches[victimLatchIndex].tryLock() == false ) )
                 {
+                    curLink = curLink.getNext();    
                     continue;
                 }
                 
+                assert( victimEntry.isEntryFreeable() == true ) : 
+                    "Snapshot victimEntry is not freeable:" + victimEntry ;
+                
                 int hashChainIndex = buckets[victimEntry.getHashIndex()].indexOf( victimEntry );
                 
                 if ( hashChainIndex != -1 )
@@ -1149,13 +1274,13 @@
                     latches[victimLatchIndex].unlock();
                 }
                 
-                it.remove();
-                this.mostRecentVersions.addLast( victimEntry.lruLink );
+                this.snapshotVersions.remove( victimEntry.getLruLink() );
+                this.mostRecentVersions.addLast( victimEntry.getLruLink() );
                 
                 return victimEntry;
             }
             
-            ExplicitList.Link<CacheEntry> curLink = mostRecentVersions.begin();
+            curLink = mostRecentVersions.begin();
             
             while ( curLink != mostRecentVersions.end() )
             {
diff --git a/jdbm/src/main/java/jdbm/recman/SnapshotRecordManager.java b/jdbm/src/main/java/jdbm/recman/SnapshotRecordManager.java
index 8c76644..115cb93 100644
--- a/jdbm/src/main/java/jdbm/recman/SnapshotRecordManager.java
+++ b/jdbm/src/main/java/jdbm/recman/SnapshotRecordManager.java
@@ -625,6 +625,17 @@
             bigLock.unlock();
         }
     }
+    
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append( "SnapshotRecordManager: " );
+        sb.append( "(lruCache:" ).append( this.versionedCache );
+        sb.append( ")\n" );
+        
+        return sb.toString();
+    }
 
 
     /**
diff --git a/jdbm/src/test/java/jdbm/btree/TestSnapshotBTree.java b/jdbm/src/test/java/jdbm/btree/TestSnapshotBTree.java
index 064c8f9..dbe79c8 100644
--- a/jdbm/src/test/java/jdbm/btree/TestSnapshotBTree.java
+++ b/jdbm/src/test/java/jdbm/btree/TestSnapshotBTree.java
@@ -24,6 +24,7 @@
 
 import java.io.IOException;
 import java.io.Serializable;
+import java.util.Random;
 import java.util.concurrent.Semaphore;
 
 import jdbm.RecordManager;
@@ -36,10 +37,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-
-import com.mycila.junit.concurrent.Concurrency;
-import com.mycila.junit.concurrent.ConcurrentJunitRunner;
 
 /**
  * 
@@ -47,8 +44,6 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(ConcurrentJunitRunner.class)
-@Concurrency()
 public class TestSnapshotBTree
 {
     @Rule
@@ -77,8 +72,8 @@
       
         int idx;
         int numReadThreads = 1;
-        TestThread readThreads[] = new TestThread[numReadThreads];
-        TestThread updateThread;
+        BasicTestThread readThreads[] = new BasicTestThread[numReadThreads];
+        BasicTestThread updateThread;
         
         Semaphore browseSem = new Semaphore( 0 );
         Semaphore updateSem = new Semaphore( 0 );
@@ -95,17 +90,17 @@
 
         for ( idx = 0; idx < numReadThreads; idx++ )
         {
-            readThreads[idx] = new TestThread( true, tree, browseSem, updateSem, numReadThreads );
+            readThreads[idx] = new BasicTestThread( true, tree, browseSem, updateSem, numReadThreads );
         }
-        updateThread = new TestThread( false, tree, browseSem, updateSem, numReadThreads );      
+        updateThread = new BasicTestThread( false, tree, browseSem, updateSem, numReadThreads );      
         
         updateThread.start();
+        
         for ( idx = 0; idx < numReadThreads; idx++ )
         {
             readThreads[idx].start();
         }
         
-        
         for ( idx = 0; idx < numReadThreads; idx++ )
         {
             readThreads[idx].join();
@@ -115,8 +110,10 @@
         snapshotRecman.close();
     }
     
+   
     
-    class TestThread extends Thread
+    
+    class BasicTestThread extends Thread
     {
         boolean readOnly;
         BTree<Integer, IntWrapper> btree;
@@ -124,8 +121,8 @@
         Semaphore updateSem;
         int numReadThreads;
 
-        TestThread( boolean readOnly, BTree<Integer, IntWrapper> btree, Semaphore firstBrowse,
-                    Semaphore updateDone, int numReadThreads)
+        BasicTestThread( boolean readOnly, BTree<Integer, IntWrapper> btree, Semaphore firstBrowse,
+                    Semaphore updateDone, int numReadThreads )
         {
             this.readOnly = readOnly;
             this.btree = btree;
@@ -158,7 +155,9 @@
 
                 // Sleep a little randomly.                                                                                                                                                               
                 if ( (count & 7) == 0 )
+                {
                     Thread.sleep( 1 );
+                }
 
                 assertTrue( tuple.getValue().value != -1 );
             }
@@ -172,6 +171,7 @@
             browser = btree.browse( new Integer( 10 ) );
 
             browseSem.release();
+            
             for ( idx = 20; idx < 1024; idx++ )
             {
                 assertTrue( browser.getNext( tuple ) );
@@ -179,6 +179,7 @@
                 //System.out.println( "key:"+ tuple.getKey().intValue() + " idx:" + idx );
                 assertTrue( tuple.getKey().intValue() == idx );
             }
+            
             browser.close();
         }
         
@@ -187,7 +188,9 @@
             int idx;
 
             for ( idx = 0; idx < numReadThreads; idx++ )
+            {
                 browseSem.acquireUninterruptibly();
+            }
 
             
             Integer key = new Integer( 1023 );
@@ -211,6 +214,7 @@
             
             btree.insert( key, value , true );
             btree.insert( new Integer(1024), new IntWrapper( -1 ), true );
+            
             for ( idx = 10; idx < 20; idx++ )
             {
                 btree.remove( new Integer( idx ) );
@@ -219,15 +223,19 @@
             updateSem.release();
 
             for ( idx = 0; idx < numReadThreads; idx++ )
+            {
                 browseSem.acquireUninterruptibly();
+            }
 
             for ( idx = 0; idx < 10; idx++ )
+            {
                 btree.remove( new Integer( idx ) );
+            }
 
             for ( idx = 20; idx < 1024; idx++ )
+            {
                 btree.remove( new Integer( idx ) );
-
-
+            }
         }
 
 
@@ -236,18 +244,364 @@
             try
             {
                 if ( readOnly )
+                {
                     this.readOnlyActions();
+                }
                 else
+                {
                     this.readWriteActions();
+                }
             }
             catch( IOException e )
             {
+                e.printStackTrace();
+                assertTrue( false );
             }
             catch( InterruptedException e )
             {
-                
+                e.printStackTrace();
+                assertTrue( false );
             }
             
         }
-    } // end of class TestThread
+    } // end of class BasicTestThread
+    
+    
+    @Test
+    public void testLongBrowsing() throws IOException, InterruptedException
+    {
+        RecordManager recman;
+        BTree<Integer, IntWrapper> tree;
+        int numElements = 10000;
+      
+        int idx;
+        int numReadThreads = 4;
+        LongBrowsingTestThread readThreads[] = new LongBrowsingTestThread[numReadThreads];
+        LongBrowsingTestThread updateThread;
+        
+        recman = RecordManagerFactory.createRecordManager( getTemporaryFile( "testLongBrowsing" ) );
+        SnapshotRecordManager snapshotRecman = new SnapshotRecordManager( recman, 1 << 10 );
+        
+        tree = new BTree<Integer, IntWrapper>( snapshotRecman, new IntegerComparator() );
+     
+        for ( idx = 0; idx < numElements; idx++ )
+        {
+            tree.insert( new Integer( idx ), new IntWrapper( 0 ), true );
+        }
+
+        for ( idx = 0; idx < numReadThreads; idx++ )
+        {
+            readThreads[idx] = new LongBrowsingTestThread( true, tree, numElements);
+        }
+        updateThread = new LongBrowsingTestThread( false, tree, numElements );      
+        
+        
+        readThreads[0].start();
+        
+        Thread.sleep( 10 );
+        
+        updateThread.start();
+        
+        for ( idx = 1; idx < numReadThreads; idx++ )
+        {
+            Thread.sleep( 1000 );
+            readThreads[idx].start();
+        }
+        
+        for ( idx = 0; idx < numReadThreads; idx++ )
+        {
+            readThreads[idx].join();
+        }
+        
+        updateThread.join();
+        
+        snapshotRecman.close();
+    }
+    
+    class LongBrowsingTestThread extends Thread
+    {
+        boolean readOnly;
+        BTree<Integer, IntWrapper> btree;
+        int numElements;
+       
+        
+        LongBrowsingTestThread( boolean readOnly, BTree<Integer, IntWrapper> btree, int numElements)
+        {
+            this.readOnly = readOnly;
+            this.btree = btree;
+            this.numElements = numElements;
+        }
+
+
+
+        private void readOnlyActions() throws IOException, InterruptedException
+        {
+            int count = 0;
+            TupleBrowser<Integer, IntWrapper> browser = btree.browse();
+            Tuple<Integer, IntWrapper> tuple = new Tuple();
+           
+            assert( browser.getNext( tuple ) );
+            int max = tuple.getValue().value;
+            count++;
+            System.out.println( " TestLongBrowsing read thread min key is"  + tuple.getKey() + "max value is" + max );
+            
+            while( browser.getNext( tuple ) )
+            {
+                count++;
+
+                // Sleep for a while to keep browsing long                                                                                                                                                               
+                Thread.sleep( 10 );
+
+                
+                if ( tuple.getValue().value > max )
+                {
+                    System.out.println(" tupe value:" + tuple.getValue().value + " Expected max:" + max + " count:" + count);
+                    
+                }
+                
+                assertTrue( tuple.getValue().value <= max );
+                
+            }
+
+
+            System.out.println( "TestLongBrowsing read thread count is " + count );
+            assertEquals( count, numElements );
+            browser.close();
+        }
+        
+        private void readWriteActions()
+        {
+            int idx;
+            Random updateRandomizer = new Random();
+            
+            try
+            {
+                for ( idx = 1; idx < 100; idx++ )
+                {
+                    Integer key = new Integer( 0 );
+                    IntWrapper value = btree.find( key );
+                    value.value = idx;
+                    btree.insert( key, value, true );
+                    
+                    for ( int updates = 0; updates < 2048; updates++ )
+                    {
+                        key = new Integer( updateRandomizer.nextInt( numElements ) );
+                        value = btree.find( key );
+                        
+                        assertTrue( value.value <= idx );
+                        
+                        value.value = idx;
+                        btree.insert( key, value, true );
+                    }
+                }
+                
+                System.out.println( "TestLongBrowsing updates ended" );
+            
+            }
+            catch( IOException e )
+            {
+                e.printStackTrace();
+                assertTrue( false );
+            }
+        }
+
+
+        public void run()
+        {
+            try
+            {
+                if ( readOnly )
+                {
+                    this.readOnlyActions();
+                }
+                else
+                {
+                    this.readWriteActions();
+                }
+            }
+            catch( IOException e )
+            {
+                e.printStackTrace();
+                assertTrue( false );
+            }
+            catch( InterruptedException e )
+            {
+                e.printStackTrace();
+                assertTrue( false );
+            }
+            
+        }
+    } // end of class LongBrowsingTestThread
+    
+    
+    
+    @Test
+    public void testRemoveInsert() throws IOException, InterruptedException
+    {
+        RecordManager recman;
+        BTree<Integer, IntWrapper> tree;
+        int numElements = 10000;
+      
+        int idx;
+        int numReadThreads = 4;
+        RemoveInsertTestThread readThreads[] = new RemoveInsertTestThread[numReadThreads];
+        RemoveInsertTestThread updateThread;
+        
+        Semaphore browseSem = new Semaphore( 0 );
+        
+        recman = RecordManagerFactory.createRecordManager( getTemporaryFile( "testRemoveInsert" ) );
+        SnapshotRecordManager snapshotRecman = new SnapshotRecordManager( recman, 1 << 12 );
+        
+        tree = new BTree<Integer, IntWrapper>( snapshotRecman, new IntegerComparator() );
+     
+        for ( idx = 0; idx < numElements; idx++ )
+        {
+            tree.insert( new Integer( idx ), new IntWrapper( 0 ), true );
+        }
+
+        for ( idx = 0; idx < numReadThreads; idx++ )
+        {
+            readThreads[idx] = new RemoveInsertTestThread( true, tree, numElements, browseSem, numReadThreads );
+        }
+        updateThread = new RemoveInsertTestThread( false, tree, numElements, browseSem, numReadThreads );      
+        
+        
+        updateThread.start();
+        
+        for ( idx = 0; idx < numReadThreads; idx++ )
+        {
+            Thread.sleep( 1000 );
+            readThreads[idx].start();
+        }
+        
+        for ( idx = 0; idx < numReadThreads; idx++ )
+        {
+            readThreads[idx].join();
+        }
+        updateThread.join();
+        
+        snapshotRecman.close();
+    }
+    
+    
+    
+    class RemoveInsertTestThread extends Thread
+    {
+        boolean readOnly;
+        BTree<Integer, IntWrapper> btree;
+        int numElements;
+        Semaphore browseSem;
+        int numReadThreads;
+        
+        RemoveInsertTestThread( boolean readOnly, BTree<Integer, IntWrapper> btree, int numElements,  Semaphore browseSem, int numReadThreads )
+        {
+            this.readOnly = readOnly;
+            this.btree = btree;
+            this.numElements = numElements;
+            this.browseSem = browseSem;
+            this.numReadThreads = numReadThreads;
+        }
+
+        private void readOnlyActions() throws IOException, InterruptedException
+        {
+            int count = 0;
+            TupleBrowser<Integer, IntWrapper> browser = btree.browse();
+            Tuple<Integer, IntWrapper> tuple = new Tuple();
+           
+            browseSem.release();
+            
+            while( browser.getNext( tuple ) )
+            {
+                count++;
+
+                // Sleep for a while to keep browsing long                                                                                                                                                               
+                Thread.sleep( 10 );
+
+                
+                if ( tuple.getValue().value == -1 )
+                {
+                    System.out.println(" tupe key:" + tuple.getKey() + " value:" + tuple.getValue().value);
+                    
+                }
+                
+                assertTrue( tuple.getValue().value != -1 );
+            }
+
+
+            System.out.println( "TestRemoveInsert read thread count is " + count );
+            assertEquals( count, numElements );
+            browser.close();
+        }
+        
+        private void readWriteActions() throws IOException, InterruptedException
+        {
+            int idx;
+            Random updateRandomizer = new Random();
+            
+            for ( idx = 0; idx < numReadThreads; idx++ )
+            {
+                browseSem.acquireUninterruptibly();
+            }
+            
+          
+            Integer key;
+            IntWrapper value = new IntWrapper( -1 );
+            
+            for ( idx = 0; idx < 10; idx++ )
+            {
+                Thread.sleep( 10000 );
+                
+                int startingIndex = updateRandomizer.nextInt( numElements );
+                
+                for ( int updates = 0; updates < 32; updates++ )
+                {                    
+                    key = new Integer( startingIndex + updates );
+                    
+                    if ( key.intValue() >= numElements )
+                    {
+                        break;
+                    }   
+                        
+                    btree.remove( key );
+                }
+                
+                for ( int updates = 0; updates < 32; updates++ )
+                {
+                    key = new Integer( startingIndex + updates );
+                    btree.insert( key, value, true );
+                }
+            }
+            
+            System.out.println( "TestRemoveInsert updates ended" );
+            
+        }
+
+
+        public void run()
+        {         
+            try
+            {
+                if ( readOnly )
+                {
+                    this.readOnlyActions();
+                }
+                else
+                {
+                    this.readWriteActions();
+                }
+            }
+            catch( IOException e )
+            {
+                e.printStackTrace();
+                assertTrue( false );
+            }
+            catch( InterruptedException e )
+            {
+                e.printStackTrace();
+                assertTrue( false );
+            }
+            
+            
+        }
+    } // end of class RemoveInsertTestThread
 }
\ No newline at end of file
diff --git a/osgi/pom.xml b/osgi/pom.xml
index bd2a97f..87abb91 100644
--- a/osgi/pom.xml
+++ b/osgi/pom.xml
@@ -24,7 +24,7 @@
   <parent>
     <groupId>org.apache.directory.server</groupId>
     <artifactId>apacheds-parent</artifactId>
-    <version>1.5.8-SNAPSHOT</version>
+    <version>2.0.0-M3-SNAPSHOT</version>
   </parent>
   <artifactId>apacheds-osgi</artifactId>
   <name>ApacheDS OSGi Bundle</name>
diff --git a/pom.xml b/pom.xml
index 6bc0918..f2fc2c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
   <parent>
     <groupId>org.apache.directory.project</groupId>
     <artifactId>project</artifactId>
-    <version>22</version>
+    <version>23</version>
   </parent>
 
   <groupId>org.apache.directory.server</groupId>
diff --git a/protocol-changepw/pom.xml b/protocol-changepw/pom.xml
index d98f39b..63e11d2 100644
--- a/protocol-changepw/pom.xml
+++ b/protocol-changepw/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>org.apache.directory.server</groupId>
     <artifactId>apacheds-parent</artifactId>
-    <version>1.5.8-SNAPSHOT</version>
+    <version>2.0.0-M3-SNAPSHOT</version>
   </parent>
   
   <artifactId>apacheds-protocol-changepw</artifactId>
diff --git a/server-config/src/test/java/org/apache/directory/server/config/ConfigWriterTest.java b/server-config/src/test/java/org/apache/directory/server/config/ConfigWriterTest.java
index a4c2fe0..41caa44 100644
--- a/server-config/src/test/java/org/apache/directory/server/config/ConfigWriterTest.java
+++ b/server-config/src/test/java/org/apache/directory/server/config/ConfigWriterTest.java
@@ -128,10 +128,12 @@
         // Reading the original config file

         LdifReader ldifReader = new LdifReader( configFile );

         List<LdifEntry> originalConfigEntries = new ArrayList<LdifEntry>();

+        

         while ( ldifReader.hasNext() )

         {

             originalConfigEntries.add( ldifReader.next() );

         }

+        

         ldifReader.close();

 

         // Getting the list of entries of generated config

diff --git a/server-tools/pom.xml b/server-tools/pom.xml
index 4eaf70c..026342f 100644
--- a/server-tools/pom.xml
+++ b/server-tools/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>org.apache.directory.server</groupId>
     <artifactId>apacheds-parent</artifactId>
-    <version>1.5.8-SNAPSHOT</version>
+    <version>2.0.0-M3-SNAPSHOT</version>
   </parent>
   
   <artifactId>apacheds-server-tools</artifactId>
diff --git a/service/ApacheDS.launch b/service/ApacheDS.launch
index 459fd7b..89a1d82 100644
--- a/service/ApacheDS.launch
+++ b/service/ApacheDS.launch
@@ -27,5 +27,5 @@
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.apache.directory.server.UberjarMain"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="./target/instance"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="apacheds-service"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dlog4j.configuration=file:./log4j.properties -Dapacheds.log.dir=./target/instance/log -Ddefault.controls=org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory -Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncModifyDnFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory -Ddefault.extendedOperation.requests=org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory -Ddefault.extendedOperation.responses=org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dlog4j.configuration=file:./log4j.properties -Dapacheds.log.dir=./target/instance/log -Ddefault.controls=org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory -Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory -Ddefault.extendedOperation.requests=org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory -Ddefault.extendedOperation.responses=org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory"/>
 </launchConfiguration>
diff --git a/service/apacheds.bat b/service/apacheds.bat
index b3d905d..9e85f57 100644
--- a/service/apacheds.bat
+++ b/service/apacheds.bat
@@ -19,7 +19,7 @@
 
 REM this script starts ApacheDS (as non-windows-service)
 
-IF NOT exist target/apacheds-service-2.0.0-M3-SNAPSHOT.jar GOTO :MVN
+IF NOT exist target/apacheds-service-2.0.0-M4-SNAPSHOT.jar GOTO :MVN
    echo "Service jar exists"
    GOTO :JAVA
 
@@ -37,11 +37,11 @@
   
 DEF_CTRLS="-Ddefault.controls=org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory"
 
-EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncModifyDnFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"
+EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"
 
 DEF_EXT_OP_REQ="-Ddefault.extendedOperation.requests=org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory"
 
 DEF_EXT_OP_RESP="-Ddefault.extendedOperation.responses=org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulDisconnectFactory"
 
-java %DEF_CTRLS% %EXT_CTRLS% %DEF_EXT_OP_REQ% %DEF_EXT_OP_RESP% -Dlog4j.configuration="file:///%cd%/target/instance/conf/log4j.properties" -jar target/apacheds-service-2.0.0-M3-SNAPSHOT.jar %cd%/target/instance
+java %DEF_CTRLS% %EXT_CTRLS% %DEF_EXT_OP_REQ% %DEF_EXT_OP_RESP% -Dlog4j.configuration="file:///%cd%/target/instance/conf/log4j.properties" -jar target/apacheds-service-2.0.0-M4-SNAPSHOT.jar %cd%/target/instance
    
diff --git a/service/apacheds.sh b/service/apacheds.sh
index 7e3b2ae..3d139e4 100755
--- a/service/apacheds.sh
+++ b/service/apacheds.sh
@@ -18,7 +18,7 @@
 # under the License.
 
 # The final jar
-JAR=target/apacheds-service-2.0.0-M3-SNAPSHOT.jar
+JAR=target/apacheds-service-2.0.0-M4-SNAPSHOT.jar
 
 # Checking if the final jar exists
 if [ -e $JAR ] ; then
@@ -42,7 +42,7 @@
 
 DEF_CTRLS="-Ddefault.controls=org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory,org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory,org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory,org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory,org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory,org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory"
 
-EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncModifyDnFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"
+EXT_CTRLS="-Dextra.controls=org.apache.directory.shared.ldap.extras.controls.ppolicy.PasswordPolicyFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncDoneValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncInfoValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncRequestValueFactory,org.apache.directory.shared.ldap.extras.controls.syncrepl_impl.SyncStateValueFactory"
 
 DEF_EXT_OP_REQ="-Ddefault.extendedOperation.requests=org.apache.directory.shared.ldap.extras.extended.ads_impl.cancel.CancelFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.certGeneration.CertGenerationFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.gracefulShutdown.GracefulShutdownFactory,org.apache.directory.shared.ldap.extras.extended.ads_impl.storedProcedure.StoredProcedureFactory"
 
diff --git a/syncrepl/pom.xml b/syncrepl/pom.xml
index a8b305e..e483285 100644
--- a/syncrepl/pom.xml
+++ b/syncrepl/pom.xml
@@ -24,7 +24,7 @@
   <parent>
     <groupId>org.apache.directory.server</groupId>
     <artifactId>apacheds-parent</artifactId>
-    <version>1.5.8-SNAPSHOT</version>
+    <version>2.0.0-M3-SNAPSHOT</version>
   </parent>
   <artifactId>syncrepl</artifactId>
   <name>ApacheDS replication</name>