1 25 26 package org.objectweb.perseus.cache.replacement.lib; 27 28 import org.objectweb.fractal.api.control.BindingController; 29 import org.objectweb.perseus.cache.api.CacheException; 30 import org.objectweb.perseus.cache.api.FixableCacheEntry; 31 import org.objectweb.perseus.cache.api.UnbindManager; 32 import org.objectweb.perseus.cache.api.CacheCapacityEventListener; 33 import org.objectweb.perseus.cache.api.CacheCapacityEvent; 34 import org.objectweb.perseus.cache.replacement.api.ReplaceableCacheEntry; 35 import org.objectweb.perseus.cache.replacement.api.ReplacementManager; 36 import org.objectweb.util.monolog.api.BasicLevel; 37 import org.objectweb.util.monolog.api.Logger; 38 39 import java.lang.ref.ReferenceQueue ; 40 import java.lang.ref.WeakReference ; 41 import java.util.ArrayList ; 42 import java.util.Collection ; 43 import java.util.HashMap ; 44 import java.util.Iterator ; 45 import java.util.SortedSet ; 46 import java.util.TreeSet ; 47 import java.util.Collections ; 48 49 55 public abstract class AbstractReplacementManager 56 implements ReplacementManager, BindingController, CacheCapacityEventListener { 57 58 public final static String UNBIND_MANAGER_BINDING = "unbind-manager"; 59 60 protected UnbindManager ub; 61 62 66 protected SortedSet entries; 67 protected HashMap oid2wentry; 68 69 72 protected ReferenceQueue queue; 73 74 protected Logger logger = null; 75 76 public AbstractReplacementManager() { 77 entries = new TreeSet (); 78 oid2wentry = new HashMap (); 79 queue = new ReferenceQueue (); 80 } 81 82 85 public String [] listFc() { 86 return new String [] { 87 UNBIND_MANAGER_BINDING, 88 }; 89 } 90 91 public Object lookupFc(String s) { 92 if (UNBIND_MANAGER_BINDING.equals(s)) { 93 return ub; 94 } 95 return null; 96 } 97 98 public void bindFc(String s, Object o) { 99 if (UNBIND_MANAGER_BINDING.equals(s)) { 100 ub = (UnbindManager) o; 101 } else if ("logger".equals(s)) { 102 logger = (Logger) o; 103 } 104 } 105 106 public void unbindFc(String s) { 107 if (UNBIND_MANAGER_BINDING.equals(s)) { 108 ub = null; 109 } 110 } 111 112 115 public void cacheResized(CacheCapacityEvent event) { 116 int size = event.getSize(); 117 if (size > 0) { 118 synchronized(entries) { 119 if (oid2wentry.size() == 0) { 120 oid2wentry = new HashMap (size); 121 } 122 } 123 } 124 } 125 126 129 public void addForReplacement(FixableCacheEntry entry) 130 throws CacheException { 131 if (logger.isLoggable(BasicLevel.DEBUG)) 132 logger.log(BasicLevel.DEBUG, 133 "add the entry " + entry.getCeIdentifier()); 134 ReplaceableCacheEntry dentry = check(entry); 135 synchronized(entries) { 136 clean(); 137 WeakReplaceableCacheEntry we = (WeakReplaceableCacheEntry) 138 oid2wentry.get(entry.getCeIdentifier()); 139 add(dentry); 140 if (we != null) { 141 entries.remove(we); 142 we.updateEntry((ReplaceableCacheEntry) entry); 143 } else { 144 we = new WeakReplaceableCacheEntry(dentry, queue); 145 oid2wentry.put(entry.getCeIdentifier(), we); 146 } 147 entries.add(we); 148 } 149 } 150 151 public void adjustForReplacement(FixableCacheEntry entry) 152 throws CacheException { 153 if (logger.isLoggable(BasicLevel.DEBUG)) { 154 logger.log(BasicLevel.DEBUG, 155 "touch the entry " + entry.getCeIdentifier()); 156 } 157 ReplaceableCacheEntry dentry = check(entry); 158 synchronized(entries) { 159 clean(); 160 WeakReplaceableCacheEntry we = (WeakReplaceableCacheEntry) 161 oid2wentry.get(entry.getCeIdentifier()); 162 touch(dentry); 163 if (we != null) { 164 entries.remove(we); 165 we.updateEntry((ReplaceableCacheEntry) entry); 166 } else { 167 we = new WeakReplaceableCacheEntry(dentry, queue); 168 oid2wentry.put(entry.getCeIdentifier(), we); 169 } 170 } 171 } 172 173 public int forceFree(int capacity) throws CacheException { 174 boolean debug = logger.isLoggable(BasicLevel.DEBUG); 175 if (debug) { 176 logger.log(BasicLevel.DEBUG, "forceFree: requested: " + capacity); 177 } 178 ArrayList oids = new ArrayList (capacity); 180 int count = 0; 181 synchronized(entries) { 182 Iterator i = entries.iterator(); 183 while (count < capacity && i.hasNext()) { 184 WeakReplaceableCacheEntry wentry = (WeakReplaceableCacheEntry) i.next(); 185 ReplaceableCacheEntry entry = (ReplaceableCacheEntry) wentry.get(); 186 if (entry != null && entry.getCeFixCount() == 0) { 187 oids.add(entry.getCeIdentifier()); 188 count++; 189 } 190 } 191 } 192 if (debug) { 193 logger.log(BasicLevel.DEBUG, "forceFree: try to unbound, oids=" + oids); 194 } 195 Collection _oids = ub.unbindAll(oids, false); 197 if (debug) { 198 logger.log(BasicLevel.DEBUG, "forceFree: entries unbound, oid=" + _oids); 199 } 200 return _oids.size(); 201 } 202 203 public void removeForReplacement(Object oid) { 204 synchronized(entries) { 205 Object we = oid2wentry.remove(oid); 206 if (we != null) { 207 entries.remove(we); 208 } 209 } 210 } 211 212 213 public Collection unbindAll(Collection _oids, boolean force) throws CacheException { 216 boolean debug = logger.isLoggable(BasicLevel.DEBUG); 217 ArrayList oids = new ArrayList (); 219 synchronized(entries) { 220 if (entries.isEmpty()) { 221 return Collections.EMPTY_SET; 222 } 223 oids = new ArrayList (); 224 Iterator it = _oids.iterator(); 225 while(it.hasNext()) { 226 Object oid = it.next(); 227 WeakReplaceableCacheEntry wentry = 228 (WeakReplaceableCacheEntry) oid2wentry.get(oid); 229 if (wentry != null) { 230 oids.add(oid); 231 } 232 } 233 } 234 if (debug) { 235 logger.log(BasicLevel.DEBUG, "unbindAll(oids, " + force 236 + ") try to unbound, oids=" + oids); 237 } 238 _oids = ub.unbindAll(oids, force); 240 if (debug) { 241 logger.log(BasicLevel.DEBUG, "entries unbound, oid=" + _oids); 242 } 243 return _oids; 244 } 245 246 public Collection unbindUnfixed(boolean force) throws CacheException { 247 boolean debug = logger.isLoggable(BasicLevel.DEBUG); 248 ArrayList oids; 250 synchronized(entries) { 251 if (entries.isEmpty()) { 252 return Collections.EMPTY_SET; 253 } 254 oids = new ArrayList (); 255 Iterator it = entries.iterator(); 256 while(it.hasNext()) { 257 WeakReplaceableCacheEntry wentry = (WeakReplaceableCacheEntry) it.next(); 258 ReplaceableCacheEntry ce = (ReplaceableCacheEntry) wentry.get(); 259 if (ce == null || ce.getCeFixCount() == 0) { 260 oids.add(wentry.getCeIdentifier()); 261 } 262 } 263 } 264 if (debug) { 265 logger.log(BasicLevel.DEBUG, "unbindAll(" + force 266 + ") try to unbound, oids=" + oids); 267 } 268 Collection _oids = ub.unbindAll(oids, force); 270 if (debug) { 271 logger.log(BasicLevel.DEBUG, "entries unbound, oid=" + _oids); 272 } 273 return _oids; 274 } 275 276 280 public boolean unbind(Object oid, boolean force) throws CacheException { 281 boolean debug = logger.isLoggable(BasicLevel.DEBUG); 282 if (oid == null) { 283 return false; 284 } 285 if (debug) 286 logger.log(BasicLevel.DEBUG, "unbind, oid=" + oid); 287 WeakReplaceableCacheEntry we; 288 try { 289 we = (WeakReplaceableCacheEntry ) oid2wentry.get(oid); 291 } catch (Throwable e) { 292 synchronized(entries) { 295 we = (WeakReplaceableCacheEntry ) oid2wentry.get(oid); 296 } 297 } 298 if (we != null) { 299 return ub.unbind(oid, force); 300 } else { 301 logger.log(BasicLevel.WARN, 302 "The entry has not been found from the cache"); 303 return false; 304 } 305 } 306 307 309 private ReplaceableCacheEntry check(FixableCacheEntry entry) { 310 try { 311 return (ReplaceableCacheEntry) entry; 312 } catch (ClassCastException e) { 313 throw new IllegalArgumentException ( 314 "This replacement manager works only with ReplaceableCacheEntry entries"); 315 } 316 } 317 318 protected abstract void add(ReplaceableCacheEntry entry); 319 320 protected abstract void touch(ReplaceableCacheEntry entry); 321 322 325 private void clean() { 326 boolean debug = logger.isLoggable(BasicLevel.DEBUG); 327 while (true) { 328 WeakReplaceableCacheEntry wentry = 329 (WeakReplaceableCacheEntry) queue.poll(); 330 if (wentry != null) { 331 if (debug) { 332 logger.log(BasicLevel.DEBUG, "auto cleanup, oid=" 333 + wentry.getCeIdentifier()); 334 } 335 entries.remove(wentry); 336 oid2wentry.remove(wentry.getCeIdentifier()); 337 } else { 338 return; 339 } 340 } 341 } 342 343 348 private static class WeakReplaceableCacheEntry 349 extends WeakReference implements Comparable { 350 351 private long date; 352 private Object oid; 353 354 public WeakReplaceableCacheEntry(ReplaceableCacheEntry ce, ReferenceQueue queue) { 355 super(ce, queue); 356 oid = ce.getCeIdentifier(); 357 date = ce.getCeAge(); 358 } 359 360 public Object getCeIdentifier() { 361 return oid; 362 } 363 364 public int compareTo(Object o) { 365 long odate = ((WeakReplaceableCacheEntry) o).date; 366 if (date == odate) { 367 return 0; 368 } else { 369 return date < odate ? -1 : 1; 370 } 371 } 372 373 public boolean equals(Object o) { 374 return date == ((WeakReplaceableCacheEntry) o).date; 375 } 376 377 public void updateEntry(ReplaceableCacheEntry ce) { 378 oid = ce.getCeIdentifier(); 379 date = ce.getCeAge(); 380 } 381 } 382 } 383 | Popular Tags |