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 2009/03/11 18:32:38 UTC

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

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();
+  }
 }