Clover coverage report -
Coverage timestamp: Sa Jul 7 2007 09:11:40 CEST
file stats: LOC: 156   Methods: 7
NCLOC: 65   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
LRUCache.java 50% 83,3% 100% 81,4%
coverage coverage
 1    /*
 2    * Copyright (c) 2002-2003 by OpenSymphony
 3    * All rights reserved.
 4    */
 5    package com.opensymphony.oscache.base.algorithm;
 6   
 7    import java.util.*;
 8   
 9    /**
 10    * <p>LRU (Least Recently Used) algorithm for the cache.</p>
 11    *
 12    * <p>Since release 2.3 this class requires Java 1.4
 13    * to use the <code>LinkedHashSet</code>. Use prior OSCache release which
 14    * require the Jakarta commons-collections <code>SequencedHashMap</code>
 15    * class or the <code>LinkedList</code> class if neither of the above
 16    * classes are available.</p>
 17    *
 18    * <p>No synchronization is required in this class since the
 19    * <code>AbstractConcurrentReadCache</code> already takes care of any
 20    * synchronization requirements.</p>
 21    *
 22    * @version $Revision: 427 $
 23    * @author <a href="mailto:salaman@teknos.com">Victor Salaman</a>
 24    * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
 25    * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
 26    * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
 27    */
 28    public class LRUCache extends AbstractConcurrentReadCache {
 29   
 30    private static final long serialVersionUID = -7379608101794788534L;
 31   
 32    /**
 33    * Cache queue containing all cache keys.
 34    */
 35    private Collection list = new LinkedHashSet();
 36   
 37    /**
 38    * A flag indicating whether there is a removal operation in progress.
 39    */
 40    private volatile boolean removeInProgress = false;
 41   
 42    /**
 43    * Constructs an LRU Cache.
 44    */
 45  98 public LRUCache() {
 46  98 super();
 47    }
 48   
 49    /**
 50    * Constructors a LRU Cache of the specified capacity.
 51    *
 52    * @param capacity The maximum cache capacity.
 53    */
 54  68 public LRUCache(int capacity) {
 55  68 this();
 56  68 maxEntries = capacity;
 57    }
 58   
 59    /**
 60    * An item was retrieved from the list. The LRU implementation moves
 61    * the retrieved item's key to the front of the list.
 62    *
 63    * @param key The cache key of the item that was retrieved.
 64    */
 65  10318 protected void itemRetrieved(Object key) {
 66    // Prevent list operations during remove
 67  10318 while (removeInProgress) {
 68  0 try {
 69  0 Thread.sleep(5);
 70    } catch (InterruptedException ie) {
 71    }
 72    }
 73   
 74    // We need to synchronize here because AbstractConcurrentReadCache
 75    // doesn't prevent multiple threads from calling this method simultaneously.
 76  10318 synchronized (list) {
 77  10318 list.remove(key);
 78  10318 list.add(key);
 79    }
 80    }
 81   
 82    /**
 83    * An object was put in the cache. This implementation adds/moves the
 84    * key to the end of the list.
 85    *
 86    * @param key The cache key of the item that was put.
 87    */
 88  65465 protected void itemPut(Object key) {
 89    // Since this entry was just accessed, move it to the back of the list.
 90  65465 synchronized (list) { // A further fix for CACHE-44
 91  65465 list.remove(key);
 92  65465 list.add(key);
 93    }
 94    }
 95   
 96    /**
 97    * An item needs to be removed from the cache. The LRU implementation
 98    * removes the first element in the list (ie, the item that was least-recently
 99    * accessed).
 100    *
 101    * @return The key of whichever item was removed.
 102    */
 103  9065 protected Object removeItem() {
 104  9065 Object toRemove = null;
 105   
 106  9065 removeInProgress = true;
 107  9065 try {
 108  9065 while (toRemove == null) {
 109  9065 try {
 110  9065 toRemove = removeFirst();
 111    } catch (Exception e) {
 112    // List is empty.
 113    // this is theorically possible if we have more than the size concurrent
 114    // thread in getItem. Remove completed but add not done yet.
 115    // We simply wait for add to complete.
 116  0 do {
 117  0 try {
 118  0 Thread.sleep(5);
 119    } catch (InterruptedException ie) {
 120    }
 121  0 } while (list.isEmpty());
 122    }
 123    }
 124    } finally {
 125  9065 removeInProgress = false;
 126    }
 127   
 128  9065 return toRemove;
 129    }
 130   
 131    /**
 132    * Remove specified key since that object has been removed from the cache.
 133    *
 134    * @param key The cache key of the item that was removed.
 135    */
 136  171 protected void itemRemoved(Object key) {
 137  171 list.remove(key);
 138    }
 139   
 140    /**
 141    * Removes the first object from the list of keys.
 142    *
 143    * @return the object that was removed
 144    */
 145  9065 private Object removeFirst() {
 146  9065 Object toRemove = null;
 147   
 148  9065 synchronized (list) { // A further fix for CACHE-44 and CACHE-246
 149  9065 Iterator it = list.iterator();
 150  9065 toRemove = it.next();
 151  9065 it.remove();
 152    }
 153   
 154  9065 return toRemove;
 155    }
 156    }