lucene-java-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From o...@apache.org
Subject svn commit: r477084 - in /lucene/java/trunk: CHANGES.txt src/java/org/apache/lucene/search/FieldCacheImpl.java src/java/org/apache/lucene/search/FieldSortedHitQueue.java
Date Mon, 20 Nov 2006 07:10:07 GMT
Author: otis
Date: Sun Nov 19 23:10:04 2006
New Revision: 477084

URL: http://svn.apache.org/viewvc?view=rev&rev=477084
Log:
LUCENE-651: Fixed a race condition in initialization of FieldCache.

Modified:
    lucene/java/trunk/CHANGES.txt
    lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java
    lucene/java/trunk/src/java/org/apache/lucene/search/FieldSortedHitQueue.java

Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?view=diff&rev=477084&r1=477083&r2=477084
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Sun Nov 19 23:10:04 2006
@@ -185,12 +185,16 @@
     to recognize ordered spans if they overlaped with unordered spans.
     (Paul Elschot via Chris Hostetter)
 
-20. LUCENE-706: Updated fileformats.xml|html concerning the docdelta value in the frequency
file. (Johan Stuyts, Doron Cohen via Grant Ingersoll)
+20. LUCENE-706: Updated fileformats.xml|html concerning the docdelta value
+    in the frequency file. (Johan Stuyts, Doron Cohen via Grant Ingersoll)
 
 21. LUCENE-715: Fixed private constructor in IndexWriter.java to
     properly release the acquired write lock if there is an
     IOException after acquiring the write lock but before finishing
-    instantiation (Matthew Bogosian via Mike McCandless)
+    instantiation. (Matthew Bogosian via Mike McCandless)
+
+22. LUCENE-651: Fixed a race condition in initialization of FieldCache.
+    (Oliver Hutchison via Otis Gospodnetic)
 
 Optimizations
 

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java?view=diff&rev=477084&r1=477083&r2=477084
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java Sun Nov 19 23:10:04
2006
@@ -40,8 +40,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;
+
+    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;
+    }
+  }
 
-  /** Expert: Every key in the internal cache is of this type. */
+  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
@@ -99,66 +143,24 @@
       }
     };
 
-  /** 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);
   }
 
   // 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, ""));
@@ -176,11 +178,9 @@
         termDocs.close();
         termEnum.close();
       }
-      store (reader, field, parser, retArray);
       return retArray;
     }
-    return (int[]) ret;
-  }
+  };
 
   // inherit javadocs
   public float[] getFloats (IndexReader reader, String field)
@@ -189,11 +189,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, ""));
@@ -211,18 +218,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 {
-    field = field.intern();
-    Object ret = lookup (reader, field, SortField.STRING, null);
-    if (ret == null) {
+  public String[] getStrings(IndexReader reader, String field)
+      throws IOException {
+    return (String[]) stringsCache.get(reader, field);
+  }
+
+  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, ""));
@@ -240,18 +250,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 {
-    field = field.intern();
-    Object ret = lookup (reader, field, STRING_INDEX, null);
-    if (ret == null) {
+  public StringIndex getStringIndex(IndexReader reader, String field)
+      throws IOException {
+    return (StringIndex) stringsIndexCache.get(reader, field);
+  }
+
+  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();
@@ -301,11 +314,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
@@ -318,18 +329,23 @@
    * 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();
         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();
 
@@ -354,27 +370,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 {
-    field = field.intern();
-    Object ret = lookup (reader, field, comparator);
-    if (ret == null) {
+  public Comparable[] getCustom(IndexReader reader, String field,
+      SortComparator comparator) throws IOException {
+    return (Comparable[]) customCache.get(reader, new Entry(field, comparator));
+  }
+
+  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, ""));
@@ -392,11 +411,9 @@
         termDocs.close();
         termEnum.close();
       }
-      store (reader, field, comparator, retArray);
       return retArray;
     }
-    return (Comparable[]) ret;
-  }
-
+  };
+  
 }
 

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/FieldSortedHitQueue.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FieldSortedHitQueue.java?view=diff&rev=477084&r1=477083&r2=477084
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FieldSortedHitQueue.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FieldSortedHitQueue.java Sun Nov 19
23:10:04 2006
@@ -21,9 +21,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;
 
@@ -147,44 +144,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);
@@ -205,10 +187,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.



Mime
View raw message