Index: org/apache/lucene/index/DirectoryIndexReader.java
===================================================================
--- org/apache/lucene/index/DirectoryIndexReader.java	(revision 671210)
+++ org/apache/lucene/index/DirectoryIndexReader.java	(working copy)
@@ -18,10 +18,9 @@
  */
 
 import java.io.IOException;
-
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
-import java.util.Collection;
-import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.lucene.store.Directory;
@@ -97,11 +96,15 @@
       }
     }.run();
   }
-
+  
   public final synchronized IndexReader reopen() throws CorruptIndexException, IOException {
+    return reopen(false);
+  }
+  
+  public final synchronized IndexReader reopen(final boolean force) throws CorruptIndexException, IOException {
     ensureOpen();
 
-    if (this.hasChanges || this.isCurrent()) {
+    if ( (this.hasChanges || this.isCurrent()) && !force) {
       // this has changes, therefore we have the lock and don't need to reopen
       // OR: the index in the directory hasn't changed - nothing to do here
       return this;
@@ -113,7 +116,7 @@
         SegmentInfos infos = new SegmentInfos();
         infos.read(directory, segmentFileName);
 
-        DirectoryIndexReader newReader = doReopen(infos);
+        DirectoryIndexReader newReader = doReopen(infos, force);
         
         if (DirectoryIndexReader.this != newReader) {
           newReader.init(directory, infos, closeDirectory);
@@ -124,11 +127,19 @@
       }
     }.run();
   }
-
+  
+  protected void setLock(Lock writeLock) {
+    this.writeLock = writeLock;
+  }
+  
+  protected Lock getWriteLock() {
+    return writeLock;
+  }
+  
   /**
    * Re-opens the index using the passed-in SegmentInfos 
    */
-  protected abstract DirectoryIndexReader doReopen(SegmentInfos infos) throws CorruptIndexException, IOException;
+  protected abstract DirectoryIndexReader doReopen(SegmentInfos infos, boolean force) throws CorruptIndexException, IOException;
   
   public void setDeletionPolicy(IndexDeletionPolicy deletionPolicy) {
     this.deletionPolicy = deletionPolicy;
Index: org/apache/lucene/index/IndexReader.java
===================================================================
--- org/apache/lucene/index/IndexReader.java	(revision 671210)
+++ org/apache/lucene/index/IndexReader.java	(working copy)
@@ -17,17 +17,21 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.store.*;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collection;
 
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.store.AlreadyClosedException;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.store.IndexInput;
+import org.apache.lucene.store.LockObtainFailedException;
+
 /** IndexReader is an abstract class, providing an interface for accessing an
  index.  Search of an index is done entirely through this abstract interface,
  so that any subclass which implements it is searchable.
@@ -247,6 +251,10 @@
   public synchronized IndexReader reopen() throws CorruptIndexException, IOException {
     throw new UnsupportedOperationException("This reader does not support reopen().");
   }
+  
+  public synchronized IndexReader reopen(boolean force) throws CorruptIndexException, IOException {
+    throw new UnsupportedOperationException("This reader does not support reopen().");
+  }
 
   /** 
    * Returns the directory associated with this index.  The Default 
Index: org/apache/lucene/index/MultiReader.java
===================================================================
--- org/apache/lucene/index/MultiReader.java	(revision 671210)
+++ org/apache/lucene/index/MultiReader.java	(working copy)
@@ -17,13 +17,12 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
-
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Hashtable;
 
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.index.MultiSegmentReader.MultiTermDocs;
 import org.apache.lucene.index.MultiSegmentReader.MultiTermEnum;
 import org.apache.lucene.index.MultiSegmentReader.MultiTermPositions;
@@ -86,7 +85,11 @@
     }
     starts[subReaders.length] = maxDoc;
   }
-
+  
+  public IndexReader reopen() throws CorruptIndexException, IOException {
+    return reopen(false);
+  }
+  
   /**
    * Tries to reopen the subreaders.
    * <br>
@@ -106,7 +109,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error 
    */
-  public IndexReader reopen() throws CorruptIndexException, IOException {
+  public IndexReader reopen(boolean force) throws CorruptIndexException, IOException {
     ensureOpen();
     
     boolean reopened = false;
@@ -116,7 +119,7 @@
     boolean success = false;
     try {
       for (int i = 0; i < subReaders.length; i++) {
-        newSubReaders[i] = subReaders[i].reopen();
+        newSubReaders[i] = subReaders[i].reopen(force);
         // if at least one of the subreaders was updated we remember that
         // and return a new MultiReader
         if (newSubReaders[i] != subReaders[i]) {
Index: org/apache/lucene/index/MultiSegmentReader.java
===================================================================
--- org/apache/lucene/index/MultiSegmentReader.java	(revision 671210)
+++ org/apache/lucene/index/MultiSegmentReader.java	(working copy)
@@ -17,10 +17,6 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.store.Directory;
-
 import java.io.IOException;
 import java.util.Collection;
 import java.util.HashMap;
@@ -30,6 +26,10 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.store.Directory;
+
 /** 
  * An IndexReader which reads indexes with multiple segments.
  */
@@ -70,7 +70,7 @@
   }
 
   /** This contructor is only used for {@link #reopen()} */
-  MultiSegmentReader(Directory directory, SegmentInfos infos, boolean closeDirectory, SegmentReader[] oldReaders, int[] oldStarts, Map oldNormsCache) throws IOException {
+  MultiSegmentReader(Directory directory, SegmentInfos infos, boolean closeDirectory, SegmentReader[] oldReaders, int[] oldStarts, Map oldNormsCache, boolean force) throws IOException {
     super(directory, infos, closeDirectory);
     
     // we put the old SegmentReaders in a map, that allows us
@@ -108,7 +108,7 @@
           // this is a new reader; in case we hit an exception we can close it safely
           newReader = SegmentReader.get(infos.info(i));
         } else {
-          newReader = (SegmentReader) newReaders[i].reopenSegment(infos.info(i));
+          newReader = (SegmentReader) newReaders[i].reopenSegment(infos.info(i), force);
         }
         if (newReader == newReaders[i]) {
           // this reader will be shared between the old and the new one,
@@ -193,14 +193,14 @@
     starts[subReaders.length] = maxDoc;
   }
 
-  protected synchronized DirectoryIndexReader doReopen(SegmentInfos infos) throws CorruptIndexException, IOException {
+  protected synchronized DirectoryIndexReader doReopen(SegmentInfos infos, boolean force) throws CorruptIndexException, IOException {
     if (infos.size() == 1) {
       // The index has only one segment now, so we can't refresh the MultiSegmentReader.
       // Return a new SegmentReader instead
       SegmentReader newReader = SegmentReader.get(infos, infos.info(0), false);
       return newReader;
     } else {
-      return new MultiSegmentReader(directory, infos, closeDirectory, subReaders, starts, normsCache);
+      return new MultiSegmentReader(directory, infos, closeDirectory, subReaders, starts, normsCache, force);
     }            
   }
 
Index: org/apache/lucene/index/ParallelReader.java
===================================================================
--- org/apache/lucene/index/ParallelReader.java	(revision 671210)
+++ org/apache/lucene/index/ParallelReader.java	(working copy)
@@ -17,15 +17,24 @@
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.document.FieldSelectorResult;
 import org.apache.lucene.document.Fieldable;
 
-import java.io.IOException;
-import java.util.*;
 
-
 /** An IndexReader which reads multiple, parallel indexes.  Each index added
  * must have the same number of documents, but typically each contains
  * different fields.  Each document contains the union of the fields of all
@@ -122,7 +131,11 @@
     }
     decrefOnClose.add(Boolean.valueOf(incRefReaders));
   }
-
+  
+  public IndexReader reopen() throws CorruptIndexException, IOException {
+    return reopen(false);
+  }
+  
   /**
    * Tries to reopen the subreaders.
    * <br>
@@ -142,7 +155,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error 
    */
-  public IndexReader reopen() throws CorruptIndexException, IOException {
+  public IndexReader reopen(boolean force) throws CorruptIndexException, IOException {
     ensureOpen();
     
     boolean reopened = false;
@@ -155,7 +168,7 @@
     
       for (int i = 0; i < readers.size(); i++) {
         IndexReader oldReader = (IndexReader) readers.get(i);
-        IndexReader newReader = oldReader.reopen();
+        IndexReader newReader = oldReader.reopen(force);
         newReaders.add(newReader);
         // if at least one of the subreaders was updated we remember that
         // and return a new MultiReader
Index: org/apache/lucene/index/SegmentReader.java
===================================================================
--- org/apache/lucene/index/SegmentReader.java	(revision 671210)
+++ org/apache/lucene/index/SegmentReader.java	(working copy)
@@ -34,6 +34,7 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
+import org.apache.lucene.store.Lock;
 import org.apache.lucene.util.BitVector;
 
 /**
@@ -50,7 +51,9 @@
   TermInfosReader tis;
   TermVectorsReader termVectorsReaderOrig = null;
   ThreadLocal termVectorsLocal = new ThreadLocal();
-
+  
+  boolean openNewFieldsReader = true;
+  
   BitVector deletedDocs = null;
   private boolean deletedDocsDirty = false;
   private boolean normsDirty = false;
@@ -264,7 +267,11 @@
     instance.initialize(si, readBufferSize, doOpenStores);
     return instance;
   }
-
+  
+  protected void doInitialize() {
+    
+  }
+  
   private void initialize(SegmentInfo si, int readBufferSize, boolean doOpenStores) throws CorruptIndexException, IOException {
     segment = si.name;
     this.si = si;
@@ -334,6 +341,7 @@
           vectorsSegment = segment;
         termVectorsReaderOrig = new TermVectorsReader(storeDir, vectorsSegment, fieldInfos, readBufferSize, si.getDocStoreOffset(), si.docCount);
       }
+      doInitialize();
       success = true;
     } finally {
 
@@ -365,26 +373,32 @@
       assert si.getDelCount() == 0;
   }
   
-  protected synchronized DirectoryIndexReader doReopen(SegmentInfos infos) throws CorruptIndexException, IOException {
+  protected synchronized DirectoryIndexReader doReopen(SegmentInfos infos, boolean force) throws CorruptIndexException, IOException {
     DirectoryIndexReader newReader;
     
     if (infos.size() == 1) {
       SegmentInfo si = infos.info(0);
       if (segment.equals(si.name) && si.getUseCompoundFile() == SegmentReader.this.si.getUseCompoundFile()) {
-        newReader = reopenSegment(si);
+        newReader = reopenSegment(si, force);
       } else { 
         // segment not referenced anymore, reopen not possible
         // or segment format changed
         newReader = SegmentReader.get(infos, infos.info(0), false);
       }
     } else {
-      return new MultiSegmentReader(directory, infos, closeDirectory, new SegmentReader[] {this}, null, null);
+      return new MultiSegmentReader(directory, infos, closeDirectory, new SegmentReader[] {this}, null, null, force);
     }
     
     return newReader;
   }
   
-  synchronized SegmentReader reopenSegment(SegmentInfo si) throws CorruptIndexException, IOException {
+  protected BitVector cloneDeletedDocs() {
+    if (this.deletedDocs == null) return null;
+    BitVector bitVector = new BitVector(this.deletedDocs.getBits(), this.deletedDocs.size(), this.deletedDocs.count());
+    return bitVector;
+  }
+  
+  synchronized SegmentReader reopenSegment(SegmentInfo si, boolean force) throws CorruptIndexException, IOException {
     boolean deletionsUpToDate = (this.si.hasDeletions() == si.hasDeletions()) 
                                   && (!si.hasDeletions() || this.si.getDelFileName().equals(si.getDelFileName()));
     boolean normsUpToDate = true;
@@ -400,15 +414,22 @@
       }
     }
 
-    if (normsUpToDate && deletionsUpToDate) {
+    if ( (normsUpToDate && deletionsUpToDate) && !force) {
       return this;
     }    
     
 
       // clone reader
-    SegmentReader clone = new SegmentReader();
+    //SegmentReader clone = new SegmentReader();
+    SegmentReader clone;
+    try {
+      clone = (SegmentReader)IMPL.newInstance();
+    } catch (Exception e) {
+      throw new RuntimeException("cannot load SegmentReader class: " + e, e);
+    }
     boolean success = false;
     try {
+      clone.openNewFieldsReader = openNewFieldsReader;
       clone.directory = directory;
       clone.si = si;
       clone.segment = segment;
@@ -442,9 +463,11 @@
         }
       }
   
-      if (fieldsReader != null) {
+      if (fieldsReader != null && openNewFieldsReader) {
         clone.fieldsReader = new FieldsReader(storeDir, fieldsSegment, fieldInfos, readBufferSize,
                                         si.getDocStoreOffset(), si.docCount);
+      } else if (!openNewFieldsReader) {
+        clone.fieldsReader = fieldsReader;
       }
       
       
@@ -453,7 +476,18 @@
         clone.deletedDocs = null;
         clone.loadDeletedDocs();
       } else {
-        clone.deletedDocs = this.deletedDocs;
+        if (force) {
+          if (this.deletedDocs != null) {
+            Lock otherLock = getWriteLock();
+            if (otherLock != null) {
+              System.out.println("otherLock not null");
+              //clone.setLock(otherLock);
+            }
+            clone.deletedDocs = cloneDeletedDocs();//(BitVector)this.deletedDocs.clone();
+          }
+        } else {
+          clone.deletedDocs = this.deletedDocs;
+        }
       }
   
       clone.norms = new HashMap();
@@ -578,7 +612,7 @@
     }
     
     // re-opened SegmentReaders have their own instance of FieldsReader
-    if (fieldsReader != null) {
+    if (fieldsReader != null && openNewFieldsReader) {
       fieldsReader.close();
     }
 
Index: org/apache/lucene/util/BitVector.java
===================================================================
--- org/apache/lucene/util/BitVector.java	(revision 671210)
+++ org/apache/lucene/util/BitVector.java	(working copy)
@@ -35,12 +35,35 @@
 
   @version $Id$
   */
-public final class BitVector {
+public final class BitVector implements Cloneable {
 
   private byte[] bits;
   private int size;
   private int count = -1;
-
+  
+  public Object clone() {
+    BitVector newBitVector = new BitVector();
+    byte[] newbits = new byte[bits.length];
+    System.arraycopy(bits, 0, newbits, 0, bits.length);
+    
+    newBitVector.bits = newbits;
+    newBitVector.size = size;
+    newBitVector.count = count;
+    return newBitVector;
+  }
+  
+  public byte[] getBits() {
+    return bits;
+  }
+  
+  public BitVector(byte[] bits, int size, int count) {
+    this.bits = bits;
+    this.size = size;
+    this.count = count;
+  }
+  
+  private BitVector() {}
+  
   /** Constructs a vector capable of holding <code>n</code> bits. */
   public BitVector(int n) {
     size = n;
