Index: src/java/org/apache/lucene/search/FieldCacheImpl.java =================================================================== --- src/java/org/apache/lucene/search/FieldCacheImpl.java (revision 431272) +++ src/java/org/apache/lucene/search/FieldCacheImpl.java (working copy) @@ -39,8 +39,52 @@ */ class FieldCacheImpl implements FieldCache { + + /** Expert: Internal cache. */ + abstract static class Cache { + private final Map readerCache = new WeakHashMap(); + + protected abstract Object createValue(IndexReader reader, Object key) + throws IOException; - /** Expert: Every key in the internal cache is of this type. */ + public Object get(IndexReader reader, Object key) throws IOException { + Map innerCache; + Object value; + synchronized (readerCache) { + innerCache = (Map) readerCache.get(reader); + if (innerCache == null) { + innerCache = new HashMap(); + readerCache.put(reader, innerCache); + value = null; + } else { + value = innerCache.get(key); + } + if (value == null) { + value = new CreationPlaceholder(); + innerCache.put(reader, value); + } + } + if (value instanceof CreationPlaceholder) { + synchronized (value) { + CreationPlaceholder progress = (CreationPlaceholder) value; + if (progress.value == null) { + progress.value = createValue(reader, key); + synchronized (readerCache) { + innerCache.put(key, progress.value); + } + } + return progress.value; + } + } + return value; + } + } + + static final class CreationPlaceholder { + Object value; + } + + /** Expert: Every composite-key in the internal cache is of this type. */ static class Entry { final String field; // which Fieldable final int type; // which SortField type @@ -98,55 +142,6 @@ } }; - /** The internal cache. Maps Entry to array of interpreted term values. **/ - final Map cache = new WeakHashMap(); - - /** See if an object is in the cache. */ - Object lookup (IndexReader reader, String field, int type, Locale locale) { - Entry entry = new Entry (field, type, locale); - synchronized (this) { - HashMap readerCache = (HashMap)cache.get(reader); - if (readerCache == null) return null; - return readerCache.get (entry); - } - } - - /** See if a custom object is in the cache. */ - Object lookup (IndexReader reader, String field, Object comparer) { - Entry entry = new Entry (field, comparer); - synchronized (this) { - HashMap readerCache = (HashMap)cache.get(reader); - if (readerCache == null) return null; - return readerCache.get (entry); - } - } - - /** Put an object into the cache. */ - Object store (IndexReader reader, String field, int type, Locale locale, Object value) { - Entry entry = new Entry (field, type, locale); - synchronized (this) { - HashMap readerCache = (HashMap)cache.get(reader); - if (readerCache == null) { - readerCache = new HashMap(); - cache.put(reader,readerCache); - } - return readerCache.put (entry, value); - } - } - - /** Put a custom object into the cache. */ - Object store (IndexReader reader, String field, Object comparer, Object value) { - Entry entry = new Entry (field, comparer); - synchronized (this) { - HashMap readerCache = (HashMap)cache.get(reader); - if (readerCache == null) { - readerCache = new HashMap(); - cache.put(reader, readerCache); - } - return readerCache.put (entry, value); - } - } - // inherit javadocs public int[] getInts (IndexReader reader, String field) throws IOException { return getInts(reader, field, INT_PARSER); @@ -153,11 +148,18 @@ } // inherit javadocs - public int[] getInts (IndexReader reader, String field, IntParser parser) - throws IOException { - field = field.intern(); - Object ret = lookup (reader, field, parser); - if (ret == null) { + public int[] getInts(IndexReader reader, String field, IntParser parser) + throws IOException { + return (int[]) intsCache.get(reader, new Entry(field, parser)); + } + + Cache intsCache = new Cache() { + + protected Object createValue(IndexReader reader, Object entryKey) + throws IOException { + Entry entry = (Entry) entryKey; + String field = entry.field; + IntParser parser = (IntParser) entry.custom; final int[] retArray = new int[reader.maxDoc()]; TermDocs termDocs = reader.termDocs(); TermEnum termEnum = reader.terms (new Term (field, "")); @@ -175,11 +177,9 @@ termDocs.close(); termEnum.close(); } - store (reader, field, parser, retArray); return retArray; } - return (int[]) ret; - } + }; // inherit javadocs public float[] getFloats (IndexReader reader, String field) @@ -188,11 +188,18 @@ } // inherit javadocs - public float[] getFloats (IndexReader reader, String field, - FloatParser parser) throws IOException { - field = field.intern(); - Object ret = lookup (reader, field, parser); - if (ret == null) { + public float[] getFloats(IndexReader reader, String field, FloatParser parser) + throws IOException { + return (float[]) floatsCache.get(reader, new Entry(field, parser)); + } + + Cache floatsCache = new Cache() { + + protected Object createValue(IndexReader reader, Object entryKey) + throws IOException { + Entry entry = (Entry) entryKey; + String field = entry.field; + FloatParser parser = (FloatParser) entry.custom; final float[] retArray = new float[reader.maxDoc()]; TermDocs termDocs = reader.termDocs(); TermEnum termEnum = reader.terms (new Term (field, "")); @@ -210,18 +217,21 @@ termDocs.close(); termEnum.close(); } - store (reader, field, parser, retArray); return retArray; } - return (float[]) ret; + }; + + // inherit javadocs + public String[] getStrings(IndexReader reader, String field) + throws IOException { + return (String[]) stringsCache.get(reader, field); } - // inherit javadocs - public String[] getStrings (IndexReader reader, String field) - throws IOException { - field = field.intern(); - Object ret = lookup (reader, field, SortField.STRING, null); - if (ret == null) { + Cache stringsCache = new Cache() { + + protected Object createValue(IndexReader reader, Object fieldKey) + throws IOException { + String field = ((String) fieldKey).intern(); final String[] retArray = new String[reader.maxDoc()]; TermDocs termDocs = reader.termDocs(); TermEnum termEnum = reader.terms (new Term (field, "")); @@ -239,18 +249,21 @@ termDocs.close(); termEnum.close(); } - store (reader, field, SortField.STRING, null, retArray); return retArray; } - return (String[]) ret; + }; + + // inherit javadocs + public StringIndex getStringIndex(IndexReader reader, String field) + throws IOException { + return (StringIndex) stringsIndexCache.get(reader, field); } - // inherit javadocs - public StringIndex getStringIndex (IndexReader reader, String field) - throws IOException { - field = field.intern(); - Object ret = lookup (reader, field, STRING_INDEX, null); - if (ret == null) { + Cache stringsIndexCache = new Cache() { + + protected Object createValue(IndexReader reader, Object fieldKey) + throws IOException { + String field = ((String) fieldKey).intern(); final int[] retArray = new int[reader.maxDoc()]; String[] mterms = new String[reader.maxDoc()+1]; TermDocs termDocs = reader.termDocs(); @@ -300,11 +313,9 @@ } StringIndex value = new StringIndex (retArray, mterms); - store (reader, field, STRING_INDEX, null, value); return value; } - return (StringIndex) ret; - } + }; /** The pattern used to detect integer values in a field */ /** removed for java 1.3 compatibility @@ -317,12 +328,16 @@ * protected static final Object pFloats = Pattern.compile ("[0-9+\\-\\.eEfFdD]+"); */ - // inherit javadocs - public Object getAuto (IndexReader reader, String field) - throws IOException { - field = field.intern(); - Object ret = lookup (reader, field, SortField.AUTO, null); - if (ret == null) { + // inherit javadocs + public Object getAuto(IndexReader reader, String field) throws IOException { + return autoCache.get(reader, field); + } + + Cache autoCache = new Cache() { + + protected Object createValue(IndexReader reader, Object fieldKey) + throws IOException { + String field = ((String)fieldKey).intern(); TermEnum enumerator = reader.terms (new Term (field, "")); try { Term term = enumerator.term(); @@ -329,6 +344,7 @@ if (term == null) { throw new RuntimeException ("no terms in field " + field + " - cannot determine sort type"); } + Object ret = null; if (term.field() == field) { String termtext = term.text().trim(); @@ -353,27 +369,30 @@ } catch (NumberFormatException nfe2) { ret = getStringIndex (reader, field); } - } - if (ret != null) { - store (reader, field, SortField.AUTO, null, ret); - } + } } else { throw new RuntimeException ("field \"" + field + "\" does not appear to be indexed"); } + return ret; } finally { enumerator.close(); } + } + }; - } - return ret; + // inherit javadocs + public Comparable[] getCustom(IndexReader reader, String field, + SortComparator comparator) throws IOException { + return (Comparable[]) customCache.get(reader, new Entry(field, comparator)); } - // inherit javadocs - public Comparable[] getCustom (IndexReader reader, String field, SortComparator comparator) - throws IOException { - field = field.intern(); - Object ret = lookup (reader, field, comparator); - if (ret == null) { + Cache customCache = new Cache() { + + protected Object createValue(IndexReader reader, Object entryKey) + throws IOException { + Entry entry = (Entry) entryKey; + String field = entry.field; + SortComparator comparator = (SortComparator) entry.custom; final Comparable[] retArray = new Comparable[reader.maxDoc()]; TermDocs termDocs = reader.termDocs(); TermEnum termEnum = reader.terms (new Term (field, "")); @@ -391,11 +410,9 @@ termDocs.close(); termEnum.close(); } - store (reader, field, comparator, retArray); return retArray; } - return (Comparable[]) ret; - } - + }; + } Index: src/java/org/apache/lucene/search/FieldSortedHitQueue.java =================================================================== --- src/java/org/apache/lucene/search/FieldSortedHitQueue.java (revision 431272) +++ src/java/org/apache/lucene/search/FieldSortedHitQueue.java (working copy) @@ -20,9 +20,6 @@ import org.apache.lucene.util.PriorityQueue; import java.io.IOException; -import java.util.WeakHashMap; -import java.util.HashMap; -import java.util.Map; import java.util.Locale; import java.text.Collator; @@ -146,44 +143,29 @@ SortField[] getFields() { return fields; } - - /** Internal cache of comparators. Similar to FieldCache, only - * caches comparators instead of term values. */ - static final Map Comparators = new WeakHashMap(); - - /** Returns a comparator if it is in the cache. */ - static ScoreDocComparator lookup (IndexReader reader, String field, int type, Locale locale, Object factory) { + + static ScoreDocComparator getCachedComparator (IndexReader reader, String field, int type, Locale locale, SortComparatorSource factory) + throws IOException { + if (type == SortField.DOC) return ScoreDocComparator.INDEXORDER; + if (type == SortField.SCORE) return ScoreDocComparator.RELEVANCE; FieldCacheImpl.Entry entry = (factory != null) ? new FieldCacheImpl.Entry (field, factory) : new FieldCacheImpl.Entry (field, type, locale); - synchronized (Comparators) { - HashMap readerCache = (HashMap)Comparators.get(reader); - if (readerCache == null) return null; - return (ScoreDocComparator) readerCache.get (entry); - } + return (ScoreDocComparator)Comparators.get(reader, entry); } - /** Stores a comparator into the cache. */ - static Object store (IndexReader reader, String field, int type, Locale locale, Object factory, Object value) { - FieldCacheImpl.Entry entry = (factory != null) - ? new FieldCacheImpl.Entry (field, factory) - : new FieldCacheImpl.Entry (field, type, locale); - synchronized (Comparators) { - HashMap readerCache = (HashMap)Comparators.get(reader); - if (readerCache == null) { - readerCache = new HashMap(); - Comparators.put(reader,readerCache); - } - return readerCache.put (entry, value); - } - } + /** Internal cache of comparators. Similar to FieldCache, only + * caches comparators instead of term values. */ + static final FieldCacheImpl.Cache Comparators = new FieldCacheImpl.Cache() { - static ScoreDocComparator getCachedComparator (IndexReader reader, String fieldname, int type, Locale locale, SortComparatorSource factory) - throws IOException { - if (type == SortField.DOC) return ScoreDocComparator.INDEXORDER; - if (type == SortField.SCORE) return ScoreDocComparator.RELEVANCE; - ScoreDocComparator comparator = lookup (reader, fieldname, type, locale, factory); - if (comparator == null) { + protected Object createValue(IndexReader reader, Object entryKey) + throws IOException { + FieldCacheImpl.Entry entry = (FieldCacheImpl.Entry) entryKey; + String fieldname = entry.field; + int type = entry.type; + Locale locale = entry.locale; + SortComparatorSource factory = (SortComparatorSource) entry.custom; + ScoreDocComparator comparator; switch (type) { case SortField.AUTO: comparator = comparatorAuto (reader, fieldname); @@ -204,10 +186,9 @@ default: throw new RuntimeException ("unknown field type: "+type); } - store (reader, fieldname, type, locale, factory, comparator); + return comparator; } - return comparator; - } + }; /** * Returns a comparator for sorting hits according to a field containing integers.