Index: src/java/org/apache/lucene/index/FieldsReader.java
===================================================================
--- src/java/org/apache/lucene/index/FieldsReader.java	(revision 724919)
+++ src/java/org/apache/lucene/index/FieldsReader.java	(working copy)
@@ -38,7 +38,7 @@
  *
  * @version $Id$
  */
-final class FieldsReader {
+final class FieldsReader implements Cloneable {
   private final FieldInfos fieldInfos;
 
   // The main fieldStream, used only for cloning.
@@ -47,7 +47,8 @@
   // This is a clone of cloneableFieldsStream used for reading documents.
   // It should not be cloned outside of a synchronized context.
   private final IndexInput fieldsStream;
-
+  
+  private final IndexInput cloneableIndexStream;
   private final IndexInput indexStream;
   private int numTotalDocs;
   private int size;
@@ -60,7 +61,27 @@
   private int docStoreOffset;
 
   private CloseableThreadLocal fieldsStreamTL = new CloseableThreadLocal();
-
+  private boolean isOriginal = false;
+  
+  public Object clone() {
+    return new FieldsReader(fieldInfos, numTotalDocs, size, closed, format, formatSize, docStoreOffset, cloneableFieldsStream, cloneableIndexStream);
+  }
+  
+  // Used by clone
+  FieldsReader(FieldInfos fieldInfos, int numTotalDocs, int size, boolean closed, int format, int formatSize, int docStoreOffset, IndexInput cloneableFieldsStream, IndexInput cloneableIndexStream) {
+    this.fieldInfos = fieldInfos;
+    this.numTotalDocs = numTotalDocs;
+    this.size = size;
+    this.closed = closed;
+    this.format = format;
+    this.formatSize = formatSize;
+    this.docStoreOffset = docStoreOffset;
+    this.cloneableFieldsStream = cloneableFieldsStream;
+    this.cloneableIndexStream = cloneableIndexStream;
+    fieldsStream = (IndexInput)cloneableFieldsStream.clone();
+    indexStream = (IndexInput)cloneableIndexStream.clone();
+  }
+  
   FieldsReader(Directory d, String segment, FieldInfos fn) throws IOException {
     this(d, segment, fn, BufferedIndexInput.BUFFER_SIZE, -1, 0);
   }
@@ -71,17 +92,17 @@
 
   FieldsReader(Directory d, String segment, FieldInfos fn, int readBufferSize, int docStoreOffset, int size) throws IOException {
     boolean success = false;
-
+    isOriginal = true;
     try {
       fieldInfos = fn;
 
       cloneableFieldsStream = d.openInput(segment + "." + IndexFileNames.FIELDS_EXTENSION, readBufferSize);
-      indexStream = d.openInput(segment + "." + IndexFileNames.FIELDS_INDEX_EXTENSION, readBufferSize);
-
+      cloneableIndexStream = d.openInput(segment + "." + IndexFileNames.FIELDS_INDEX_EXTENSION, readBufferSize);
+      
       // First version of fdx did not include a format
       // header, but, the first int will always be 0 in that
       // case
-      int firstInt = indexStream.readInt();
+      int firstInt = cloneableIndexStream.readInt();
       if (firstInt == 0)
         format = 0;
       else
@@ -101,8 +122,8 @@
 
       fieldsStream = (IndexInput) cloneableFieldsStream.clone();
 
-      final long indexSize = indexStream.length()-formatSize;
-
+      final long indexSize = cloneableIndexStream.length()-formatSize;
+      
       if (docStoreOffset != -1) {
         // We read only a slice out of this shared fields file
         this.docStoreOffset = docStoreOffset;
@@ -115,7 +136,7 @@
         this.docStoreOffset = 0;
         this.size = (int) (indexSize >> 3);
       }
-
+      indexStream = (IndexInput)cloneableIndexStream.clone();
       numTotalDocs = (int) (indexSize >> 3);
       success = true;
     } finally {
@@ -150,13 +171,18 @@
       if (fieldsStream != null) {
         fieldsStream.close();
       }
-      if (cloneableFieldsStream != null) {
-        cloneableFieldsStream.close();
+      if (isOriginal) {
+        if (cloneableFieldsStream != null) {
+          cloneableFieldsStream.close();
+        }
+        fieldsStreamTL.close();
+        if (cloneableIndexStream != null) {
+          cloneableIndexStream.close();
+        }
       }
       if (indexStream != null) {
         indexStream.close();
       }
-      fieldsStreamTL.close();
       closed = true;
     }
   }
Index: src/java/org/apache/lucene/index/SegmentReader.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentReader.java	(revision 724919)
+++ src/java/org/apache/lucene/index/SegmentReader.java	(working copy)
@@ -47,11 +47,13 @@
   private int readBufferSize;
 
   FieldInfos fieldInfos;
-  private FieldsReader fieldsReader;
+  FieldsReader fieldsReaderOrig = null;
+  //private FieldsReader fieldsReader;
 
   TermInfosReader tis;
   TermVectorsReader termVectorsReaderOrig = null;
   CloseableThreadLocal termVectorsLocal = new CloseableThreadLocal();
+  CloseableThreadLocal fieldsReaderLocal = new FieldsReaderLocal();
 
   BitVector deletedDocs = null;
   private boolean deletedDocsDirty = false;
@@ -79,6 +81,15 @@
   // in case this is a re-opened reader
   private SegmentReader referencedSegmentReader = null;
   
+  /**
+   * Sets the initial value 
+   */
+  private class FieldsReaderLocal extends CloseableThreadLocal {
+    protected Object initialValue() {
+      return (FieldsReader)fieldsReaderOrig.clone();
+    }
+  }
+  
   private class Norm {
     volatile int refCount;
     boolean useSingleNormStream;
@@ -354,12 +365,12 @@
         fieldsSegment = segment;
 
       if (doOpenStores) {
-        fieldsReader = new FieldsReader(storeDir, fieldsSegment, fieldInfos, readBufferSize,
+        fieldsReaderOrig = new FieldsReader(storeDir, fieldsSegment, fieldInfos, readBufferSize,
                                         si.getDocStoreOffset(), si.docCount);
 
         // Verify two sources of "maxDoc" agree:
-        if (si.getDocStoreOffset() == -1 && fieldsReader.size() != si.docCount) {
-          throw new CorruptIndexException("doc counts differ for segment " + si.name + ": fieldsReader shows " + fieldsReader.size() + " but segmentInfo shows " + si.docCount);
+        if (si.getDocStoreOffset() == -1 && fieldsReaderOrig.size() != si.docCount) {
+          throw new CorruptIndexException("doc counts differ for segment " + si.name + ": fieldsReader shows " + fieldsReaderOrig.size() + " but segmentInfo shows " + si.docCount);
         }
       }
 
@@ -499,9 +510,10 @@
         }
       }
   
-      if (fieldsReader != null) {
-        clone.fieldsReader = new FieldsReader(storeDir, fieldsSegment, fieldInfos, readBufferSize,
-                                        si.getDocStoreOffset(), si.docCount);
+      if (fieldsReaderOrig != null) {
+        
+        //clone.fieldsReaderOrig = new FieldsReader(storeDir, fieldsSegment, fieldInfos, readBufferSize,
+        //                                si.getDocStoreOffset(), si.docCount);
       }
       
       
@@ -613,13 +625,14 @@
   }
 
   FieldsReader getFieldsReader() {
-    return fieldsReader;
+    return (FieldsReader)fieldsReaderLocal.get();
   }
 
   protected void doClose() throws IOException {
     boolean hasReferencedReader = (referencedSegmentReader != null);
 
     termVectorsLocal.close();
+    fieldsReaderLocal.close();
 
     if (hasReferencedReader) {
       referencedSegmentReader.decRefReaderNotNorms();
@@ -637,17 +650,12 @@
       singleNormStream = null;
     }
     
-    // re-opened SegmentReaders have their own instance of FieldsReader
-    if (fieldsReader != null) {
-      fieldsReader.close();
-    }
-
     if (!hasReferencedReader) { 
       // close everything, nothing is shared anymore with other readers
       if (tis != null) {
         tis.close();
       }
-  
+      if (fieldsReaderOrig != null) fieldsReaderOrig.close();
       if (freqStream != null)
         freqStream.close();
       if (proxStream != null)
@@ -720,17 +728,17 @@
   FieldInfos getFieldInfos() {
     return fieldInfos;
   }
-
+  
   /**
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public synchronized Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
     ensureOpen();
-    if (isDeleted(n))
+    if (deletedDocs != null && deletedDocs.get(n))
       throw new IllegalArgumentException
               ("attempt to access a deleted document");
-    return fieldsReader.doc(n, fieldSelector);
+    return getFieldsReader().doc(n, fieldSelector);
   }
 
   public synchronized boolean isDeleted(int n) {
