1 package org.gffs.cache;
 
   16 import java.util.ArrayList;
 
   17 import java.util.Date;
 
   18 import java.util.HashMap;
 
   19 import java.util.HashSet;
 
   20 import java.util.List;
 
   23 import org.apache.commons.logging.Log;
 
   24 import org.apache.commons.logging.LogFactory;
 
   43   private HashMap<KeyType, RoleBasedCacheNode<KeyType, DataType>> _map;
 
   44   private LRUList<KeyType, DataType> _lruList;
 
   45   private TimeoutList<KeyType, DataType> _timeoutList;
 
   47   private int _maxElements;
 
   48   private long _defaultTimeoutMS;
 
   49   private Thread _activeTimeoutThread = 
null;
 
   50   private boolean _logCacheEjection = 
false;
 
   56       throw new IllegalArgumentException(
"\"maxElements\" must be greater than 0.");
 
   59       throw new IllegalArgumentException(
"must provide a non-null cache name");
 
   61     _maxElements = maxElements;
 
   62     _defaultTimeoutMS = defaultTimeoutMS;
 
   63     _map = 
new HashMap<KeyType, RoleBasedCacheNode<KeyType, DataType>>(_maxElements);
 
   64     _lruList = 
new LRUList<KeyType, DataType>();
 
   65     _timeoutList = 
new TimeoutList<KeyType, DataType>();
 
   81     _logCacheEjection = logRemovals;
 
   87       if (_activeTimeoutThread == 
null) {
 
  102   public void put(KeyType key, DataType data, 
long timeoutMS)
 
  104     RoleBasedCacheNode<KeyType, DataType> newNode =
 
  105       new RoleBasedCacheNode<KeyType, DataType>(key, data, 
new Date(System.currentTimeMillis() + timeoutMS));
 
  107     synchronized (_map) {
 
  108       RoleBasedCacheNode<KeyType, DataType> oldNode = _map.remove(key);
 
  109       if (oldNode != 
null) {
 
  110         _lruList.remove(oldNode);
 
  111         _timeoutList.remove(oldNode);
 
  114       if (_map.size() >= _maxElements)
 
  117       while (_map.size() >= _maxElements) {
 
  118         RoleBasedCacheNode<KeyType, DataType> node = _lruList.removeFirst();
 
  119         if (_logCacheEjection && _logger.isDebugEnabled())
 
  120           _logger.debug(
debugPrefix() + 
"overloaded cache: removing cached item with key: " + node.getKey());
 
  121         _timeoutList.remove(node);
 
  122         _map.remove(node.getKey());
 
  125       _map.put(key, newNode);
 
  126       _lruList.insert(newNode);
 
  127       _timeoutList.insert(newNode);
 
  133   public void put(KeyType key, DataType data)
 
  135     put(key, data, _defaultTimeoutMS);
 
  149     synchronized (_map) {
 
  150       RoleBasedCacheNode<KeyType, DataType> node = _map.get(key);
 
  153       _lruList.remove(node);
 
  154       node.setInvalidationDate(_defaultTimeoutMS);
 
  156       _lruList.insert(node);
 
  158       _timeoutList.remove(node);
 
  159       _timeoutList.insert(node);
 
  166   private final long CHECK_INTERVAL = 1000 * 10;
 
  168   private Date _nextDeepSizeCheck = 
new Date((
new Date().getTime()) + CHECK_INTERVAL);
 
  170   public DataType 
get(KeyType key)
 
  172     Date 
now = 
new Date();
 
  174     if (
now.after(_nextDeepSizeCheck)) {
 
  191       _nextDeepSizeCheck = 
new Date((
new Date().getTime()) + CHECK_INTERVAL);
 
  194     synchronized (_map) {
 
  195       RoleBasedCacheNode<KeyType, DataType> node = _map.get(key);
 
  198       _lruList.remove(node);
 
  199       if (node.getInvalidationDate().before(
now)) {
 
  201         if (_logCacheEjection && _logger.isDebugEnabled())
 
  202           _logger.debug(
debugPrefix() + 
"timed-out entry in get: removing cached item with key: " + node.getKey());
 
  204         _timeoutList.remove(node);
 
  208       _lruList.insert(node);
 
  209       return node.getData();
 
  215     ArrayList<DataType> toReturn = 
new ArrayList<DataType>();
 
  216     synchronized (_map) {
 
  217       for (KeyType key : _map.keySet()) {
 
  218         toReturn.add(_map.get(key).getData());
 
  226     ArrayList<DataType> toReturn = 
new ArrayList<DataType>();
 
  227     synchronized (_map) {
 
  228       for (KeyType key : references) {
 
  230         if (_map.containsKey(key)) {
 
  231           toReturn.add(_map.get(key).getData());
 
  233           _logger.error(
debugPrefix() + 
"failed to locate referenced object in cache: " + key);
 
  242     Date 
now = 
new Date();
 
  244     synchronized (_map) {
 
  246         RoleBasedCacheNode<KeyType, DataType> node = _timeoutList.peekFirst();
 
  250         if (node.getInvalidationDate().compareTo(
now) <= 0) {
 
  251           if (_logCacheEjection && _logger.isDebugEnabled())
 
  252             _logger.debug(
debugPrefix() + 
"removing timed-out node: " + node.getKey());
 
  253           _map.remove(node.getKey());
 
  254           _timeoutList.removeFirst();
 
  255           _lruList.remove(node);
 
  263   public void remove(KeyType key)
 
  265     synchronized (_map) {
 
  266       RoleBasedCacheNode<KeyType, DataType> node = _map.remove(key);
 
  268         _lruList.remove(node);
 
  269         _timeoutList.remove(node);
 
  276     synchronized (_map) {
 
  277       return new HashSet<KeyType>(_map.keySet());
 
  283     synchronized (_map) {
 
  286       _timeoutList.clear();
 
  292     _activeTimeoutThread = 
new Thread(
new ActiveTimeoutWorker(), 
"Active Cache Timeout Thread");
 
  293     _activeTimeoutThread.setDaemon(
true);
 
  294     _activeTimeoutThread.start();
 
  299     Thread tmp = _activeTimeoutThread;
 
  300     _activeTimeoutThread = 
null;
 
  301     synchronized (_map) {
 
  307     } 
catch (InterruptedException cause) {
 
  311   private class ActiveTimeoutWorker 
implements Runnable
 
  315       synchronized (_map) {
 
  316         while (_activeTimeoutThread != 
null) {
 
  319             RoleBasedCacheNode<KeyType, DataType> firstNode = _timeoutList.peekFirst();
 
  320             if (firstNode == 
null) {
 
  323               Date nextStale = firstNode.getInvalidationDate();
 
  324               long timeout = nextStale.getTime() - System.currentTimeMillis();
 
  329           } 
catch (InterruptedException ie) {
 
void put(KeyType key, DataType data, long timeoutMS)
void activelyTimeoutElements(boolean activelyTimeout)
boolean refresh(KeyType key)
void put(KeyType key, DataType data)
List< DataType > getAll()
void setCacheEjectionLogging(boolean logRemovals)
List< DataType > getAllReferenced(List< KeyType > references)
TimedOutLRUCache(int maxElements, long defaultTimeoutMS, String cacheName)
void startActiveTimeout()
time_locus now()
returns our current locus in the time continuum.