/*
* This file or a portion of this file is licensed under the terms of
* the Globus Toolkit Public License, found in file ../GTPL, or at
* http://www.globus.org/toolkit/download/license.html. This notice must
* appear in redistributions of this file, with or without modification.
*
* Redistributions of this Software, with or without modification, must
* reproduce the GTPL in: (1) the Software, or (2) the Documentation or
* some other similar material which is provided with the Software (if
* any).
*
* Copyright 1999-2004 University of Chicago and The University of
* Southern California. All rights reserved.
*/
package org.griphyn.vdl.router;
import java.util.*;
import org.griphyn.vdl.util.Logging;
/**
* @author Jens-S. Vöckler
* @author Yong Zhao
* @version $Revision$
*/
public class Cache
{
/**
* remember how long to save a cache entry.
*/
long m_ttl = 0;
/**
* Interior class to encapsulate cached objects and their additional
* management keys.
*/
public class CacheEntry
{
/**
* This is the cached object.
*/
Object m_value;
/**
* This is expiration date of the object.
*/
long m_expire;
/**
* Constructs a cache item with its management data. The time to live
* is determined from the member variable.
*
* @param value is the object to be cached.
*/
CacheEntry( Object value )
{
this.m_value = value;
this.m_expire = System.currentTimeMillis() + m_ttl;
}
}
/**
* remember the objects to cache for. The cache consists of a concise
* key to locate any object, a value for the located large object, and
* a lifetime for the object.
*/
java.util.Map m_cache = null;
/**
* Maintains statistics.
*/
static long[] m_stats = null;
/**
* ctor: Initialize the base functionalities of the cache.
* @param ttl is the lifetime of a positive entry in seconds.
*/
public Cache( int ttl )
{
this.m_ttl = 1000*ttl;
this.m_cache = new java.util.HashMap();
if ( m_stats == null ) {
// Singleton:
Cache.m_stats = new long[5]; // insert, update, miss, expired, hit
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
Logging.instance().log( "cache", 0, "ins=" + Cache.m_stats[0] +
",updt=" + Cache.m_stats[1] +
",miss=" + Cache.m_stats[2] +
",hit=" + Cache.m_stats[4] );
}
});
}
}
/**
* Enters a value into the cache.
* @param key is a concise, unique description of the object.
* @param value is the object to be cached.
* @return <code>null</code> for a fresh object, or the old CacheEntry.
*/
public Object set( Object key, Object value )
{
CacheEntry ce =
(CacheEntry) this.m_cache.put( key, new CacheEntry(value) );
this.m_stats[ ce == null ? 0 : 1]++; // count insert or update
return ( ce == null ? null : ce.m_value );
}
/**
* Requests an item from the cache.
* @param key is the descriptor of the object.
*/
public Object get( Object key )
{
CacheEntry ce = (CacheEntry) this.m_cache.get(key);
// new object?
if ( ce == null ) {
this.m_stats[2]++; // count MISS
return null;
}
// expired object?
if ( ce.m_expire < System.currentTimeMillis() ) {
this.m_stats[3]++; // count EXPIRED
this.m_cache.remove(key);
return null;
}
// known object!
this.m_stats[4]++;
return ce.m_value;
}
/**
* Requests a copy of the statistics counters.
* @return the counter values.
*/
public long[] getStatistics()
{
long[] result = new long[5];
System.arraycopy(this.m_stats,0,result,0,5);
return result;
}
}