mirror of https://github.com/apache/lucene.git
LUCENE-1551: add expert IndexReader.reopen(IndexCommit)
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@752538 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cce1e98416
commit
75d6fab25b
|
@ -173,6 +173,11 @@ New features
|
|||
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
|
||||
|
|
|
@ -149,11 +149,15 @@ abstract class DirectoryIndexReader extends IndexReader implements Cloneable {
|
|||
|
||||
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 @@ abstract class DirectoryIndexReader extends IndexReader implements Cloneable {
|
|||
// 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 @@ abstract class DirectoryIndexReader extends IndexReader implements Cloneable {
|
|||
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;
|
||||
|
|
|
@ -369,6 +369,16 @@ public abstract class IndexReader implements Cloneable {
|
|||
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).
|
||||
|
|
|
@ -1052,6 +1052,7 @@ public class TestIndexReaderReopen extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private void assertReaderOpen(IndexReader reader) {
|
||||
reader.ensureOpen();
|
||||
|
||||
|
@ -1062,6 +1063,7 @@ public class TestIndexReaderReopen extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private void assertRefCountEquals(int refCount, IndexReader reader) {
|
||||
assertEquals("Reader has wrong refCount value.", refCount, reader.getRefCount());
|
||||
|
@ -1225,4 +1227,64 @@ public class TestIndexReaderReopen extends LuceneTestCase {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue