Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 833547) +++ CHANGES.txt (working copy) @@ -12,6 +12,10 @@ * oal.Lock.isLocked is now allowed to throw an IOException +* LUCENE-2030: CachingWrapperFilter and CachingSpanFilter now hide + the internal cache implementation for thread safety, before it was + declared protected. (Peter Lenahan, Uwe Schindler, Simon Willnauer) + Changes in runtime behavior * LUCENE-1677: Remove the system property to set SegmentReader class Index: src/java/org/apache/lucene/search/CachingSpanFilter.java =================================================================== --- src/java/org/apache/lucene/search/CachingSpanFilter.java (revision 833547) +++ src/java/org/apache/lucene/search/CachingSpanFilter.java (working copy) @@ -28,13 +28,16 @@ * filters to simply filter, and then wrap with this class to add caching. */ public class CachingSpanFilter extends SpanFilter { - protected SpanFilter filter; + private SpanFilter filter; /** - * A transient Filter cache. + * A transient Filter cache (package private because of test) */ - protected transient Map cache; + private transient Map cache; + // serializable, should normally be Object: + private final String lock = new String(); + /** * @param filter Filter to cache results of */ @@ -49,18 +52,18 @@ } private SpanFilterResult getCachedResult(IndexReader reader) throws IOException { - SpanFilterResult result = null; - if (cache == null) { - cache = new WeakHashMap(); - } - - synchronized (cache) { // check cache - result = cache.get(reader); - if (result == null) { - result = filter.bitSpans(reader); - cache.put(reader, result); + synchronized(lock) { + if (cache == null) { + cache = new WeakHashMap(); } + final SpanFilterResult cached = cache.get(reader); + if (cached != null) return cached; } + + final SpanFilterResult result = filter.bitSpans(reader); + synchronized(lock) { + cache.put(reader, result); + } return result; } Index: src/java/org/apache/lucene/search/CachingWrapperFilter.java =================================================================== --- src/java/org/apache/lucene/search/CachingWrapperFilter.java (revision 833547) +++ src/java/org/apache/lucene/search/CachingWrapperFilter.java (working copy) @@ -29,12 +29,15 @@ * filters to simply filter, and then wrap with this class to add caching. */ public class CachingWrapperFilter extends Filter { - protected Filter filter; + Filter filter; /** - * A transient Filter cache. + * A transient Filter cache (package private because of test) */ - protected transient Map cache; + transient Map cache; + + // serializable, should normally be Object: + private final String lock = new String(); /** * @param filter Filter to cache results of @@ -63,27 +66,21 @@ @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { - if (cache == null) { - cache = new WeakHashMap(); - } + synchronized(lock) { + if (cache == null) { + cache = new WeakHashMap(); + } - DocIdSet cached = null; - synchronized (cache) { // check cache - cached = cache.get(reader); + final DocIdSet cached = cache.get(reader); + if (cached != null) return cached; } - if (cached != null) { - return cached; - } - final DocIdSet docIdSet = docIdSetToCache(filter.getDocIdSet(reader), reader); - if (docIdSet != null) { - synchronized (cache) { // update cache + synchronized(lock) { cache.put(reader, docIdSet); } } - return docIdSet; }