pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / facet / src / java / org / apache / lucene / facet / taxonomy / writercache / lru / NameIntCacheLRU.java
diff --git a/lucene-java-3.5.0/lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/writercache/lru/NameIntCacheLRU.java b/lucene-java-3.5.0/lucene/contrib/facet/src/java/org/apache/lucene/facet/taxonomy/writercache/lru/NameIntCacheLRU.java
new file mode 100644 (file)
index 0000000..917becd
--- /dev/null
@@ -0,0 +1,144 @@
+package org.apache.lucene.facet.taxonomy.writercache.lru;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import org.apache.lucene.facet.taxonomy.CategoryPath;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An an LRU cache of mapping from name to int.
+ * Used to cache Ordinals of category paths.
+ * 
+ * @lucene.experimental
+ */
+// Note: Nothing in this class is synchronized. The caller is assumed to be
+// synchronized so that no two methods of this class are called concurrently.
+class NameIntCacheLRU {
+
+  private HashMap<Object, Integer> cache;
+  long nMisses = 0; // for debug
+  long nHits = 0;  // for debug
+  private int maxCacheSize;
+
+  NameIntCacheLRU(int maxCacheSize) {
+    this.maxCacheSize = maxCacheSize;
+    createCache(maxCacheSize);
+  }
+
+  public int getMaxSize() {
+    return maxCacheSize;
+  }
+  
+  public int getSize() {
+    return cache.size();
+  }
+
+  private void createCache (int maxSize) {
+    if (maxSize<Integer.MAX_VALUE) {
+      cache = new LinkedHashMap<Object, Integer>(1000,(float)0.7,true); //for LRU
+    } else {
+      cache = new HashMap<Object, Integer>(1000,(float)0.7); //no need for LRU
+    }
+  }
+
+  Integer get (CategoryPath name) {
+    Integer res = cache.get(key(name));
+    if (res==null) {
+      nMisses ++;
+    } else {
+      nHits ++;
+    }
+    return res;
+  }
+
+  /**
+   * Subclasses can override this to provide caching by e.g. hash of the string.
+   * @param name
+   * @return
+   */
+  Object key(CategoryPath name) {
+    // Note that a copy constructor (cloning) here is necessary, because a
+    // CategoryPath object is mutable, so we cannot save a reference to an
+    // existing CategoryPath. Subclasses which override this method can
+    // avoid this cloning by, e.g., hashing the name.
+    return new CategoryPath(name);
+  }
+
+  Object key(CategoryPath name, int prefixLen) {
+    // Note that a copy constructor (cloning) here is necessary, because a
+    // CategoryPath object is mutable, so we cannot save a reference to an
+    // existing CategoryPath. Subclasses which override this method can
+    // avoid this cloning by, e.g., hashing the name.
+    return new CategoryPath(name, prefixLen);
+  }
+
+  /**
+   * Add a new value to cache.
+   * Return true if cache became full and some room need to be made. 
+   */
+  boolean put (CategoryPath name, Integer val) {
+    cache.put(key(name), val);
+    return isCacheFull();
+  }
+
+  boolean put (CategoryPath name, int prefixLen, Integer val) {
+    cache.put(key(name, prefixLen), val);
+    return isCacheFull();
+  }
+
+  private boolean isCacheFull() {
+    return (cache.size()>maxCacheSize);
+  }
+
+  void clear() {
+    cache.clear();
+  }
+
+  String stats() {
+    return "#miss="+nMisses+" #hit="+nHits;
+  }
+
+  /**
+   * If cache is full remove least recently used entries from cache.
+   * Return true if anything was removed, false otherwise.
+   * 
+   * See comment in {@link DirectoryTaxonomyWriter#addToCache(String, Integer)}
+   * for an explanation why we clean 2/3rds of the cache, and not just one
+   * entry.
+   */ 
+  boolean makeRoomLRU() {
+    if (!isCacheFull()) {
+      return false;
+    }
+    int n = cache.size() - (2*maxCacheSize)/3;
+    if (n<=0) {
+      return false;
+    }
+    Iterator<Object> it = cache.keySet().iterator();
+    int i = 0;
+    while (i<n && it.hasNext()) {
+      it.next();
+      it.remove();
+      i++;
+    }
+    return true;
+  }
+
+}