001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file ../GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015: package org.griphyn.vdl.router;
016:
017: import java.util.*;
018: import org.griphyn.vdl.util.Logging;
019:
020: /**
021: * @author Jens-S. Vöckler
022: * @author Yong Zhao
023: * @version $Revision: 50 $
024: */
025: public class Cache {
026: /**
027: * remember how long to save a cache entry.
028: */
029: long m_ttl = 0;
030:
031: /**
032: * Interior class to encapsulate cached objects and their additional
033: * management keys.
034: */
035: public class CacheEntry {
036: /**
037: * This is the cached object.
038: */
039: Object m_value;
040:
041: /**
042: * This is expiration date of the object.
043: */
044: long m_expire;
045:
046: /**
047: * Constructs a cache item with its management data. The time to live
048: * is determined from the member variable.
049: *
050: * @param value is the object to be cached.
051: */
052: CacheEntry(Object value) {
053: this .m_value = value;
054: this .m_expire = System.currentTimeMillis() + m_ttl;
055: }
056: }
057:
058: /**
059: * remember the objects to cache for. The cache consists of a concise
060: * key to locate any object, a value for the located large object, and
061: * a lifetime for the object.
062: */
063: java.util.Map m_cache = null;
064:
065: /**
066: * Maintains statistics.
067: */
068: static long[] m_stats = null;
069:
070: /**
071: * ctor: Initialize the base functionalities of the cache.
072: * @param ttl is the lifetime of a positive entry in seconds.
073: */
074: public Cache(int ttl) {
075: this .m_ttl = 1000 * ttl;
076: this .m_cache = new java.util.HashMap();
077: if (m_stats == null) {
078: // Singleton:
079: Cache.m_stats = new long[5]; // insert, update, miss, expired, hit
080:
081: Runtime.getRuntime().addShutdownHook(new Thread() {
082: public void run() {
083: Logging.instance().log(
084: "cache",
085: 0,
086: "ins=" + Cache.m_stats[0] + ",updt="
087: + Cache.m_stats[1] + ",miss="
088: + Cache.m_stats[2] + ",hit="
089: + Cache.m_stats[4]);
090: }
091: });
092: }
093: }
094:
095: /**
096: * Enters a value into the cache.
097: * @param key is a concise, unique description of the object.
098: * @param value is the object to be cached.
099: * @return <code>null</code> for a fresh object, or the old CacheEntry.
100: */
101: public Object set(Object key, Object value) {
102: CacheEntry ce = (CacheEntry) this .m_cache.put(key,
103: new CacheEntry(value));
104: this .m_stats[ce == null ? 0 : 1]++; // count insert or update
105: return (ce == null ? null : ce.m_value);
106: }
107:
108: /**
109: * Requests an item from the cache.
110: * @param key is the descriptor of the object.
111: */
112: public Object get(Object key) {
113: CacheEntry ce = (CacheEntry) this .m_cache.get(key);
114:
115: // new object?
116: if (ce == null) {
117: this .m_stats[2]++; // count MISS
118: return null;
119: }
120:
121: // expired object?
122: if (ce.m_expire < System.currentTimeMillis()) {
123: this .m_stats[3]++; // count EXPIRED
124: this .m_cache.remove(key);
125: return null;
126: }
127:
128: // known object!
129: this .m_stats[4]++;
130: return ce.m_value;
131: }
132:
133: /**
134: * Requests a copy of the statistics counters.
135: * @return the counter values.
136: */
137: public long[] getStatistics() {
138: long[] result = new long[5];
139: System.arraycopy(this .m_stats, 0, result, 0, 5);
140: return result;
141: }
142: }
|