1 11 package org.eclipse.jdt.internal.core; 12 13 import java.util.Enumeration ; 14 import java.util.Iterator ; 15 16 import org.eclipse.jdt.internal.core.util.LRUCache; 17 import org.eclipse.jdt.internal.core.util.Messages; 18 19 51 public abstract class OverflowingLRUCache extends LRUCache { 52 55 protected int fOverflow = 0; 56 59 protected boolean fTimestampsOn = true; 60 64 protected double fLoadFactor = 0.333; 65 69 public OverflowingLRUCache(int size) { 70 this(size, 0); 71 } 72 77 public OverflowingLRUCache(int size, int overflow) { 78 super(size); 79 fOverflow = overflow; 80 } 81 86 public Object clone() { 87 88 OverflowingLRUCache newCache = (OverflowingLRUCache)newInstance(fSpaceLimit, fOverflow); 89 LRUCacheEntry qEntry; 90 91 92 qEntry = this.fEntryQueueTail; 93 while (qEntry != null) { 94 newCache.privateAdd (qEntry._fKey, qEntry._fValue, qEntry._fSpace); 95 qEntry = qEntry._fPrevious; 96 } 97 return newCache; 98 } 99 107 protected abstract boolean close(LRUCacheEntry entry); 108 112 public Enumeration elements() { 113 if (fEntryQueue == null) 114 return new LRUCacheEnumerator(null); 115 LRUCacheEnumerator.LRUEnumeratorElement head = 116 new LRUCacheEnumerator.LRUEnumeratorElement(fEntryQueue._fValue); 117 LRUCacheEntry currentEntry = fEntryQueue._fNext; 118 LRUCacheEnumerator.LRUEnumeratorElement currentElement = head; 119 while(currentEntry != null) { 120 currentElement.fNext = new LRUCacheEnumerator.LRUEnumeratorElement(currentEntry._fValue); 121 currentElement = currentElement.fNext; 122 123 currentEntry = currentEntry._fNext; 124 } 125 return new LRUCacheEnumerator(head); 126 } 127 public double fillingRatio() { 128 return (fCurrentSpace + fOverflow) * 100.0 / fSpaceLimit; 129 } 130 136 public java.util.Hashtable getEntryTable() { 137 return fEntryTable; 138 } 139 144 public double getLoadFactor() { 145 return fLoadFactor; 146 } 147 150 public int getOverflow() { 151 return fOverflow; 152 } 153 161 protected boolean makeSpace(int space) { 162 163 int limit = fSpaceLimit; 164 if (fOverflow == 0 && fCurrentSpace + space <= limit) { 165 166 return true; 167 } 168 169 170 int spaceNeeded = (int)((1 - fLoadFactor) * limit); 171 spaceNeeded = (spaceNeeded > space) ? spaceNeeded : space; 172 LRUCacheEntry entry = fEntryQueueTail; 173 174 try { 175 fTimestampsOn = false; 178 179 while (fCurrentSpace + spaceNeeded > limit && entry != null) { 180 this.privateRemoveEntry(entry, false, false); 181 entry = entry._fPrevious; 182 } 183 } finally { 184 fTimestampsOn = true; 185 } 186 187 188 if (fCurrentSpace + space <= limit) { 189 fOverflow = 0; 190 return true; 191 } 192 193 194 fOverflow = fCurrentSpace + space - limit; 195 return false; 196 } 197 200 protected abstract LRUCache newInstance(int size, int overflow); 201 204 public void printStats() { 205 int forwardListLength = 0; 206 LRUCacheEntry entry = fEntryQueue; 207 while(entry != null) { 208 forwardListLength++; 209 entry = entry._fNext; 210 } 211 System.out.println("Forward length: " + forwardListLength); 213 int backwardListLength = 0; 214 entry = fEntryQueueTail; 215 while(entry != null) { 216 backwardListLength++; 217 entry = entry._fPrevious; 218 } 219 System.out.println("Backward length: " + backwardListLength); 221 Enumeration keys = fEntryTable.keys(); 222 class Temp { 223 public Class fClass; 224 public int fCount; 225 public Temp(Class aClass) { 226 fClass = aClass; 227 fCount = 1; 228 } 229 public String toString() { 230 return "Class: " + fClass + " has " + fCount + " entries."; } 232 } 233 java.util.HashMap h = new java.util.HashMap (); 234 while(keys.hasMoreElements()) { 235 entry = (LRUCacheEntry)fEntryTable.get(keys.nextElement()); 236 Class key = entry._fValue.getClass(); 237 Temp t = (Temp)h.get(key); 238 if (t == null) { 239 h.put(key, new Temp(key)); 240 } else { 241 t.fCount++; 242 } 243 } 244 245 for (Iterator iter = h.values().iterator(); iter.hasNext();){ 246 System.out.println(iter.next()); 247 } 248 } 249 256 protected void privateRemoveEntry (LRUCacheEntry entry, boolean shuffle) { 257 privateRemoveEntry(entry, shuffle, true); 258 } 259 270 protected void privateRemoveEntry(LRUCacheEntry entry, boolean shuffle, boolean external) { 271 272 if (!shuffle) { 273 if (external) { 274 fEntryTable.remove(entry._fKey); 275 fCurrentSpace -= entry._fSpace; 276 } else { 277 if (!close(entry)) return; 278 if (fEntryTable.get(entry._fKey) == null){ 281 return; 282 } else { 283 fEntryTable.remove(entry._fKey); 285 fCurrentSpace -= entry._fSpace; 286 } 287 } 288 } 289 LRUCacheEntry previous = entry._fPrevious; 290 LRUCacheEntry next = entry._fNext; 291 292 293 if (previous == null) { 294 fEntryQueue = next; 295 } else { 296 previous._fNext = next; 297 } 298 299 if (next == null) { 300 fEntryQueueTail = previous; 301 } else { 302 next._fPrevious = previous; 303 } 304 } 305 312 public Object put(Object key, Object value) { 313 314 if (fOverflow > 0) 315 shrink(); 316 317 318 int newSpace = spaceFor(value); 319 LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get (key); 320 321 if (entry != null) { 322 323 328 int oldSpace = entry._fSpace; 329 int newTotal = fCurrentSpace - oldSpace + newSpace; 330 if (newTotal <= fSpaceLimit) { 331 updateTimestamp (entry); 332 entry._fValue = value; 333 entry._fSpace = newSpace; 334 fCurrentSpace = newTotal; 335 fOverflow = 0; 336 return value; 337 } else { 338 privateRemoveEntry (entry, false, false); 339 } 340 } 341 342 makeSpace(newSpace); 344 345 privateAdd (key, value, newSpace); 348 349 return value; 350 } 351 358 public Object remove(Object key) { 359 return removeKey(key); 360 } 361 367 public void setLoadFactor(double newLoadFactor) throws IllegalArgumentException { 368 if(newLoadFactor <= 1.0 && newLoadFactor > 0.0) 369 fLoadFactor = newLoadFactor; 370 else 371 throw new IllegalArgumentException (Messages.cache_invalidLoadFactor); 372 } 373 378 public void setSpaceLimit(int limit) { 379 if (limit < fSpaceLimit) { 380 makeSpace(fSpaceLimit - limit); 381 } 382 fSpaceLimit = limit; 383 } 384 388 public boolean shrink() { 389 if (fOverflow > 0) 390 return makeSpace(0); 391 return true; 392 } 393 397 public String toString() { 398 return 399 toStringFillingRation("OverflowingLRUCache ") + toStringContents(); 401 } 402 408 protected void updateTimestamp(LRUCacheEntry entry) { 409 if (fTimestampsOn) { 410 entry._fTimestamp = fTimestampCounter++; 411 if (fEntryQueue != entry) { 412 this.privateRemoveEntry(entry, true); 413 this.privateAddEntry(entry, true); 414 } 415 } 416 } 417 } 418 | Popular Tags |