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
1 package org.apache.lucene.facet.taxonomy.writercache.lru;
2
3 import java.util.HashMap;
4 import java.util.Iterator;
5 import java.util.LinkedHashMap;
6 import org.apache.lucene.facet.taxonomy.CategoryPath;
7
8 /**
9  * Licensed to the Apache Software Foundation (ASF) under one or more
10  * contributor license agreements.  See the NOTICE file distributed with
11  * this work for additional information regarding copyright ownership.
12  * The ASF licenses this file to You under the Apache License, Version 2.0
13  * (the "License"); you may not use this file except in compliance with
14  * the License.  You may obtain a copy of the License at
15  *
16  *     http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24
25 /**
26  * An an LRU cache of mapping from name to int.
27  * Used to cache Ordinals of category paths.
28  * 
29  * @lucene.experimental
30  */
31 // Note: Nothing in this class is synchronized. The caller is assumed to be
32 // synchronized so that no two methods of this class are called concurrently.
33 class NameIntCacheLRU {
34
35   private HashMap<Object, Integer> cache;
36   long nMisses = 0; // for debug
37   long nHits = 0;  // for debug
38   private int maxCacheSize;
39
40   NameIntCacheLRU(int maxCacheSize) {
41     this.maxCacheSize = maxCacheSize;
42     createCache(maxCacheSize);
43   }
44
45   public int getMaxSize() {
46     return maxCacheSize;
47   }
48   
49   public int getSize() {
50     return cache.size();
51   }
52
53   private void createCache (int maxSize) {
54     if (maxSize<Integer.MAX_VALUE) {
55       cache = new LinkedHashMap<Object, Integer>(1000,(float)0.7,true); //for LRU
56     } else {
57       cache = new HashMap<Object, Integer>(1000,(float)0.7); //no need for LRU
58     }
59   }
60
61   Integer get (CategoryPath name) {
62     Integer res = cache.get(key(name));
63     if (res==null) {
64       nMisses ++;
65     } else {
66       nHits ++;
67     }
68     return res;
69   }
70
71   /**
72    * Subclasses can override this to provide caching by e.g. hash of the string.
73    * @param name
74    * @return
75    */
76   Object key(CategoryPath name) {
77     // Note that a copy constructor (cloning) here is necessary, because a
78     // CategoryPath object is mutable, so we cannot save a reference to an
79     // existing CategoryPath. Subclasses which override this method can
80     // avoid this cloning by, e.g., hashing the name.
81     return new CategoryPath(name);
82   }
83
84   Object key(CategoryPath name, int prefixLen) {
85     // Note that a copy constructor (cloning) here is necessary, because a
86     // CategoryPath object is mutable, so we cannot save a reference to an
87     // existing CategoryPath. Subclasses which override this method can
88     // avoid this cloning by, e.g., hashing the name.
89     return new CategoryPath(name, prefixLen);
90   }
91
92   /**
93    * Add a new value to cache.
94    * Return true if cache became full and some room need to be made. 
95    */
96   boolean put (CategoryPath name, Integer val) {
97     cache.put(key(name), val);
98     return isCacheFull();
99   }
100
101   boolean put (CategoryPath name, int prefixLen, Integer val) {
102     cache.put(key(name, prefixLen), val);
103     return isCacheFull();
104   }
105
106   private boolean isCacheFull() {
107     return (cache.size()>maxCacheSize);
108   }
109
110   void clear() {
111     cache.clear();
112   }
113
114   String stats() {
115     return "#miss="+nMisses+" #hit="+nHits;
116   }
117
118   /**
119    * If cache is full remove least recently used entries from cache.
120    * Return true if anything was removed, false otherwise.
121    * 
122    * See comment in {@link DirectoryTaxonomyWriter#addToCache(String, Integer)}
123    * for an explanation why we clean 2/3rds of the cache, and not just one
124    * entry.
125    */ 
126   boolean makeRoomLRU() {
127     if (!isCacheFull()) {
128       return false;
129     }
130     int n = cache.size() - (2*maxCacheSize)/3;
131     if (n<=0) {
132       return false;
133     }
134     Iterator<Object> it = cache.keySet().iterator();
135     int i = 0;
136     while (i<n && it.hasNext()) {
137       it.next();
138       it.remove();
139       i++;
140     }
141     return true;
142   }
143
144 }