1 24 package org.objectweb.jalisto.se.impl.cache; 25 26 import org.objectweb.jalisto.se.api.cache.JalistoCache; 27 import org.objectweb.jalisto.se.impl.trace.Trace; 28 29 import java.io.PrintStream ; 30 import java.lang.ref.ReferenceQueue ; 31 import java.util.*; 32 33 public class WeakReferenceCache implements JalistoCache { 34 35 public WeakReferenceCache() { 36 table = new HashMap(); 37 queue = new ReferenceQueue (); 38 } 39 40 public void init(int size, String name, double clearPourcent) { 41 this.maxSize = size; 42 this.name = name; 43 this.cacheClearPourcent = clearPourcent; 44 } 45 46 public void setTrace(Trace trace) { 47 this.trace = trace; 48 } 49 50 public boolean isEmpty() { 51 return table.isEmpty(); 52 } 53 54 public void clear() { 55 trace.println(Trace.CACHE, "{0} : clear()", name); 56 table.clear(); 57 firstCell = null; 58 lastCell = null; 59 } 60 61 public boolean containsKey(Object key) { 62 return table.containsKey(key); 63 } 64 65 public boolean containsValue(Object value) { 66 throw new UnsupportedOperationException ("not used in this implementation"); 67 } 68 69 public Set entrySet() { 70 throw new UnsupportedOperationException ("not used in this implementation"); 71 } 72 73 public Object get(Object key) { 74 trace.println(Trace.CACHE, "{0} : get({1})", name, key); 75 Object result = table.get(key); 76 if (result != null) { 77 return ((WeakCacheCell) result).get(); 78 } 79 return null; 80 } 81 82 public Set keySet() { 83 return table.keySet(); 84 } 85 86 public Object put(Object key, Object value) { 87 trace.println(Trace.CACHE, "{0} : put({1}, {2})", name, key, value); 88 remove(key); 89 if (table.size() >= maxSize) { 90 makeSpace(); 91 } 92 WeakCacheCell availableCacheCell = WeakCacheCell.newInstance(key, value, queue); 93 if (lastCell != null) { 94 lastCell.setNextCell(availableCacheCell); 95 availableCacheCell.setPrecedingCell(lastCell); 96 lastCell = availableCacheCell; 97 } else { 98 lastCell = availableCacheCell; 99 firstCell = availableCacheCell; 100 } 101 table.put(key, availableCacheCell); 102 return null; 103 } 104 105 public void putAll(Map map) { 106 Iterator keys = map.keySet().iterator(); 107 while (keys.hasNext()) { 108 Object key = keys.next(); 109 put(key, map.get(key)); 110 } 111 } 112 113 public Object remove(Object key) { 114 trace.println(Trace.CACHE, "{0} : remove({1})", name, key); 115 if (containsKey(key)) { 116 synchronized (table) { 117 WeakCacheCell cell = (WeakCacheCell) table.remove(key); 118 if (cell.equals(firstCell)) { 119 firstCell = cell.getNextCell(); 120 } 121 if (cell.equals(lastCell)) { 122 lastCell = cell.getPrecedingCell(); 123 } 124 cell.delink(); 125 if (table.isEmpty()) { 126 lastCell = null; 127 firstCell = null; 128 } 129 return cell.get(); 130 } 131 } 132 return null; 133 } 134 135 public int size() { 136 return table.size(); 137 } 138 139 public synchronized void setMaxSize(int size) { 140 maxSize = size; 141 WeakCacheCell myFirst = firstCell; 142 synchronized (table) { 143 while (table.size() > maxSize) { 144 WeakCacheCell mySecond = myFirst.getNextCell(); 145 table.remove(myFirst.getId()); 146 myFirst.delink(); 147 myFirst = mySecond; 148 } 149 if (table.isEmpty()) { 150 lastCell = null; 151 firstCell = null; 152 } 153 firstCell = myFirst; 154 } 155 } 156 157 public int getMaxSize() { 158 return maxSize; 159 } 160 161 public Collection values() { 162 throw new UnsupportedOperationException ("not used in this implementation"); 163 } 164 165 166 private void makeSpace() { 167 int nbrToRemove = (new Double (maxSize * cacheClearPourcent)).intValue() + 1; 168 trace.println(Trace.CACHE, "{0} : makeSpace() : clear {1} objects", name, new Integer (nbrToRemove)); 169 170 171 int cleaned = cleanQueue(); 172 if (cleaned < nbrToRemove) { 173 nbrToRemove = nbrToRemove - cleaned; 174 WeakCacheCell myFirst = firstCell; 175 synchronized (table) { 176 for (int i = 0; i < nbrToRemove; i++) { 177 WeakCacheCell mySecond = myFirst.getNextCell(); 178 if (mySecond == null) { 179 throw new NullPointerException (); 180 } 181 table.remove(myFirst.getId()); 182 myFirst.delink(); 183 myFirst = mySecond; 184 } 185 } 186 firstCell = myFirst; 187 } 188 } 189 190 private int cleanQueue() { 191 trace.println(Trace.CACHE, "{0} : cleanQueue()", name); 192 WeakCacheCell ref = (WeakCacheCell) queue.poll(); 193 int initSize = table.size(); 194 if (initSize == 0) { 195 return 0; 196 } 197 if (ref != null) { 198 int i = 0; 199 synchronized (table) { 200 while (ref != null) { 201 table.remove(ref.getId()); 202 if (firstCell == ref) { 203 firstCell = ref.getNextCell(); 204 } 205 if (lastCell == ref) { 206 lastCell = ref.getPrecedingCell(); 207 } 208 ref.delink(); 209 i++; 210 ref = (WeakCacheCell) queue.poll(); 211 } 212 } 213 return i; 214 } 215 return 0; 216 } 217 218 public void print(PrintStream out) { 219 out.println(table.toString()); 220 } 221 222 public String toString() { 223 return table.toString(); 224 } 225 226 227 private WeakCacheCell firstCell; 228 private WeakCacheCell lastCell; 229 private HashMap table; 230 private ReferenceQueue queue; 231 private String name; 232 private double cacheClearPourcent; 233 private int maxSize; 234 private Trace trace; 235 } 236 | Popular Tags |