FileDocCategorySizeDatePackage
CacheIdentityMap.javaAPI DocGlassfish v2 API7452Tue May 22 16:54:34 BST 2007oracle.toplink.essentials.internal.identitymaps

CacheIdentityMap

public class CacheIdentityMap extends FullIdentityMap

Purpose: A fixed size LRU cache

Using a linked list as well as the hashtable from the superclass a LRU cache is maintained. When a get is executed the LRU list is updated and when a new object is inserted the object at the start of the list is deleted (provided the maxSize has been reached).

Responsibilities:

  • Guarantees identity through primary key values
  • Keeps the LRU linked list updated.
since
TOPLink/Java 1.0

Fields Summary
protected LinkedCacheKey
first
Provide handles on the linked list
protected LinkedCacheKey
last
Provide handles on the linked list
Constructors Summary
public CacheIdentityMap(int size)
Initialize newly instantiated CacheIdentityMap.

param
size int The size of the Cache

        super(size);
        this.first = new LinkedCacheKey(new Vector(2), null, null, 0);
        this.last = new LinkedCacheKey(new Vector(2), null, null, 0);
        this.first.setNext(this.last);
        this.last.setPrevious(this.first);
    
Methods Summary
public oracle.toplink.essentials.internal.identitymaps.CacheKeycreateCacheKey(java.util.Vector primaryKey, java.lang.Object object, java.lang.Object writeLockValue, long readTime)

        return new LinkedCacheKey(primaryKey, object, writeLockValue, readTime);
    
protected voidensureFixedSize()
Reduces the size of the receiver down to the maxSize removing objects from the start of the linked list.

        // protect the case where someone attempts to break the cache by
        // setting max size to 0.
        synchronized(this.first) {
        while (getMaxSize() > 0 && getSize() > getMaxSize()) {
            remove(last.getPrevious());
            }
        }
    
protected oracle.toplink.essentials.internal.identitymaps.CacheKeygetCacheKey(java.util.Vector primaryKeys)
Access the object within the table for the given primaryKey. Move the accessed key to the top of the order keys linked list to maintain LRU.

param
aVector is the primary key for the object to search for.
return
The LinkedCacheKey or null if none found for primaryKey

        LinkedCacheKey cacheKey = (LinkedCacheKey)super.getCacheKey(primaryKeys);

        if (cacheKey != null) {
            synchronized (this.first) {
                removeLink(cacheKey);
                insertLink(cacheKey);
            }
        }

        return cacheKey;
    
protected oracle.toplink.essentials.internal.identitymaps.LinkedCacheKeyinsertLink(oracle.toplink.essentials.internal.identitymaps.LinkedCacheKey key)
Insert a new element into the linked list of LinkedCacheKeys. New elements (Recently Used) are added at the end (last).

return
The added LinkedCacheKey

        if (key == null){
            return key;
        }
        // no sence on locking the entire cache, just lock on the list
        synchronized (this.first){
            this.first.getNext().setPrevious(key);
            key.setNext(this.first.getNext());
            key.setPrevious(this.first);
            this.first.setNext(key);
        }
        return key;
    
protected voidput(oracle.toplink.essentials.internal.identitymaps.CacheKey cacheKey)
Store the object in the identity map with the linked cache key

        super.put(cacheKey);
        insertLink((LinkedCacheKey)cacheKey);
        ensureFixedSize();
    
public java.lang.Objectremove(oracle.toplink.essentials.internal.identitymaps.CacheKey key)
Remove the LinkedCacheKey from the cache as well as from the linked list.

return
The LinkedCacheKey to be removed

        super.remove(key);
        // CR2408
        if (key == null) {
            Class cacheItemClass = null;

            // Get the class of the CacheKey which we could not remove
            // (if possible) for client debugging purposes.
            // We can't get the descriptor, because we don't know the session.
            if (!getCacheKeys().isEmpty()) {
                CacheKey aKey = (CacheKey)getCacheKeys().keys().nextElement();
                if ((aKey != null) && (aKey.getObject() != null)) {
                    cacheItemClass = aKey.getObject().getClass();
                }
            }
            throw ValidationException.nullCacheKeyFoundOnRemoval(this, cacheItemClass);
        }
        return removeLink((LinkedCacheKey)key).getObject();
    
protected oracle.toplink.essentials.internal.identitymaps.LinkedCacheKeyremoveLink(oracle.toplink.essentials.internal.identitymaps.LinkedCacheKey key)
Remove the LinkedCacheKey from the linked list.

return
The removed LinkedCacheKey

        if (key == null){
            return key;
        }
        synchronized (this.first) {
            if (key.getPrevious() == null || key.getNext() == null){
                //already removed by a competing thread, just return
                return key;
            }
            key.getPrevious().setNext(key.getNext());
            key.getNext().setPrevious(key.getPrevious());
            key.setNext(null);
            key.setPrevious(null);
        }
        return key;
    
public synchronized voidupdateMaxSize(int maxSize)
INTERNAL: This method will be used to update the max cache size, any objects exceeding the max cache size will be remove from the cache. Please note that this does not remove the object from the identityMap, except in the case of the CacheIdentityMap.

        setMaxSize(maxSize);
        ensureFixedSize();