You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by yo...@apache.org on 2006/10/20 05:08:03 UTC

svn commit: r465958 - in /lucene/java/trunk: CHANGES.txt src/java/org/apache/lucene/index/FieldsReader.java

Author: yonik
Date: Thu Oct 19 20:08:02 2006
New Revision: 465958

URL: http://svn.apache.org/viewvc?view=rev&rev=465958
Log:
unsafe use of IndexInput.clone(): LUCENE-690

Modified:
    lucene/java/trunk/CHANGES.txt
    lucene/java/trunk/src/java/org/apache/lucene/index/FieldsReader.java

Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?view=diff&rev=465958&r1=465957&r2=465958
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Thu Oct 19 20:08:02 2006
@@ -140,6 +140,9 @@
     lock to be shared between different directories.
     (Michael McCandless via Yonik Seeley)
 
+17. LUCENE-690: Fixed thread unsafe use of IndexInput by lazy loaded fields.
+    (Yonik Seeley)
+
 Optimizations
 
   1. LUCENE-586: TermDocs.skipTo() is now more efficient for multi-segment

Modified: lucene/java/trunk/src/java/org/apache/lucene/index/FieldsReader.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/index/FieldsReader.java?view=diff&rev=465958&r1=465957&r2=465958
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/index/FieldsReader.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/index/FieldsReader.java Thu Oct 19 20:08:02 2006
@@ -40,7 +40,14 @@
  */
 final class FieldsReader {
   private final FieldInfos fieldInfos;
+
+  // The main fieldStream, used only for cloning.
+  private final IndexInput cloneableFieldsStream;
+
+  // 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 indexStream;
   private int size;
 
@@ -49,7 +56,8 @@
   FieldsReader(Directory d, String segment, FieldInfos fn) throws IOException {
     fieldInfos = fn;
 
-    fieldsStream = d.openInput(segment + ".fdt");
+    cloneableFieldsStream = d.openInput(segment + ".fdt");
+    fieldsStream = (IndexInput)cloneableFieldsStream.clone();
     indexStream = d.openInput(segment + ".fdx");
     size = (int) (indexStream.length() / 8);
   }
@@ -62,6 +70,7 @@
    */
   final void close() throws IOException {
     fieldsStream.close();
+    cloneableFieldsStream.close();
     indexStream.close();
     IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get();
     if (localFieldsStream != null) {
@@ -280,6 +289,15 @@
       lazy = true;
     }
 
+    private IndexInput getFieldStream() {
+      IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get();
+      if (localFieldsStream == null) {
+        localFieldsStream = (IndexInput) cloneableFieldsStream.clone();
+        fieldsStreamTL.set(localFieldsStream);
+      }
+      return localFieldsStream;
+    }
+
     /**
      * The value of the field in Binary, or null.  If null, the Reader or
      * String value is used.  Exactly one of stringValue(), readerValue() and
@@ -288,11 +306,7 @@
     public byte[] binaryValue() {
       if (fieldsData == null) {
         final byte[] b = new byte[toRead];
-        IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get();
-        if (localFieldsStream == null) {
-          localFieldsStream = (IndexInput) fieldsStream.clone();
-          fieldsStreamTL.set(localFieldsStream);
-        }
+        IndexInput localFieldsStream = getFieldStream();
         //Throw this IO Exception since IndexREader.document does so anyway, so probably not that big of a change for people
         //since they are already handling this exception when getting the document
         try {
@@ -326,11 +340,7 @@
      */
     public String stringValue() {
       if (fieldsData == null) {
-        IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get();
-        if (localFieldsStream == null) {
-          localFieldsStream = (IndexInput) fieldsStream.clone();
-          fieldsStreamTL.set(localFieldsStream);
-        }
+        IndexInput localFieldsStream = getFieldStream();
         try {
           localFieldsStream.seek(pointer);
           //read in chars b/c we already know the length we need to read