Methods Summary |
---|
protected java.lang.Object | _put(int hashCode, java.lang.Object key, java.lang.Object value, int size, boolean addValue)cache the given value at the specified key and return previous value
int index = getIndex(hashCode);
CacheItem item, newItem = null, oldItem = null, overflow = null;
Object oldValue;
int oldSize = 0;
// lookup the item
synchronized (bucketLocks[index]) {
for (item = buckets[index]; item != null; item = item.next) {
if ((hashCode == item.hashCode) && eq(key, item.key)) {
oldItem = item;
break;
}
}
// if there was no item in the cache, insert the given item
if (addValue || oldItem == null) {
newItem = createItem(hashCode, key, value, size);
// add the item at the head of the bucket list
newItem.next = buckets[index];
buckets[index] = newItem;
oldValue = null;
overflow = itemAdded(newItem);
} else {
oldSize = oldItem.getSize();
oldValue = oldItem.refreshValue(value, size);
itemRefreshed(oldItem, oldSize);
}
}
if (newItem != null) {
incrementEntryCount();
incrementAddCount();
// make sure we are are not crossing the threshold
if (overflow != null) {
trimItem(overflow);
}
} else {
incrementRefreshCount();
}
return oldValue;
|
protected com.sun.ejb.containers.util.cache.BaseCache$CacheItem | _remove(int hashCode, java.lang.Object key, java.lang.Object value)remove the item stored at the key.
int index = getIndex(hashCode);
CacheItem prev = null, item = null;
synchronized (bucketLocks[index]) {
for (item = buckets[index]; item != null; item = item.next) {
if (hashCode == item.hashCode && key.equals(item.key)) {
if (value == null || value == item.value) {
if (prev == null) {
buckets[index] = item.next;
} else {
prev.next = item.next;
}
item.next = null;
itemRemoved(item);
break;
}
}
prev = item;
}
}
if (item != null) {
decrementEntryCount();
incrementRemovalCount();
incrementHitCount();
} else {
incrementMissCount();
}
return item;
|
protected com.sun.ejb.containers.util.cache.BaseCache$CacheItem | _removeItem(com.sun.ejb.containers.util.cache.BaseCache$CacheItem ritem)remove the item stored at the key.
int index = getIndex(ritem.hashCode);
CacheItem prev = null, item = null;
synchronized (bucketLocks[index]) {
for (item = buckets[index]; item != null; item = item.next) {
if (item == ritem) {
if (prev == null) {
buckets[index] = item.next;
} else {
prev.next = item.next;
}
item.next = null;
break;
}
prev = item;
}
}
if (item != null) {
decrementEntryCount();
}
return item;
|
public void | add(java.lang.Object key, java.lang.Object value)add the given value to the cache at the specified key
int hashCode = hash(key);
_put(hashCode, key, value, -1, true);
|
public void | add(java.lang.Object key, java.lang.Object value, int size)add the given value with specified size to the cache at specified key
int hashCode = hash(key);
_put(hashCode, key, value, size, true);
|
public void | addCacheListener(com.sun.appserv.util.cache.CacheListener listener)add the cache module listener
listeners.add(listener);
|
public int | clear()clear all the entries from the cache.
CacheItem item=null, next=null;
int count = 0;
for (int index = 0; index < maxBuckets; index++) {
synchronized (bucketLocks[index]) {
for (item = buckets[index]; item != null;
item = item.next) {
next = item.next;
item.next = null;
count++;
decrementEntryCount();
itemRemoved(item);
if (entryCount == 0) {
break;
}
}
buckets[index] = null;
}
}
return count;
|
public void | clearStats()clear the stats
hitCount = 0;
missCount = 0;
removalCount = 0;
refreshCount = 0;
overflowCount = 0;
addCount = 0;
|
public boolean | contains(java.lang.Object key)check if the cache contains the item at the key
return (get(key) != null);
|
protected com.sun.ejb.containers.util.cache.BaseCache$CacheItem | createItem(int hashCode, java.lang.Object key, java.lang.Object value, int size)create new item
return new CacheItem(hashCode, key, value, size);
|
protected final void | decrementEntryCount()
synchronized(entryCountLk) {
entryCount--;
}
|
public void | destroy()Sets all references to null. This method should be called
at the end of this object's life cycle.
if ((listeners != null) && (buckets != null) && (bucketLocks != null)){
clear();
this.listeners.clear();
}
this.entryCountLk = null;
this.hitCountLk = null;
this.missCountLk = null;
this.removalCountLk = null;
this.refreshCountLk = null;
this.addCountLk = null;
this.overflowCountLk = null;
this.buckets = null;
this.bucketLocks = null;
this.refreshFlags = null;
this.listeners = null;
|
public java.util.Enumeration | elements()get an Enumeration for the keys stored in the cache
Vector keyList = new Vector();
for (int index=0; index < maxBuckets; index++) {
synchronized (bucketLocks[index]) {
for (CacheItem item = buckets[index]; item != null;
item = item.next) {
keyList.addElement(item.value);
}
}
}
return keyList.elements();
|
protected boolean | eq(java.lang.Object x, java.lang.Object y)Check for equality of non-null reference x and possibly-null y.
return x == y || x.equals(y);
|
public java.lang.Object | get(java.lang.Object key)get the item stored at the key.
int hashCode = hash(key);
return get(hashCode, key);
|
public java.lang.Object | get(int hashCode, java.lang.Object key)get the item stored at the given pre-computed hash code and the key.
int index = getIndex(hashCode);
Object value;
CacheItem item = null;
synchronized (bucketLocks[index]) {
item = buckets[index];
for (; item != null; item = item.next) {
if ( (hashCode == item.hashCode) && eq(key, item.key) ) {
break;
}
}
// update the stats in line
if (item != null) {
value = item.getValue();
itemAccessed(item);
}
else {
value = loadValue(key, hashCode);
}
}
if (item != null) {
incrementHitCount();
} else {
incrementMissCount();
}
return value;
|
public java.util.Iterator | getAll(java.lang.Object key)get all the items stored at the key.
int hashCode = hash(key);
int index = getIndex(hashCode);
ArrayList valueList = new ArrayList(entryCount);
synchronized (bucketLocks[index]) {
CacheItem item = buckets[index];
for (; item != null; item = item.next) {
if ( (hashCode == item.hashCode) && eq(key, item.key) ) {
incrementHitCount();
valueList.add(item.getValue());
}
}
}
return valueList.iterator();
|
public int | getEntryCount()get the number of entries in the cache
return entryCount;
|
protected final int | getIndex(int hashCode)get the index of the item in the cache
return (hashCode & (maxBuckets - 1));
|
public final int | getIndex(java.lang.Object key)get the index of the item given a key
return getIndex(hash(key));
|
public java.lang.Object | getStatByName(java.lang.String key)get the desired statistic counter
Object stat = null;
if (key == null)
return null;
if (key.equals(Constants.STAT_BASECACHE_MAX_ENTRIES))
stat = new Integer(maxEntries);
else if (key.equals(Constants.STAT_BASECACHE_THRESHOLD))
stat = new Integer(threshold);
else if (key.equals(Constants.STAT_BASECACHE_TABLE_SIZE))
stat = new Integer(maxBuckets);
else if (key.equals(Constants.STAT_BASECACHE_ENTRY_COUNT))
stat = new Integer(entryCount);
else if (key.equals(Constants.STAT_BASECACHE_HIT_COUNT))
stat = new Integer(hitCount);
else if (key.equals(Constants.STAT_BASECACHE_MISS_COUNT))
stat = new Integer(missCount);
else if (key.equals(Constants.STAT_BASECACHE_REMOVAL_COUNT))
stat = new Integer(removalCount);
else if (key.equals(Constants.STAT_BASECACHE_REFRESH_COUNT))
stat = new Integer(refreshCount);
else if (key.equals(Constants.STAT_BASECACHE_OVERFLOW_COUNT))
stat = new Integer(overflowCount);
else if (key.equals(Constants.STAT_BASECACHE_ADD_COUNT))
stat = new Integer(addCount);
return stat;
|
public java.util.Map | getStats()get the stats snapshot
HashMap stats = new HashMap();
stats.put(Constants.STAT_BASECACHE_MAX_ENTRIES,
new Integer(maxEntries));
stats.put(Constants.STAT_BASECACHE_THRESHOLD,
new Integer(threshold));
stats.put(Constants.STAT_BASECACHE_TABLE_SIZE,
new Integer(maxBuckets));
stats.put(Constants.STAT_BASECACHE_ENTRY_COUNT,
new Integer(entryCount));
stats.put(Constants.STAT_BASECACHE_HIT_COUNT,
new Integer(hitCount));
stats.put(Constants.STAT_BASECACHE_MISS_COUNT,
new Integer(missCount));
stats.put(Constants.STAT_BASECACHE_REMOVAL_COUNT,
new Integer(removalCount));
stats.put(Constants.STAT_BASECACHE_REFRESH_COUNT,
new Integer(refreshCount));
stats.put(Constants.STAT_BASECACHE_OVERFLOW_COUNT,
new Integer(overflowCount));
stats.put(Constants.STAT_BASECACHE_ADD_COUNT,
new Integer(addCount));
return stats;
|
protected void | handleOverflow()increase the threshold
// just double the threshold; this may degenerate the cache.
threshold = (threshold * 2);
incrementOverflowCount();
|
protected int | hash(java.lang.Object x)Returns a hash code for non-null Object x.
int h = x.hashCode();
return h - (h << 7); // i.e., -127 * h
|
protected final void | incrementAddCount()
synchronized (addCountLk) {
addCount++;
}
|
protected final void | incrementEntryCount()synchronized counter updates
synchronized(entryCountLk) {
entryCount++;
}
|
protected final void | incrementHitCount()
synchronized (hitCountLk) {
hitCount++;
}
|
protected final void | incrementMissCount()
synchronized (missCountLk) {
missCount++;
}
|
protected final void | incrementOverflowCount()
synchronized (overflowCountLk) {
overflowCount++;
}
|
protected final void | incrementRefreshCount()
synchronized (refreshCountLk) {
refreshCount++;
}
|
protected final void | incrementRemovalCount()
synchronized (removalCountLk) {
removalCount++;
}
|
public void | init(int maxEntries, java.util.Properties props)initialize the cache
init(maxEntries, DEFAULT_LOAD_FACTOR, props);
|
public void | init(int maxEntries, float loadFactor, java.util.Properties props)initialize the cache
// web container logger
_rb = LogDomains.getLogger(LogDomains.UTIL_LOGGER).getResourceBundle();
if (maxEntries <= 0) {
String msg = _rb.getString("cache.BaseCache.illegalMaxEntries");
Integer obj = new Integer(maxEntries);
Object[] params = { obj };
msg = MessageFormat.format(msg, params);
throw new IllegalArgumentException(msg);
}
if (maxEntries > MAX_ENTRIES) {
maxEntries = MAX_ENTRIES;
}
this.maxEntries = maxEntries;
// find a power of 2 >= maxEntries
maxBuckets = 1;
while (maxBuckets < maxEntries) {
maxBuckets <<= 1;
}
/** initialize the threshold; a zero value for maxEntries
* implies no caching.
*/
if (maxEntries != 0) {
threshold = (int)(maxEntries * loadFactor) + 1;
}
// create the cache and the bucket locks
entryCount = 0;
buckets = new CacheItem[maxBuckets];
bucketLocks = new Object[maxBuckets];
refreshFlags = new boolean[maxBuckets];
for (int i=0; i<maxBuckets; i++) {
buckets[i] = null;
bucketLocks[i] = new Object();
refreshFlags[i] = false;
}
|
public boolean | isEmpty()is this cache empty?
return (entryCount == 0);
|
protected boolean | isThresholdReached()has cache reached its threshold
return (entryCount > threshold);
|
protected void | itemAccessed(com.sun.ejb.containers.util.cache.BaseCache$CacheItem item)this item is accessed
|
protected com.sun.ejb.containers.util.cache.BaseCache$CacheItem | itemAdded(com.sun.ejb.containers.util.cache.BaseCache$CacheItem item)this item is just added to the cache
if (isThresholdReached()) {
handleOverflow();
}
return null;
|
protected void | itemRefreshed(com.sun.ejb.containers.util.cache.BaseCache$CacheItem item, int oldSize)item value has been refreshed
|
protected void | itemRemoved(com.sun.ejb.containers.util.cache.BaseCache$CacheItem item)item value has been removed from the cache
|
public java.util.Iterator | keys()get an Iterator for the keys stored in the cache
ArrayList keyList = new ArrayList(entryCount);
for (int index=0; index < maxBuckets; index++) {
synchronized (bucketLocks[index]) {
for (CacheItem item = buckets[index]; item != null;
item = item.next) {
keyList.add(item.key);
}
}
}
return keyList.iterator();
|
protected java.lang.Object | loadValue(java.lang.Object key, int hashCode)Cannot find an item with the given key and hashCode
return null;
|
public void | notifyRefresh(int index)notify threads waiting for a refresh on the object associated
with the key
// notify other threads waiting for refresh
synchronized (bucketLocks[index]) {
refreshFlags[index] = false;
bucketLocks[index].notifyAll();
}
|
public java.lang.Object | put(java.lang.Object key, java.lang.Object value)cache the given value at the specified key and return previous value
int hashCode = hash(key);
return _put(hashCode, key, value, -1, false);
|
public java.lang.Object | put(java.lang.Object key, java.lang.Object value, int size)cache the given value at the specified key and return previous value
int hashCode = hash(key);
return _put(hashCode, key, value, size, false);
|
public java.lang.Object | remove(java.lang.Object key)remove the item stored at the key.
int hashCode = hash(key);
Object retVal = null;
CacheItem removed = _remove( hashCode, key, null);
if (removed != null) {
retVal = removed.getValue();
}
return retVal;
|
public java.lang.Object | remove(int hashCode, java.lang.Object key)remove the item stored at the key.
Object retVal = null;
CacheItem removed = _remove( hashCode, key, null);
if (removed != null) {
retVal = removed.getValue();
}
return retVal;
|
public java.lang.Object | remove(java.lang.Object key, java.lang.Object value)remove the given value stored at the key; value-specific removals.
int hashCode = hash(key);
Object retVal = null;
CacheItem removed = _remove( hashCode, key, value);
if (removed != null) {
retVal = removed.getValue();
}
return retVal;
|
public void | removeAll(java.lang.Object key)remove all the item with the given key.
int hashCode = hash(key);
int index = getIndex(hashCode);
CacheItem prev = null, item = null;
ArrayList items = new ArrayList(entryCount);
synchronized (bucketLocks[index]) {
for (item = buckets[index]; item != null;
item = item.next) {
if (hashCode == item.hashCode && key.equals(item.key)) {
if (prev == null) {
buckets[index] = item.next;
} else {
prev.next = item.next;
}
item.next = null;
decrementEntryCount();
incrementRemovalCount();
items.add(item);
}
prev = item;
}
}
// notify subclasses
for (int i = 0; i < items.size(); i++) {
itemRemoved((CacheItem)items.get(i));
}
|
public void | trimExpiredEntries(int maxCount)trim the expired entries from the cache.
|
protected void | trimItem(com.sun.ejb.containers.util.cache.BaseCache$CacheItem item)trim the item from the cache and notify listeners
CacheItem removed = _removeItem(item);
if (removed != null) {
for (int i = 0; i < listeners.size(); i++) {
CacheListener listener = (CacheListener) listeners.get(i);
listener.trimEvent(removed.key, removed.value);
}
}
|
public java.util.Iterator | values()get an Iterator for the values stored in the cache
ArrayList valueList = new ArrayList(entryCount);
for (int index=0; index < maxBuckets; index++) {
synchronized (bucketLocks[index]) {
for (CacheItem item = buckets[index]; item != null;
item = item.next) {
valueList.add(item.value);
}
}
}
return valueList.iterator();
|
public boolean | waitRefresh(int index)wait for a refresh on the object associated with the key
synchronized (bucketLocks[index]) {
if (refreshFlags[index] == false) {
refreshFlags[index] = true;
return false;
}
// wait till refresh is finished
try {
bucketLocks[index].wait();
} catch (InterruptedException ie) {}
}
return true;
|