001: // jTDS JDBC Driver for Microsoft SQL Server and Sybase
002: // Copyright (C) 2004 The jTDS Project
003: //
004: // This library is free software; you can redistribute it and/or
005: // modify it under the terms of the GNU Lesser General Public
006: // License as published by the Free Software Foundation; either
007: // version 2.1 of the License, or (at your option) any later version.
008: //
009: // This library is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: // Lesser General Public License for more details.
013: //
014: // You should have received a copy of the GNU Lesser General Public
015: // License along with this library; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: //
018: package net.sourceforge.jtds.jdbc.cache;
019:
020: import java.util.HashMap;
021: import java.util.LinkedList;
022:
023: /**
024: * Simple LRU cache for any type of object. Implemented as an extended
025: * <code>HashMap</code> with a maximum size and an aggregated <code>List</code>
026: * as LRU queue.
027: *
028: * @author Brett Wooldridge
029: * @version $Id: SimpleLRUCache.java,v 1.1 2005/04/25 11:46:56 alin_sinpalean Exp $
030: */
031: public class SimpleLRUCache extends HashMap {
032: /** Maximum cache size. */
033: private final int maxCacheSize;
034: /** LRU list. */
035: private final LinkedList list;
036:
037: /**
038: * Constructs a new LRU cache instance.
039: *
040: * @param maxCacheSize the maximum number of entries in this cache before
041: * entries are aged off
042: */
043: public SimpleLRUCache(int maxCacheSize) {
044: super (maxCacheSize);
045: this .maxCacheSize = Math.max(0, maxCacheSize);
046: this .list = new LinkedList();
047: }
048:
049: /**
050: * Overrides clear() to also clear the LRU list.
051: */
052: public synchronized void clear() {
053: super .clear();
054: list.clear();
055: }
056:
057: /**
058: * Overrides <code>put()</code> so that it also updates the LRU list.
059: *
060: * @param key key with which the specified value is to be associated
061: * @param value value to be associated with the key
062: * @return previous value associated with key or <code>null</code> if there
063: * was no mapping for key; a <code>null</code> return can also
064: * indicate that the cache previously associated <code>null</code>
065: * with the specified key
066: * @see java.util.Map#put(Object, Object)
067: */
068: public synchronized Object put(Object key, Object value) {
069: if (maxCacheSize == 0) {
070: return null;
071: }
072:
073: // if the key isn't in the cache and the cache is full...
074: if (!super .containsKey(key) && !list.isEmpty()
075: && list.size() + 1 > maxCacheSize) {
076: Object deadKey = list.removeLast();
077: super .remove(deadKey);
078: }
079:
080: freshenKey(key);
081: return super .put(key, value);
082: }
083:
084: /**
085: * Overrides <code>get()</code> so that it also updates the LRU list.
086: *
087: * @param key key with which the expected value is associated
088: * @return the value to which the cache maps the specified key, or
089: * <code>null</code> if the map contains no mapping for this key
090: */
091: public synchronized Object get(Object key) {
092: Object value = super .get(key);
093: if (value != null) {
094: freshenKey(key);
095: }
096: return value;
097: }
098:
099: /**
100: * @see java.util.Map#remove(Object)
101: */
102: public synchronized Object remove(Object key) {
103: list.remove(key);
104: return super .remove(key);
105: }
106:
107: /**
108: * Moves the specified value to the top of the LRU list (the bottom of the
109: * list is where least recently used items live).
110: *
111: * @param key key of the value to move to the top of the list
112: */
113: private void freshenKey(Object key) {
114: list.remove(key);
115: list.addFirst(key);
116: }
117: }
|