Return-Path: Delivered-To: apmail-lucene-java-commits-archive@www.apache.org Received: (qmail 559 invoked from network); 18 Nov 2008 09:58:44 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 18 Nov 2008 09:58:44 -0000 Received: (qmail 63023 invoked by uid 500); 18 Nov 2008 09:58:52 -0000 Delivered-To: apmail-lucene-java-commits-archive@lucene.apache.org Received: (qmail 63009 invoked by uid 500); 18 Nov 2008 09:58:52 -0000 Mailing-List: contact java-commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: java-dev@lucene.apache.org Delivered-To: mailing list java-commits@lucene.apache.org Received: (qmail 63000 invoked by uid 99); 18 Nov 2008 09:58:52 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Nov 2008 01:58:52 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Nov 2008 09:57:39 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 8690423889B7; Tue, 18 Nov 2008 01:57:53 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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 Date: Tue, 18 Nov 2008 09:57:52 -0000 To: java-commits@lucene.apache.org From: mikemccand@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20081118095753.8690423889B7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 + } + } }