1 31 32 package org.opencms.cache; 33 34 import org.opencms.main.CmsLog; 35 36 import org.apache.commons.logging.Log; 37 38 63 public class CmsLruCache extends java.lang.Object { 64 65 66 private static final Log LOG = CmsLog.getLog(CmsLruCache.class); 67 68 69 private int m_avgCacheCosts; 70 71 72 private I_CmsLruCacheObject m_listHead; 73 74 75 private I_CmsLruCacheObject m_listTail; 76 77 78 private int m_maxCacheCosts; 79 80 81 private int m_maxObjectCosts; 82 83 84 private int m_objectCosts; 85 86 87 private int m_objectCount; 88 89 96 public CmsLruCache(int theMaxCacheCosts, int theAvgCacheCosts, int theMaxObjectCosts) { 97 98 m_maxCacheCosts = theMaxCacheCosts; 99 m_avgCacheCosts = theAvgCacheCosts; 100 m_maxObjectCosts = theMaxObjectCosts; 101 102 m_objectCosts = 0; 103 m_objectCount = 0; 104 m_listHead = null; 105 m_listTail = null; 106 } 107 108 117 public synchronized boolean add(I_CmsLruCacheObject theCacheObject) { 118 119 if (theCacheObject == null) { 120 return false; 122 } 123 124 if ((m_maxObjectCosts != -1) && (theCacheObject.getLruCacheCosts() > m_maxObjectCosts)) { 126 if (LOG.isInfoEnabled()) { 127 LOG.info(Messages.get().getBundle().key( 128 Messages.LOG_CACHE_COSTS_TOO_HIGH_2, 129 new Integer (theCacheObject.getLruCacheCosts()), 130 new Integer (m_maxObjectCosts))); 131 } 132 return false; 133 } 134 135 if (!isCached(theCacheObject)) { 136 addHead(theCacheObject); 138 } else { 139 touch(theCacheObject); 140 } 141 142 if (m_objectCosts > m_maxCacheCosts) { 144 gc(); 145 } 146 147 return true; 148 } 149 150 153 public void clear() { 154 155 I_CmsLruCacheObject currentObject = m_listTail; 157 while (currentObject != null) { 158 currentObject = currentObject.getNextLruObject(); 159 removeTail(); 160 } 161 162 m_objectCosts = 0; 164 m_objectCount = 0; 165 m_listHead = null; 166 m_listTail = null; 167 168 } 169 170 175 public int getAvgCacheCosts() { 176 177 return m_avgCacheCosts; 178 } 179 180 185 public int getMaxCacheCosts() { 186 187 return m_maxCacheCosts; 188 } 189 190 195 public int getMaxObjectCosts() { 196 197 return m_maxObjectCosts; 198 } 199 200 205 public int getObjectCosts() { 206 207 return m_objectCosts; 208 } 209 210 217 public synchronized I_CmsLruCacheObject remove(I_CmsLruCacheObject theCacheObject) { 218 219 if (!isCached(theCacheObject)) { 220 return null; 222 } 223 224 if (theCacheObject.getNextLruObject() == null) { 226 I_CmsLruCacheObject newHead = theCacheObject.getPreviousLruObject(); 228 229 if (newHead != null) { 230 newHead.setNextLruObject(null); 233 } 234 235 m_listHead = newHead; 236 } else if (theCacheObject.getPreviousLruObject() == null) { 237 I_CmsLruCacheObject newTail = theCacheObject.getNextLruObject(); 239 240 if (newTail != null) { 241 newTail.setPreviousLruObject(null); 244 } 245 246 m_listTail = newTail; 247 } else { 248 theCacheObject.getPreviousLruObject().setNextLruObject(theCacheObject.getNextLruObject()); 250 theCacheObject.getNextLruObject().setPreviousLruObject(theCacheObject.getPreviousLruObject()); 251 } 252 253 decreaseCache(theCacheObject); 255 256 return theCacheObject; 257 } 258 259 264 public int size() { 265 266 return m_objectCount; 267 } 268 269 273 public String toString() { 274 275 StringBuffer buf = new StringBuffer (); 276 buf.append("max. costs: " + m_maxCacheCosts).append(", "); 277 buf.append("avg. costs: " + m_avgCacheCosts).append(", "); 278 buf.append("max. costs/object: " + m_maxObjectCosts).append(", "); 279 buf.append("costs: " + m_objectCosts).append(", "); 280 buf.append("count: " + m_objectCount); 281 return buf.toString(); 282 } 283 284 291 public synchronized boolean touch(I_CmsLruCacheObject theCacheObject) { 292 293 if (!isCached(theCacheObject)) { 294 return false; 295 } 296 297 if ((m_maxObjectCosts != -1) && (theCacheObject.getLruCacheCosts() > m_maxObjectCosts)) { 299 if (LOG.isInfoEnabled()) { 300 LOG.info(Messages.get().getBundle().key( 301 Messages.LOG_CACHE_COSTS_TOO_HIGH_2, 302 new Integer (theCacheObject.getLruCacheCosts()), 303 new Integer (m_maxObjectCosts))); 304 } 305 remove(theCacheObject); 306 return false; 307 } 308 309 I_CmsLruCacheObject nextObj = theCacheObject.getNextLruObject(); 311 if (nextObj == null) { 312 return true; 314 } 315 I_CmsLruCacheObject prevObj = theCacheObject.getPreviousLruObject(); 316 if (prevObj == null) { 317 I_CmsLruCacheObject newTail = nextObj; 319 newTail.setPreviousLruObject(null); 320 m_listTail = newTail; 321 } else { 322 prevObj.setNextLruObject(nextObj); 324 nextObj.setPreviousLruObject(prevObj); 325 } 326 327 I_CmsLruCacheObject oldHead = m_listHead; 329 if (oldHead != null) { 330 oldHead.setNextLruObject(theCacheObject); 331 theCacheObject.setNextLruObject(null); 332 theCacheObject.setPreviousLruObject(oldHead); 333 } 334 m_listHead = theCacheObject; 335 336 return true; 337 } 338 339 343 protected void finalize() throws Throwable { 344 345 try { 346 clear(); 347 } catch (Throwable t) { 348 } 350 super.finalize(); 351 } 352 353 358 private void addHead(I_CmsLruCacheObject theCacheObject) { 359 360 if (m_objectCount > 0) { 362 I_CmsLruCacheObject oldHead = m_listHead; 364 oldHead.setNextLruObject(theCacheObject); 365 theCacheObject.setPreviousLruObject(oldHead); 366 m_listHead = theCacheObject; 367 } else { 368 m_listTail = theCacheObject; 370 m_listHead = theCacheObject; 371 theCacheObject.setPreviousLruObject(null); 372 } 373 theCacheObject.setNextLruObject(null); 374 375 increaseCache(theCacheObject); 377 } 378 379 385 private void decreaseCache(I_CmsLruCacheObject theCacheObject) { 386 387 theCacheObject.removeFromLruCache(); 390 391 theCacheObject.setNextLruObject(null); 393 theCacheObject.setPreviousLruObject(null); 394 395 m_objectCosts -= theCacheObject.getLruCacheCosts(); 397 m_objectCount--; 398 } 399 400 404 private void gc() { 405 406 I_CmsLruCacheObject currentObject = m_listTail; 407 while (currentObject != null) { 408 if (m_objectCosts < m_avgCacheCosts) { 409 break; 410 } 411 currentObject = currentObject.getNextLruObject(); 412 removeTail(); 413 } 414 415 } 416 417 423 private void increaseCache(I_CmsLruCacheObject theCacheObject) { 424 425 theCacheObject.addToLruCache(); 428 429 m_objectCosts += theCacheObject.getLruCacheCosts(); 431 m_objectCount++; 432 } 433 434 440 private boolean isCached(I_CmsLruCacheObject theCacheObject) { 441 442 if (theCacheObject == null || m_objectCount == 0) { 443 return false; 445 } 446 447 I_CmsLruCacheObject nextObj = theCacheObject.getNextLruObject(); 448 I_CmsLruCacheObject prevObj = theCacheObject.getPreviousLruObject(); 449 450 if ((nextObj != null) || (prevObj != null)) { 451 return true; 454 } 455 456 if ((nextObj == null) && (prevObj == null)) { 457 if ((m_objectCount == 1) 458 && (m_listHead != null) 459 && (m_listTail != null) 460 && m_listHead.equals(theCacheObject) 461 && m_listTail.equals(theCacheObject)) { 462 return true; 464 } 465 } 466 467 return false; 468 } 469 470 473 private synchronized void removeTail() { 474 475 I_CmsLruCacheObject oldTail = m_listTail; 476 if (oldTail != null) { 477 I_CmsLruCacheObject newTail = oldTail.getNextLruObject(); 478 479 if (newTail != null) { 481 newTail.setPreviousLruObject(null); 483 m_listTail = newTail; 484 } else { 485 m_listTail = null; 487 m_listHead = null; 488 } 489 490 decreaseCache(oldTail); 492 } 493 } 494 } | Popular Tags |