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
|
15. LUCENE-1398: Add ReverseStringFilter to contrib/analyzers, a filter
|
||||||
to reverse the characters in each token. (Koji Sekiguchi via yonik)
|
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
|
Optimizations
|
||||||
|
|
||||||
1. LUCENE-1427: Fixed QueryWrapperFilter to not waste time computing
|
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 {
|
public final synchronized IndexReader reopen() throws CorruptIndexException, IOException {
|
||||||
// Preserve current readOnly
|
// Preserve current readOnly
|
||||||
return doReopen(readOnly);
|
return doReopen(readOnly, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final synchronized IndexReader reopen(boolean openReadOnly) throws CorruptIndexException, IOException {
|
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() {
|
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
|
// If there are no changes to the index, simply return
|
||||||
// ourself. If there are changes, load the latest
|
// ourself. If there are changes, load the latest
|
||||||
// SegmentInfos and reopen based on that
|
// 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();
|
ensureOpen();
|
||||||
|
|
||||||
if (hasChanges) {
|
assert commit == null || openReadOnly;
|
||||||
// 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) {
|
if (commit == null) {
|
||||||
return (IndexReader) clone(openReadOnly);
|
if (hasChanges) {
|
||||||
} else {
|
// We have changes, which means we are not readOnly:
|
||||||
return this;
|
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()) {
|
} else {
|
||||||
if (openReadOnly != readOnly) {
|
if (directory != commit.getDirectory())
|
||||||
// Just fallback to clone
|
throw new IOException("the specified commit does not match the specified Directory");
|
||||||
return (IndexReader) clone(openReadOnly);
|
if (segmentInfos != null && commit.getSegmentsFileName().equals(segmentInfos.getCurrentSegmentFileName())) {
|
||||||
} else {
|
if (readOnly != openReadOnly) {
|
||||||
return this;
|
// Just fallback to clone
|
||||||
|
return (IndexReader) clone(openReadOnly);
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +266,11 @@ abstract class DirectoryIndexReader extends IndexReader implements Cloneable {
|
||||||
closeDirectory = false;
|
closeDirectory = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
reader = (DirectoryIndexReader) finder.run();
|
if (commit == null) {
|
||||||
|
reader = (DirectoryIndexReader) finder.run();
|
||||||
|
} else {
|
||||||
|
reader = (DirectoryIndexReader) finder.doBody(commit.getSegmentsFileName());
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (myCloseDirectory) {
|
if (myCloseDirectory) {
|
||||||
assert directory instanceof FSDirectory;
|
assert directory instanceof FSDirectory;
|
||||||
|
|
|
@ -369,6 +369,16 @@ public abstract class IndexReader implements Cloneable {
|
||||||
throw new UnsupportedOperationException("This reader does not support reopen().");
|
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
|
* Efficiently clones the IndexReader (sharing most
|
||||||
* internal state).
|
* internal state).
|
||||||
|
|
|
@ -1052,6 +1052,7 @@ public class TestIndexReaderReopen extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private void assertReaderOpen(IndexReader reader) {
|
private void assertReaderOpen(IndexReader reader) {
|
||||||
reader.ensureOpen();
|
reader.ensureOpen();
|
||||||
|
|
||||||
|
@ -1062,6 +1063,7 @@ public class TestIndexReaderReopen extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
private void assertRefCountEquals(int refCount, IndexReader reader) {
|
private void assertRefCountEquals(int refCount, IndexReader reader) {
|
||||||
assertEquals("Reader has wrong refCount value.", refCount, reader.getRefCount());
|
assertEquals("Reader has wrong refCount value.", refCount, reader.getRefCount());
|
||||||
|
@ -1225,4 +1227,64 @@ public class TestIndexReaderReopen extends LuceneTestCase {
|
||||||
r2.close();
|
r2.close();
|
||||||
dir.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