1 4 package com.tc.object.cache; 5 6 import com.tc.logging.TCLogger; 7 import com.tc.logging.TCLogging; 8 import com.tc.text.PrettyPrinter; 9 10 import gnu.trove.TLinkedList; 11 12 import java.util.Collection ; 13 import java.util.Collections ; 14 import java.util.HashSet ; 15 16 19 public class LRUEvictionPolicy implements EvictionPolicy { 20 private static final TCLogger logger = TCLogging.getLogger(LRUEvictionPolicy.class); 21 private final TLinkedList cache = new TLinkedList(); 22 private final int capacity; 23 private final int evictionSize; 24 25 public LRUEvictionPolicy(int capacity) { 26 this(capacity, capacity / 10); 27 } 28 29 public LRUEvictionPolicy(int capacity, int evictionSize) { 30 if (logger.isDebugEnabled()) { 31 logger.debug("new " + getClass().getName() + "(" + capacity + ")"); 32 } 33 this.capacity = capacity; 34 this.evictionSize = (evictionSize <= 0 ? 1 : evictionSize); 35 } 36 37 public synchronized boolean add(Cacheable obj) { 38 if (logger.isDebugEnabled()) { 40 logger.debug("Adding: " + obj); 41 } 42 cache.addLast(obj); 43 44 return isCacheFull(); 45 } 46 47 private boolean isCacheFull() { 48 return (capacity > 0 && cache.size() > capacity); 49 } 50 51 public synchronized Collection getRemovalCandidates(int maxCount) { 52 if (capacity > 0) { 53 if (!isCacheFull()) { return Collections.EMPTY_LIST; } 54 if (maxCount <= 0 || maxCount > evictionSize) { 55 maxCount = evictionSize; 56 } 57 } else if (maxCount <= 0) { 58 throw new AssertionError ("Please specify maxcount > 0 as capacity is set to : " + capacity + " Max Count = " 60 + maxCount); 61 } 62 63 Collection rv = new HashSet (); 64 int count = Math.min(cache.size(), maxCount); 65 Cacheable c = (Cacheable) cache.getFirst(); 66 Object save = c; 67 while (cache.size() - rv.size() > capacity && count > 0) { 68 moveToTail(c); 69 if (c.canEvict()) { 70 rv.add(c); 71 count--; 72 } 73 c = (Cacheable) cache.getFirst(); 74 if (save == c) break; 75 } 76 return rv; 77 } 78 79 public synchronized void remove(Cacheable obj) { 80 if (logger.isDebugEnabled()) { 81 logger.debug("Removing: " + obj); 82 } 83 if (contains(obj)) cache.remove(obj); 84 } 85 86 private boolean contains(Cacheable obj) { 87 return obj != null && (obj.getNext() != null || obj.getPrevious() != null); 89 } 90 91 public synchronized void markReferenced(Cacheable obj) { 92 moveToTail(obj); 93 } 94 95 private synchronized void moveToTail(Cacheable obj) { 96 if (contains(obj)) { 97 cache.remove(obj); 98 cache.addLast(obj); 99 } 100 } 101 102 public synchronized PrettyPrinter prettyPrint(PrettyPrinter out) { 103 PrettyPrinter rv = out; 104 out.println(getClass().getName()); 105 out = out.duplicateAndIndent(); 106 out.indent().println("max size: " + capacity).indent().print("cache: ").visit(cache).println(); 107 return rv; 108 } 109 110 public int getCacheCapacity() { 111 return capacity; 112 } 113 114 } 115 | Popular Tags |