Index: lucene/src/java/org/apache/lucene/index/ParallelReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/ParallelReader.java (revision 944320) +++ lucene/src/java/org/apache/lucene/index/ParallelReader.java (revision ) @@ -561,7 +561,7 @@ } } - FieldCache.DEFAULT.purge(this); + raiseCacheEvictionEvent(this); } @Override Index: lucene/src/java/org/apache/lucene/index/MultiReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/MultiReader.java (revision 931278) +++ lucene/src/java/org/apache/lucene/index/MultiReader.java (revision ) @@ -462,7 +462,7 @@ // NOTE: only needed in case someone had asked for // FieldCache for top-level reader (which is generally // not a good idea): - FieldCache.DEFAULT.purge(this); + raiseCacheEvictionEvent(this); } @Override Index: lucene/src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/IndexReader.java (revision 933613) +++ lucene/src/java/org/apache/lucene/index/IndexReader.java (revision ) @@ -19,6 +19,7 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.FieldSelector; +import org.apache.lucene.search.FieldCache; import org.apache.lucene.search.Similarity; import org.apache.lucene.index.codecs.CodecProvider; import org.apache.lucene.store.*; @@ -33,6 +34,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; /** IndexReader is an abstract class, providing an interface for accessing an @@ -80,7 +82,22 @@ */ public abstract class IndexReader implements Cloneable,Closeable { - /** + /** + * A custom listener that can be added to the index reader which will + * be called when the index reader (or its {@link org.apache.lucene.index.IndexReader#getFieldCacheKey()}) + * can be removed from a custom cache. + */ + public static interface CacheEvictionListener { + void purgeReaderCache(IndexReader reader); + } + + private static class FieldCacheCacheEvictionListener implements CacheEvictionListener { + public void purgeReaderCache(IndexReader reader) { + FieldCache.DEFAULT.purge(reader); + } + } + + /** * Constants describing field properties, for example used for * {@link IndexReader#getFieldNames(FieldOption)}. */ @@ -123,6 +140,8 @@ private final AtomicInteger refCount = new AtomicInteger(); + CopyOnWriteArrayList cacheEvictionListeners = new CopyOnWriteArrayList(); + static int DEFAULT_TERMS_INDEX_DIVISOR = 1; /** Expert: returns the current refCount for this reader */ @@ -199,8 +218,15 @@ protected IndexReader() { refCount.set(1); + cacheEvictionListeners.add(new FieldCacheCacheEvictionListener()); } - + + protected void raiseCacheEvictionEvent(IndexReader reader) { + for (CacheEvictionListener listener : cacheEvictionListeners) { + listener.purgeReaderCache(reader); + } + } + /** * @throws AlreadyClosedException if this IndexReader is closed */ @@ -1366,6 +1392,16 @@ throw new UnsupportedOperationException(); } + /** Expert - When caching (ususaly using #getFieldCacheKey) can be used + * to eagerly release cache entries */ + public void addCacheEvictionListener(CacheEvictionListener listener) { + cacheEvictionListeners.add(listener); + } + + public void removeCacheEvictionListener(CacheEvictionListener listener) { + cacheEvictionListeners.remove(listener); + } + /** Expert */ public Object getFieldCacheKey() { return this; Index: lucene/src/java/org/apache/lucene/index/FilterIndexReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/FilterIndexReader.java (revision 944320) +++ lucene/src/java/org/apache/lucene/index/FilterIndexReader.java (revision ) @@ -261,7 +261,7 @@ // NOTE: only needed in case someone had asked for // FieldCache for top-level reader (which is generally // not a good idea): - FieldCache.DEFAULT.purge(this); + raiseCacheEvictionEvent(this); } Index: lucene/src/java/org/apache/lucene/index/DirectoryReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/DirectoryReader.java (revision 944320) +++ lucene/src/java/org/apache/lucene/index/DirectoryReader.java (revision ) @@ -956,7 +956,7 @@ // NOTE: only needed in case someone had asked for // FieldCache for top-level reader (which is generally // not a good idea): - FieldCache.DEFAULT.purge(this); + raiseCacheEvictionEvent(this); if (writer != null) { // Since we just closed, writer may now be able to Index: lucene/src/java/org/apache/lucene/index/SegmentReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/SegmentReader.java (revision 944320) +++ lucene/src/java/org/apache/lucene/index/SegmentReader.java (revision ) @@ -201,7 +201,7 @@ // origInstance will be null, and we don't want // to call FieldCache.purge (it leads to NPE): if (origInstance != null) { - FieldCache.DEFAULT.purge(origInstance); + origInstance.raiseCacheEvictionEvent(origInstance); } } } @@ -648,6 +648,7 @@ try { core.incRef(); clone.core = core; + clone.cacheEvictionListeners = cacheEvictionListeners; clone.readOnly = openReadOnly; clone.si = si; clone.readBufferSize = readBufferSize;