KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > cache > LRUEvictionPolicy


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

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 JavaDoc;
13 import java.util.Collections JavaDoc;
14 import java.util.HashSet JavaDoc;
15
16 /**
17  * Whimpy implementation of an LRU cache
18  */

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     // Assert.eval(!contains(obj));
39
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 JavaDoc 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       // disallow negetative maxCount when capacity is negative
59
throw new AssertionError JavaDoc("Please specify maxcount > 0 as capacity is set to : " + capacity + " Max Count = "
60                                + maxCount);
61     }
62
63     Collection JavaDoc rv = new HashSet JavaDoc();
64     int count = Math.min(cache.size(), maxCount);
65     Cacheable c = (Cacheable) cache.getFirst();
66     Object JavaDoc 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     // XXX: This is here to get around bogus implementation of TLinkedList.contains(Object)
88
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