1 19 package org.openharmonise.commons.cache; 20 21 import java.util.*; 22 import java.util.logging.*; 23 24 import EDU.oswego.cs.dl.util.concurrent.*; 25 26 39 public abstract class AbstractCache { 40 41 44 public static final int DEFAULT_CACHESIZE = 3500; 45 46 49 public static final String CHANGE_SAVE = "save"; 50 51 54 public static final String CHANGE_DELETE = "delete"; 55 56 59 public static final String CHANGE_UPDATE = "update"; 60 61 64 public static final String CHANGE_TEMP = "temp"; 65 66 70 public static final double DEFAULT_CACHELIMIT_PERCENT = 0.9; 71 72 76 public static final double DEFAULT_CACHEREDUCTION_RATIO = 0.95; 77 78 81 private static List m_protected_caches = null; 82 83 86 private static Map m_all_caches; 87 88 91 private static Logger m_logger = Logger.getLogger(AbstractCache.class.getName()); 92 93 static { 94 m_all_caches = Collections.synchronizedMap(new HashMap()); 96 } 97 98 101 private String m_cache_name; 102 103 106 private LRUCacheMap m_cache; 107 108 111 private int m_max_cache_size; 112 113 116 private int m_init_max_cache_size; 117 118 121 private long m_total_object_size_estimate = 0; 122 123 126 private int m_heap_size = -1; 128 129 132 private ReadWriteLock lock = new WriterPreferenceReadWriteLock(); 133 134 142 protected AbstractCache(String cache_name, int cache_size) throws CacheException { 143 m_cache_name = cache_name; 144 m_init_max_cache_size = cache_size; 145 m_max_cache_size = cache_size; 146 m_cache = new LRUCacheMap(cache_size); 147 148 m_all_caches.put(m_cache_name, this); 149 } 150 151 157 protected AbstractCache(String cache_name) throws CacheException { 158 this(cache_name, DEFAULT_CACHESIZE); 159 160 m_all_caches.put(m_cache_name, this); 161 } 162 163 172 public Object getObject(final Object key) throws CacheException { 173 174 Object cached_object = null; 176 try { 177 lock.readLock().acquire(); 178 cached_object = m_cache.get(key); 179 lock.readLock().release(); 180 if (cached_object == null) { 181 cached_object = addToCache(key); 182 } 183 184 } catch (InterruptedException e) { 185 throw new CacheException (e); 186 } 187 188 return cached_object; 189 } 190 191 200 public CachePointer getObjectPointer(Object key) throws CacheException { 201 202 Object obj = getObject(key); 205 206 return new CachePointer(key,this); 207 } 208 209 221 protected Object addToCache(Object key) throws CacheException { 222 Object cacheable_object = null; 223 try { 224 225 cacheable_object = getCacheableObject(key); 226 addToCache(key, cacheable_object); 227 } catch (java.lang.OutOfMemoryError e) { 228 AbstractCache.clearAllCaches(); 231 232 Runtime runtime = Runtime.getRuntime(); 233 234 String error_msg = (m_cache_name + " cache: " + 235 " Thrown OutOfMemoryError Exception" + 236 " Not enough memory to allocate cacheable object " + 237 ", free memory: " + runtime.freeMemory() + 238 ", total memory: " + runtime.totalMemory() + 239 ", probable needed memory: " + 240 getAvgObjectSizeOfEstimate()); 241 242 m_logger.log(Level.SEVERE, error_msg, e); 243 } catch (Exception e) { 244 throw new CacheException(e); 245 } 246 return cacheable_object; 247 } 248 249 254 public long getAvgObjectSizeOfEstimate() { 255 return (m_cache.size() == 0) 257 ? 0 : Math.round(m_total_object_size_estimate / m_cache.size()); 258 } 259 260 270 public void addToCache(Object key, Object cacheable_object) { 271 272 273 if(m_logger.getLevel() == Level.FINE) { 274 StringBuffer sbuf = new StringBuffer (); 275 sbuf.append(m_cache_name) 276 .append(": cache size - ") 277 .append( m_cache.size()) 278 .append(", m_max_cache_size - ") 279 .append(m_max_cache_size); 280 m_logger.log(Level.FINE, sbuf.toString()); 281 } 282 283 try { 284 lock.writeLock().acquire(); 285 m_cache.put(key, cacheable_object); 286 lock.writeLock().release(); 287 } catch (InterruptedException e) { 288 throw new RuntimeException (e); 289 } 290 291 } 292 293 299 protected void removeObjectFromCache(Object key) { 300 try { 301 lock.writeLock().acquire(); 302 m_cache.remove(key); 303 lock.writeLock().release(); 304 } catch (InterruptedException e) { 305 m_logger.log(Level.WARNING, e.getLocalizedMessage(), e); 306 } 307 } 308 309 313 static synchronized public void clearAllCaches() { 314 315 Iterator cache_iter = m_all_caches.values().iterator(); 316 317 while (cache_iter.hasNext()) { 318 ((AbstractCache) cache_iter.next()).clearCache(); 319 } 320 } 321 322 327 public void clearCache() { 328 try { 329 lock.writeLock().acquire(); 330 331 m_cache.clear(); 332 lock.writeLock().release(); 333 } catch (InterruptedException e) { 334 throw new RuntimeException (e); 335 } 336 } 337 338 344 public int getCacheSize() { 345 return m_cache.size(); 346 } 347 348 353 public String getCacheName() { 354 return this.m_cache_name; 355 } 356 357 358 359 364 public int getCacheMaxSize() { 365 return m_max_cache_size; 366 } 367 368 373 public void setCacheMaxSize(int maxSize) { 374 375 try { 376 LRUCacheMap new_cache = new LRUCacheMap(maxSize); 377 lock.readLock().acquire(); 378 int i=0; 379 for (Iterator iter = m_cache.keySet().iterator(); iter.hasNext() && i<maxSize;i++) { 380 Object key = (Object ) iter.next(); 381 new_cache.put(key, m_cache.get(key)); 382 } 383 lock.readLock().release(); 384 385 lock.writeLock().acquire(); 386 m_cache = new_cache; 387 lock.writeLock().release(); 388 } catch (InterruptedException e) { 389 m_logger.log(Level.WARNING, e.getLocalizedMessage(), e); 390 } 391 } 392 393 394 401 public List getCacheTopKeys(int num_favourites) { 402 List toReturn = null; 403 404 try { 405 lock.readLock().acquire(); 406 toReturn = new Vector(m_cache.values()).subList(0, 407 (m_cache.size() > num_favourites) 408 ? num_favourites 409 : m_cache.size()); 410 lock.readLock().release(); 411 } catch (InterruptedException e) { 412 m_logger.log(Level.WARNING, e.getLocalizedMessage(), e); 413 } 414 return toReturn; 415 416 } 417 418 423 public Set getCacheKeys() { 424 Set toReturn = null; 425 try { 426 lock.readLock().acquire(); 427 toReturn = new HashSet(m_cache.keySet()); 428 lock.readLock().release(); 429 } 430 catch (InterruptedException e) { 431 m_logger.log(Level.WARNING, e.getLocalizedMessage(), e); 432 } 433 return toReturn; 434 } 435 436 443 public boolean containsKey(Object cache_key) throws InterruptedException { 444 lock.readLock().acquire(); 445 boolean containsKeyFlag = m_cache.containsKey(cache_key); 446 lock.readLock().release(); 447 return containsKeyFlag; 448 } 449 450 459 public void setDependancyAware(boolean bIsDepAware) { 460 m_cache.setDependancyAware(bIsDepAware); 461 } 462 463 469 public boolean isDependancyAware() { 470 return m_cache.isDependancyAware(); 471 } 472 473 480 protected abstract Object getCacheableObject(Object key) 481 throws Exception ; 482 483 493 public void changeObject(Object cache_key, String sChangeCode, 494 Object newObject) { 495 496 try { 497 lock.writeLock().acquire(); 498 m_cache.remove(cache_key); 499 500 if (sChangeCode.equalsIgnoreCase(CHANGE_SAVE) || 501 sChangeCode.equalsIgnoreCase(CHANGE_UPDATE)) { 502 addToCache(cache_key, newObject); 503 } 504 lock.writeLock().release(); 505 } catch (InterruptedException e) { 506 m_logger.log(Level.WARNING, e.getLocalizedMessage(), e); 507 throw new RuntimeException (e); 508 } 509 } 510 511 } | Popular Tags |