mirror of https://github.com/apache/lucene.git
LUCENE-1579: make sure cloned SegmentReaders share the same entry in FieldCache
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@760486 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7be6fa54f0
commit
12e212ccae
|
@ -1248,4 +1248,10 @@ public abstract class IndexReader implements Cloneable {
|
|||
public IndexReader[] getSequentialSubReaders() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Expert
|
||||
* @deprecated */
|
||||
public Object getFieldCacheKey() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1250,4 +1250,11 @@ class SegmentReader extends DirectoryIndexReader {
|
|||
norm.dirty = norm.rollbackDirty;
|
||||
}
|
||||
}
|
||||
|
||||
// This is necessary so that cloned SegmentReaders (which
|
||||
// share the underlying postings data) will map to the
|
||||
// same entry in the FieldCache. See LUCENE-1579.
|
||||
public final Object getFieldCacheKey() {
|
||||
return freqStream;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,13 @@ implements FieldCache {
|
|||
public Object get(IndexReader reader, Object key) throws IOException {
|
||||
Map innerCache;
|
||||
Object value;
|
||||
final Object readerKey = reader.getFieldCacheKey();
|
||||
|
||||
synchronized (readerCache) {
|
||||
innerCache = (Map) readerCache.get(reader);
|
||||
innerCache = (Map) readerCache.get(readerKey);
|
||||
if (innerCache == null) {
|
||||
innerCache = new HashMap();
|
||||
readerCache.put(reader, innerCache);
|
||||
readerCache.put(readerKey, innerCache);
|
||||
value = null;
|
||||
} else {
|
||||
value = innerCache.get(key);
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.apache.lucene.search.MultiReaderHitCollector;
|
|||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.FieldCache;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
|
@ -1685,4 +1686,112 @@ public class TestIndexReader extends LuceneTestCase
|
|||
s.close();
|
||||
r.close();
|
||||
}
|
||||
|
||||
// LUCENE-1579: Ensure that on a cloned reader, segments
|
||||
// reuse the doc values arrays in FieldCache
|
||||
public void testFieldCacheReuseAfterClone() throws Exception {
|
||||
Directory dir = new MockRAMDirectory();
|
||||
IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
|
||||
Document doc = new Document();
|
||||
doc.add(new Field("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
|
||||
writer.addDocument(doc);
|
||||
writer.close();
|
||||
|
||||
// Open reader
|
||||
IndexReader r = IndexReader.open(dir);
|
||||
assertTrue(r instanceof SegmentReader);
|
||||
final int[] ints = FieldCache.DEFAULT.getInts(r, "number");
|
||||
assertEquals(1, ints.length);
|
||||
assertEquals(17, ints[0]);
|
||||
|
||||
// Clone reader
|
||||
IndexReader r2 = (IndexReader) r.clone();
|
||||
r.close();
|
||||
assertTrue(r2 != r);
|
||||
assertTrue(r2 instanceof SegmentReader);
|
||||
final int[] ints2 = FieldCache.DEFAULT.getInts(r2, "number");
|
||||
r2.close();
|
||||
|
||||
assertEquals(1, ints2.length);
|
||||
assertEquals(17, ints2[0]);
|
||||
assertTrue(ints == ints2);
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
// LUCENE-1579: Ensure that on a reopened reader, that any
|
||||
// shared segments reuse the doc values arrays in
|
||||
// FieldCache
|
||||
public void testFieldCacheReuseAfterReopen() throws Exception {
|
||||
Directory dir = new MockRAMDirectory();
|
||||
IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
|
||||
Document doc = new Document();
|
||||
doc.add(new Field("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
|
||||
writer.addDocument(doc);
|
||||
writer.commit();
|
||||
|
||||
// Open reader1
|
||||
IndexReader r = IndexReader.open(dir);
|
||||
assertTrue(r instanceof SegmentReader);
|
||||
final int[] ints = FieldCache.DEFAULT.getInts(r, "number");
|
||||
assertEquals(1, ints.length);
|
||||
assertEquals(17, ints[0]);
|
||||
|
||||
// Add new segment
|
||||
writer.addDocument(doc);
|
||||
writer.commit();
|
||||
|
||||
// Reopen reader1 --> reader2
|
||||
IndexReader r2 = (IndexReader) r.reopen();
|
||||
r.close();
|
||||
assertTrue(r2 instanceof MultiSegmentReader);
|
||||
IndexReader sub0 = r2.getSequentialSubReaders()[0];
|
||||
assertTrue(sub0 instanceof SegmentReader);
|
||||
final int[] ints2 = FieldCache.DEFAULT.getInts(sub0, "number");
|
||||
r2.close();
|
||||
assertTrue(ints == ints2);
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
// LUCENE-1579: Make sure all SegmentReaders are new when
|
||||
// reopen switches readOnly
|
||||
public void testReopenChangeReadonly() throws Exception {
|
||||
Directory dir = new MockRAMDirectory();
|
||||
IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
|
||||
Document doc = new Document();
|
||||
doc.add(new Field("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
|
||||
writer.addDocument(doc);
|
||||
writer.commit();
|
||||
|
||||
// Open reader1
|
||||
IndexReader r = IndexReader.open(dir);
|
||||
assertTrue(r instanceof SegmentReader);
|
||||
final int[] ints = FieldCache.DEFAULT.getInts(r, "number");
|
||||
assertEquals(1, ints.length);
|
||||
assertEquals(17, ints[0]);
|
||||
|
||||
// Reopen to readonly w/ no chnages
|
||||
IndexReader r3 = (IndexReader) r.reopen(true);
|
||||
assertTrue(r3 instanceof ReadOnlySegmentReader);
|
||||
r3.close();
|
||||
|
||||
// Add new segment
|
||||
writer.addDocument(doc);
|
||||
writer.commit();
|
||||
|
||||
// Reopen reader1 --> reader2
|
||||
IndexReader r2 = (IndexReader) r.reopen(true);
|
||||
r.close();
|
||||
assertTrue(r2 instanceof MultiSegmentReader);
|
||||
IndexReader[] subs = r2.getSequentialSubReaders();
|
||||
final int[] ints2 = FieldCache.DEFAULT.getInts(subs[0], "number");
|
||||
r2.close();
|
||||
|
||||
assertTrue(subs[0] instanceof ReadOnlySegmentReader);
|
||||
assertTrue(subs[1] instanceof ReadOnlySegmentReader);
|
||||
assertTrue(ints == ints2);
|
||||
|
||||
dir.close();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue