| Method from org.apache.catalina.session.PersistentManagerBase Detail: |
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
Add a lifecycle event listener to this component. |
public void clearStore() {
if (store == null)
return;
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged(new PrivilegedStoreClear());
}catch(PrivilegedActionException ex){
Exception exception = ex.getException();
log.error("Exception clearing the Store: " + exception);
exception.printStackTrace();
}
} else {
store.clear();
}
} catch (IOException e) {
log.error("Exception clearing the Store: " + e);
e.printStackTrace();
}
}
Clear all sessions from the Store. |
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
Get the lifecycle listeners associated with this lifecycle. If this
Lifecycle has no listeners registered, a zero-length array is returned. |
public Session findSession(String id) throws IOException {
Session session = super.findSession(id);
// OK, at this point, we're not sure if another thread is trying to
// remove the session or not so the only way around this is to lock it
// (or attempt to) and then try to get it by this session id again. If
// the other code ran swapOut, then we should get a null back during
// this run, and if not, we lock it out so we can access the session
// safely.
if(session != null) {
synchronized(session){
session = super.findSession(session.getIdInternal());
if(session != null){
// To keep any external calling code from messing up the
// concurrency.
session.access();
session.endAccess();
}
}
}
if (session != null)
return (session);
// See if the Session is in the Store
session = swapIn(id);
return (session);
}
Return the active Session, associated with this Manager, with the
specified session id (if any); otherwise return null.
This method checks the persistence store if persistence is enabled,
otherwise just uses the functionality from ManagerBase. |
public String getInfo() {
return (info);
}
Return descriptive information about this Manager implementation and
the corresponding version number, in the format
<description>/<version>. |
public int getMaxActiveSessions() {
return (this.maxActiveSessions);
}
Return the maximum number of active Sessions allowed, or -1 for
no limit. |
public int getMaxIdleBackup() {
return maxIdleBackup;
}
Indicates how many seconds old a session can get, after its last use in a
request, before it should be backed up to the store. -1 means sessions
are not backed up. |
public int getMaxIdleSwap() {
return maxIdleSwap;
}
The time in seconds after which a session should be swapped out of
memory to disk. |
public int getMinIdleSwap() {
return minIdleSwap;
}
The minimum time in seconds that a session must be idle before
it can be swapped out of memory, or -1 if it can be swapped out
at any time. |
public String getName() {
return (name);
}
Return the descriptive short name of this Manager implementation. |
public int getRejectedSessions() {
return rejectedSessions;
}
Number of session creations that failed due to maxActiveSessions. |
public boolean getSaveOnRestart() {
return saveOnRestart;
}
Indicates whether sessions are saved when the Manager is shut down
properly. This requires the unload() method to be called. |
public Store getStore() {
return (this.store);
}
Return the Store object which manages persistent Session
storage for this Manager. |
public boolean isLoaded(String id) {
try {
if ( super.findSession(id) != null )
return true;
} catch (IOException e) {
log.error("checking isLoaded for id, " + id + ", "+e.getMessage(), e);
}
return false;
}
Return true, if the session id is loaded in memory
otherwise false is returned |
protected boolean isStarted() {
return started;
}
|
public void load() {
// Initialize our internal data structures
sessions.clear();
if (store == null)
return;
String[] ids = null;
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
ids = (String[])
AccessController.doPrivileged(new PrivilegedStoreKeys());
}catch(PrivilegedActionException ex){
Exception exception = ex.getException();
log.error("Exception in the Store during load: "
+ exception);
exception.printStackTrace();
}
} else {
ids = store.keys();
}
} catch (IOException e) {
log.error("Can't load sessions from store, " + e.getMessage(), e);
return;
}
int n = ids.length;
if (n == 0)
return;
if (log.isDebugEnabled())
log.debug(sm.getString("persistentManager.loading", String.valueOf(n)));
for (int i = 0; i < n; i++)
try {
swapIn(ids[i]);
} catch (IOException e) {
log.error("Failed load session from store, " + e.getMessage(), e);
}
}
Load all sessions found in the persistence mechanism, assuming
they are marked as valid and have not passed their expiration
limit. If persistence is not supported, this method returns
without doing anything.
Note that by default, this method is not called by the MiddleManager
class. In order to use it, a subclass must specifically call it,
for example in the start() and/or processPersistenceChecks() methods. |
public void processExpires() {
long timeNow = System.currentTimeMillis();
Session sessions[] = findSessions();
int expireHere = 0 ;
if(log.isDebugEnabled())
log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);
for (int i = 0; i < sessions.length; i++) {
if (!sessions[i].isValid()) {
expiredSessions++;
expireHere++;
}
}
processPersistenceChecks();
if ((getStore() != null) && (getStore() instanceof StoreBase)) {
((StoreBase) getStore()).processExpires();
}
long timeEnd = System.currentTimeMillis();
if(log.isDebugEnabled())
log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);
processingTime += (timeEnd - timeNow);
}
Implements the Manager interface, direct call to processExpires and processPersistenceChecks |
protected void processMaxActiveSwaps() {
if (!isStarted() || getMaxActiveSessions() < 0)
return;
Session sessions[] = findSessions();
// FIXME: Smarter algorithm (LRU)
if (getMaxActiveSessions() >= sessions.length)
return;
if(log.isDebugEnabled())
log.debug(sm.getString
("persistentManager.tooManyActive",
new Integer(sessions.length)));
int toswap = sessions.length - getMaxActiveSessions();
long timeNow = System.currentTimeMillis();
for (int i = 0; i < sessions.length && toswap > 0; i++) {
StandardSession session = (StandardSession) sessions[i];
synchronized (session) {
int timeIdle = // Truncate, do not round up
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle > minIdleSwap) {
if (session.accessCount != null &&
session.accessCount.get() > 0) {
// Session is currently being accessed - skip it
continue;
}
if(log.isDebugEnabled())
log.debug(sm.getString
("persistentManager.swapTooManyActive",
session.getIdInternal(), new Integer(timeIdle)));
try {
swapOut(session);
} catch (IOException e) {
; // This is logged in writeSession()
}
toswap--;
}
}
}
}
Swap idle sessions out to Store if too many are active |
protected void processMaxIdleBackups() {
if (!isStarted() || maxIdleBackup < 0)
return;
Session sessions[] = findSessions();
long timeNow = System.currentTimeMillis();
// Back up all sessions idle longer than maxIdleBackup
if (maxIdleBackup >= 0) {
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
synchronized (session) {
if (!session.isValid())
continue;
int timeIdle = // Truncate, do not round up
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle > maxIdleBackup) {
if (log.isDebugEnabled())
log.debug(sm.getString
("persistentManager.backupMaxIdle",
session.getIdInternal(), new Integer(timeIdle)));
try {
writeSession(session);
} catch (IOException e) {
; // This is logged in writeSession()
}
}
}
}
}
}
|
protected void processMaxIdleSwaps() {
if (!isStarted() || maxIdleSwap < 0)
return;
Session sessions[] = findSessions();
long timeNow = System.currentTimeMillis();
// Swap out all sessions idle longer than maxIdleSwap
if (maxIdleSwap >= 0) {
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
synchronized (session) {
if (!session.isValid())
continue;
int timeIdle = // Truncate, do not round up
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
if (session.accessCount != null &&
session.accessCount.get() > 0) {
// Session is currently being accessed - skip it
continue;
}
if (log.isDebugEnabled())
log.debug(sm.getString
("persistentManager.swapMaxIdle",
session.getIdInternal(), new Integer(timeIdle)));
try {
swapOut(session);
} catch (IOException e) {
; // This is logged in writeSession()
}
}
}
}
}
}
Swap idle sessions out to Store if they are idle too long. |
public void processPersistenceChecks() {
processMaxIdleSwaps();
processMaxActiveSwaps();
processMaxIdleBackups();
}
Called by the background thread after active sessions have been checked
for expiration, to allow sessions to be swapped out, backed up, etc. |
public void propertyChange(PropertyChangeEvent event) {
// Validate the source of this event
if (!(event.getSource() instanceof Context))
return;
Context context = (Context) event.getSource();
// Process a relevant property change
if (event.getPropertyName().equals("sessionTimeout")) {
try {
setMaxInactiveInterval
( ((Integer) event.getNewValue()).intValue()*60 );
} catch (NumberFormatException e) {
log.error(sm.getString("standardManager.sessionTimeout",
event.getNewValue().toString()));
}
}
}
Process property change events from our associated Context. |
public void remove(Session session) {
super.remove (session);
if (store != null){
removeSession(session.getIdInternal());
}
}
Remove this Session from the active Sessions for this Manager,
and from the Store. |
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
Remove a lifecycle event listener from this component. |
protected void removeSession(String id) {
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged(new PrivilegedStoreRemove(id));
}catch(PrivilegedActionException ex){
Exception exception = ex.getException();
log.error("Exception in the Store during removeSession: "
+ exception);
exception.printStackTrace();
}
} else {
store.remove(id);
}
} catch (IOException e) {
log.error("Exception removing session " + e.getMessage());
e.printStackTrace();
}
}
Remove this Session from the active Sessions for this Manager,
and from the Store. |
public void removeSuper(Session session) {
super.remove (session);
}
Remove this Session from the active Sessions for this Manager,
but not from the Store. (Used by the PersistentValve) |
public void setContainer(Container container) {
// De-register from the old Container (if any)
if ((this.container != null) && (this.container instanceof Context))
((Context) this.container).removePropertyChangeListener(this);
// Default processing provided by our superclass
super.setContainer(container);
// Register with the new Container (if any)
if ((this.container != null) && (this.container instanceof Context)) {
setMaxInactiveInterval
( ((Context) this.container).getSessionTimeout()*60 );
((Context) this.container).addPropertyChangeListener(this);
}
}
Set the Container with which this Manager has been associated. If it is a
Context (the usual case), listen for changes to the session timeout
property. |
public void setMaxActiveSessions(int max) {
int oldMaxActiveSessions = this.maxActiveSessions;
this.maxActiveSessions = max;
support.firePropertyChange("maxActiveSessions",
new Integer(oldMaxActiveSessions),
new Integer(this.maxActiveSessions));
}
Set the maximum number of actives Sessions allowed, or -1 for
no limit. |
public void setMaxIdleBackup(int backup) {
if (backup == this.maxIdleBackup)
return;
int oldBackup = this.maxIdleBackup;
this.maxIdleBackup = backup;
support.firePropertyChange("maxIdleBackup",
new Integer(oldBackup),
new Integer(this.maxIdleBackup));
}
Sets the option to back sessions up to the Store after they
are used in a request. Sessions remain available in memory
after being backed up, so they are not passivated as they are
when swapped out. The value set indicates how old a session
may get (since its last use) before it must be backed up: -1
means sessions are not backed up.
Note that this is not a hard limit: sessions are checked
against this age limit periodically according to processExpiresFrequency.
This value should be considered to indicate when a session is
ripe for backing up.
So it is possible that a session may be idle for maxIdleBackup +
processExpiresFrequency * engine.backgroundProcessorDelay seconds, plus the time it takes to handle other
session expiration, swapping, etc. tasks. |
public void setMaxIdleSwap(int max) {
if (max == this.maxIdleSwap)
return;
int oldMaxIdleSwap = this.maxIdleSwap;
this.maxIdleSwap = max;
support.firePropertyChange("maxIdleSwap",
new Integer(oldMaxIdleSwap),
new Integer(this.maxIdleSwap));
}
Sets the time in seconds after which a session should be swapped out of
memory to disk. |
public void setMinIdleSwap(int min) {
if (this.minIdleSwap == min)
return;
int oldMinIdleSwap = this.minIdleSwap;
this.minIdleSwap = min;
support.firePropertyChange("minIdleSwap",
new Integer(oldMinIdleSwap),
new Integer(this.minIdleSwap));
}
Sets the minimum time in seconds that a session must be idle before
it can be swapped out of memory due to maxActiveSession. Set it to -1
if it can be swapped out at any time. |
public void setRejectedSessions(int rejectedSessions) {
this.rejectedSessions = rejectedSessions;
}
|
public void setSaveOnRestart(boolean saveOnRestart) {
if (saveOnRestart == this.saveOnRestart)
return;
boolean oldSaveOnRestart = this.saveOnRestart;
this.saveOnRestart = saveOnRestart;
support.firePropertyChange("saveOnRestart",
new Boolean(oldSaveOnRestart),
new Boolean(this.saveOnRestart));
}
Set the option to save sessions to the Store when the Manager is
shut down, then loaded when the Manager starts again. If set to
false, any sessions found in the Store may still be picked up when
the Manager is started again. |
protected void setStarted(boolean started) {
this.started = started;
}
|
public void setStore(Store store) {
this.store = store;
store.setManager(this);
}
Set the Store object which will manage persistent Session
storage for this Manager. |
public void start() throws LifecycleException {
// Validate and update our current component state
if (started) {
log.info(sm.getString("standardManager.alreadyStarted"));
return;
}
if( ! initialized )
init();
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Force initialization of the random number generator
if (log.isDebugEnabled())
log.debug("Force random number initialization starting");
String dummy = generateSessionId();
if (log.isDebugEnabled())
log.debug("Force random number initialization completed");
if (store == null)
log.error("No Store configured, persistence disabled");
else if (store instanceof Lifecycle)
((Lifecycle)store).start();
}
Prepare for the beginning of active use of the public methods of this
component. This method should be called after configure(),
and before any of the public methods of the component are utilized. |
public void stop() throws LifecycleException {
if (log.isDebugEnabled())
log.debug("Stopping");
// Validate and update our current component state
if (!isStarted()) {
log.info(sm.getString("standardManager.notStarted"));
return;
}
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
setStarted(false);
if (getStore() != null && saveOnRestart) {
unload();
} else {
// Expire all active sessions
Session sessions[] = findSessions();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
if (!session.isValid())
continue;
session.expire();
}
}
if (getStore() != null && getStore() instanceof Lifecycle)
((Lifecycle)getStore()).stop();
// Require a new random number generator if we are restarted
this.random = null;
if( initialized )
destroy();
}
Gracefully terminate the active use of the public methods of this
component. This method should be the last one called on a given
instance of this component. |
protected Session swapIn(String id) throws IOException {
if (store == null)
return null;
Object swapInLock = null;
/*
* The purpose of this sync and these locks is to make sure that a
* session is only loaded once. It doesn't matter if the lock is removed
* and then another thread enters this method and tries to load the same
* session. That thread will re-create a swapIn lock for that session,
* quickly find that the session is already in sessions, use it and
* carry on.
*/
synchronized (this) {
swapInLock = sessionSwapInLocks.get(id);
if (swapInLock == null) {
swapInLock = new Object();
sessionSwapInLocks.put(id, swapInLock);
}
}
Session session = null;
synchronized (swapInLock) {
// First check to see if another thread has loaded the session into
// the manager
session = sessions.get(id);
if (session == null) {
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try {
session = (Session) AccessController.doPrivileged(
new PrivilegedStoreLoad(id));
} catch (PrivilegedActionException ex) {
Exception e = ex.getException();
log.error(sm.getString(
"persistentManager.swapInException", id),
e);
if (e instanceof IOException){
throw (IOException)e;
} else if (e instanceof ClassNotFoundException) {
throw (ClassNotFoundException)e;
}
}
} else {
session = store.load(id);
}
} catch (ClassNotFoundException e) {
String msg = sm.getString(
"persistentManager.deserializeError", id);
log.error(msg, e);
throw new IllegalStateException(msg, e);
}
if (session != null && !session.isValid()) {
log.error(sm.getString(
"persistentManager.swapInInvalid", id));
session.expire();
removeSession(id);
session = null;
}
if (session != null) {
if(log.isDebugEnabled())
log.debug(sm.getString("persistentManager.swapIn", id));
session.setManager(this);
// make sure the listeners know about it.
((StandardSession)session).tellNew();
add(session);
((StandardSession)session).activate();
// endAccess() to ensure timeouts happen correctly.
// access() to keep access count correct or it will end up
// negative
session.access();
session.endAccess();
}
}
}
// Make sure the lock is removed
synchronized (this) {
sessionSwapInLocks.remove(id);
}
return (session);
}
Look for a session in the Store and, if found, restore
it in the Manager's list of active sessions if appropriate.
The session will be removed from the Store after swapping
in, but will not be added to the active session list if it
is invalid or past its expiration. |
protected void swapOut(Session session) throws IOException {
if (store == null || !session.isValid()) {
return;
}
((StandardSession)session).passivate();
writeSession(session);
super.remove(session);
session.recycle();
}
Remove the session from the Manager's list of active
sessions and write it out to the Store. If the session
is past its expiration or invalid, this method does
nothing. |
public void unload() {
if (store == null)
return;
Session sessions[] = findSessions();
int n = sessions.length;
if (n == 0)
return;
if (log.isDebugEnabled())
log.debug(sm.getString("persistentManager.unloading",
String.valueOf(n)));
for (int i = 0; i < n; i++)
try {
swapOut(sessions[i]);
} catch (IOException e) {
; // This is logged in writeSession()
}
}
Save all currently active sessions in the appropriate persistence
mechanism, if any. If persistence is not supported, this method
returns without doing anything.
Note that by default, this method is not called by the MiddleManager
class. In order to use it, a subclass must specifically call it,
for example in the stop() and/or processPersistenceChecks() methods. |
protected void writeSession(Session session) throws IOException {
if (store == null || !session.isValid()) {
return;
}
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged(new PrivilegedStoreSave(session));
}catch(PrivilegedActionException ex){
Exception exception = ex.getException();
log.error("Exception in the Store during writeSession: "
+ exception);
exception.printStackTrace();
}
} else {
store.save(session);
}
} catch (IOException e) {
log.error(sm.getString
("persistentManager.serializeError", session.getIdInternal(), e));
throw e;
}
}
Write the provided session to the Store without modifying
the copy in memory or triggering passivation events. Does
nothing if the session is invalid or past its expiration. |