Return-Path: Delivered-To: apmail-lucene-java-commits-archive@www.apache.org Received: (qmail 75664 invoked from network); 11 Mar 2009 17:33:06 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 11 Mar 2009 17:33:06 -0000 Received: (qmail 28927 invoked by uid 500); 11 Mar 2009 17:33:06 -0000 Delivered-To: apmail-lucene-java-commits-archive@lucene.apache.org Received: (qmail 28896 invoked by uid 500); 11 Mar 2009 17:33:06 -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 28887 invoked by uid 99); 11 Mar 2009 17:33:06 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 11 Mar 2009 10:33:06 -0700 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; Wed, 11 Mar 2009 17:32:59 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D876C23888E7; Wed, 11 Mar 2009 17:32:38 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r752538 - in /lucene/java/trunk: CHANGES.txt src/java/org/apache/lucene/index/DirectoryIndexReader.java src/java/org/apache/lucene/index/IndexReader.java src/test/org/apache/lucene/index/TestIndexReaderReopen.java Date: Wed, 11 Mar 2009 17:32:38 -0000 To: java-commits@lucene.apache.org From: mikemccand@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090311173238.D876C23888E7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: mikemccand Date: Wed Mar 11 17:32:37 2009 New Revision: 752538 URL: http://svn.apache.org/viewvc?rev=752538&view=rev Log: LUCENE-1551: add expert IndexReader.reopen(IndexCommit) Modified: lucene/java/trunk/CHANGES.txt lucene/java/trunk/src/java/org/apache/lucene/index/DirectoryIndexReader.java lucene/java/trunk/src/java/org/apache/lucene/index/IndexReader.java lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java Modified: lucene/java/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?rev=752538&r1=752537&r2=752538&view=diff ============================================================================== --- lucene/java/trunk/CHANGES.txt (original) +++ lucene/java/trunk/CHANGES.txt Wed Mar 11 17:32:37 2009 @@ -173,6 +173,11 @@ 15. LUCENE-1398: Add ReverseStringFilter to contrib/analyzers, a filter to reverse the characters in each token. (Koji Sekiguchi via yonik) +16. LUCENE-1551: Add expert IndexReader.reopen(IndexCommit) to allow + efficiently opening a new reader on a specific commit, sharing + resources with the original reader. (Torin Danil via Mike + McCandless) + Optimizations 1. LUCENE-1427: Fixed QueryWrapperFilter to not waste time computing 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=752538&r1=752537&r2=752538&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 Wed Mar 11 17:32:37 2009 @@ -149,11 +149,15 @@ public final synchronized IndexReader reopen() throws CorruptIndexException, IOException { // Preserve current readOnly - return doReopen(readOnly); + return doReopen(readOnly, null); } public final synchronized IndexReader reopen(boolean openReadOnly) throws CorruptIndexException, IOException { - return doReopen(openReadOnly); + return doReopen(openReadOnly, null); + } + + public final synchronized IndexReader reopen(final IndexCommit commit) throws CorruptIndexException, IOException { + return doReopen(true, commit); } public final synchronized Object clone() { @@ -194,29 +198,44 @@ // If there are no changes to the index, simply return // ourself. If there are changes, load the latest // SegmentInfos and reopen based on that - protected final synchronized IndexReader doReopen(final boolean openReadOnly) throws CorruptIndexException, IOException { + protected final synchronized IndexReader doReopen(final boolean openReadOnly, IndexCommit commit) throws CorruptIndexException, IOException { ensureOpen(); - if (hasChanges) { - // We have changes, which means we are not readOnly: - assert readOnly == false; - // and we hold the write lock: - assert writeLock != null; - // so no other writer holds the write lock, which - // means no changes could have been done to the index: - assert isCurrent(); + assert commit == null || openReadOnly; - if (openReadOnly) { - return (IndexReader) clone(openReadOnly); - } else { - return this; + if (commit == null) { + if (hasChanges) { + // We have changes, which means we are not readOnly: + assert readOnly == false; + // and we hold the write lock: + assert writeLock != null; + // so no other writer holds the write lock, which + // means no changes could have been done to the index: + assert isCurrent(); + + if (openReadOnly) { + return (IndexReader) clone(openReadOnly); + } else { + return this; + } + } else if (isCurrent()) { + if (openReadOnly != readOnly) { + // Just fallback to clone + return (IndexReader) clone(openReadOnly); + } else { + return this; + } } - } else if (isCurrent()) { - if (openReadOnly != readOnly) { - // Just fallback to clone - return (IndexReader) clone(openReadOnly); - } else { - return this; + } else { + if (directory != commit.getDirectory()) + throw new IOException("the specified commit does not match the specified Directory"); + if (segmentInfos != null && commit.getSegmentsFileName().equals(segmentInfos.getCurrentSegmentFileName())) { + if (readOnly != openReadOnly) { + // Just fallback to clone + return (IndexReader) clone(openReadOnly); + } else { + return this; + } } } @@ -247,7 +266,11 @@ closeDirectory = false; try { - reader = (DirectoryIndexReader) finder.run(); + if (commit == null) { + reader = (DirectoryIndexReader) finder.run(); + } else { + reader = (DirectoryIndexReader) finder.doBody(commit.getSegmentsFileName()); + } } finally { if (myCloseDirectory) { assert directory instanceof FSDirectory; Modified: lucene/java/trunk/src/java/org/apache/lucene/index/IndexReader.java URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/index/IndexReader.java?rev=752538&r1=752537&r2=752538&view=diff ============================================================================== --- lucene/java/trunk/src/java/org/apache/lucene/index/IndexReader.java (original) +++ lucene/java/trunk/src/java/org/apache/lucene/index/IndexReader.java Wed Mar 11 17:32:37 2009 @@ -369,6 +369,16 @@ throw new UnsupportedOperationException("This reader does not support reopen()."); } + /** Expert: reopen this reader on a specific commit point. + * This always returns a readOnly reader. If the + * specified commit point matches what this reader is + * already on, and this reader is already readOnly, then + * this same instance is returned; if it is not already + * readOnly, a readOnly clone is returned. */ + public synchronized IndexReader reopen(final IndexCommit commit) throws CorruptIndexException, IOException { + throw new UnsupportedOperationException("This reader does not support reopen(IndexCommit)."); + } + /** * Efficiently clones the IndexReader (sharing most * internal state). 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=752538&r1=752537&r2=752538&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 Wed Mar 11 17:32:37 2009 @@ -1052,6 +1052,7 @@ } } + /* private void assertReaderOpen(IndexReader reader) { reader.ensureOpen(); @@ -1062,6 +1063,7 @@ } } } + */ private void assertRefCountEquals(int refCount, IndexReader reader) { assertEquals("Reader has wrong refCount value.", refCount, reader.getRefCount()); @@ -1225,4 +1227,64 @@ r2.close(); dir.close(); } + + private static class KeepAllCommits implements IndexDeletionPolicy { + public void onInit(List commits) { + } + public void onCommit(List commits) { + } + } + + public void testReopenOnCommit() throws Throwable { + Directory dir = new MockRAMDirectory(); + IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), new KeepAllCommits(), IndexWriter.MaxFieldLength.UNLIMITED); + for(int i=0;i<4;i++) { + Document doc = new Document(); + doc.add(new Field("id", ""+i, Field.Store.NO, Field.Index.NOT_ANALYZED)); + writer.addDocument(doc); + writer.commit(""+i); + } + for(int i=0;i<4;i++) { + writer.deleteDocuments(new Term("id", ""+i)); + writer.commit(""+(4+i)); + } + writer.close(); + + IndexReader r = IndexReader.open(dir); + assertEquals(0, r.numDocs()); + assertEquals(4, r.maxDoc()); + + Iterator it = IndexReader.listCommits(dir).iterator(); + while(it.hasNext()) { + IndexCommit commit = (IndexCommit) it.next(); + IndexReader r2 = r.reopen(commit); + assertTrue(r2 != r); + + // Reader should be readOnly + try { + r2.deleteDocument(0); + fail("no exception hit"); + } catch (UnsupportedOperationException uoe) { + // expected + } + + final String s = commit.getUserData(); + final int v; + if (s == null) { + // First commit created by IW + v = -1; + } else { + v = Integer.parseInt(s); + } + if (v < 4) { + assertEquals(1+v, r2.numDocs()); + } else { + assertEquals(7-v, r2.numDocs()); + } + r.close(); + r = r2; + } + r.close(); + dir.close(); + } }