001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.util.cache;
020:
021: import java.util.Collections;
022: import java.util.Date;
023: import java.util.HashMap;
024: import java.util.LinkedHashMap;
025: import java.util.Map;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028:
029: /**
030: * A simple LRU Cache.
031: */
032: public class LRUCacheImpl implements Cache {
033:
034: private static Log log = LogFactory.getLog(LRUCacheImpl.class);
035:
036: private String id = null;
037: private Map cache = null;
038:
039: // for metrics
040: protected double hits = 0;
041: protected double misses = 0;
042: protected double puts = 0;
043: protected double removes = 0;
044: protected Date startTime = new Date();
045:
046: protected LRUCacheImpl(String id) {
047:
048: this .id = id;
049: this .cache = Collections.synchronizedMap(new LRULinkedHashMap(
050: 100));
051: }
052:
053: protected LRUCacheImpl(String id, int maxsize) {
054:
055: this .id = id;
056: this .cache = Collections.synchronizedMap(new LRULinkedHashMap(
057: maxsize));
058: }
059:
060: public String getId() {
061: return this .id;
062: }
063:
064: /**
065: * Store an entry in the cache.
066: */
067: public synchronized void put(String key, Object value) {
068:
069: this .cache.put(key, value);
070: puts++;
071: }
072:
073: /**
074: * Retrieve an entry from the cache.
075: */
076: public synchronized Object get(String key) {
077:
078: Object obj = this .cache.get(key);
079:
080: // for metrics
081: if (obj == null) {
082: misses++;
083: } else {
084: hits++;
085: }
086:
087: return obj;
088: }
089:
090: public synchronized void remove(String key) {
091:
092: this .cache.remove(key);
093: removes++;
094: }
095:
096: public synchronized void clear() {
097:
098: this .cache.clear();
099:
100: // clear metrics
101: hits = 0;
102: misses = 0;
103: puts = 0;
104: removes = 0;
105: startTime = new Date();
106: }
107:
108: public Map getStats() {
109:
110: Map stats = new HashMap();
111: stats.put("startTime", this .startTime);
112: stats.put("hits", new Double(this .hits));
113: stats.put("misses", new Double(this .misses));
114: stats.put("puts", new Double(this .puts));
115: stats.put("removes", new Double(this .removes));
116:
117: // calculate efficiency
118: if ((misses - removes) > 0) {
119: double efficiency = hits / (misses + hits);
120: stats.put("efficiency", new Double(efficiency * 100));
121: }
122:
123: return stats;
124: }
125:
126: // David Flanaghan: http://www.davidflanagan.com/blog/000014.html
127: private static class LRULinkedHashMap extends LinkedHashMap {
128: protected int maxsize;
129:
130: public LRULinkedHashMap(int maxsize) {
131: super (maxsize * 4 / 3 + 1, 0.75f, true);
132: this .maxsize = maxsize;
133: }
134:
135: protected boolean removeEldestEntry(Map.Entry eldest) {
136: return this.size() > this.maxsize;
137: }
138: }
139:
140: }
|