Coverage Report - org.apache.commons.cache.LRUEvictionPolicy
 
Classes in this File Line Coverage Branch Coverage Complexity
LRUEvictionPolicy
0%
0/167
0%
0/48
2.304
 
 1  
 /*
 2  
  * Copyright 2001-2004 The Apache Software Foundation
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.commons.cache;
 17  
 
 18  
 import java.util.HashMap;
 19  
 import java.util.ArrayList;
 20  
 import java.util.NoSuchElementException;
 21  
 import java.io.Serializable;
 22  
 import java.io.ObjectInputStream;
 23  
 import java.io.IOException;
 24  
 import java.io.NotActiveException;
 25  
 import org.apache.commons.cache.adt.Listable;
 26  
 import org.apache.commons.cache.adt.WListableObject;
 27  
 
 28  
 /**
 29  
  * tk.
 30  
  * @version $Id: LRUEvictionPolicy.java 155435 2005-02-26 13:17:27Z dirkv $
 31  
  * @author Rodney Waldhoff
 32  
  */
 33  
 public class LRUEvictionPolicy implements EvictionPolicy, StorageListener, RetrievalListener, CachedObjectIterator {
 34  0
   transient protected HashMap _hash = new HashMap();
 35  0
   transient protected WListableObject _leastRecent = null;
 36  0
   transient protected WListableObject _mostRecent = null;
 37  0
   transient protected WListableObject _current = null;
 38  
 
 39  0
   protected boolean _canRemove = false;
 40  0
   public Cache _cache = null;
 41  
   protected int _objsbetweennaps;
 42  
   protected long _sleeptimemillis;
 43  
 
 44  
   public LRUEvictionPolicy() {
 45  0
     this(StaleObjectEvictor.DEFAULT_OBJECTS_BETWEEN_NAPS,StaleObjectEvictor.DEFAULT_SLEEP_TIME_MILLIS);
 46  0
   }
 47  
 
 48  0
   public LRUEvictionPolicy(int objsbetweennaps, long sleeptimemillis) {
 49  0
     _objsbetweennaps = objsbetweennaps;
 50  0
     _sleeptimemillis = sleeptimemillis;
 51  0
     Thread t = new Thread(new StaleObjectEvictor(this,_objsbetweennaps,_sleeptimemillis));
 52  0
     t.setDaemon(true);
 53  0
     t.start();
 54  0
   }
 55  
 
 56  
   private void writeObject(java.io.ObjectOutputStream out) throws IOException {
 57  0
      out.defaultWriteObject();
 58  0
      WListableObject cur = _leastRecent;
 59  0
      while(null != cur) {
 60  0
         out.writeObject(cur.getValue());
 61  0
         cur =(WListableObject)(cur.getNext());
 62  
      }
 63  0
      out.writeObject(null);
 64  0
   }
 65  
 
 66  
   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
 67  
     try {
 68  0
       in.defaultReadObject();
 69  0
       _hash = new HashMap();
 70  
       for(;;) {
 71  0
          Object obj = in.readObject();
 72  0
          if(null == obj) {
 73  0
             break;
 74  
          } else {
 75  0
             WListableObject temp = new WListableObject(obj,_mostRecent,null);
 76  0
             if(null == _leastRecent) {
 77  0
                _leastRecent = temp;
 78  0
                _current = temp;
 79  
             }
 80  0
             if(null != _mostRecent) {
 81  0
                _mostRecent.setNext(temp);
 82  
             }
 83  0
             _mostRecent = temp;
 84  0
             _hash.put(((CachedObjectInfo)obj).getKey(),_mostRecent);
 85  
          }
 86  0
       }
 87  
 
 88  0
       Thread t = new Thread(new StaleObjectEvictor(this,_objsbetweennaps,_sleeptimemillis));
 89  0
       t.setDaemon(true);
 90  0
       t.start();
 91  0
     } catch(NotActiveException e) {
 92  0
       e.printStackTrace();
 93  0
     }
 94  0
   }
 95  
 
 96  
   protected synchronized void addToList(WListableObject cur) {
 97  0
     if(null == _mostRecent) {
 98  0
       _mostRecent = cur;
 99  0
       _leastRecent = cur;
 100  
     } else {
 101  0
       _mostRecent.setNext(cur);
 102  0
       cur.setPrev(_mostRecent);
 103  0
       _mostRecent = cur;
 104  
     }
 105  0
   }
 106  
 
 107  
   protected synchronized void removeFromList(WListableObject cur) {
 108  
     // post condition: cur.next and cur.prev are both null
 109  0
     if(_current == cur) {
 110  0
       _current = (WListableObject)(_current.getPrev());
 111  0
       _canRemove = false;
 112  
     }
 113  0
     if(cur.hasPrev()) {
 114  0
       if(cur.hasNext()) {
 115  0
         cur.getPrev().setNext(cur.getNext());
 116  0
         cur.getNext().setPrev(cur.getPrev());
 117  0
         cur.setNext(null);
 118  0
         cur.setPrev(null);
 119  
       } else {
 120  
         // else cur is the most recent and cur.next is null
 121  0
         _mostRecent = (WListableObject)(cur.getPrev());
 122  0
         cur.getPrev().setNext(null);
 123  0
         cur.setPrev(null);
 124  
       }
 125  
     } else {
 126  
       // else cur is the least recent and cur.prev is null
 127  0
       _leastRecent = (WListableObject)(cur.getNext());
 128  0
       if(cur.hasNext()) {
 129  0
         cur.getNext().setPrev(null);
 130  0
         cur.setNext(null);
 131  
       } else {
 132  
         // else cur is both least and most recent
 133  
         // and both next and prev are null
 134  0
         _leastRecent = null;
 135  0
         _mostRecent = null;
 136  
       }
 137  
     }
 138  0
   }
 139  
 
 140  
 
 141  
   public synchronized boolean hasNext() {
 142  0
     return (null != _mostRecent);
 143  
   }
 144  
 
 145  
   public synchronized CachedObjectInfo getNext() throws NoSuchElementException {
 146  0
     if(null != _current) {
 147  0
       _current = (WListableObject)(_current.getNext());
 148  
     }
 149  0
     if(null == _current) { _current = _leastRecent; }
 150  0
     if(null == _current) {
 151  0
       throw new NoSuchElementException();
 152  
     } else {
 153  0
       _canRemove = true;
 154  0
       return (CachedObjectInfo)(_current.getValue());
 155  
     }
 156  
   }
 157  
 
 158  
   public synchronized Object next() throws NoSuchElementException {
 159  0
     return getNext();
 160  
   }
 161  
 
 162  
   public void remove() throws NoSuchElementException, IllegalStateException {
 163  
     // grab a lock on _cache first, since _cache may try to grab a lock on this
 164  0
     synchronized(_cache) {
 165  0
       synchronized(this) {
 166  0
         if(null == _current) {
 167  0
           throw new IllegalStateException();
 168  
         }
 169  0
         if(_canRemove) {
 170  0
           _cache.clear( ((CachedObjectInfo)(_current.getValue())).getKey() );
 171  
         } else {
 172  0
           throw new IllegalStateException();
 173  
         }
 174  0
       }
 175  0
     }
 176  0
   }
 177  
 
 178  
 
 179  
   /** Sets my cache. */
 180  
   public void setCache(Cache c) {
 181  0
     if(null != _cache) {
 182  0
       Object mutex = _cache;
 183  0
       synchronized(mutex) {
 184  0
         synchronized(c) {
 185  0
           synchronized(this) {
 186  0
             unsetCache();
 187  0
             _cache = c;
 188  0
             _cache.registerRetrievalListener(this);
 189  0
             _cache.registerStorageListener(this);
 190  0
           }
 191  0
         }
 192  0
       }
 193  0
     } else {
 194  0
       synchronized(c) {
 195  0
         synchronized(this) {
 196  0
           _cache = c;
 197  0
           _cache.registerRetrievalListener(this);
 198  0
           _cache.registerStorageListener(this);
 199  0
         }
 200  0
       }
 201  
     }
 202  0
   }
 203  
 
 204  
   /** Unsets my cache. */
 205  
   public void unsetCache() {
 206  0
     if(null != _cache) {
 207  0
       Object mutex = _cache;
 208  0
       synchronized(mutex) {
 209  0
         synchronized(this) {
 210  0
           _cache.unregisterRetrievalListener(this);
 211  0
           _cache.unregisterStorageListener(this);
 212  0
           _cache = null;
 213  0
         }
 214  0
       }
 215  
     }
 216  0
   }
 217  
 
 218  0
   public void storeRequested(Serializable key, Serializable val, Long expiresAt, Long cost, Serializable group) { }
 219  
 
 220  0
   public void notStored(Serializable key, Serializable val, Long expiresAt, Long cost, Serializable group) { }
 221  
 
 222  
   public synchronized void stored(Serializable key, Serializable val, Long expiresAt, Long cost, Serializable group) {
 223  0
     WListableObject cur = (WListableObject)(_hash.get(key));
 224  0
     if(null == cur) {
 225  0
       cur = new WListableObject(new CachedObjectInfoImpl(key,expiresAt,cost));
 226  0
       addToList(cur);
 227  0
       _hash.put(key,cur);
 228  
     } else {
 229  0
       removeFromList(cur);
 230  0
       addToList(cur);
 231  
     }
 232  0
   }
 233  
 
 234  
   public synchronized void cleared(Serializable key) {
 235  0
     WListableObject cur = (WListableObject)(_hash.get(key));
 236  0
     if(cur != null) {
 237  0
       removeFromList(cur);
 238  0
       _hash.remove(key);
 239  
     }
 240  0
   }
 241  
 
 242  
   public synchronized void cleared() {
 243  0
     _hash.clear();
 244  0
     _mostRecent = null;
 245  0
     _leastRecent = null;
 246  0
     _current = null;
 247  0
   }
 248  
 
 249  
   public void retrieveRequested(Serializable key) {
 250  0
   }
 251  
 
 252  
   public synchronized void retrieved(Serializable key) {
 253  0
     WListableObject cur = (WListableObject)(_hash.get(key));
 254  0
     if(null == cur) {
 255  0
       cur = new WListableObject(new CachedObjectInfoImpl(key,null,null));
 256  0
       addToList(cur);
 257  0
       _hash.put(key,cur);
 258  
     } else {
 259  0
       removeFromList(cur);
 260  0
       addToList(cur);
 261  
     }
 262  0
   }
 263  
 
 264  
   public void notRetrieved(Serializable key) {
 265  0
   }
 266  
 
 267  
   public synchronized Serializable getEvictionCandidate() {
 268  
     try {
 269  0
       return ((CachedObjectInfoImpl)(_leastRecent.getValue())).getKey();
 270  0
     } catch(NullPointerException e) {
 271  0
       return null;
 272  
     }
 273  
   }
 274  
 
 275  
   public synchronized Serializable[] getEvictionCandidates(int n) {
 276  0
     ArrayList v = new ArrayList(n);
 277  0
     WListableObject c = _leastRecent;
 278  0
     while(n-- > 0) {
 279  0
       if(null != c) {
 280  0
         v.add(((CachedObjectInfoImpl)(c.getValue())).getKey());
 281  0
         c = (WListableObject)(c.getNext());
 282  
       } else {
 283  
         break;
 284  
       }
 285  
     }
 286  0
     return (Serializable[])(v.toArray(new Serializable[0]));
 287  
   }
 288  
 
 289  
   public synchronized String toString() {
 290  0
     StringBuffer buf = new StringBuffer();
 291  0
     WListableObject c = _leastRecent;
 292  0
     while(c != null) {
 293  0
       if(c.hasPrev()) {
 294  0
         buf.append(", ");
 295  
       }
 296  0
       buf.append(c.getValue());
 297  0
       c = (WListableObject)(c.getNext());
 298  
     }
 299  0
     return buf.toString();
 300  
   }
 301  
 }