mirror of https://github.com/apache/lucene.git
LUCENE-1976: make IndexReader.isCurrent work correctly for NRT readers
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@826029 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a0776e5cd0
commit
052e1f5630
|
@ -90,6 +90,10 @@ Bug fixes
|
|||
* LUCENE-1124: Make sure FuzzyQuery always matches the precise term.
|
||||
(stefatwork@gmail.com via Mike McCandless)
|
||||
|
||||
* LUCENE-1976: Fix IndexReader.isCurrent() to return the right thing
|
||||
when the reader is a near real-time reader. (Jake Mannix via Mike
|
||||
McCandless)
|
||||
|
||||
New features
|
||||
|
||||
* LUCENE-1933: Provide a convenience AttributeFactory that creates a
|
||||
|
|
|
@ -50,6 +50,7 @@ class DirectoryReader extends IndexReader implements Cloneable {
|
|||
private final HashSet synced = new HashSet();
|
||||
private Lock writeLock;
|
||||
private SegmentInfos segmentInfos;
|
||||
private SegmentInfos segmentInfosStart;
|
||||
private boolean stale;
|
||||
private final int termInfosIndexDivisor;
|
||||
|
||||
|
@ -124,6 +125,7 @@ class DirectoryReader extends IndexReader implements Cloneable {
|
|||
this.directory = writer.getDirectory();
|
||||
this.readOnly = true;
|
||||
this.segmentInfos = infos;
|
||||
segmentInfosStart = (SegmentInfos) infos.clone();
|
||||
this.termInfosIndexDivisor = termInfosIndexDivisor;
|
||||
if (!readOnly) {
|
||||
// We assume that this segments_N was previously
|
||||
|
@ -769,19 +771,14 @@ class DirectoryReader extends IndexReader implements Cloneable {
|
|||
return segmentInfos.getUserData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this IndexReader is still using the current (i.e., most recently committed) version of the index. If
|
||||
* a writer has committed any changes to the index since this reader was opened, this will return <code>false</code>,
|
||||
* in which case you must open a new IndexReader in order
|
||||
* to see the changes. Use {@link IndexWriter#commit} to
|
||||
* commit changes to the index.
|
||||
*
|
||||
* @throws CorruptIndexException if the index is corrupt
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public boolean isCurrent() throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion();
|
||||
if (writer == null || writer.isClosed()) {
|
||||
// we loaded SegmentInfos from the directory
|
||||
return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion();
|
||||
} else {
|
||||
return writer.nrtIsCurrent(segmentInfosStart);
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void doClose() throws IOException {
|
||||
|
|
|
@ -535,6 +535,13 @@ final class DocumentsWriter {
|
|||
return true;
|
||||
}
|
||||
|
||||
synchronized boolean anyChanges() {
|
||||
return numDocsInRAM != 0 ||
|
||||
deletesInRAM.numTerms != 0 ||
|
||||
deletesInRAM.docIDs.size() != 0 ||
|
||||
deletesInRAM.queries.size() != 0;
|
||||
}
|
||||
|
||||
synchronized private void initFlushState(boolean onlyDocStore) {
|
||||
initSegmentName(onlyDocStore);
|
||||
flushState = new SegmentWriteState(this, directory, segment, docStoreSegment, numDocsInRAM, numDocsInStore, writer.getTermIndexInterval());
|
||||
|
|
|
@ -468,7 +468,27 @@ public abstract class IndexReader implements Cloneable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Version number when this IndexReader was opened. Not implemented in the IndexReader base class.
|
||||
* Version number when this IndexReader was opened. Not
|
||||
* implemented in the IndexReader base class.
|
||||
*
|
||||
* <p>If this reader is based on a Directory (ie, was
|
||||
* created by calling {@link #open}, or {@link #reopen} on
|
||||
* a reader based on a Directory), then this method
|
||||
* returns the version recorded in the commit that the
|
||||
* reader opened. This version is advanced every time
|
||||
* {@link IndexWriter#commit} is called.</p>
|
||||
*
|
||||
* <p>If instead this reader is a near real-time reader
|
||||
* (ie, obtained by a call to {@link
|
||||
* IndexWriter#getReader}, or by calling {@link #reopen}
|
||||
* on a near real-time reader), then this method returns
|
||||
* the version of the last commit done by the writer.
|
||||
* Note that even as further changes are made with the
|
||||
* writer, the version will not changed until a commit is
|
||||
* completed. Thus, you should not rely on this method to
|
||||
* determine when a near real-time reader should be
|
||||
* opened. Use {@link #isCurrent} instead.</p>
|
||||
*
|
||||
* @throws UnsupportedOperationException unless overridden in subclass
|
||||
*/
|
||||
public long getVersion() {
|
||||
|
@ -487,21 +507,32 @@ public abstract class IndexReader implements Cloneable {
|
|||
throw new UnsupportedOperationException("This reader does not support this method.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether this IndexReader is still using the
|
||||
* current (i.e., most recently committed) version of the
|
||||
* index. If a writer has committed any changes to the
|
||||
* index since this reader was opened, this will return
|
||||
* <code>false</code>, in which case you must open a new
|
||||
* IndexReader in order to see the changes. Changes must
|
||||
* be committed using {@link IndexWriter#commit} to be
|
||||
* visible to readers.
|
||||
*
|
||||
* <p>
|
||||
* Not implemented in the IndexReader base class.
|
||||
* </p>
|
||||
* Check whether any new changes have occurred to the
|
||||
* index since this reader was opened.
|
||||
*
|
||||
* <p>If this reader is based on a Directory (ie, was
|
||||
* created by calling {@link #open}, or {@link #reopen} on
|
||||
* a reader based on a Directory), then this method checks
|
||||
* if any further commits (see {@link IndexWriter#commit}
|
||||
* have occurred in that directory).</p>
|
||||
*
|
||||
* <p>If instead this reader is a near real-time reader
|
||||
* (ie, obtained by a call to {@link
|
||||
* IndexWriter#getReader}, or by calling {@link #reopen}
|
||||
* on a near real-time reader), then this method checks if
|
||||
* either a new commmit has occurred, or any new
|
||||
* uncommitted changes have taken place via the writer.
|
||||
* Note that even if the writer has only performed
|
||||
* merging, this method will still return false.</p>
|
||||
*
|
||||
* <p>In any event, if this returns false, you should call
|
||||
* {@link #reopen} to get a new reader that sees the
|
||||
* changes.</p>
|
||||
*
|
||||
* @throws CorruptIndexException if the index is corrupt
|
||||
* @throws IOException if there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
* @throws UnsupportedOperationException unless overridden in subclass
|
||||
*/
|
||||
public boolean isCurrent() throws CorruptIndexException, IOException {
|
||||
|
|
|
@ -4844,4 +4844,18 @@ public class IndexWriter {
|
|||
boolean testPoint(String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
synchronized boolean nrtIsCurrent(SegmentInfos infos) {
|
||||
if (!infos.equals(segmentInfos)) {
|
||||
// if any structural changes (new segments), we are
|
||||
// stale
|
||||
return false;
|
||||
} else {
|
||||
return !docWriter.anyChanges();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class TestIndexWriterReader extends LuceneTestCase {
|
|||
|
||||
Directory dir1 = new MockRAMDirectory();
|
||||
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(),
|
||||
IndexWriter.MaxFieldLength.LIMITED);
|
||||
IndexWriter.MaxFieldLength.LIMITED);
|
||||
|
||||
// create the index
|
||||
createIndexNoClose(!optimize, "index1", writer);
|
||||
|
@ -85,6 +85,7 @@ public class TestIndexWriterReader extends LuceneTestCase {
|
|||
|
||||
// get a reader
|
||||
IndexReader r1 = writer.getReader();
|
||||
assertTrue(r1.isCurrent());
|
||||
|
||||
String id10 = r1.document(10).getField("id").stringValue();
|
||||
|
||||
|
@ -92,18 +93,37 @@ public class TestIndexWriterReader extends LuceneTestCase {
|
|||
newDoc.removeField("id");
|
||||
newDoc.add(new Field("id", Integer.toString(8000), Store.YES, Index.NOT_ANALYZED));
|
||||
writer.updateDocument(new Term("id", id10), newDoc);
|
||||
assertFalse(r1.isCurrent());
|
||||
|
||||
IndexReader r2 = writer.getReader();
|
||||
assertTrue(r2.isCurrent());
|
||||
assertEquals(0, count(new Term("id", id10), r2));
|
||||
assertEquals(1, count(new Term("id", Integer.toString(8000)), r2));
|
||||
|
||||
r1.close();
|
||||
r2.close();
|
||||
writer.close();
|
||||
assertTrue(r2.isCurrent());
|
||||
|
||||
IndexReader r3 = IndexReader.open(dir1, true);
|
||||
assertTrue(r3.isCurrent());
|
||||
assertTrue(r2.isCurrent());
|
||||
assertEquals(0, count(new Term("id", id10), r3));
|
||||
assertEquals(1, count(new Term("id", Integer.toString(8000)), r3));
|
||||
|
||||
writer = new IndexWriter(dir1, new WhitespaceAnalyzer(),
|
||||
IndexWriter.MaxFieldLength.LIMITED);
|
||||
Document doc = new Document();
|
||||
doc.add(new Field("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
|
||||
writer.addDocument(doc);
|
||||
assertTrue(r2.isCurrent());
|
||||
assertTrue(r3.isCurrent());
|
||||
|
||||
writer.close();
|
||||
|
||||
assertFalse(r2.isCurrent());
|
||||
assertTrue(!r3.isCurrent());
|
||||
|
||||
r2.close();
|
||||
r3.close();
|
||||
|
||||
dir1.close();
|
||||
|
@ -133,9 +153,18 @@ public class TestIndexWriterReader extends LuceneTestCase {
|
|||
createIndexNoClose(!optimize, "index2", writer2);
|
||||
writer2.close();
|
||||
|
||||
IndexReader r0 = writer.getReader();
|
||||
assertTrue(r0.isCurrent());
|
||||
writer.addIndexesNoOptimize(new Directory[] { dir2 });
|
||||
assertFalse(r0.isCurrent());
|
||||
r0.close();
|
||||
|
||||
IndexReader r1 = writer.getReader();
|
||||
assertTrue(r1.isCurrent());
|
||||
|
||||
writer.commit();
|
||||
assertTrue(r1.isCurrent());
|
||||
|
||||
assertEquals(200, r1.maxDoc());
|
||||
|
||||
int index2df = r1.docFreq(new Term("indexname", "index2"));
|
||||
|
|
Loading…
Reference in New Issue