<s> package org . eclipse . jdt . internal . core ; import java . util . Enumeration ; import java . util . Iterator ; import org . eclipse . jdt . internal . core . util . LRUCache ; import org . eclipse . jdt . internal . core . util . Messages ; public abstract class OverflowingLRUCache extends LRUCache { protected int overflow = 0 ; protected boolean timestampsOn = true ; protected double loadFactor = 0.333 ; public OverflowingLRUCache ( int size ) { this ( size , 0 ) ; } public OverflowingLRUCache ( int size , int overflow ) { super ( size ) ; this . overflow = overflow ; } public Object clone ( ) { OverflowingLRUCache newCache = ( OverflowingLRUCache ) newInstance ( this . spaceLimit , this . overflow ) ; LRUCacheEntry qEntry ; qEntry = this . entryQueueTail ; while ( qEntry != null ) { newCache . privateAdd ( qEntry . key , qEntry . value , qEntry . space ) ; qEntry = qEntry . previous ; } return newCache ; } protected abstract boolean close ( LRUCacheEntry entry ) ; public Enumeration elements ( ) { if ( this . entryQueue == null ) return new LRUCacheEnumerator ( null ) ; LRUCacheEnumerator . LRUEnumeratorElement head = new LRUCacheEnumerator . LRUEnumeratorElement ( this . entryQueue . value ) ; LRUCacheEntry currentEntry = this . entryQueue . next ; LRUCacheEnumerator . LRUEnumeratorElement currentElement = head ; while ( currentEntry != null ) { currentElement . next = new LRUCacheEnumerator . LRUEnumeratorElement ( currentEntry . value ) ; currentElement = currentElement . next ; currentEntry = currentEntry . next ; } return new LRUCacheEnumerator ( head ) ; } public double fillingRatio ( ) { return ( this . currentSpace + this . overflow ) * 100.0 / this . spaceLimit ; } public java . util . Hashtable getEntryTable ( ) { return this . entryTable ; } public double getLoadFactor ( ) { return this . loadFactor ; } public int getOverflow ( ) { return this . overflow ; } protected boolean makeSpace ( int space ) { int limit = this . spaceLimit ; if ( this . overflow == 0 && this . currentSpace + space <= limit ) { return true ; } int spaceNeeded = ( int ) ( ( 1 - this . loadFactor ) * limit ) ; spaceNeeded = ( spaceNeeded > space ) ? spaceNeeded : space ; LRUCacheEntry entry = this . entryQueueTail ; try { this . timestampsOn = false ; while ( this . currentSpace + spaceNeeded > limit && entry != null ) { this . privateRemoveEntry ( entry , false , false ) ; entry = entry . previous ; } } finally { this . timestampsOn = true ; } if ( this . currentSpace + space <= limit ) { this . overflow = 0 ; return true ; } this . overflow = this . currentSpace + space - limit ; return false ; } protected abstract LRUCache newInstance ( int size , int newOverflow ) ; public void printStats ( ) { int forwardListLength = 0 ; LRUCacheEntry entry = this . entryQueue ; while ( entry != null ) { forwardListLength ++ ; entry = entry . next ; } System . out . println ( "" + forwardListLength ) ; int backwardListLength = 0 ; entry = this . entryQueueTail ; while ( entry != null ) { backwardListLength ++ ; entry = entry . previous ; } System . out . println ( "" + backwardListLength ) ; Enumeration keys = this . entryTable . keys ( ) ; class Temp { public Class clazz ; public int count ; public Temp ( Class aClass ) { this . clazz = aClass ; this . count = 1 ; } public String toString ( ) { return "Class: " + this . clazz + " has " + this . count + " entries." ; } } java . util . HashMap h = new java . util . HashMap ( ) ; while ( keys . hasMoreElements ( ) ) { entry = ( LRUCacheEntry ) this . entryTable . get ( keys . nextElement ( ) ) ; Class key = entry . value . getClass ( ) ; Temp t = ( Temp ) h . get ( key ) ; if ( t == null ) { h . put ( key , new Temp ( key ) ) ; } else { t . count ++ ; } } for ( Iterator iter = h . values ( ) . iterator ( ) ; iter . hasNext ( ) ; ) { System . out . println ( iter . next ( ) ) ; } } protected void privateRemoveEntry ( LRUCacheEntry entry , boolean shuffle ) { privateRemoveEntry ( entry , shuffle , true ) ; } protected void privateRemoveEntry ( LRUCacheEntry entry , boolean shuffle , boolean external ) { if ( ! shuffle ) { if ( external ) { this . entryTable . remove ( entry . key ) ; this . currentSpace -= entry . space ; } else { if ( ! close ( entry ) ) return ; if ( this . entryTable . get ( entry . key ) == null ) { return ; } else { this . entryTable . remove ( entry . key ) ; this . currentSpace -= entry . space ; } } } LRUCacheEntry previous = entry . previous ; LRUCacheEntry next = entry . next ; if ( previous == null ) { this . entryQueue = next ; } else { previous . next = next ; } if ( next == null ) { this . entryQueueTail = previous ; } else { next . previous = previous ; } } public Object put ( Object key , Object value ) { if ( this . overflow > 0 ) shrink ( ) ; int newSpace = spaceFor ( value ) ; LRUCacheEntry entry = ( LRUCacheEntry ) this . entryTable . get ( key ) ; if ( entry != null ) { int oldSpace = entry . space ; int newTotal = this . currentSpace - oldSpace + newSpace ; if ( newTotal <= this . spaceLimit ) { updateTimestamp ( entry ) ; entry . value = value ; entry . space = newSpace ; this . currentSpace = newTotal ; this . overflow = 0 ; return value ; } else { privateRemoveEntry ( entry , false , false ) ; } } makeSpace ( newSpace ) ; privateAdd ( key , value , newSpace ) ; return value ; } public Object remove ( Object key ) { return removeKey ( key ) ; } public void setLoadFactor ( double newLoadFactor ) throws IllegalArgumentException { if ( newLoadFactor <= 1.0 && newLoadFactor > 0.0 ) this . loadFactor = newLoadFactor ; else throw new IllegalArgumentException ( Messages . cache_invalidLoadFactor ) ; } public void setSpaceLimit ( int limit ) { if ( limit < this . spaceLimit ) { makeSpace ( this . spaceLimit - limit ) ; } this . spaceLimit = limit ; } public boolean shrink ( ) { if ( this . overflow > 0 ) return makeSpace ( 0 ) ; return true ; } public String toString ( ) { return toStringFillingRation ( "" ) + toStringContents ( ) ; } protected void updateTimestamp ( LRUCacheEntry entry ) { if ( this . timestampsOn ) { entry . timestamp = this . timestampCounter ++ ; if ( this . entryQueue != entry ) { this . privateRemoveEntry ( entry , true ) ; privateAddEntry ( entry , true ) ; } } } } </s>