LUCENE-1201: add IndexReader.getIndexCommit to see which index commit a reader is reading

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@634251 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2008-03-06 12:57:08 +00:00
parent 69f35943bd
commit c113c6419d
13 changed files with 235 additions and 57 deletions

View File

@ -110,6 +110,9 @@ New features
and isLocked methods (deprecating the ones in IndexReader). (Mike
McCandless)
10. LUCENE-1201: Add IndexReader.getIndexCommit() method. (Tim Brennan
via Mike McCandless)
Optimizations
1. LUCENE-705: When building a compound file, use

View File

@ -20,6 +20,8 @@ package org.apache.lucene.index;
import java.io.IOException;
import java.util.HashSet;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.store.Directory;
@ -96,7 +98,6 @@ abstract class DirectoryIndexReader extends IndexReader {
}.run();
}
public final synchronized IndexReader reopen() throws CorruptIndexException, IOException {
ensureOpen();
@ -337,4 +338,42 @@ abstract class DirectoryIndexReader extends IndexReader {
}
}
private static class ReaderCommit extends IndexCommit {
private String segmentsFileName;
Collection files;
Directory dir;
ReaderCommit(SegmentInfos infos, Directory dir) throws IOException {
segmentsFileName = infos.getCurrentSegmentFileName();
this.dir = dir;
final int size = infos.size();
files = new ArrayList(size);
files.add(segmentsFileName);
for(int i=0;i<size;i++) {
SegmentInfo info = infos.info(i);
if (info.dir == dir)
files.addAll(info.files());
}
}
public String getSegmentsFileName() {
return segmentsFileName;
}
public Collection getFileNames() {
return files;
}
public Directory getDirectory() {
return dir;
}
}
/**
* Expert: return the IndexCommit that this reader has
* opened.
*
* <p><b>WARNING</b>: this API is new and experimental and
* may suddenly change.</p>
*/
public IndexCommit getIndexCommit() throws IOException {
return new ReaderCommit(segmentInfos, directory);
}
}

View File

@ -0,0 +1,92 @@
package org.apache.lucene.index;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Collection;
import java.io.IOException;
import org.apache.lucene.store.Directory;
/**
* <p>Expert: represents a single commit into an index as seen by the
* {@link IndexDeletionPolicy} or {@link IndexReader}.</p>
*
* <p> Changes to the content of an index are made visible
* only after the writer who made that change commits by
* writing a new segments file
* (<code>segments_N</code>). This point in time, when the
* action of writing of a new segments file to the directory
* is completed, is an index commit.</p>
*
* <p>Each index commit point has a unique segments file
* associated with it. The segments file associated with a
* later index commit point would have a larger N.</p>
*
* <p><b>WARNING</b>: This API is a new and experimental and
* may suddenly change. </p>
*/
public abstract class IndexCommit implements IndexCommitPoint {
/**
* Get the segments file (<code>segments_N</code>) associated
* with this commit point.
*/
public abstract String getSegmentsFileName();
/**
* Returns all index files referenced by this commit point.
*/
public abstract Collection getFileNames() throws IOException;
/**
* Returns the {@link Directory} for the index.
*/
public abstract Directory getDirectory();
/**
* Delete this commit point. This only applies when using
* the commit point in the context of IndexWriter's
* IndexDeletionPolicy.
* <p>
* Upon calling this, the writer is notified that this commit
* point should be deleted.
* <p>
* Decision that a commit-point should be deleted is taken by the {@link IndexDeletionPolicy} in effect
* and therefore this should only be called by its {@link IndexDeletionPolicy#onInit onInit()} or
* {@link IndexDeletionPolicy#onCommit onCommit()} methods.
*/
public void delete() {
throw new UnsupportedOperationException("This IndexCommit does not support this method.");
}
/**
* Two IndexCommits are equal if both their Directory and
* segmentsFileName are equal.
*/
public boolean equals(Object other) {
if (other instanceof IndexCommit) {
IndexCommit otherCommit = (IndexCommit) other;
return otherCommit.getDirectory().equals(getDirectory()) && otherCommit.getSegmentsFileName().equals(getSegmentsFileName());
} else
return false;
}
public int hashCode() {
return getDirectory().hashCode() + getSegmentsFileName().hashCode();
}
}

View File

@ -17,24 +17,13 @@ package org.apache.lucene.index;
* limitations under the License.
*/
/**
* <p>Expert: represents a single commit into an index as seen by the
* {@link IndexDeletionPolicy}.
* <p>
* Changes to the content of an index are made visible only
* after the writer who made that change had written to the
* directory a new segments file (<code>segments_N</code>). This point in
* time, when the action of writing of a new segments file to the
* directory is completed, is therefore an index commit point.
* <p>
* Each index commit point has a unique segments file associated
* with it. The segments file associated with a later
* index commit point would have a larger N.
*/
import java.util.Collection;
import java.io.IOException;
/**
* @deprecated Please subclass IndexCommit class instead
*/
public interface IndexCommitPoint {
/**

View File

@ -21,12 +21,12 @@ import java.util.List;
import java.io.IOException;
/**
* <p>Expert: policy for deletion of stale {@link IndexCommitPoint index commits}.
* <p>Expert: policy for deletion of stale {@link IndexCommit index commits}.
*
* <p>Implement this interface, and pass it to one
* of the {@link IndexWriter} or {@link IndexReader}
* constructors, to customize when older
* {@link IndexCommitPoint point-in-time commits}
* {@link IndexCommit point-in-time commits}
* are deleted from the index directory. The default deletion policy
* is {@link KeepOnlyLastCommitDeletionPolicy}, which always
* removes old commits as soon as a new commit is done (this
@ -58,8 +58,8 @@ public interface IndexDeletionPolicy {
* <p>The writer locates all index commits present in the
* index directory and calls this method. The policy may
* choose to delete some of the commit points, doing so by
* calling method {@link IndexCommitPoint#delete delete()}
* of {@link IndexCommitPoint}.</p>
* calling method {@link IndexCommit#delete delete()}
* of {@link IndexCommit}.</p>
*
* <p><u>Note:</u> the last CommitPoint is the most recent one,
* i.e. the "front index state". Be careful not to delete it,
@ -67,7 +67,7 @@ public interface IndexDeletionPolicy {
* you can afford to lose the index content while doing that.
*
* @param commits List of current
* {@link IndexCommitPoint point-in-time commits},
* {@link IndexCommit point-in-time commits},
* sorted by age (the 0th one is the oldest commit).
*/
public void onInit(List commits) throws IOException;
@ -78,8 +78,8 @@ public interface IndexDeletionPolicy {
* with each commit.</p>
*
* <p>The policy may now choose to delete old commit points
* by calling method {@link IndexCommitPoint#delete delete()}
* of {@link IndexCommitPoint}.</p>
* by calling method {@link IndexCommit#delete delete()}
* of {@link IndexCommit}.</p>
*
* <p>If writer has <code>autoCommit = true</code> then
* this method will in general be called many times during
@ -94,7 +94,7 @@ public interface IndexDeletionPolicy {
* unless you know for sure what you are doing, and unless
* you can afford to lose the index content while doing that.
*
* @param commits List of {@link IndexCommitPoint},
* @param commits List of {@link IndexCommit},
* sorted by age (the 0th one is the oldest commit).
*/
public void onCommit(List commits) throws IOException;

View File

@ -48,7 +48,7 @@ import java.util.Collection;
* force a blocking commit.
*
* The same directory file may be referenced by more than
* one IndexCommitPoints, i.e. more than one SegmentInfos.
* one IndexCommit, i.e. more than one SegmentInfos.
* Therefore we count how many commits reference each file.
* When all the commits referencing a certain file have been
* deleted, the refcount for that file becomes zero, and the
@ -569,7 +569,7 @@ final class IndexFileDeleter {
* equals.
*/
final private static class CommitPoint implements Comparable, IndexCommitPoint {
final private static class CommitPoint extends IndexCommit implements Comparable {
long gen;
List files;
@ -594,9 +594,6 @@ final class IndexFileDeleter {
}
}
/**
* Get the segments_N file for this commit point.
*/
public String getSegmentsFileName() {
return segmentsFileName;
}
@ -605,6 +602,10 @@ final class IndexFileDeleter {
return Collections.unmodifiableCollection(files);
}
public Directory getDirectory() {
return directory;
}
/**
* Called only be the deletion policy, to remove this
* commit point from the index.

View File

@ -885,6 +885,19 @@ public abstract class IndexReader {
directory.makeLock(IndexWriter.WRITE_LOCK_NAME).release();
}
/**
* Expert: return the IndexCommit that this reader has
* opened. This method is only implemented by those
* readers that correspond to a Directory with its own
* segments_N file.
*
* <p><b>WARNING</b>: this API is new and experimental and
* may suddenly change.</p>
*/
public IndexCommit getIndexCommit() throws IOException {
throw new UnsupportedOperationException("This reader does not support this method.");
}
/**
* Prints the filename and size of each file within a given compound file.
* Add the -extract flag to extract files to the current working directory.

View File

@ -187,7 +187,7 @@ import java.util.Iterator;
* modified) directory files, we have a new "check point".
* If the modified/new SegmentInfos is written to disk - as a new
* (generation of) segments_N file - this check point is also an
* IndexCommitPoint.
* IndexCommit.
*
* With autoCommit=true, every checkPoint is also a CommitPoint.
* With autoCommit=false, some checkPoints may not be commits.

View File

@ -44,7 +44,7 @@ public final class KeepOnlyLastCommitDeletionPolicy implements IndexDeletionPoli
// called by onInit above):
int size = commits.size();
for(int i=0;i<size-1;i++) {
((IndexCommitPoint) commits.get(i)).delete();
((IndexCommit) commits.get(i)).delete();
}
}
}

View File

@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import org.apache.lucene.store.Directory;
/** A {@link IndexDeletionPolicy} that wraps around any other
* {@link IndexDeletionPolicy} and adds the ability to hold and
@ -35,11 +36,14 @@ import java.io.IOException;
* SnapshotDeletionPolicy across multiple writers as long
* as they are against the same index Directory. Any
* snapshot held when a writer is closed will "survive"
* when the next writer is opened. */
* when the next writer is opened.
*
* <p><b>WARNING</b>: This API is a new and experimental and
* may suddenly change.</p> */
public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
private IndexCommitPoint lastCommit;
private IndexCommit lastCommit;
private IndexDeletionPolicy primary;
private String snapshot;
@ -49,12 +53,12 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
public synchronized void onInit(List commits) throws IOException {
primary.onInit(wrapCommits(commits));
lastCommit = (IndexCommitPoint) commits.get(commits.size()-1);
lastCommit = (IndexCommit) commits.get(commits.size()-1);
}
public synchronized void onCommit(List commits) throws IOException {
primary.onCommit(wrapCommits(commits));
lastCommit = (IndexCommitPoint) commits.get(commits.size()-1);
lastCommit = (IndexCommit) commits.get(commits.size()-1);
}
/** Take a snapshot of the most recent commit to the
@ -66,6 +70,7 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
* you call optimize()) then in the worst case this could
* consume an extra 1X of your total index size, until
* you release the snapshot. */
// TODO 3.0: change this to return IndexCommit instead
public synchronized IndexCommitPoint snapshot() {
if (snapshot == null)
snapshot = lastCommit.getSegmentsFileName();
@ -82,9 +87,9 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
throw new IllegalStateException("snapshot was not set; please call snapshot() first");
}
private class MyCommitPoint implements IndexCommitPoint {
IndexCommitPoint cp;
MyCommitPoint(IndexCommitPoint cp) {
private class MyCommitPoint extends IndexCommit {
IndexCommit cp;
MyCommitPoint(IndexCommit cp) {
this.cp = cp;
}
public String getSegmentsFileName() {
@ -93,6 +98,9 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
public Collection getFileNames() throws IOException {
return cp.getFileNames();
}
public Directory getDirectory() {
return cp.getDirectory();
}
public void delete() {
synchronized(SnapshotDeletionPolicy.this) {
// Suppress the delete request if this commit point is
@ -107,7 +115,7 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
final int count = commits.size();
List myCommits = new ArrayList(count);
for(int i=0;i<count;i++)
myCommits.add(new MyCommitPoint((IndexCommitPoint) commits.get(i)));
myCommits.add(new MyCommitPoint((IndexCommit) commits.get(i)));
return myCommits;
}
}

View File

@ -31,7 +31,7 @@ import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.MockRAMDirectory;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexCommitPoint;
import org.apache.lucene.index.IndexCommit;
import org.apache.lucene.index.KeepOnlyLastCommitDeletionPolicy;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.TestIndexWriter;
@ -75,25 +75,25 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
doc.add(new Field("content", "aaa", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
for(int i=0;i<7;i++)
writer.addDocument(doc);
IndexCommitPoint cp = dp.snapshot();
copyFiles(dir, dp, cp);
IndexCommit cp = (IndexCommit) dp.snapshot();
copyFiles(dir, cp);
writer.close();
copyFiles(dir, dp, cp);
copyFiles(dir, cp);
writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp,
IndexWriter.MaxFieldLength.LIMITED);
copyFiles(dir, dp, cp);
copyFiles(dir, cp);
for(int i=0;i<7;i++)
writer.addDocument(doc);
copyFiles(dir, dp, cp);
copyFiles(dir, cp);
writer.close();
copyFiles(dir, dp, cp);
copyFiles(dir, cp);
dp.release();
writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp,
IndexWriter.MaxFieldLength.LIMITED);
writer.close();
try {
copyFiles(dir, dp, cp);
copyFiles(dir, cp);
fail("did not hit expected IOException");
} catch (IOException ioe) {
// expected
@ -177,7 +177,7 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
public void backupIndex(Directory dir, SnapshotDeletionPolicy dp) throws IOException {
// To backup an index we first take a snapshot:
try {
copyFiles(dir, dp, dp.snapshot());
copyFiles(dir, (IndexCommit) dp.snapshot());
} finally {
// Make sure to release the snapshot, otherwise these
// files will never be deleted during this IndexWriter
@ -186,7 +186,7 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
}
}
private void copyFiles(Directory dir, SnapshotDeletionPolicy dp, IndexCommitPoint cp) throws IOException {
private void copyFiles(Directory dir, IndexCommit cp) throws IOException {
// While we hold the snapshot, and nomatter how long
// we take to do the backup, the IndexWriter will

View File

@ -43,9 +43,9 @@ import java.util.HashSet;
public class TestDeletionPolicy extends LuceneTestCase
{
private void verifyCommitOrder(List commits) {
long last = SegmentInfos.generationFromSegmentsFileName(((IndexCommitPoint) commits.get(0)).getSegmentsFileName());
long last = SegmentInfos.generationFromSegmentsFileName(((IndexCommit) commits.get(0)).getSegmentsFileName());
for(int i=1;i<commits.size();i++) {
long now = SegmentInfos.generationFromSegmentsFileName(((IndexCommitPoint) commits.get(i)).getSegmentsFileName());
long now = SegmentInfos.generationFromSegmentsFileName(((IndexCommit) commits.get(i)).getSegmentsFileName());
assertTrue("SegmentInfos commits are out-of-order", now > last);
last = now;
}
@ -77,7 +77,7 @@ public class TestDeletionPolicy extends LuceneTestCase
// On init, delete all commit points:
Iterator it = commits.iterator();
while(it.hasNext()) {
((IndexCommitPoint) it.next()).delete();
((IndexCommit) it.next()).delete();
}
}
public void onCommit(List commits) {
@ -85,7 +85,7 @@ public class TestDeletionPolicy extends LuceneTestCase
int size = commits.size();
// Delete all but last one:
for(int i=0;i<size-1;i++) {
((IndexCommitPoint) commits.get(i)).delete();
((IndexCommit) commits.get(i)).delete();
}
numOnCommit++;
}
@ -119,7 +119,7 @@ public class TestDeletionPolicy extends LuceneTestCase
// Assert that we really are only called for each new
// commit:
if (isCommit) {
String fileName = ((IndexCommitPoint) commits.get(commits.size()-1)).getSegmentsFileName();
String fileName = ((IndexCommit) commits.get(commits.size()-1)).getSegmentsFileName();
if (seen.contains(fileName)) {
throw new RuntimeException("onCommit was called twice on the same commit point: " + fileName);
}
@ -128,7 +128,7 @@ public class TestDeletionPolicy extends LuceneTestCase
}
int size = commits.size();
for(int i=0;i<size-numToKeep;i++) {
((IndexCommitPoint) commits.get(i)).delete();
((IndexCommit) commits.get(i)).delete();
numDelete++;
}
}
@ -157,7 +157,7 @@ public class TestDeletionPolicy extends LuceneTestCase
public void onCommit(List commits) throws IOException {
verifyCommitOrder(commits);
IndexCommitPoint lastCommit = (IndexCommitPoint) commits.get(commits.size()-1);
IndexCommit lastCommit = (IndexCommit) commits.get(commits.size()-1);
// Any commit older than expireTime should be deleted:
double expireTime = dir.fileModified(lastCommit.getSegmentsFileName())/1000.0 - expirationTimeSeconds;
@ -165,7 +165,7 @@ public class TestDeletionPolicy extends LuceneTestCase
Iterator it = commits.iterator();
while(it.hasNext()) {
IndexCommitPoint commit = (IndexCommitPoint) it.next();
IndexCommit commit = (IndexCommit) it.next();
double modTime = dir.fileModified(commit.getSegmentsFileName())/1000.0;
if (commit != lastCommit && modTime < expireTime) {
commit.delete();

View File

@ -1276,4 +1276,37 @@ public class TestIndexReader extends LuceneTestCase
}
}
public void testGetIndexCommit() throws IOException {
RAMDirectory d = new MockRAMDirectory();
// set up writer
IndexWriter writer = new IndexWriter(d, new StandardAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
writer.setMaxBufferedDocs(2);
for(int i=0;i<27;i++)
addDocumentWithFields(writer);
writer.close();
SegmentInfos sis = new SegmentInfos();
sis.read(d);
IndexReader r = IndexReader.open(d);
IndexCommit c = r.getIndexCommit();
assertEquals(sis.getCurrentSegmentFileName(), c.getSegmentsFileName());
assertTrue(c.equals(r.getIndexCommit()));
// Change the index
writer = new IndexWriter(d, new StandardAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED);
writer.setMaxBufferedDocs(2);
for(int i=0;i<7;i++)
addDocumentWithFields(writer);
writer.close();
IndexReader r2 = r.reopen();
assertFalse(c.equals(r2.getIndexCommit()));
r.close();
r2.close();
d.close();
}
}