net.sf.farrago.util
Class FarragoObjectCache

java.lang.Object
  extended by net.sf.farrago.util.FarragoObjectCache
All Implemented Interfaces:
FarragoAllocation, ClosableAllocation

public class FarragoObjectCache
extends Object
implements FarragoAllocation

FarragoObjectCache implements generic object caching. It doesn't use SoftReferences since those don't provide enough programmatic control over memory-sensitive caching policies.

Key objects must implement hashCode/equals properly since FarragoObjectCache is based on a HashMap internally.

See FarragoObjectCacheTest for examples of usage patterns.

Note that closeAllocation() should only be called with no entries pinned, no calls in progress, and no further calls planned.

Version:
$Id: //open/dev/farrago/src/net/sf/farrago/util/FarragoObjectCache.java#30 $
Author:
John V. Sichi

Nested Class Summary
static interface FarragoObjectCache.CachedObjectFactory
          Factory interface for producing cached objects.
static interface FarragoObjectCache.Entry
          Interface for a cache entry; same as Map.Entry except that there is no requirement on equals/hashCode.
static interface FarragoObjectCache.UninitializedEntry
          Callback interface for entry initialization.
 
Field Summary
private  long bytesMax
           
private  long bytesUsed
          Number of bytes currently in use by cached objects.
protected  MultiMap<Object,FarragoCacheEntry> mapKeyToEntry
          Map from cache key to EntryImpl.
private static Logger tracer
           
private  FarragoCacheVictimPolicy victimPolicy
          Victimization policy for this cache
 
Constructor Summary
FarragoObjectCache(FarragoAllocationOwner owner, long bytesMax, FarragoCacheVictimPolicy victimPolicy)
          Creates an empty cache.
 
Method Summary
private  void adjustMemoryUsage(long incBytes)
           
 void closeAllocation()
          Closes this object.
 void discard(Object key)
          Discards any entries associated with a key.
 void discardAll()
          Discards all entries.
private  void discardEntry(FarragoCacheEntry entry)
           
private  FarragoCacheEntry findOrCreateEntry(Thread currentThread, Object key, FarragoObjectCache.CachedObjectFactory factory, boolean exclusive)
           
 long getBytesCached()
           
 long getBytesMax()
           
 FarragoObjectCache.Entry pin(Object key, FarragoObjectCache.CachedObjectFactory factory, boolean exclusive)
          Pins an entry in the cache.
 void setMaxBytes(long bytesMaxNew)
          Changes the cache size limit, discarding entries if necessary.
private  FarragoObjectCache.Entry tryPin(Object key, FarragoObjectCache.CachedObjectFactory factory, boolean exclusive)
           
 void tryUnpin(String key)
          Just like unpin except that it takes only the key to the cache entry and doesn't call adjustMemoryUsage.
 void unpin(FarragoObjectCache.Entry pinnedEntry)
          Unpins an entry returned by pin.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

tracer

private static final Logger tracer

mapKeyToEntry

protected MultiMap<Object,FarragoCacheEntry> mapKeyToEntry
Map from cache key to EntryImpl. To avoid deadlock, synchronize on either map or entry but not both at once. See code comments in tryPin for more info on this.


bytesMax

private long bytesMax

bytesUsed

private long bytesUsed
Number of bytes currently in use by cached objects. This and bytesMax are synchronized via mapKeyToEntry monitor.


victimPolicy

private FarragoCacheVictimPolicy victimPolicy
Victimization policy for this cache

Constructor Detail

FarragoObjectCache

public FarragoObjectCache(FarragoAllocationOwner owner,
                          long bytesMax,
                          FarragoCacheVictimPolicy victimPolicy)
Creates an empty cache.

Parameters:
owner - FarragoAllocationOwner for this cache, to make sure everything gets discarded eventually
bytesMax - maximum number of bytes to cache
victimPolicy - victimization policy to use when the cache is full
Method Detail

pin

public FarragoObjectCache.Entry pin(Object key,
                                    FarragoObjectCache.CachedObjectFactory factory,
                                    boolean exclusive)
Pins an entry in the cache. When the caller is done with it, the returned entry must be unpinned, otherwise the entry can never be discarded from the cache.

Note that for a cache miss with exclusive=false, other callers requesting to pin the same key near-simultaneously will wait for the initialization of the new object to complete. If it completes successfully, AND it is initialized as reusable, then the new object will be shared. If it completes unsuccessfully, the first caller will receive the thrown exception, and subsequent callers will retry the attempt themselves. If it completes successfully, but turns out to be non-reusable, then subsequent callers will give up on it and create their own private copies instead.

Parameters:
key - key of the entry to pin
factory - CachedObjectFactory to call if an existing entry can't be used (cache miss), in which case a new entry will be created and initialized by calling the factory's initializeEntry method
exclusive - if true, only reuse unpinned entries; note that this flag is not remembered along with the entry, so callers must be consistent in setting this flag for objects in the same keyspace
Returns:
pinned entry

tryPin

private FarragoObjectCache.Entry tryPin(Object key,
                                        FarragoObjectCache.CachedObjectFactory factory,
                                        boolean exclusive)

findOrCreateEntry

private FarragoCacheEntry findOrCreateEntry(Thread currentThread,
                                            Object key,
                                            FarragoObjectCache.CachedObjectFactory factory,
                                            boolean exclusive)

adjustMemoryUsage

private void adjustMemoryUsage(long incBytes)

setMaxBytes

public void setMaxBytes(long bytesMaxNew)
Changes the cache size limit, discarding entries if necessary.

Parameters:
bytesMaxNew - new limit

getBytesMax

public long getBytesMax()
Returns:
cache size limit

getBytesCached

public long getBytesCached()
Returns:
current number of bytes cached (regardless of whether they are pinned or not)

unpin

public void unpin(FarragoObjectCache.Entry pinnedEntry)
Unpins an entry returned by pin. After unpin, the caller should immediately nullify its reference to the entry, its key, its value, and any sub-objects so that they can be garbage collected.

Parameters:
pinnedEntry - pinned Entry

tryUnpin

public void tryUnpin(String key)
Just like unpin except that it takes only the key to the cache entry and doesn't call adjustMemoryUsage. It is used just like unpin but it is a bit more forgiving and calls closeAllocation on the cache entry if it is truely unpinned. It is currently used only by a specific extention to Farrago and not Farrago itself.

Parameters:
key - the key to the pinned Entry

discard

public void discard(Object key)
Discards any entries associated with a key. If the bound value of an entry is a ClosableObject, it will be closed.

REVIEW jvs 10-Jun-2007: This method is unsafe since the associated entries may still be pinned. Code which is relying on it (such as FarragoDataWrapperCache) should probably be changed to use either a staleness test or a different key scheme.

Parameters:
key - key of the Entry to discard

discardAll

public void discardAll()
Discards all entries. May only be called at a time when no entries are currently pinned (otherwise assertion failures may result).


discardEntry

private void discardEntry(FarragoCacheEntry entry)

closeAllocation

public void closeAllocation()
Description copied from interface: ClosableAllocation
Closes this object.

Specified by:
closeAllocation in interface ClosableAllocation