LUCENE-1314: allow clone of subreaders; add note to getSequentialSubReaders javadoc to not use sub-readers to make changes

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@744653 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2009-02-15 10:56:36 +00:00
parent 8b79fa51a5
commit cd89bc9de3
4 changed files with 53 additions and 13 deletions

View File

@ -167,11 +167,16 @@ abstract class DirectoryIndexReader extends IndexReader implements Cloneable {
public final synchronized IndexReader clone(boolean openReadOnly) throws CorruptIndexException, IOException { public final synchronized IndexReader clone(boolean openReadOnly) throws CorruptIndexException, IOException {
final SegmentInfos infos = (SegmentInfos) segmentInfos.clone(); final SegmentInfos clonedInfos;
DirectoryIndexReader newReader = doReopen(infos, true, openReadOnly); if (segmentInfos != null) {
clonedInfos = (SegmentInfos) segmentInfos.clone();
} else {
clonedInfos = null;
}
DirectoryIndexReader newReader = doReopen(clonedInfos, true, openReadOnly);
if (this != newReader) { if (this != newReader) {
newReader.init(directory, infos, closeDirectory, openReadOnly); newReader.init(directory, clonedInfos, closeDirectory, openReadOnly);
newReader.deletionPolicy = deletionPolicy; newReader.deletionPolicy = deletionPolicy;
} }

View File

@ -1184,13 +1184,21 @@ public abstract class IndexReader implements Cloneable {
return DirectoryIndexReader.listCommits(dir); return DirectoryIndexReader.listCommits(dir);
} }
/** Returns the sequential sub readers that this reader is /** Expert: returns the sequential sub readers that this
* logically composed of. IndexSearcher uses this API to * reader is logically composed of. For example,
* drive searching by one sub reader at a time. If this * IndexSearcher uses this API to drive searching by one
* reader is not composed of sequential child readers, it * sub reader at a time. If this reader is not composed
* should return null. If this method returns an empty * of sequential child readers, it should return null.
* array, that means this reader is a null reader (for * If this method returns an empty array, that means this
* example a MultiReader that has no sub readers).*/ * reader is a null reader (for example a MultiReader
* that has no sub readers).
* <p>
* NOTE: for a MultiSegmentReader, which is obtained by
* {@link #open} when the index has more than one
* segment, you should not use the sub-readers returned
* by this method to make any changes (setNorm,
* deleteDocument, etc.). Doing so will likely lead to
* index corruption. Use the parent reader instead. */
public IndexReader[] getSequentialSubReaders() { public IndexReader[] getSequentialSubReaders() {
return null; return null;
} }

View File

@ -626,7 +626,14 @@ class SegmentReader extends DirectoryIndexReader {
protected synchronized DirectoryIndexReader doReopen(SegmentInfos infos, boolean doClone, boolean openReadOnly) throws CorruptIndexException, IOException { protected synchronized DirectoryIndexReader doReopen(SegmentInfos infos, boolean doClone, boolean openReadOnly) throws CorruptIndexException, IOException {
DirectoryIndexReader newReader; DirectoryIndexReader newReader;
if (infos.size() == 1) { if (infos == null) {
if (doClone) {
// OK: directly clone myself
newReader = reopenSegment(si, doClone, openReadOnly);
} else {
throw new UnsupportedOperationException("cannot reopen a standalone SegmentReader");
}
} else if (infos.size() == 1) {
SegmentInfo si = infos.info(0); SegmentInfo si = infos.info(0);
if (segment.equals(si.name) && si.getUseCompoundFile() == SegmentReader.this.si.getUseCompoundFile()) { if (segment.equals(si.name) && si.getUseCompoundFile() == SegmentReader.this.si.getUseCompoundFile()) {
newReader = reopenSegment(si, doClone, openReadOnly); newReader = reopenSegment(si, doClone, openReadOnly);

View File

@ -403,4 +403,24 @@ public class TestIndexReaderClone extends LuceneTestCase {
private void assertDelDocsRefCountEquals(int refCount, SegmentReader reader) { private void assertDelDocsRefCountEquals(int refCount, SegmentReader reader) {
assertEquals(refCount, reader.deletedDocsRef.refCount()); assertEquals(refCount, reader.deletedDocsRef.refCount());
} }
public void testCloneSubreaders() throws Exception {
final Directory dir1 = new MockRAMDirectory();
TestIndexReaderReopen.createIndex(dir1, true);
IndexReader reader = IndexReader.open(dir1);
reader.deleteDocument(1); // acquire write lock
IndexReader[] subs = reader.getSequentialSubReaders();
assert subs.length > 1;
IndexReader[] clones = new IndexReader[subs.length];
for (int x=0; x < subs.length; x++) {
clones[x] = (IndexReader) subs[x].clone();
}
reader.close();
for (int x=0; x < subs.length; x++) {
clones[x].close();
}
dir1.close();
}
} }