Index: lucene/test-framework/src/java/org/apache/lucene/search/QueryUtils.java =================================================================== --- lucene/test-framework/src/java/org/apache/lucene/search/QueryUtils.java (revision 1528588) +++ lucene/test-framework/src/java/org/apache/lucene/search/QueryUtils.java (working copy) @@ -132,7 +132,7 @@ public static void purgeFieldCache(IndexReader r) throws IOException { // this is just a hack, to get an atomic reader that contains all subreaders for insanity checks - FieldCache.DEFAULT.purge(SlowCompositeReaderWrapper.wrap(r)); + FieldCache.DEFAULT.purgeByCacheKey(SlowCompositeReaderWrapper.wrap(r).getCoreCacheKey()); } /** This is a MultiReader that can be used for randomly wrapping other readers Index: lucene/core/src/test/org/apache/lucene/search/TestFieldCache.java =================================================================== --- lucene/core/src/test/org/apache/lucene/search/TestFieldCache.java (revision 1528588) +++ lucene/core/src/test/org/apache/lucene/search/TestFieldCache.java (working copy) @@ -297,7 +297,7 @@ termOrds = cache.getDocTermOrds(reader, "bogusfield"); assertTrue(termOrds.getValueCount() == 0); - FieldCache.DEFAULT.purge(reader); + FieldCache.DEFAULT.purgeByCacheKey(reader.getCoreCacheKey()); } public void testEmptyIndex() throws Exception { @@ -308,7 +308,7 @@ AtomicReader reader = SlowCompositeReaderWrapper.wrap(r); FieldCache.DEFAULT.getTerms(reader, "foobar", true); FieldCache.DEFAULT.getTermsIndex(reader, "foobar"); - FieldCache.DEFAULT.purge(reader); + FieldCache.DEFAULT.purgeByCacheKey(reader.getCoreCacheKey()); r.close(); dir.close(); } Index: lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java (revision 1528588) +++ lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java (working copy) @@ -172,7 +172,7 @@ AtomicReader slowR = SlowCompositeReaderWrapper.wrap(r); verify(slowR, idToOrds, termsArray, null); - FieldCache.DEFAULT.purge(slowR); + FieldCache.DEFAULT.purgeByCacheKey(slowR.getCoreCacheKey()); r.close(); dir.close(); @@ -291,7 +291,7 @@ verify(slowR, idToOrdsPrefix, termsArray, prefixRef); } - FieldCache.DEFAULT.purge(slowR); + FieldCache.DEFAULT.purgeByCacheKey(slowR.getCoreCacheKey()); r.close(); dir.close(); Index: lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java (revision 1528588) +++ lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java (working copy) @@ -78,9 +78,9 @@ } @Override - public synchronized void purge(AtomicReader r) { + public synchronized void purgeByCacheKey(Object coreCacheKey) { for(Cache c : caches.values()) { - c.purge(r); + c.purgeByCacheKey(coreCacheKey); } } @@ -110,8 +110,8 @@ // per-segment fieldcaches don't purge until the shared core closes. final SegmentReader.CoreClosedListener purgeCore = new SegmentReader.CoreClosedListener() { @Override - public void onClose(SegmentReader owner) { - FieldCacheImpl.this.purge(owner); + public void onClose(Object ownerCoreCacheKey) { + FieldCacheImpl.this.purgeByCacheKey(ownerCoreCacheKey); } }; @@ -120,7 +120,7 @@ @Override public void onClose(IndexReader owner) { assert owner instanceof AtomicReader; - FieldCacheImpl.this.purge((AtomicReader) owner); + FieldCacheImpl.this.purgeByCacheKey(((AtomicReader) owner).getCoreCacheKey()); } }; @@ -155,10 +155,9 @@ throws IOException; /** Remove this reader from the cache, if present. */ - public void purge(AtomicReader r) { - Object readerKey = r.getCoreCacheKey(); + public void purgeByCacheKey(Object coreCacheKey) { synchronized(readerCache) { - readerCache.remove(readerKey); + readerCache.remove(coreCacheKey); } } Index: lucene/core/src/java/org/apache/lucene/search/FieldCache.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/FieldCache.java (revision 1528588) +++ lucene/core/src/java/org/apache/lucene/search/FieldCache.java (working copy) @@ -29,6 +29,7 @@ import org.apache.lucene.index.AtomicReader; import org.apache.lucene.index.BinaryDocValues; import org.apache.lucene.index.DocTermOrds; +import org.apache.lucene.index.IndexReader; // javadocs import org.apache.lucene.index.SortedDocValues; import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.index.Terms; @@ -260,7 +261,7 @@ * * @see #getInts(AtomicReader, String, IntParser, boolean) */ - public Ints getInts (AtomicReader reader, String field, boolean setDocsWithField) throws IOException; + public Ints getInts(AtomicReader reader, String field, boolean setDocsWithField) throws IOException; /** * Returns an {@link Ints} over the values found in documents in the given @@ -286,7 +287,7 @@ * @throws IOException * If any error occurs. */ - public Ints getInts (AtomicReader reader, String field, IntParser parser, boolean setDocsWithField) throws IOException; + public Ints getInts(AtomicReader reader, String field, IntParser parser, boolean setDocsWithField) throws IOException; /** * Returns a {@link Floats} over the values found in documents in the given @@ -294,7 +295,7 @@ * * @see #getFloats(AtomicReader, String, FloatParser, boolean) */ - public Floats getFloats (AtomicReader reader, String field, boolean setDocsWithField) throws IOException; + public Floats getFloats(AtomicReader reader, String field, boolean setDocsWithField) throws IOException; /** * Returns a {@link Floats} over the values found in documents in the given @@ -320,7 +321,7 @@ * @throws IOException * If any error occurs. */ - public Floats getFloats (AtomicReader reader, String field, FloatParser parser, boolean setDocsWithField) throws IOException; + public Floats getFloats(AtomicReader reader, String field, FloatParser parser, boolean setDocsWithField) throws IOException; /** * Returns a {@link Longs} over the values found in documents in the given @@ -401,14 +402,14 @@ * @return The values in the given field for each document. * @throws IOException If any error occurs. */ - public BinaryDocValues getTerms (AtomicReader reader, String field, boolean setDocsWithField) throws IOException; + public BinaryDocValues getTerms(AtomicReader reader, String field, boolean setDocsWithField) throws IOException; /** Expert: just like {@link #getTerms(AtomicReader,String,boolean)}, * but you can specify whether more RAM should be consumed in exchange for * faster lookups (default is "true"). Note that the * first call for a given reader and field "wins", * subsequent calls will share the same cache entry. */ - public BinaryDocValues getTerms (AtomicReader reader, String field, boolean setDocsWithField, float acceptableOverheadRatio) throws IOException; + public BinaryDocValues getTerms(AtomicReader reader, String field, boolean setDocsWithField, float acceptableOverheadRatio) throws IOException; /** Checks the internal cache for an appropriate entry, and if none * is found, reads the term values in field @@ -420,7 +421,7 @@ * @return The values in the given field for each document. * @throws IOException If any error occurs. */ - public SortedDocValues getTermsIndex (AtomicReader reader, String field) throws IOException; + public SortedDocValues getTermsIndex(AtomicReader reader, String field) throws IOException; /** Expert: just like {@link * #getTermsIndex(AtomicReader,String)}, but you can specify @@ -428,7 +429,7 @@ * faster lookups (default is "true"). Note that the * first call for a given reader and field "wins", * subsequent calls will share the same cache entry. */ - public SortedDocValues getTermsIndex (AtomicReader reader, String field, float acceptableOverheadRatio) throws IOException; + public SortedDocValues getTermsIndex(AtomicReader reader, String field, float acceptableOverheadRatio) throws IOException; /** * Checks the internal cache for an appropriate entry, and if none is found, reads the term values @@ -533,7 +534,7 @@ *

* @lucene.experimental */ - public abstract CacheEntry[] getCacheEntries(); + public CacheEntry[] getCacheEntries(); /** *

@@ -546,16 +547,17 @@ *

* @lucene.experimental */ - public abstract void purgeAllCaches(); + public void purgeAllCaches(); /** * Expert: drops all cache entries associated with this - * reader. NOTE: this reader must precisely match the - * reader that the cache entry is keyed on. If you pass a - * top-level reader, it usually will have no effect as - * Lucene now caches at the segment reader level. + * reader {@link IndexReader#getCoreCacheKey}. NOTE: this cache key must + * precisely match the reader that the cache entry is + * keyed on. If you pass a top-level reader, it usually + * will have no effect as Lucene now caches at the segment + * reader level. */ - public abstract void purge(AtomicReader r); + public void purgeByCacheKey(Object coreCacheKey); /** * If non-null, FieldCacheImpl will warn whenever Index: lucene/core/src/java/org/apache/lucene/index/SegmentCoreReaders.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/SegmentCoreReaders.java (revision 1528588) +++ lucene/core/src/java/org/apache/lucene/index/SegmentCoreReaders.java (working copy) @@ -53,7 +53,7 @@ final FieldsProducer fields; final DocValuesProducer normsProducer; - private final SegmentReader owner; + private final Object ownerCoreCacheKey; final StoredFieldsReader fieldsReaderOrig; final TermVectorsReader termVectorsReaderOrig; @@ -88,7 +88,12 @@ Collections.synchronizedSet(new LinkedHashSet()); SegmentCoreReaders(SegmentReader owner, Directory dir, SegmentInfoPerCommit si, IOContext context) throws IOException { - + + // SegmentReader uses us as the coreCacheKey; we cannot + // call owner.getCoreCacheKey() because that will return + // null!: + this.ownerCoreCacheKey = this; + final Codec codec = si.info.getCodec(); final Directory cfsDir; // confusing name: if (cfs) its the cfsdir, otherwise its the segment's directory. @@ -134,12 +139,6 @@ decRef(); } } - - // Must assign this at the end -- if we hit an - // exception above core, we don't want to attempt to - // purge the FieldCache (will hit NPE because core is - // not assigned yet). - this.owner = owner; } int getRefCount() { @@ -176,7 +175,7 @@ private void notifyCoreClosedListeners() { synchronized(coreClosedListeners) { for (CoreClosedListener listener : coreClosedListeners) { - listener.onClose(owner); + listener.onClose(ownerCoreCacheKey); } } } @@ -196,9 +195,4 @@ ((fieldsReaderOrig!=null)? fieldsReaderOrig.ramBytesUsed() : 0) + ((termVectorsReaderOrig!=null) ? termVectorsReaderOrig.ramBytesUsed() : 0); } - - @Override - public String toString() { - return "SegmentCoreReader(owner=" + owner + ")"; - } } Index: lucene/core/src/java/org/apache/lucene/index/SegmentReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/SegmentReader.java (revision 1528588) +++ lucene/core/src/java/org/apache/lucene/index/SegmentReader.java (working copy) @@ -407,6 +407,8 @@ // same entry in the FieldCache. See LUCENE-1579. @Override public Object getCoreCacheKey() { + // NOTE: if this every changes, be sure to fix + // SegmentCoreReader's ownerCoreCacheKey to match! return core; } @@ -576,9 +578,9 @@ * @lucene.experimental */ public static interface CoreClosedListener { - /** Invoked when the shared core of the provided {@link + /** Invoked when the shared core of the original {@code * SegmentReader} has closed. */ - public void onClose(SegmentReader owner); + public void onClose(Object ownerCoreCacheKey); } /** Expert: adds a CoreClosedListener to this reader's shared core */