Methods Summary |
---|
public void | appendStats(java.lang.StringBuffer sbuf)
sbuf.append("[Cache: ")
.append("Size=").append(entryCount).append("; ")
.append("HitCount=").append(hitCount).append("; ")
.append("MissCount=").append(missCount).append("; ")
.append("Passivations=").append(getNumPassivations()).append("; ");
if (configData != null) {
sbuf.append(configData);
}
sbuf.append("]");
|
protected CacheItem | createItem(int hashCode, java.lang.Object sessionKey, java.lang.Object value, int size)
return new LruSessionCacheItem(hashCode, sessionKey, value, size);
|
public void | destroy()Destroys all references. This is the last method call of this object's
life cycle.
This method is called during undeploy of ejb container.
this.currentCacheState = STATE_DESTROYED;
this.container = null;
super.destroy();
|
public int | getCacheHits()
return hitCount;
|
public int | getCacheMisses()
return missCount;
|
public int | getLoadFromBackupCount()
return loadFromBackupCount;
|
public int | getMaxCacheSize()
return confMaxCacheSize;
|
public int | getNumBeansInCache()
return entryCount;
|
public int | getNumExpiredSessionsRemoved()
return (sfsbStoreMonitor == null)
? 0 : sfsbStoreMonitor.getNumExpiredSessionsRemoved();
|
public int | getNumPassivationErrors()
return (sfsbStoreMonitor == null)
? 0 : sfsbStoreMonitor.getNumPassivationErrors();
|
public int | getNumPassivationSuccess()
return (sfsbStoreMonitor == null)
? 0 : sfsbStoreMonitor.getNumPassivationSuccess();
|
public int | getNumPassivations()
return (sfsbStoreMonitor == null)
? 0 : sfsbStoreMonitor.getNumPassivations();
|
public int | getNumVictimsAccessed()
return numVictimsAccessed;
|
private java.lang.Object | getStateFromStore(java.lang.Object sessionKey, com.sun.ejb.spi.container.SFSBContainerCallback container)
Object object = null;
try {
SFSBBeanState beanState = storeManager.getState(sessionKey);
byte[] data = (beanState != null)
? beanState.getState()
: null;
if ( data == null ) {
if(_logger.isLoggable(Level.SEVERE)) {
_logger.log(Level.SEVERE, cacheName + ": Cannot load from "
+ " BACKUPSTORE FOR Key: <" + sessionKey + ">");
}
} else {
sfsbStoreMonitor.setActivationSize(data.length);
incrementLoadFromBackupCount();
object = IOUtils.deserializeObject(data, true,
container.getClassLoader());
}
} catch ( Exception ex ) {
_logger.log(Level.SEVERE, cacheName + ": Exception while "
+ " loading from backup session: <" + sessionKey + ">", ex);
} catch ( Error ex ) {
_logger.log(Level.SEVERE, cacheName + ": Error while "
+ " loading from backup session: <" + sessionKey + ">", ex);
}
return object;
|
protected void | incrementLoadFromBackupCount()
synchronized (loadCountLock) {
loadFromBackupCount++;
}
|
protected void | itemAccessed(CacheItem item)
LruCacheItem lc = (LruCacheItem) item;
synchronized (this) {
if (lc.isTrimmed) {
lc.isTrimmed = false;
numVictimsAccessed += 1;
CacheItem overflow = super.itemAdded(item);
if (overflow != null) {
trimItem(overflow);
}
} else {
super.itemAccessed(item);
}
}
|
public com.sun.ejb.spi.container.StatefulEJBContext | lookupEJB(java.lang.Object sessionKey, com.sun.ejb.spi.container.SFSBContainerCallback container, java.lang.Object cookie)
int hashCode = hash(sessionKey);
int index = getIndex(hashCode);
CacheItem item = null;
LruSessionCacheItem newItem = null;
Object value = null;
synchronized (bucketLocks[index]) {
item = buckets[index];
for (; item != null; item = item.next) {
if ( (hashCode == item.hashCode) &&
(item.key.equals(sessionKey)) )
{
value = item.value;
break;
}
}
// update the stats in line
if (value != null) {
itemAccessed(item);
} else if (item == null) {
newItem = new LruSessionCacheItem(hashCode, sessionKey,
null, -1, CACHE_ITEM_LOADING);
newItem.next = buckets[index];
buckets[index] = newItem;
}
}
if (value != null) {
incrementHitCount();
return (StatefulEJBContext) value;
}
incrementMissCount();
if (item != null) {
synchronized (item) {
LruSessionCacheItem lruItem = (LruSessionCacheItem) item;
if ((lruItem.value == null) && (lruItem.cacheItemState == CACHE_ITEM_LOADING)) {
lruItem.waitCount++;
try { item.wait(); } catch (InterruptedException inEx) {}
}
return (StatefulEJBContext) item.value;
}
}
//This is the thread that actually does the I/O
long activationStartTime = -1;
if (sfsbStoreMonitor.isMonitoringOn()) {
activationStartTime = System.currentTimeMillis();
}
try {
newItem.value = value = getStateFromStore(sessionKey, container);
synchronized (buckets[index]) {
if (value == null) {
//Remove the temp cacheItem that we created.
CacheItem prev = null;
for (CacheItem current = buckets[index]; current != null;
current = current.next)
{
if (current == newItem) {
if (prev == null) {
buckets[index] = current.next;
} else {
prev.next = current.next;
}
current.next = null;
break;
}
prev = current;
}
} else {
container.activateEJB(sessionKey,
(StatefulEJBContext) value, cookie);
sfsbStoreMonitor.incrementActivationCount(true);
CacheItem overflow = itemAdded(newItem);
incrementEntryCount();
// make sure we are are not crossing the threshold
if (overflow != null) {
trimItem(overflow);
}
}
} //end of sync
} catch (javax.ejb.EJBException ejbEx) {
sfsbStoreMonitor.incrementActivationCount(false);
remove(sessionKey);
value = null;
} finally {
synchronized (newItem) {
newItem.cacheItemState = CACHE_ITEM_VALID;
if (newItem.waitCount > 0) {
newItem.notifyAll();
}
}
if (activationStartTime != -1) {
long timeSpent = System.currentTimeMillis()
- activationStartTime;
sfsbStoreMonitor.setActivationTime(timeSpent);
}
}
return (StatefulEJBContext) value;
|
public boolean | passivateEJB(com.sun.ejb.spi.container.StatefulEJBContext ctx, java.lang.Object sessionKey)
try {
int hashCode = hash(sessionKey);
int index = getIndex(hashCode);
boolean itemRemoved = false;
CacheItem prev = null, item = null;
synchronized (bucketLocks[index]) {
for (item = buckets[index]; item != null; item = item.next) {
if (item.value == ctx) {
LruCacheItem lruSCItem = (LruCacheItem) item;
if (lruSCItem.isTrimmed == false) {
//Was accessed just after marked for passivation
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, cacheName + ": session accessed after marked for passivation: " + sessionKey);
}
return false;
}
break;
}
prev = item;
}
if (item == null) {
//Could have been removed
return true; //???????
//return (storeManager.contains(sessionKey));
}
if (removeIfIdle) {
long idleThreshold = System.currentTimeMillis() -
removalTimeoutInSeconds*1000;
//XXX: Avoid currentTimeMillis
if (ctx.getLastAccessTime() <= idleThreshold) {
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, cacheName +
": Removing session "
+ " instead of passivating for key: " + sessionKey);
}
if (prev == null) {
buckets[index] = item.next;
} else {
prev.next = item.next;
}
item.next = null;
itemRemoved = true;
//TODO::store.incrementExpiredSessionsRemoved();
}
}
}
if (itemRemoved) {
decrementEntryCount();
incrementRemovalCount();
return true;
}
if (saveStateToStore(sessionKey, ctx) == false) {
return false;
}
synchronized (bucketLocks[index]) {
prev = null;
for (item = buckets[index]; item != null; item = item.next) {
if (item.value == ctx) {
LruCacheItem lruSCItem = (LruCacheItem) item;
if (lruSCItem.isTrimmed == false) {
//Was accessed just after marked for passivation
return false;
}
if (prev == null) {
buckets[index] = item.next;
} else {
prev.next = item.next;
}
item.next = null;
break;
}
prev = item;
}
}
if (item != null) {
decrementEntryCount();
incrementRemovalCount();
}
return true;
} catch (java.io.NotSerializableException notSerEx) {
throw notSerEx;
} catch (Exception ex) {
_logger.log(Level.WARNING,
"[" + cacheName + "]: passivateEJB(), Exception caught -> ",ex);
}
return false;
|
public java.lang.Object | remove(java.lang.Object sessionKey)
return remove(sessionKey, true);
|
public java.lang.Object | remove(java.lang.Object sessionKey, boolean removeFromStore)
int hashCode = hash(sessionKey);
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) && sessionKey.equals(item.key)) {
if (prev == null) {
buckets[index] = item.next;
} else {
prev.next = item.next;
}
item.next = null;
itemRemoved(item);
((LruSessionCacheItem) item).cacheItemState = CACHE_ITEM_REMOVED;
break;
}
prev = item;
}
//remove it from the storeManager also
//In case it had been checkpointed
// remove it from storeManager outside sync block
if (removeFromStore) {
try {
storeManager.remove(sessionKey);
} catch (SFSBStoreManagerException sfsbEx) {
_logger.log(Level.WARNING, "[" + cacheName + "]: Exception in "
+ "storeManager.remove(" + sessionKey + ")", sfsbEx);
}
}
}
if (item != null) {
decrementEntryCount();
incrementRemovalCount();
incrementHitCount();
} else {
incrementMissCount();
}
return null;
|
private boolean | saveStateToStore(java.lang.Object sessionKey, com.sun.ejb.spi.container.StatefulEJBContext ctx)
byte[] data = IOUtils.serializeObject(ctx.getSessionContext(), true);
//If we are here then we were able to serialize the object successfully
boolean status = false;
if (data != null) {
SFSBBeanState beanState = storeManager.createSFSBBeanState(
sessionKey, ctx.getLastAccessTime(),
!ctx.existsInStore(), data);
//Note: Don't increment the version here because
// this is called on an async thread and the client
// already has the correct version
beanState.setVersion(ctx.getVersion());
try {
storeManager.passivateSave(beanState);
sfsbStoreMonitor.setPassivationSize(data.length);
status = true;
} catch (SFSBStoreManagerException sfsbEx) {
_logger.log(Level.WARNING, "[" + cacheName + "]: Exception during "
+ "storeManager.passivateSave(" + sessionKey + ")", sfsbEx);
}
}
return status;
|
public void | setConfigData(java.lang.String configData)
this.configData = configData;
|
public void | setMaxCacheSize(int val)
this.confMaxCacheSize = val;
|
public void | setSessionStore(com.sun.ejb.spi.sfsb.store.SFSBStoreManager storeManager)
this.storeManager = storeManager;
//this.monitorableSFSBStore = storeManager.getMonitorableSFSBStore();
|
public void | setShutdownState()
currentCacheState = STATE_SHUTTING_DOWN;
|
public void | setStatefulSessionStoreMonitor(com.sun.ejb.base.stats.StatefulSessionStoreMonitor storeMonitor)
this.sfsbStoreMonitor = storeMonitor;
|
public void | setUndeployedState()
currentCacheState = STATE_UNDEPLOYING;
|
public void | shutdown()
ArrayList<StatefulEJBContext> valueList = new ArrayList<StatefulEJBContext>();
synchronized (this) {
LruCacheItem item = tail;
while (item != null) {
StatefulEJBContext ctx = (StatefulEJBContext) item.value;
if (ctx != null) {
item.isTrimmed = true;
valueList.add(ctx);
}
// Ensure that for head the lPrev is null
if ((item == head) && (item.lPrev != null)) {
_logger.log(Level.WARNING, "[" + cacheName
+ "]: Iterator(), resetting head.lPrev");
item.lPrev = null;
}
// traverse to the previous one
item = item.lPrev;
}
}
for (StatefulEJBContext ctx : valueList) {
container.passivateEJB(ctx);
}
|
protected void | trimItem(CacheItem item)trim the item from the cache and notify listeners
LruCacheItem removed = (LruCacheItem) item;
if (removeIfIdle) {
StatefulEJBContext ctx = (StatefulEJBContext) item.value;
long idleThreshold =
System.currentTimeMillis() - removalTimeoutInSeconds*1000;
if (ctx.getLastAccessTime() <= idleThreshold) {
container.passivateEJB(ctx);
return;
}
}
for (int i = 0; i < listeners.size(); i++) {
CacheListener listener = (CacheListener) listeners.get(i);
listener.trimEvent(removed.key, removed.value);
}
|
private void | trimSelectedVictims(java.util.ArrayList victims)
int sz = victims.size();
synchronized (this) {
trimCount += sz;
}
CacheItem item = null;
for (int i=0; i<sz; i++) {
item = (CacheItem) victims.get(i);
trimItem(item);
}
|
public void | trimTimedoutItems(int maxTrimCount)trim the timedOut entries from the cache.
This call is to be scheduled by a thread managed by the container.
In this case a sorted LRU list exists based on access time and this
list is scanned
int count = 0;
LruCacheItem item;
long currentTime = System.currentTimeMillis();
long idleThresholdTime = currentTime - cacheIdleTimeoutInSeconds*1000;
ArrayList victimList = new ArrayList();
synchronized (this) {
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"[" + cacheName + "]: TrimTimedoutBeans started...");
}
if (tail == null) { // No LRU list exists
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"[" + cacheName + "]: TrimTimedoutBeans "
+ " finished after removing 0 idle beans");
}
head = null;
return;
}
// traverse LRU list and collect victims into the victimList
item = tail;
while (true) {
if (currentCacheState != STATE_RUNNING) {
_logger.log(Level.WARNING,
"[" + cacheName + "]: Exiting TrimTimedoutBeans() because "
+ "current cache state: " + currentCacheState);
break;
}
StatefulEJBContext ctx = (StatefulEJBContext) item.value;
if (ctx != null) {
// if we found a valid item, add it to the list
if ((ctx.getLastAccessTime() <= idleThresholdTime) &&
ctx.canBePassivated()) {
item.isTrimmed = true;
victimList.add(item);
} else {
break;
}
}
//Ensure that for head the lPrev is null
if( (item == head) && (item.lPrev != null) ) {
_logger.log(Level.WARNING,
"[" + cacheName + "]: TrimTimedoutBeans(), resetting head.lPrev");
item.lPrev = null;
}
// traverse to the previous one
item = item.lPrev;
if (item == null) {
break;
}
//for the last item that was picked up as a victim disconnect
//it from the list
item.lNext.lPrev = null;
item.lNext.lNext = null;
item.lNext = null;
}
if (item == tail) {
// no items were selected for trimming
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"[" + cacheName + "]: TrimTimedoutBeans "
+ " finished after removing 0 idle beans");
}
return;
}
// there is at least one item selected for trimming
if (item == null)
head = null;
tail = item;
count = victimList.size();
listSize -= count;
trimCount += count;
}
// trim the items from the BaseCache
for (int idx = 0;idx < count; idx++) {
trimItem((LruCacheItem) victimList.get(idx));
}
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"[" + cacheName + "]: TrimTimedoutBeans "
+ " finished after removing " + count + " idle beans");
}
|
public void | trimUnSortedTimedoutItems(int maxCount)This method picks idle items from a cache which does not have a sorted
LRU list
NRU cache at light loads and FIFO caches do not maintain a LRU list and
hence they have to scan the entire cache and select victims
int maxIndex = buckets.length;
long idleThreshold = System.currentTimeMillis() - timeout;
ArrayList victims = new ArrayList();
int sz = 0;
int totalSize = 0;
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"[" + cacheName + "]: TrimUnsortedTimedoutBeans started...");
}
// Go through each bucket in the cache and if there are entries in that
// bucket scan them and select victims
for (int index = 0; index < maxIndex ; index++) {
if (buckets[index] != null) {
synchronized (bucketLocks[index]) {
for (CacheItem item = buckets[index]; item != null;
item = item.next) {
StatefulEJBContext ctx =
(StatefulEJBContext) item.value;
//Note ctx can be null if bean is in BEING_REFRESHED state
if ((ctx != null) &&
(ctx.getLastAccessTime() <= idleThreshold) &&
ctx.canBePassivated()) {
LruCacheItem litem = (LruCacheItem)item;
synchronized (this) {
if (currentCacheState != STATE_RUNNING) {
_logger.log(Level.WARNING,
"[" + cacheName + "]: Exiting TrimUnSortedTimedoutBeans() "
+ "because current cache state: " + currentCacheState);
break;
}
if (litem.isTrimmed == false) {
itemRemoved(litem);
litem.isTrimmed = true;
victims.add(litem);
}
}
}
}
}
// Check and see if we have collected enough victims
// to start a cleaner task
sz = victims.size();
if (sz >= container.getPassivationBatchCount()) {
trimSelectedVictims(victims);
totalSize += sz;
victims.clear();
}
}
}
sz = victims.size();
if (sz > 0) {
trimSelectedVictims(victims);
totalSize += sz;
}
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "[" + cacheName + "]: TrimUnsortedTimedoutBeans "
+ " finished after removing " + totalSize + " idle beans");
}
|
public java.util.Iterator | values()get an Iterator for the values stored in the cache
ArrayList valueList = new ArrayList();
synchronized (this) {
LruCacheItem item = tail;
while (item != null) {
StatefulEJBContext ctx = (StatefulEJBContext) item.value;
if (ctx != null) {
valueList.add(ctx);
}
//Ensure that for head the lPrev is null
if( (item == head) && (item.lPrev != null) ) {
_logger.log(Level.WARNING,
"[" + cacheName + "]: Iterator(), resetting head.lPrev");
item.lPrev = null;
}
// traverse to the previous one
item = item.lPrev;
}
}
return valueList.iterator();
|