[jboss-cvs] JBossAS SVN: r57326 - branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sun Oct 1 11:30:53 EDT 2006
Author: bstansberry at jboss.com
Date: 2006-10-01 11:30:51 -0400 (Sun, 01 Oct 2006)
New Revision: 57326
Modified:
branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java
branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java
branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml
Log:
[JBAS-3096] Add maxEmptyLife concept
Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java 2006-10-01 14:22:21 UTC (rev 57325)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java 2006-10-01 15:30:51 UTC (rev 57326)
@@ -16,13 +16,12 @@
package org.jboss.web.tomcat.tc5.sso;
-import org.jboss.web.tomcat.tc5.Tomcat5;
-import org.jboss.web.tomcat.tc5.session.JBossManager;
-
import java.io.IOException;
import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import javax.management.ObjectName;
@@ -34,15 +33,19 @@
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Manager;
+import org.apache.catalina.Realm;
import org.apache.catalina.Session;
-import org.apache.catalina.Realm;
import org.apache.catalina.SessionEvent;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.session.ManagerBase;
+import org.jboss.web.tomcat.tc5.Tomcat5;
+import org.jboss.web.tomcat.tc5.session.JBossManager;
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
+
/**
* A <strong>Valve</strong> that supports a "single sign on" user experience,
* where the security identity of a user who successfully authenticates to one
@@ -67,7 +70,11 @@
extends org.apache.catalina.authenticator.SingleSignOn
implements LifecycleListener
{
-
+ /** By default we process expired SSOs no more often than once per minute */
+ public static final int DEFAULT_PROCESS_EXPIRES_INTERVAL = 60;
+ /** By default we let SSOs without active sessions live for 30 mins */
+ public static final int DEFAULT_MAX_EMPTY_LIFE = 1800;
+
// Override the superclass value
static
{
@@ -97,7 +104,37 @@
*/
private String treeCacheName = Tomcat5.DEFAULT_CACHE_NAME;
+// DISABLED UNTIL 4.0.6.CR1
+// /**
+// * Object name of the thread pool used by SSOClusterManager.
+// * Only relevant if the SSOClusterManager implementation is
+// * TreeCacheSSOClusterManager.
+// */
+// private String threadPoolName = "jboss.system:service=ThreadPool";
+
+ /** Currently started Managers that have associated as session with an SSO */
private Set activeManagers = Collections.synchronizedSet(new HashSet());
+
+ /** Max number of ms an SSO with no active sessions will be usable by a request */
+ private int maxEmptyLife = DEFAULT_MAX_EMPTY_LIFE * 1000;
+
+ /**
+ * Minimum number of ms since the last processExpires() run
+ * before a new run is allowed.
+ */
+ private int processExpiresInterval = DEFAULT_PROCESS_EXPIRES_INTERVAL * 1000;
+
+ /** Timestamp of the last processExpires() run */
+ private long lastProcessExpires = System.currentTimeMillis();
+
+ /**
+ * Map<String, Long> containing the ids of SSOs with no active sessions
+ * and the time at which they entered that state
+ */
+ private Map emptySSOs = new ConcurrentHashMap();
+
+ /** Used for sync locking of processExpires runs */
+ private final Object mutex = new Object();
// ------------------------------------------------------------- Properties
@@ -216,8 +253,133 @@
((TreeCacheSSOClusterManager) ssoClusterManager).setCacheName(cacheName);
}
}
+
+// DISABLED UNTIL 4.0.6.CR1
+// /**
+// * Object name of the thread pool used by SSOClusterManager.
+// * Only relevant if the SSOClusterManager implementation is
+// * TreeCacheSSOClusterManager.
+// */
+// public String getThreadPoolName()
+// {
+// return threadPoolName;
+// }
+//
+// /**
+// * Sets the object name of the thread pool used by SSOClusterManager.
+// * Only relevant if the SSOClusterManager implementation is
+// * TreeCacheSSOClusterManager.
+// */
+// public void setThreadPoolName(String poolName)
+// throws Exception
+// {
+// this.threadPoolName = poolName;
+// if (ssoClusterManager != null
+// && ssoClusterManager instanceof TreeCacheSSOClusterManager)
+// {
+// ((TreeCacheSSOClusterManager) ssoClusterManager).setThreadPoolName(poolName);
+// }
+// }
+ /**
+ * Gets the max number of seconds an SSO with no active sessions will be
+ * usable by a request.
+ *
+ * @return a non-negative number
+ *
+ * @see #DEFAULT_MAX_EMPTY_LIFE *
+ * @see #setMaxEmptyLife()
+ */
+ public int getMaxEmptyLife()
+ {
+ return (maxEmptyLife / 1000);
+ }
+
+ /**
+ * Sets the maximum number of seconds an SSO with no active sessions will be
+ * usable by a request.
+ * <p>
+ * A positive value for this property allows a user to continue to use an SSO
+ * even after all the sessions associated with it have been expired. It does not
+ * keep an SSO alive if a session associated with it has been invalidated due to
+ * an <code>HttpSession.invalidate()</code> call.
+ * </p>
+ * <p>
+ * The primary purpose of this property is to avoid the situation where a server
+ * on which all of an SSO's sessions lives is shutdown, thus expiring all the
+ * sessions and causing the invalidation of the SSO. A positive value for this
+ * property would give the user an opportunity to fail over to another server
+ * and maintain the SSO.
+ * </p>
+ *
+ * @param maxEmptyLife a non-negative number
+ *
+ * @throws IllegalArgumentException if <code>maxEmptyLife < 0</code>
+ */
+ public void setMaxEmptyLife(int maxEmptyLife)
+ {
+ if (maxEmptyLife < 0)
+ throw new IllegalArgumentException("maxEmptyLife must be >= 0");
+
+ this.maxEmptyLife = maxEmptyLife * 1000;
+ }
+
+
+ /**
+ * Gets the minimum number of seconds since the start of the last check for overaged
+ * SSO's with no active sessions before a new run is allowed.
+ *
+ * @return a positive number
+ *
+ * @see #DEFAULT_PROCESS_EXPIRES_INTERVAL
+ * @see #setMaxEmptyLife()
+ * @see #setProcessExpiresInterval(int)
+ */
+ public int getProcessExpiresInterval()
+ {
+ return processExpiresInterval / 1000;
+ }
+
+ /**
+ * Sets the minimum number of seconds since the start of the last check for overaged
+ * SSO's with no active sessions before a new run is allowed. During this check,
+ * any such overaged SSOs will be invalidated.
+ * <p>
+ * Note that setting this value does not imply that a check will be performed
+ * every <code>processExpiresInterval</code> seconds, only that it will not
+ * be performed more often than that.
+ * </p>
+ *
+ * @param processExpiresInterval a non-negative number. <code>0</code> means
+ * the overage check can be performed whenever
+ * the container wishes to.
+ *
+ * @throws IllegalArgumentException if <code>processExpiresInterval < 1</code>
+ *
+ * @see #setMaxEmptyLife()
+ */
+ public void setProcessExpiresInterval(int processExpiresInterval)
+ {
+ if (processExpiresInterval < 0)
+ throw new IllegalArgumentException("processExpiresInterval must be >= 0");
+
+ this.processExpiresInterval = processExpiresInterval * 1000;
+ }
+
+
+ /**
+ * Gets the timestamp of the start of the last check for overaged
+ * SSO's with no active sessions.
+ *
+ * @see #setProcessExpiresInterval(int)
+ */
+ public long getLastProcessExpires()
+ {
+ return lastProcessExpires;
+ }
+
+
// ------------------------------------------------------ Lifecycle Methods
@@ -314,21 +476,35 @@
if (ssoId == null)
return;
- // Was the session destroyed as the result of a timeout or
- // the undeployment of the containing webapp?
- // If so, we'll just remove the expired session from the
- // SSO. If the session was logged out, we'll log out
- // of all sessions associated with the SSO.
- if (isSessionTimedOut(session) || isManagerStopped(session))
+ try
{
- removeSession(ssoId, session);
+ // Was the session destroyed as the result of a timeout or
+ // the undeployment of the containing webapp?
+ // If so, we'll just remove the expired session from the
+ // SSO. If the session was logged out, we'll log out
+ // of all sessions associated with the SSO.
+ if (isSessionTimedOut(session) || isManagerStopped(session))
+ {
+ removeSession(ssoId, session);
+
+ // Quite poor. We hijack the caller thread (the Tomcat background thread)
+ // to do our cleanup of expired sessions
+ processExpires();
+ }
+ else
+ {
+ // The session was logged out.
+ logout(ssoId);
+ }
}
- else
+ catch (Exception e)
{
- // The session was logged out.
- logout(ssoId);
+ // Don't propagate back to the webapp; we don't want to disrupt
+ // the session expiration process
+ getContainer().getLogger().error("Caught exception updating SSO " + ssoId +
+ " following destruction of session " +
+ session.getIdInternal(), e);
}
-
}
private boolean isSessionTimedOut(Session session)
@@ -463,10 +639,11 @@
}
// Look up the cached Principal associated with this cookie value
+ String ssoId = cookie.getValue();
if (getContainer().getLogger().isDebugEnabled())
- getContainer().getLogger().debug(" Checking for cached principal for " + cookie.getValue());
+ getContainer().getLogger().debug(" Checking for cached principal for " + ssoId);
SingleSignOnEntry entry = getSingleSignOnEntry(cookie.getValue());
- if (entry != null)
+ if (entry != null && isValid(ssoId, entry))
{
Principal ssoPrinc = entry.getPrincipal();
// have to deal with the fact that the entry may not have an
@@ -693,7 +870,7 @@
}
}
}
-
+
return sso;
}
@@ -811,12 +988,12 @@
reverse.remove(session);
}
- // If there are no sessions left in the SingleSignOnEntry,
- // deregister the entry.
- if (entry.getSessionCount() == 0)
- {
- deregister(ssoId);
- }
+// // If there are no sessions left in the SingleSignOnEntry,
+// // deregister the entry.
+// if (entry.getSessionCount() == 0)
+// {
+// deregister(ssoId);
+// }
}
@@ -980,6 +1157,24 @@
}
}
+
+ /**
+ * Callback from the SSOManager when it detects an SSO without
+ * any active sessions across the cluster
+ */
+ void notifySSOEmpty(String ssoId)
+ {
+ emptySSOs.put(ssoId, new Long(System.currentTimeMillis()));
+ }
+
+ /**
+ * Callback from the SSOManager when it detects an SSO that
+ * has active sessions across the cluster
+ */
+ void notifySSONotEmpty(String ssoId)
+ {
+ emptySSOs.remove(ssoId);
+ }
// ------------------------------------------------------- Private Methods
@@ -1018,6 +1213,8 @@
if (mgr instanceof TreeCacheSSOClusterManager)
{
((TreeCacheSSOClusterManager) mgr).setCacheName(getTreeCacheName());
+// DISABLED UNTIL 4.0.6.CR1
+// ((TreeCacheSSOClusterManager) mgr).setThreadPoolName(getThreadPoolName());
}
ssoClusterManager = mgr;
clusterManagerClass = className;
@@ -1035,5 +1232,57 @@
}
}
}
+
+
+ private void processExpires()
+ {
+ long now = 0L;
+ synchronized (mutex)
+ {
+ now = System.currentTimeMillis();
+
+ if (now - lastProcessExpires > processExpiresInterval)
+ {
+ lastProcessExpires = now;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ clearExpiredSSOs(now);
+ }
+
+ private synchronized void clearExpiredSSOs(long now)
+ {
+ for (Iterator iter = emptySSOs.entrySet().iterator(); iter.hasNext();)
+ {
+ Map.Entry entry = (Map.Entry) iter.next();
+ if ( (now - ((Long) entry.getValue()).longValue()) > maxEmptyLife)
+ {
+ logout((String) entry.getKey());
+ iter.remove();
+ }
+ }
+ }
+
+ private boolean isValid(String ssoId, SingleSignOnEntry entry)
+ {
+ boolean valid = true;
+ if (entry.getSessionCount() == 0)
+ {
+ Long expired = (Long) emptySSOs.get(ssoId);
+ if (expired != null
+ && (System.currentTimeMillis() - expired.longValue()) > maxEmptyLife)
+ {
+ valid = false;
+ logout(ssoId);
+ emptySSOs.remove(ssoId);
+ }
+ }
+
+ return valid;
+ }
}
\ No newline at end of file
Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java 2006-10-01 14:22:21 UTC (rev 57325)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java 2006-10-01 15:30:51 UTC (rev 57326)
@@ -24,7 +24,9 @@
import java.io.Serializable;
import java.security.Principal;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
+import java.util.Vector;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanException;
@@ -37,14 +39,18 @@
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Session;
import org.apache.catalina.util.LifecycleSupport;
+import org.jboss.cache.AbstractTreeCacheListener;
import org.jboss.cache.Fqn;
-import org.jboss.cache.TreeCache;
import org.jboss.cache.TreeCacheListener;
import org.jboss.cache.config.Option;
import org.jboss.logging.Logger;
+import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.util.NestedRuntimeException;
+import org.jboss.util.threadpool.ThreadPool;
+import org.jboss.util.threadpool.ThreadPoolMBean;
import org.jboss.web.tomcat.tc5.Tomcat5;
+import org.jgroups.Address;
import org.jgroups.View;
/**
@@ -55,7 +61,8 @@
* @version $Revision$ $Date$
*/
public final class TreeCacheSSOClusterManager
- implements SSOClusterManager, TreeCacheListener
+ extends AbstractTreeCacheListener
+ implements SSOClusterManager
{
// ------------------------------------------------------------- Constants
@@ -108,12 +115,15 @@
{Fqn.class.getName(), Option.class.getName()};
private static final Option GRAVITATE_OPTION = new Option();
-
+ private static final Option LOCAL_OPTION = new Option();
+
static
{
GRAVITATE_OPTION.setForceDataGravitation(true);
+ LOCAL_OPTION.setCacheModeLocal(true);
}
+
// ------------------------------------------------------- Instance Fields
/**
@@ -135,7 +145,12 @@
* ObjectName of the TreeCache
*/
private ObjectName cacheObjectName = null;
-
+
+// DISABLED UNTIL 4.0.6.CR1
+// private String threadPoolName = "jboss.system:service=ThreadPool";
+//
+// private ThreadPool threadPool;
+
/**
* String version of the object name to use to access the TreeCache
*/
@@ -191,6 +206,13 @@
*/
private Serializable localAddress = null;
+// DISABLED UNTIL 4.0.6.CR1
+// /** The last view passed to viewAccepted() */
+// private View currentView;
+//
+// /** Mutex lock to ensure only one view change at a time is being processed */
+// private Object cleanupMutex = new Object();
+
// ---------------------------------------------------------- Constructors
@@ -276,8 +298,28 @@
}
}
+// DISABLED UNTIL 4.0.6.CR1
+// public String getThreadPoolName()
+// {
+// return threadPoolName;
+// }
+//
+//
+// public void setThreadPoolName(String threadPoolName)
+// {
+// if (started)
+// {
+// log.info("Call to setThreadPoolName() ignored; already started");
+// }
+// else
+// {
+// this.threadPoolName = threadPoolName;
+// }
+// }
+
// ----------------------------------------------------- SSOClusterManager
+
/**
* Notify the cluster of the addition of a Session to an SSO session.
*
@@ -319,9 +361,9 @@
if(doTx)
tm.begin();
- Set sessions = getSessionSet(fqn, true);
+ Set sessions = getSessionSet(fqn, true, false);
sessions.add(new SessionAddress(session.getId(), localAddress));
- putInTreeCache(fqn, sessions);
+ putInTreeCache(fqn, sessions, false);
}
catch (Exception e)
{
@@ -439,7 +481,7 @@
Fqn fqn = getCredentialsFqn(ssoId);
try
{
- SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn);
+ SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn, false);
if (data != null)
{
entry = new SingleSignOnEntry(null,
@@ -516,7 +558,7 @@
Fqn fqn = getSessionsFqn(ssoId);
boolean doTx = false;
- boolean removing = false;
+// boolean removing = false;
try
{
// Confirm we have a transaction manager; if not get it from TreeCache
@@ -532,24 +574,24 @@
if(doTx)
tm.begin();
- Set sessions = getSessionSet(fqn, false);
+ Set sessions = getSessionSet(fqn, false, false);
if (sessions != null)
{
sessions.remove(new SessionAddress(session.getId(), localAddress));
- if (sessions.size() == 0)
- {
- // No sessions left; remove node
-
- // Add this SSO to our list of in-process local removals so
- // this.nodeRemoved() will ignore the removal
- removing = true;
- beingLocallyRemoved.set(ssoId);
- removeFromTreeCache(getSingleSignOnFqn(ssoId));
- }
- else
- {
- putInTreeCache(fqn, sessions);
- }
+// if (sessions.size() == 0)
+// {
+// // No sessions left; remove node
+//
+// // Add this SSO to our list of in-process local removals so
+// // this.nodeRemoved() will ignore the removal
+// removing = true;
+// beingLocallyRemoved.set(ssoId);
+// removeFromTreeCache(getSingleSignOnFqn(ssoId));
+// }
+// else
+// {
+ putInTreeCache(fqn, sessions, false);
+// }
}
}
catch (Exception e)
@@ -569,18 +611,18 @@
}
finally
{
- try
- {
- if (removing)
- {
- beingLocallyRemoved.set(null);
- }
- }
- finally
- {
+// try
+// {
+// if (removing)
+// {
+// beingLocallyRemoved.set(null);
+// }
+// }
+// finally
+// {
if (doTx)
endTransaction();
- }
+// }
}
}
@@ -616,50 +658,6 @@
// ------------------------------------------------------ TreeCacheListener
/**
- * Does nothing
- */
- public void nodeCreated(Fqn fqn)
- {
- ; // do nothing
- }
-
- /**
- * Does nothing
- */
- public void nodeLoaded(Fqn fqn)
- {
- ; // do nothing
- }
-
-
- /**
- * Does nothing
- */
- public void nodeVisited(Fqn fqn)
- {
- ; // do nothing
- }
-
-
- /**
- * Does nothing
- */
- public void cacheStarted(TreeCache cache)
- {
- ; // do nothing
- }
-
-
- /**
- * Does nothing
- */
- public void cacheStopped(TreeCache cache)
- {
- ; // do nothing
- }
-
-
- /**
* Extracts an SSO session id from the Fqn and uses it in an invocation of
* {@link ClusteredSingleSignOn#deregister(String) ClusteredSingleSignOn.deregister(String)}.
* <p/>
@@ -717,14 +715,26 @@
*/
public void nodeModified(Fqn fqn)
{
- // We are only interested in changes to the CREDENTIALS node
- if (CREDENTIALS.equals(getTypeFromFqn(fqn)) == false)
+ String type = getTypeFromFqn(fqn);
+ if (CREDENTIALS.equals(type))
{
- return;
+ handleCredentialUpdate(fqn);
}
+ else if (SESSIONS.equals(type))
+ {
+ handleSessionSetChange(fqn);
+ }
+ }
- String ssoId = getIdFromFqn(fqn); // won't be null or above check fails
+ /**
+ *
+ * @param fqn an Fqn that points to the CREDENTIALS node of an SSO
+ */
+ private void handleCredentialUpdate(Fqn fqn)
+ {
+ String ssoId = getIdFromFqn(fqn); // won't be null per the API contract
+
// Ignore invocations that come as a result of our additions
if (ssoId.equals(beingLocallyAdded.get()))
{
@@ -747,7 +757,7 @@
// credentialUpdater.enqueue(sso, ssoId);
try
{
- SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn);
+ SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn, false);
if (data != null)
{
// We want to release our read lock quickly, so get the needed
@@ -774,28 +784,92 @@
log.error("failed to update credentials for SSO " + ssoId, e);
}
}
-
-
+
/**
- * Does nothing
+ *
+ * @param fqn an Fqn that points to the SESSIONS node of an SSO
*/
- public void viewChange(View new_view)
+ private void handleSessionSetChange(Fqn fqn)
{
- ; // do nothing
+ // Here we *want* to handle local activity as well as remote,
+ // as the distributed cache set of sessions is the only
+ // complete representation
+
+ String ssoId = getIdFromFqn(fqn);
+ try
+ {
+ Set sessions = (Set) getFromTreeCache(fqn, false);
+ if (sessions == null)
+ {
+ // don't think we'd get this event;
+ // in any case we don't deal with this
+ }
+ else if (sessions.size() == 0)
+ {
+ ssoValve.notifySSOEmpty(ssoId);
+ }
+ else
+ {
+ ssoValve.notifySSONotEmpty(ssoId);
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("failed in check for empty SSO " + ssoId, e);
+ }
}
-
- /**
- * Does nothing. Called when a node is evicted (not the same as remove()).
- *
- * @param fqn
- */
- public void nodeEvicted(Fqn fqn)
- {
- // TODO do we need to handle this?
- ; // do nothing
- }
-
+// DISABLE UNTIL 4.0.6.CR1
+// /**
+// * If any nodes have been removed from the view, asynchronously scans
+// * all SSOs looking for and removing sessions owned by the removed node.
+// * Notifies the SSO valve if as a result any SSOs no longer have active
+// * sessions. If the removed node is the one associated with this object,
+// * does nothing.
+// */
+// public void viewChange(View new_view)
+// {
+// if (currentView == null)
+// {
+// currentView = new_view;
+// return;
+// }
+//
+// Vector oldMembers = currentView.getMembers();
+//
+// currentView = new_view;
+//
+// // If we're not in the view, just exit
+// if (localAddress == null || !currentView.containsMember((Address) localAddress))
+// return;
+//
+// boolean hasDeadMembers = false;
+// for (Iterator iter = oldMembers.iterator(); iter.hasNext(); )
+// {
+// Address member = (Address) iter.next();
+// if (!new_view.containsMember(member))
+// {
+// hasDeadMembers = true;
+// break;
+// }
+// }
+//
+// if (hasDeadMembers)
+// {
+// DeadMemberCleaner cleaner = new DeadMemberCleaner();
+// if (threadPool != null)
+// {
+// threadPool.run(cleaner);
+// }
+// else
+// {
+// Thread t = new Thread(cleaner, "ClusteredSSOCleaner");
+// t.setDaemon(true);
+// t.start();
+// }
+// }
+//
+// }
// ------------------------------------------------------------- Lifecycle
@@ -862,6 +936,9 @@
"TransactionManager from TreeCache", e);
}
+// DISABLED UNTIL 4.0.6.CR1
+// initThreadPool();
+
started = true;
// Notify our interested LifecycleListeners
@@ -896,11 +973,20 @@
// ------------------------------------------------------- Private Methods
- private Object getFromTreeCache(Fqn fqn) throws Exception
+ private Object getFromTreeCache(Fqn fqn, boolean localOnly) throws Exception
{
- Object[] args = new Object[]{fqn, KEY, GRAVITATE_OPTION};
+ Object[] args = new Object[]{fqn, KEY, localOnly ? LOCAL_OPTION : GRAVITATE_OPTION};
return server.invoke(getCacheObjectName(), "get", args, GET_SIGNATURE);
}
+
+// DISABLED UNTIL 4.0.6.CR1
+// private Set getSSOIds() throws Exception
+// {
+// Fqn ssoRoot = new Fqn(new Object[] {SSO});
+// return (Set) server.invoke(getCacheObjectName(), "getChildrenNames",
+// new Object[]{ ssoRoot },
+// new String[]{ Fqn.class.getName() });
+// }
private Fqn getCredentialsFqn(String ssoid)
{
@@ -936,10 +1022,10 @@
return id;
}
- private Set getSessionSet(Fqn fqn, boolean create)
+ private Set getSessionSet(Fqn fqn, boolean create, boolean localOnly)
throws Exception
{
- Set sessions = (Set) getFromTreeCache(fqn);
+ Set sessions = (Set) getFromTreeCache(fqn, localOnly);
if (create && sessions == null)
{
sessions = new HashSet();
@@ -1068,9 +1154,9 @@
return avail;
}
- private void putInTreeCache(Fqn fqn, Object data) throws Exception
+ private void putInTreeCache(Fqn fqn, Object data, boolean localOnly) throws Exception
{
- Object[] args = new Object[]{fqn, KEY, data, GRAVITATE_OPTION};
+ Object[] args = new Object[]{fqn, KEY, data, localOnly ? LOCAL_OPTION : GRAVITATE_OPTION};
server.invoke(getCacheObjectName(), "put", args, PUT_SIGNATURE);
}
@@ -1172,6 +1258,24 @@
new Object[]{fqn, GRAVITATE_OPTION},
REMOVE_SIGNATURE);
}
+
+// DISABLED UNTIL 4.0.6.CR1
+// private void initThreadPool()
+// {
+// if (threadPoolName != null)
+// {
+// try
+// {
+// ObjectName on = new ObjectName(threadPoolName);
+// threadPool = (ThreadPool) MBeanProxyExt.create(ThreadPoolMBean.class, on);
+// }
+// catch (Exception e)
+// {
+// log.info("Unable to access ThreadPool at " + threadPoolName +
+// " -- will use individual threads for cleanup work");
+// }
+// }
+// }
/**
* Stores the given data to the clustered cache in a tree branch whose FQN
@@ -1200,7 +1304,7 @@
try
{
- putInTreeCache(getCredentialsFqn(ssoId), data);
+ putInTreeCache(getCredentialsFqn(ssoId), data, false);
}
catch (Exception e)
{
@@ -1345,5 +1449,97 @@
}
+// DISABLED UNTIL 4.0.6.CR1
+// /**
+// * Runnable that's run when the removal of a node from the cluster has been detected.
+// * Removes any SessionAddress objects associated with dead members from the
+// * session set of each SSO. Operates locally only so each node can independently clean
+// * its SSOs without concern about replication lock conflicts.
+// */
+// private class DeadMemberCleaner implements Runnable
+// {
+// public void run()
+// {
+// synchronized (cleanupMutex)
+// {
+// try
+// {
+// // Ensure we have a TransactionManager
+// if (tm == null)
+// configureFromCache();
+//
+// Set ids = getSSOIds();
+//
+// for (Iterator iter = ids.iterator(); iter.hasNext();)
+// {
+// cleanDeadMembersFromSSO((String) iter.next());
+//
+// }
+// }
+// catch (Exception e)
+// {
+// log.error("Caught exception cleaning sessions from dead cluster members from SSOs ", e);
+// }
+// }
+// }
+//
+// private void cleanDeadMembersFromSSO(String ssoId)
+// {
+// Fqn fqn = getSessionsFqn(ssoId);
+// boolean doTx = false;
+// try
+// {
+// // Don't start tx if there is already one associated with this thread.
+// if(tm.getTransaction() == null)
+// doTx = true;
+//
+// if(doTx)
+// tm.begin();
+//
+// Set sessions = getSessionSet(fqn, false, true);
+// if (sessions != null && sessions.size() > 0)
+// {
+// boolean changed = false;
+// for (Iterator iter = sessions.iterator(); iter.hasNext();)
+// {
+// SessionAddress session = (SessionAddress) iter.next();
+// if (!currentView.containsMember((Address) session.address))
+// {
+// iter.remove();
+// changed = true;
+// }
+// }
+//
+// if (changed)
+// {
+// if (sessions.size() == 0)
+// {
+// ssoValve.notifySSOEmpty(ssoId);
+// }
+//
+// putInTreeCache(fqn, sessions, true);
+// }
+// }
+// }
+// catch (Exception e)
+// {
+// try
+// {
+// if(doTx)
+// tm.setRollbackOnly();
+// }
+// catch (Exception ignored)
+// {
+// }
+// log.error("caught exception cleaning dead members from SSO " + ssoId, e);
+// }
+// finally
+// {
+// if (doTx)
+// endTransaction();
+// }
+// }
+// }
+
} // end TreeCacheSSOClusterManager
Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml 2006-10-01 14:22:21 UTC (rev 57325)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml 2006-10-01 15:30:51 UTC (rev 57326)
@@ -20,6 +20,19 @@
description="Should we attempt to reauthenticate each request against the security Realm?"
type="boolean"/>
+ <attribute name="maxEmptyLife"
+ description="The maximum number of seconds an SSO with no active sessions will be usable by a request"
+ type="int"/>
+
+ <attribute name="processExpiresInterval"
+ description="The maximum number of seconds an SSO with no active sessions will be usable by a request"
+ type="int"/>
+
+ <attribute name="lastProcessExpires"
+ writeable="false"
+ description="The timestamp of the start of the last check for overaged SSO's with no active sessions."
+ type="long"/>
+
<attribute name="clusterManager"
description="SSOClusterManager to use for cluster support"
type="org.jboss.web.tomcat.tc5.sso.SSOClusterManager"/>
More information about the jboss-cvs-commits
mailing list