Methods Summary |
---|
protected CacheItem | createItem(int hashCode, java.lang.Object key, java.lang.Object value, int size)create new item
return new LruCacheItem(hashCode, key, value, size);
|
private com.sun.appserv.util.cache.MultiLruCache$LruCacheItem[] | getLRUList(int index)get the LRU list associated with the index
int segment = (index/segmentSize);
return lists[segment];
|
int | getListsLength()
return lists.length;
|
public java.lang.Object | getStatByName(java.lang.String key)get the desired statistic counter
Object stat = super.getStatByName(key);
if (stat == null && key != null) {
if (key.equals(Constants.STAT_MULTILRUCACHE_SEGMENT_SIZE))
stat = Integer.valueOf(segmentSize);
else if (key.equals(Constants.STAT_MULTILRUCACHE_TRIM_COUNT))
stat = Integer.valueOf(trimCount);
else if (key.equals(Constants.STAT_MULTILRUCACHE_SEGMENT_LIST_LENGTH)) {
stat = new Integer[lists.length];
for (int i = 0; i < lists.length; i++) {
((Integer[])stat)[i] = Integer.valueOf(listsLength[i]);
}
}
}
return stat;
|
public java.util.Map | getStats()get the stats snapshot
Map stats = super.getStats();
stats.put(Constants.STAT_MULTILRUCACHE_SEGMENT_SIZE,
Integer.valueOf(segmentSize));
for (int i = 0; i < lists.length; i++) {
stats.put(Constants.STAT_MULTILRUCACHE_SEGMENT_LIST_LENGTH + "["
+ i + "]:",
Integer.valueOf(listsLength[i]));
}
stats.put(Constants.STAT_MULTILRUCACHE_TRIM_COUNT,
Integer.valueOf(trimCount));
return stats;
|
protected void | handleOverflow()cache has reached threshold so trim its size. subclasses are expected
to provide a robust cache replacement algorithm.
LruCacheItem l = null;
|
protected void | incrementTrimIndex()
synchronized (trimIndexLk) {
trimIndex = (trimIndex + 1) % lists.length;
}
|
public void | init(int maxCapacity, java.util.Properties props)initialize the LRU cache
super.init(maxCapacity, props);
segmentSize = DEFAULT_HASHTABLE_SEGMENT_SIZE;
if (props != null) {
String prop = props.getProperty("MultiLRUSegmentSize");
if (prop != null) {
try {
segmentSize = Integer.parseInt(prop);
} catch (NumberFormatException nfe) {}
}
}
// create the array of LRU lists
int segments = ((maxBuckets / segmentSize) +
(((maxBuckets % segmentSize) != 0) ? 1 : 0));
lists = new LruCacheItem[segments][2];
listsLength = new int[lists.length];
for (int i = 0; i < lists.length; i++) {
lists[i][LRU_HEAD] = null;
lists[i][LRU_TAIL] = null;
listsLength[i] = 0;
}
|
protected void | itemAccessed(CacheItem item)this item is accessed
int index = getIndex(item.hashCode());
int segment = (index/segmentSize);
LruCacheItem[] list = lists[segment];
LruCacheItem lc = (LruCacheItem) item;
// update the LRU list
synchronized (list) {
LruCacheItem prev = lc.lPrev;
LruCacheItem next = lc.lNext;
if (prev != null) {
// put the item at the head of LRU list
lc.lPrev = null;
lc.lNext = list[LRU_HEAD];
list[LRU_HEAD].lPrev = lc;
list[LRU_HEAD] = lc;
// patch up the previous neighbors
prev.lNext = next;
if (next != null)
next.lPrev = prev;
else
list[LRU_TAIL] = prev;
}
}
|
protected CacheItem | itemAdded(CacheItem item)this item is just added to the cache
CacheItem overflow = null;
LruCacheItem lc = (LruCacheItem) item;
int index = getIndex(item.hashCode());
int segment = (index/segmentSize);
LruCacheItem[] list = lists[segment];
// update the LRU
synchronized (list) {
if (list[LRU_HEAD] != null) {
list[LRU_HEAD].lPrev = lc;
lc.lNext = list[LRU_HEAD];
}
else
list[LRU_TAIL] = lc;
list[LRU_HEAD] = lc;
listsLength[segment]++;
if (isThresholdReached()) {
overflow = trimLru(trimIndex);
// go round robin for the next trim
incrementTrimIndex();
}
}
return overflow;
|
protected void | itemRefreshed(CacheItem item, int oldSize)item value has been refreshed
itemAccessed(item);
|
protected void | itemRemoved(CacheItem item)item value has been removed from the cache
LruCacheItem l = (LruCacheItem) item;
int index = getIndex(item.hashCode());
int segment = (index/segmentSize);
LruCacheItem[] list = lists[segment];
// remove the item from the LRU list
synchronized (list) {
// if the item is already trimmed from the LRU list, nothing to do.
if (l.isTrimmed)
return;
LruCacheItem prev = l.lPrev;
LruCacheItem next = l.lNext;
// patch up the neighbors and make sure head/tail are correct
if (prev != null)
prev.lNext = next;
else
list[LRU_HEAD] = next;
if (next != null)
next.lPrev = prev;
else
list[LRU_TAIL] = prev;
listsLength[segment]--;
}
|
protected CacheItem | trimLru(int segment)remove an lru item from one of the LRU lists
LruCacheItem[] list = lists[segment];
LruCacheItem l = null;
l = list[LRU_TAIL];
list[LRU_TAIL] = l.lPrev;
list[LRU_TAIL].lNext = null;
l.lPrev = null;
listsLength[segment]--;
l.isTrimmed = true;
trimCount++;
return l;
|