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 mi...@apache.org on 2008/11/18 10:57:52 UTC

svn commit: r718540 - in /lucene/java/trunk/src: java/org/apache/lucene/index/DirectoryIndexReader.java java/org/apache/lucene/index/SegmentReader.java test/org/apache/lucene/index/TestIndexReaderReopen.java

Author: mikemccand
Date: Tue Nov 18 01:57:51 2008
New Revision: 718540

URL: http://svn.apache.org/viewvc?rev=718540&view=rev
Log:
LUCENE-1453: make sure reopen of IndexReaders that own the directory don't close the directory too soon

Modified:
    lucene/java/trunk/src/java/org/apache/lucene/index/DirectoryIndexReader.java
    lucene/java/trunk/src/java/org/apache/lucene/index/SegmentReader.java
    lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java

Modified: lucene/java/trunk/src/java/org/apache/lucene/index/DirectoryIndexReader.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/index/DirectoryIndexReader.java?rev=718540&r1=718539&r2=718540&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/index/DirectoryIndexReader.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/index/DirectoryIndexReader.java Tue Nov 18 01:57:51 2008
@@ -28,6 +28,7 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.Lock;
 import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.store.FSDirectory;
 
 /**
  * IndexReader implementation that has access to a Directory. 
@@ -147,7 +148,7 @@
       return this;
     }
 
-    return (DirectoryIndexReader) new SegmentInfos.FindSegmentsFile(directory) {
+    final SegmentInfos.FindSegmentsFile finder = new SegmentInfos.FindSegmentsFile(directory) {
 
       protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
         SegmentInfos infos = new SegmentInfos();
@@ -162,7 +163,35 @@
 
         return newReader;
       }
-    }.run();
+    };
+
+    DirectoryIndexReader reader = null;
+
+    // While trying to reopen, we temporarily mark our
+    // closeDirectory as false.  This way any exceptions hit
+    // partway while opening the reader, which is expected
+    // eg if writer is committing, won't close our
+    // directory.  We restore this value below:
+    final boolean myCloseDirectory = closeDirectory;
+    closeDirectory = false;
+
+    try {
+      reader = (DirectoryIndexReader) finder.run();
+    } finally {
+      if (myCloseDirectory) {
+        assert directory instanceof FSDirectory;
+        // Restore my closeDirectory
+        closeDirectory = true;
+        if (reader != null && reader != this) {
+          // Success, and a new reader was actually opened
+          reader.closeDirectory = true;
+          // Clone the directory
+          reader.directory = FSDirectory.getDirectory(((FSDirectory) directory).getFile());
+        }
+      }
+    }
+
+    return reader;
   }
 
   /**

Modified: lucene/java/trunk/src/java/org/apache/lucene/index/SegmentReader.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/index/SegmentReader.java?rev=718540&r1=718539&r2=718540&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/index/SegmentReader.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/index/SegmentReader.java Tue Nov 18 01:57:51 2008
@@ -660,10 +660,13 @@
   
       if (storeCFSReader != null)
         storeCFSReader.close();
-      
-      // maybe close directory
-      super.doClose();
     }
+
+    // In DirectoryIndexReader.reopen, our directory
+    // instance was made private to us (cloned), so we
+    // always call super.doClose to possibly close the
+    // directory:
+    super.doClose();
   }
 
   static boolean hasDeletions(SegmentInfo si) throws IOException {

Modified: lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java?rev=718540&r1=718539&r2=718540&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java Tue Nov 18 01:57:51 2008
@@ -27,8 +27,6 @@
 import java.util.Random;
 import java.util.Set;
 
-import junit.framework.TestCase;
-
 import org.apache.lucene.analysis.KeywordAnalyzer;
 import org.apache.lucene.analysis.WhitespaceAnalyzer;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
@@ -43,6 +41,7 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.util.LuceneTestCase;
 
 public class TestIndexReaderReopen extends LuceneTestCase {
@@ -603,7 +602,7 @@
     TestIndexReader.assertIndexEquals(index1, index2);
     
     try {
-      ReaderCouple couple = refreshReader(index1, test, 0, true);
+      refreshReader(index1, test, 0, true);
       fail("Expected exception not thrown.");
     } catch (Exception e) {
       // expected exception
@@ -999,4 +998,63 @@
     indexDir = new File(tempDir, "IndexReaderReopen");
   }
   
+  // LUCENE-1453
+  public void testFSDirectoryReopen() throws CorruptIndexException, IOException {
+    Directory dir1 = FSDirectory.getDirectory(indexDir);
+    createIndex(dir1, false);
+    dir1.close();
+
+    IndexReader ir = IndexReader.open(indexDir);
+    modifyIndex(3, ir.directory());
+    IndexReader newIr = ir.reopen();
+    modifyIndex(3, newIr.directory());
+    IndexReader newIr2 = newIr.reopen();
+    modifyIndex(3, newIr2.directory());
+    IndexReader newIr3 = newIr2.reopen();
+    
+    ir.close();
+    newIr.close();
+    newIr2.close();
+    
+    // shouldn't throw Directory AlreadyClosedException
+    modifyIndex(3, newIr3.directory());
+    newIr3.close();
+  }
+
+  // LUCENE-1453
+  public void testFSDirectoryReopen2() throws CorruptIndexException, IOException {
+
+    String tempDir = System.getProperty("java.io.tmpdir");
+    if (tempDir == null)
+      throw new IOException("java.io.tmpdir undefined, cannot run test");
+    File indexDir2 = new File(tempDir, "IndexReaderReopen2");
+
+    Directory dir1 = FSDirectory.getDirectory(indexDir2);
+    createIndex(dir1, false);
+
+    IndexReader lastReader = IndexReader.open(indexDir2);
+    
+    Random r = new Random(42);
+    for(int i=0;i<10;i++) {
+      int mod = r.nextInt(5);
+      modifyIndex(mod, lastReader.directory());
+      IndexReader reader = lastReader.reopen();
+      if (reader != lastReader) {
+        lastReader.close();
+        lastReader = reader;
+      }
+    }
+    lastReader.close();
+
+    // Make sure we didn't pick up too many incRef's along
+    // the way -- this close should be the final close:
+    dir1.close();
+
+    try {
+      dir1.list();
+      fail("did not hit AlreadyClosedException");
+    } catch (AlreadyClosedException ace) {
+      // expected
+    }
+  }
 }