[jboss-cvs] JBossAS SVN: r75571 - in branches/JBPAPP_4_2_0_GA-JBPAPP-947: testsuite and 5 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed Jul 9 21:53:54 EDT 2008
Author: bstansberry at jboss.com
Date: 2008-07-09 21:53:54 -0400 (Wed, 09 Jul 2008)
New Revision: 75571
Modified:
branches/JBPAPP_4_2_0_GA-JBPAPP-947/server/src/main/org/jboss/metadata/WebMetaData.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/build.xml
branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/imports/sections/cluster.xml
branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/DeployerConfig.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWeb.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWebMBean.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/TomcatDeployer.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java
branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/resources/webserver-xmbean.xml
Log:
[JBPAPP-947] Default maxUnreplicatedInterval to 60 secs; make configurable
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/server/src/main/org/jboss/metadata/WebMetaData.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/server/src/main/org/jboss/metadata/WebMetaData.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/server/src/main/org/jboss/metadata/WebMetaData.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -153,6 +153,10 @@
* for pojo replication or not.
*/
private boolean replicationFieldBatchMode = true;
+
+ /** By default replicate clustered session metadata at least every 60 seconds */
+ public static final int DEFAULT_MAX_UNREPLICATED_INTERVAL = 60;
+ private Integer maxUnreplicatedInterval = null;
/** Should the context use session cookies or use default */
private int sessionCookies = SESSION_COOKIES_DEFAULT;
@@ -758,6 +762,21 @@
return replicationFieldBatchMode;
}
+ public void setReplicationFieldBatchMode(boolean batchMode)
+ {
+ this.replicationFieldBatchMode = batchMode;
+ }
+
+ public Integer getMaxUnreplicatedInterval()
+ {
+ return maxUnreplicatedInterval;
+ }
+
+ public void setMaxUnreplicatedInterval(Integer maxUnreplicatedInterval)
+ {
+ this.maxUnreplicatedInterval = maxUnreplicatedInterval;
+ }
+
public void importXml(Element element) throws DeploymentException
{
String rootTag = element.getOwnerDocument().getDocumentElement().getTagName();
@@ -1220,7 +1239,7 @@
+ "' (should be ['SYNC', 'ASYNC']) in jboss-web.xml");
}
- // ... then manage "replication-type".
+ // ... then manage "replication-granularity".
//
Element replicationGranularityElement = MetaData.getOptionalChild(sessionReplicationRootElement, "replication-granularity");
if (replicationGranularityElement != null)
@@ -1243,6 +1262,21 @@
Boolean flag = Boolean.valueOf(MetaData.getElementContent(batchModeElement));
replicationFieldBatchMode = flag.booleanValue();
}
+
+ Element maxUnreplicatedIntervalElement = MetaData.getOptionalChild(sessionReplicationRootElement, "max-unreplicated-interval");
+ if (maxUnreplicatedIntervalElement != null)
+ {
+ String maxUnrep = MetaData.getElementContent(maxUnreplicatedIntervalElement);
+ try
+ {
+ maxUnreplicatedInterval = Integer.valueOf(maxUnrep);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new DeploymentException("max-unreplicated-interval value set to a non-integer value: '" + maxUnrep
+ + " in jboss-web.xml");
+ }
+ }
}
// Check for a war level class loading config
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/build.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/build.xml 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/build.xml 2008-07-10 01:53:54 UTC (rev 75571)
@@ -1125,6 +1125,7 @@
<antcall target="tests-clustering-unit">
<param name="cluster.includes.refid" value="cluster.http.includes"/>
<param name="jboss-junit-configuration" value="BuddyReplEnabled-${jboss-junit-configuration}"/>
+ <param name="jbosstest.cluster.web.cache.br" value="true"/>
<param name="jbosstest.cluster.node0.config" value="cluster-${jboss-junit-configuration}-BR-0"/>
<param name="jbosstest.cluster.node1.config" value="cluster-${jboss-junit-configuration}-BR-1"/>
</antcall>
@@ -2851,7 +2852,21 @@
<property name="jboss-junit-configuration" value="TCP"/>
<antcall target="one-cluster-test" inheritRefs="true"/>
</target>
+
+ <target name="one-cluster-test-nostart" if="test">
+ <property name="jboss-junit-configuration" value="UDP"/>
+
+ <echo message="Going to call target tests-clustering-unit for ${test}"/>
+
+ <antcall target="tests-clustering-unit">
+ <param name="cluster.includes.refid" value="one.test.includes"/>
+ <param name="jboss-junit-configuration" value="Default-${jboss-junit-configuration}"/>
+ <param name="jbosstest.cluster.node0.config" value="cluster-${jboss-junit-configuration}-0"/>
+ <param name="jbosstest.cluster.node1.config" value="cluster-${jboss-junit-configuration}-1"/>
+ </antcall>
+ </target>
+
<!-- Misc tests of the testing framework itself
-->
<target name="tests-apache" description="Test that apache can be started/stopped from ant">
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/imports/sections/cluster.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/imports/sections/cluster.xml 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/imports/sections/cluster.xml 2008-07-10 01:53:54 UTC (rev 75571)
@@ -43,7 +43,10 @@
<!-- build httpsessionreplication.jar -->
<war warfile="${build.lib}/http-sr.war"
- webxml="${build.resources}/cluster/http/web.xml">
+ webxml="${build.resources}/cluster/http/http-sr/WEB-INF/web.xml">
+ <webinf dir="${build.resources}/cluster/http/http-sr/WEB-INF">
+ <include name="jboss-web.xml"/>
+ </webinf>
<fileset dir="${build.resources}/cluster/http">
<include name="*.jsp"/>
</fileset>
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -22,8 +22,8 @@
package org.jboss.test.cluster.test;
import junit.framework.Test;
+
import org.apache.commons.httpclient.HttpClient;
-import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
import org.jboss.test.JBossClusteredTestCase;
/**
@@ -107,16 +107,6 @@
HttpClient client = new HttpClient();
makeGet(client, baseURL0_ +setURLName);
- // Create a session on server 1.
- HttpClient client1 = new HttpClient();
- makeGet(client1, baseURL1_ +setURLName);
-
- // Find out the session id and use it to build an FQN
- String sessionID = getSessionID(client1, servers_[1]);
- // Strip off the jvmRoute, if there is one
- sessionID = stripJvmRoute(sessionID);
- String sessionFqn = "/JSESSION/localhost/http-sr/" + sessionID;
-
sleepThread(6000);
// Set the server0 session to ensure replication occurs
@@ -125,7 +115,7 @@
attr = makeGetWithState(client, baseURL0_ +getURLName);
assertNotNull("Http session get", attr);
- // Sleep 15 secs. This plus the previous 18 secs is enough to expire
+ // Sleep 15 secs. This plus the previous 6 secs is enough to expire
// session0 on server1 if replication failed to keep it alive
sleepThread(15000);
@@ -146,32 +136,20 @@
attr = makeGetWithState(client, baseURL0_ +getURLName);
assertFalse("Original session not present", attr2.equals(attr));
- // sleep 45 more seconds so session 1 will expire on server0.
- // need a total of 70 secs -- 60 to expire and 10 to ensure the
- // bg thread runs. 20 secs to expire is not enough as the reduced
- // life of this session is not available to the manager w/o
- // deserializing the session
- sleepThread(45000);
-
- // Confirm 2nd session is gone from the distributed cache on node 0
- RMIAdaptor[] adaptors = getAdaptors();
- assertEquals("Session gone from distributed cache for " + sessionFqn,
- null,
- SessionTestUtil.getSessionVersion(adaptors[0], sessionFqn));
- assertEquals("Session gone from distributed cache for " + sessionFqn,
- null,
- SessionTestUtil.getBuddySessionVersion(adaptors[0], sessionFqn));
-
getLog().debug("Exit testSessionTimeout");
}
+ /**
+ * Tests that a request before maxUnreplicatedInterval has passed doesn't
+ * trigger replication.
+ */
public void testMaxUnreplicatedInterval()
{
getLog().debug("Enter testMaxUnreplicatedInterval");
String setURLName = "/http-sr/testsessionreplication.jsp";
String getURLName = "/http-sr/getattribute.jsp";
- String accessURLName = "/http-sr/access.jsp";
+ String versionURLName = "/http-sr/version.jsp";
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
@@ -181,18 +159,23 @@
// Get the Attribute set by testsessionreplication.jsp
String attr = makeGetWithState(client, baseURL0_ +getURLName);
- // Sleep 90% of the maxInactiveInterval
- sleepThread(18000);
+ // Sleep a bit, but less than the 16 sec maxUnreplicatedInterval
+ sleepThread(500);
// Access the session without touching any attribute
- makeGet(client, baseURL0_ +accessURLName);
+ String ver = makeGetWithState(client, baseURL0_ +versionURLName);
- // Sleep some more, long enough for the session to expire
- // if access didn't cause replication and for the bg thread to run
- sleepThread(17000);
+ // Sleep some more, long enough for the session to replicate
+ // if the last request incorrectly caused replication
+ sleepThread(2000);
// Switch servers
setCookieDomainToThisServer(client, servers_[1]);
+
+ String ver1 = makeGetWithState(client, baseURL1_ +versionURLName);
+
+ assertEquals("Session version count unchanged", ver, ver1);
+
// Get the Attribute set by testsessionreplication.jsp
String attr1 = makeGetWithState(client, baseURL1_ +getURLName);
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/DeployerConfig.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/DeployerConfig.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/DeployerConfig.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -108,6 +108,12 @@
* if it detects a failover.
*/
private boolean useJK = false;
+
+ /**
+ * Maximum interval a clustered session should allow request to not
+ * replicate the session timestamp.
+ */
+ private int maxUnreplicatedInterval;
/**
* Get the request attribute name under which the JAAS Subject is store
@@ -287,6 +293,16 @@
this.useJK = useJK;
}
+ public int getMaxUnreplicatedInterval()
+ {
+ return maxUnreplicatedInterval;
+ }
+
+ public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval)
+ {
+ this.maxUnreplicatedInterval = maxUnreplicatedInterval;
+ }
+
public String getSubjectAttributeName()
{
return subjectAttributeName;
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWeb.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWeb.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWeb.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -41,6 +41,7 @@
import org.apache.tomcat.util.modeler.Registry;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.deployment.SubDeployerExt;
+import org.jboss.metadata.WebMetaData;
import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.security.plugins.JaasSecurityManagerServiceMBean;
import org.jboss.system.ServiceControllerMBean;
@@ -130,6 +131,12 @@
* Whether we are using Apache MOD_JK(2) module or not
*/
private boolean useJK = false;
+
+ /**
+ * Maximum interval a clustered session should allow request to not
+ * replicate the session timestamp.
+ */
+ private int maxUnreplicatedInterval = WebMetaData.DEFAULT_MAX_UNREPLICATED_INTERVAL;
/**
* A flag indicating if the JBoss Loader should be used
@@ -301,8 +308,18 @@
public void setUseJK(boolean useJK)
{
this.useJK = useJK;
- }
+ }
+ public int getMaxUnreplicatedInterval()
+ {
+ return maxUnreplicatedInterval;
+ }
+
+ public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval)
+ {
+ this.maxUnreplicatedInterval = maxUnreplicatedInterval;
+ }
+
public boolean getDeleteWorkDirOnContextDestroy()
{
return deleteWorkDirOnContextDestroy;
@@ -647,6 +664,7 @@
config.setSnapshotMode(this.snapshotMode);
config.setUseLocalCache(this.useLocalCache);
config.setUseJK(this.useJK);
+ config.setMaxUnreplicatedInterval(this.maxUnreplicatedInterval);
config.setSubjectAttributeName(this.subjectAttributeName);
config.setUseJBossWebLoader(this.useJBossWebLoader);
config.setAllowSelfPrivilegedWebApps(this.allowSelfPrivilegedWebApps);
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWebMBean.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWebMBean.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/JBossWebMBean.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -124,6 +124,45 @@
public void setCacheName(String cacheName);
/**
+ * Get the maximum interval between requests, in seconds, after which a
+ * request will trigger replication of the session's metadata regardless
+ * of whether the request has otherwise made the session dirty. Such
+ * replication ensures that other nodes in the cluster are aware of a
+ * relatively recent value for the session's timestamp and won't incorrectly
+ * expire an unreplicated session upon failover.
+ * <p/>
+ * Default value is {@link #DEFAULT_MAX_UNREPLICATED_INTERVAL}.
+ * <p/>
+ * The cost of the metadata replication depends on the configured
+ * {@link #setReplicationGranularityString(String) replication granularity}.
+ * With <code>SESSION</code>, the sesssion's attribute map is replicated
+ * along with the metadata, so it can be fairly costly. With other
+ * granularities, the metadata object is replicated separately from the
+ * attributes and only contains a String, and a few longs, ints and booleans.
+ *
+ * @return the maximum interval since last replication after which a request
+ * will trigger session metadata replication. A value of
+ * <code>0</code> means replicate metadata on every request; a value
+ * of <code>-1</code> means never replicate metadata unless the
+ * session is otherwise dirty.
+ */
+ public int getMaxUnreplicatedInterval();
+
+ /**
+ * Sets the maximum interval between requests, in seconds, after which a
+ * request will trigger replication of the session's metadata regardless
+ * of whether the request has otherwise made the session dirty.
+ *
+ * @param maxUnreplicatedInterval
+ * the maximum interval since last replication after which a request
+ * will trigger session metadata replication. A value of
+ * <code>0</code> means replicate metadata on every request; a value
+ * of <code>-1</code> means never replicate metadata unless the
+ * session is otherwise dirty.
+ */
+ public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval);
+
+ /**
* Get the JBoss UCL use flag
*/
public boolean getUseJBossWebLoader();
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/TomcatDeployer.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/TomcatDeployer.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/TomcatDeployer.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -332,6 +332,13 @@
jbcm.setSnapshotInterval(snapshotInterval);
}
+ // JBAS-5706 -- use the DeployerConfig value as a default for
+ // WebMetaData.maxUnreplicatedInterval
+ if (metaData.getMaxUnreplicatedInterval() == null)
+ {
+ metaData.setMaxUnreplicatedInterval(new Integer(config.getMaxUnreplicatedInterval()));
+ }
+
String name = "//" + ((hostName == null) ? "localhost" : hostName) + ctxPath;
manager.init(name, metaData, config.isUseJK(), config.isUseLocalCache());
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -91,7 +91,13 @@
// situation, this will cause data gravitation, which will occur
// thus outside of the scope of the tx we are about to start.
// JBossCacheManager will ensure the gravitation is in its own tx
- request.getSession(false);
+ String requestedId = request.getRequestedSessionId();
+ if (requestedId != null)
+ {
+ // Use the manager directly so we don't invoke access() on a session
+ // that the request otherwise doesn't use
+ manager_.findSession(requestedId);
+ }
// Start a new transaction, we need transaction so all the replication are sent in batch.
try
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -151,10 +151,7 @@
protected transient long lastReplicated;
/**
- * Maximum percentage of the inactive interval this session
- * should be allowed to go unreplicated if access to the
- * session doesn't mark it as dirty. Drives the calculation
- * of maxUnreplicatedInterval.
+ * @deprecated Not used
*/
protected transient int maxUnreplicatedFactor = 80;
@@ -163,8 +160,11 @@
* should be allowed to go unreplicated if access to the
* session doesn't mark it as dirty.
*/
- protected transient long maxUnreplicatedInterval;
+ protected transient long maxUnreplicatedInterval = 0;
+ /** True if maxUnreplicatedInterval is 0 or less than maxInactiveInterval */
+ protected transient boolean alwaysReplicateMetadata = true;
+
/**
* Whether any of this session's attributes implement
* HttpSessionActivationListener.
@@ -200,7 +200,7 @@
invalidationPolicy = manager.getInvalidateSessionPolicy();
this.useJK = useJK;
this.firstAccess = true;
- calcMaxUnreplicatedInterval();
+ checkAlwaysReplicateMetadata();
}
/**
@@ -342,40 +342,18 @@
}
/**
- * Gets the maximum percentage of the <code>maxInactiveInterval</code>
- * beyond which a session should be replicated upon access even if it
- * isn't dirty. Used to ensure that even a read-only session gets
- * replicated before it expires, so that it isn't removed from other
- * nodes.
- *
- * @return an int between 1 and 100, or -1 if replicating on access is
- * disabled
+ * @deprecated Returns a meaningless value; use {@link #setMaxUnreplicatedInterval(int)}
*/
public int getMaxUnreplicatedFactor()
{
- return maxUnreplicatedFactor;
+ return 80;
}
/**
- * Sets the maximum percentage of the <code>maxInactiveInterval</code>
- * beyond which a session should be replicated upon access even if it
- * isn't dirty. Used to ensure that even a read-only session gets
- * replicated before it expires, so that it isn't removed from other
- * nodes.
- *
- * @param maxUnreplicatedFactor an int between 1 and 100, or -1 to
- * disable replicating on access
- *
- * @throws IllegalArgumentException if the factor isn't -1 or between
- * 1 and 100
+ * @deprecated Ignored; use {@link #setMaxUnreplicatedInterval(int)}
*/
public void setMaxUnreplicatedFactor(int factor)
- {
- if ((factor != -1 && factor < 1) || factor > 100)
- throw new IllegalArgumentException("Invalid factor " + factor +
- " -- must be between 1 and 100 or -1");
- this.maxUnreplicatedFactor = factor;
- calcMaxUnreplicatedInterval();
+ {
}
@@ -386,7 +364,7 @@
public void setMaxInactiveInterval(int interval)
{
super.setMaxInactiveInterval(interval);
- calcMaxUnreplicatedInterval();
+ checkAlwaysReplicateMetadata();
sessionMetadataDirty();
}
@@ -408,32 +386,74 @@
lastReplicated = System.currentTimeMillis();
}
+ /**
+ * Get the maximum interval between requests, in <strong>milliseconds</strong>,
+ * after which a request will trigger replication of the session's metadata
+ * regardless of whether the request has otherwise made the session dirty.
+ * <p/>
+ * <strong>NOTE:</strong> This value is in milliseconds while the equivalent
+ * property in JBossCacheManager is in seconds.
+ *
+ * @return the maximum interval since last replication after which a request
+ * will trigger session metadata replication. A value of
+ * <code>0</code> means replicate metadata on every request; a value
+ * of <code>-1</code> means never replicate metadata unless the
+ * session is otherwise dirty.
+ */
public long getMaxUnreplicatedInterval()
{
return maxUnreplicatedInterval;
}
+
+ /**
+ * Sets the maximum interval between requests, in <strong>milliseconds</strong>,
+ * after which a request will trigger replication of the session's metadata
+ * regardless of whether the request has otherwise made the session dirty.
+ * <p/>
+ * <strong>NOTE:</strong> This value is in milliseconds while the equivalent
+ * property in JBossCacheManager is in seconds.
+ *
+ * @param maxUnreplicatedInterval
+ * the maximum interval since last replication after which a request
+ * will trigger session metadata replication. A value of
+ * <code>0</code> means replicate metadata on every request; a value
+ * of <code>-1</code> means never replicate metadata unless the
+ * session is otherwise dirty. A value less than <code>-1</code> is
+ * treated as <code>-1</code>.
+ */
+ public void setMaxUnreplicatedInterval(long interval)
+ {
+ this.maxUnreplicatedInterval = Math.max(interval, -1);
+ checkAlwaysReplicateMetadata();
+ }
public boolean getExceedsMaxUnreplicatedInterval()
{
- boolean result = false;
+ boolean exceeds = alwaysReplicateMetadata;
- if (maxUnreplicatedInterval > 0) // -1 means ignore; 0 means expire now
+ if (!exceeds && maxUnreplicatedInterval > 0) // -1 means ignore
{
- result = ((System.currentTimeMillis() - lastReplicated) >= maxUnreplicatedInterval);
+ long unrepl = System.currentTimeMillis() - lastReplicated;
+ exceeds = (unrepl >= maxUnreplicatedInterval);
}
- return result;
+ return exceeds;
}
- private void calcMaxUnreplicatedInterval()
+ private void checkAlwaysReplicateMetadata()
{
- if (maxInactiveInterval < 0 || maxUnreplicatedFactor < 0)
- maxUnreplicatedInterval = -1;
- else
+ boolean was = this.alwaysReplicateMetadata;
+ this.alwaysReplicateMetadata =
+ (maxUnreplicatedInterval == 0
+ || (maxUnreplicatedInterval > 0 && maxInactiveInterval >= 0
+ && maxUnreplicatedInterval > (maxInactiveInterval * 1000)));
+
+ if (this.alwaysReplicateMetadata && !was && log.isTraceEnabled())
{
- // Ignoring casting would be (mII * 1000) * (mUF / 100)
- maxUnreplicatedInterval = maxInactiveInterval * maxUnreplicatedFactor * 10;
- }
+ log.trace(id + " will always replicate metadata; maxUnreplicatedInterval="
+ + maxUnreplicatedInterval
+ + ", maxInactiveInterval=" + maxInactiveInterval);
+ }
}
/**
@@ -1012,8 +1032,8 @@
version = 0;
hasActivationListener = null;
lastReplicated = 0;
- maxUnreplicatedFactor = 80;
- calcMaxUnreplicatedInterval();
+ maxUnreplicatedInterval = 0;
+ this.alwaysReplicateMetadata = true;
}
/**
@@ -1132,6 +1152,12 @@
// access cannot be the first.
this.firstAccess = false;
+ // Assume deserialization means replication and use thisAccessedTime
+ // as a proxy for when replication occurred
+ this.lastReplicated = this.thisAccessedTime;
+
+ checkAlwaysReplicateMetadata();
+
// TODO uncomment when work on JBAS-1900 is completed
// // Session notes -- for FORM auth apps, allow replicated session
// // to be used without requiring a new login
@@ -1426,7 +1452,8 @@
public boolean getReplicateSessionBody()
{
- return sessionMetadataDirty || getExceedsMaxUnreplicatedInterval();
+ return sessionMetadataDirty || getExceedsMaxUnreplicatedInterval()
+ || (maxUnreplicatedInterval == -1 && sessionAttributesDirty);
}
protected boolean isGetDirty(Object attribute)
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -51,13 +51,15 @@
// Valve-lifecycle_ helper object
protected LifecycleSupport support = new LifecycleSupport(this);
+
+ protected Manager manager;
/**
* Create a new Valve.
*/
- public ClusteredSessionValve()
+ public ClusteredSessionValve(Manager manager)
{
- super();
+ this.manager = manager;
}
/**
@@ -83,6 +85,14 @@
SessionReplicationContext.enterWebapp(request, response, true);
try
{
+ // Workaround to JBAS-5735. Ensure we get the session from the manager
+ // rather than a cached ref from the Request.
+ String requestedId = request.getRequestedSessionId();
+ if (requestedId != null)
+ {
+ manager.findSession(requestedId);
+ }
+
// let the servlet invocation go through
getNext().invoke(request, response);
}
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -45,6 +45,8 @@
public JBossCacheClusteredSession(JBossCacheManager manager)
{
super(manager, manager.getUseJK());
+ int maxUnrep = manager.getMaxUnreplicatedInterval() * 1000;
+ setMaxUnreplicatedInterval(maxUnrep);
establishProxy();
}
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -45,6 +45,7 @@
import org.apache.catalina.Valve;
import org.apache.catalina.core.ContainerBase;
import org.jboss.cache.CacheException;
+import org.jboss.cache.aop.PojoCacheMBean;
import org.jboss.metadata.WebMetaData;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.web.tomcat.service.JBossWeb;
@@ -130,6 +131,8 @@
* Whether we are doing trace level logging
*/
private boolean trace;
+
+ private int maxUnreplicatedInterval_ = WebMetaData.DEFAULT_MAX_UNREPLICATED_INTERVAL;
// ---------------------------------------------------------- Constructors
@@ -137,6 +140,17 @@
{
super();
}
+
+ /**
+ * Create a new JBossCacheManager using the given cache. For use in unit testing.
+ *
+ * @param pojoCache
+ */
+ public JBossCacheManager(PojoCacheMBean pojoCache)
+ {
+ super();
+ this.proxy_ = new JBossCacheService(pojoCache);
+ }
/**
* Initializes this Manager when running in embedded mode.
@@ -154,7 +168,14 @@
this.replicationFieldBatchMode_ =
webMetaData.getReplicationFieldBatchMode() ? Boolean.TRUE : Boolean.FALSE;
- proxy_ = new JBossCacheService(cacheObjectNameString_);
+ Integer maxUnrep = webMetaData.getMaxUnreplicatedInterval();
+ if (maxUnrep != null)
+ {
+ this.maxUnreplicatedInterval_ = maxUnrep.intValue();
+ }
+
+ if (proxy_ == null)
+ proxy_ = new JBossCacheService(cacheObjectNameString_);
// Confirm our replication granularity is compatible with the cache
// Throws ISE if not
@@ -377,6 +398,16 @@
{
this.useLocalCache_ = useLocalCache;
}
+
+ public int getMaxUnreplicatedInterval()
+ {
+ return maxUnreplicatedInterval_;
+ }
+
+ public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval)
+ {
+ this.maxUnreplicatedInterval_ = maxUnreplicatedInterval;
+ }
// JBossCacheManagerMBean-methods -------------------------------------
@@ -1019,7 +1050,7 @@
}
catch (Exception exn)
{
- exn.printStackTrace();
+ log_.error("Problem rolling back session mgmt transaction", exn);
}
// We will need to alert Tomcat of this exception.
@@ -1248,12 +1279,18 @@
long now = System.currentTimeMillis();
Map unloaded = new HashMap(unloadedSessions_);
Set entries = unloaded.entrySet();
+ // We may have not gotten replication of a timestamp for requests
+ // that occurred w/in maxUnreplicatedInterval_ of the previous
+ // request. So we add a grace period to avoid flushing a session early
+ // and permanently losing part of its node structure in JBoss Cache.
+ long maxUnrep = maxUnreplicatedInterval_ < 0 ? 60 : maxUnreplicatedInterval_;
+ long maxUnused = maxInactiveInterval_ + maxUnrep;
for (Iterator it = entries.iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
OwnedSessionUpdate osu = (OwnedSessionUpdate) entry.getValue();
int elapsed = (int) ((now - osu.updateTime) / 1000L);
- if (elapsed >= maxInactiveInterval_)
+ if (elapsed >= maxUnused)
{
String realId = (String) entry.getKey();
try
@@ -1699,7 +1736,7 @@
}
// Add clustered session valve
- ClusteredSessionValve valve = new ClusteredSessionValve();
+ ClusteredSessionValve valve = new ClusteredSessionValve(this);
installContextValve(valve);
}
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -109,6 +109,45 @@
* is used.
*/
int getSnapshotInterval();
+
+ /**
+ * Get the maximum interval between requests, in seconds, after which a
+ * request will trigger replication of the session's metadata regardless
+ * of whether the request has otherwise made the session dirty. Such
+ * replication ensures that other nodes in the cluster are aware of a
+ * relatively recent value for the session's timestamp and won't incorrectly
+ * expire an unreplicated session upon failover.
+ * <p/>
+ * Default value is {@link #DEFAULT_MAX_UNREPLICATED_INTERVAL}.
+ * <p/>
+ * The cost of the metadata replication depends on the configured
+ * {@link #setReplicationGranularityString(String) replication granularity}.
+ * With <code>SESSION</code>, the sesssion's attribute map is replicated
+ * along with the metadata, so it can be fairly costly. With other
+ * granularities, the metadata object is replicated separately from the
+ * attributes and only contains a String, and a few longs, ints and booleans.
+ *
+ * @return the maximum interval since last replication after which a request
+ * will trigger session metadata replication. A value of
+ * <code>0</code> means replicate metadata on every request; a value
+ * of <code>-1</code> means never replicate metadata unless the
+ * session is otherwise dirty.
+ */
+ public int getMaxUnreplicatedInterval();
+
+ /**
+ * Sets the maximum interval between requests, in seconds, after which a
+ * request will trigger replication of the session's metadata regardless
+ * of whether the request has otherwise made the session dirty.
+ *
+ * @param maxUnreplicatedInterval
+ * the maximum interval since last replication after which a request
+ * will trigger session metadata replication. A value of
+ * <code>0</code> means replicate metadata on every request; a value
+ * of <code>-1</code> means never replicate metadata unless the
+ * session is otherwise dirty.
+ */
+ public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval);
/**
* Lists all session ids known to this manager, including those in the
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java 2008-07-10 01:53:54 UTC (rev 75571)
@@ -71,11 +71,10 @@
public static final String SESSION = "JSESSION";
public static final String ATTRIBUTE = "ATTRIBUTE";
// Needed for cache invalidation
- static final String VERSION_KEY = "VERSION";
+ public static final String VERSION_KEY = "VERSION";
static final String FQN_DELIMITER = "/";
private PojoCacheMBean proxy_;
- private ObjectName cacheServiceName_;
// name of webapp's virtual host(JBAS-2194).
// Idea is host_name + web_app_path + session id is a unique combo.
@@ -95,39 +94,46 @@
private WeakHashMap typeMap = new WeakHashMap();
- public JBossCacheService(String treeCacheObjectName) throws ClusteringNotSupportedException
+ /**
+ * Creates a JMX proxy PojoCacheMBean for the given object name.
+ *
+ * @param objectName the object name
+ * @return the proxy
+ * @throws ClusteringNotSupportedException if there is a problem
+ */
+ private static PojoCacheMBean getPojoCacheMBean(String objectName)
+ throws ClusteringNotSupportedException
{
- // Find JBossCacheService
try
{
- cacheServiceName_ = new ObjectName(treeCacheObjectName);
+ ObjectName cacheServiceName = new ObjectName(objectName);
// Create Proxy-Object for this service
- proxy_ = (PojoCacheMBean) MBeanProxyExt.create(PojoCacheMBean.class,
- cacheServiceName_);
+ return (PojoCacheMBean) MBeanProxyExt.create(PojoCacheMBean.class,
+ cacheServiceName);
}
catch (Throwable t)
{
-
String str = "Could not access TreeCache service " +
- (cacheServiceName_ == null ? "<null>" : cacheServiceName_.toString()) +
+ (objectName == null ? "<null>" : objectName) +
" for Tomcat clustering";
log_.debug(str);
throw new ClusteringNotSupportedException(str, t);
- }
-
- if (proxy_ == null)
- {
- String str = "Could not access TreeCache service " +
- (cacheServiceName_ == null ? "<null>" : cacheServiceName_.toString()) +
- " for Tomcat clustering";
- log_.debug(str);
- throw new ClusteringNotSupportedException(str);
- }
+ }
+ }
+
+ public JBossCacheService(PojoCacheMBean pojoCache)
+ {
+ this.proxy_ = pojoCache;
cacheWrapper_ = new JBossCacheWrapper(proxy_);
useTreeCacheMarshalling_ = proxy_.getUseRegionBasedMarshalling();
}
+
+ public JBossCacheService(String treeCacheObjectName) throws ClusteringNotSupportedException
+ {
+ this(getPojoCacheMBean(treeCacheObjectName));
+ }
public void start(ClassLoader tcl, JBossCacheManager manager)
{
@@ -280,7 +286,7 @@
}
catch (Exception e)
{
- log_.error("loadSession(): id: " + realId + "exception occurred during serialization: " +e);
+ log_.error("loadSession(): id: " + realId + " exception occurred during deserialization", e);
return null;
}
finally {
Modified: branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/resources/webserver-xmbean.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/resources/webserver-xmbean.xml 2008-07-10 00:04:56 UTC (rev 75570)
+++ branches/JBPAPP_4_2_0_GA-JBPAPP-947/tomcat/src/resources/webserver-xmbean.xml 2008-07-10 01:53:54 UTC (rev 75571)
@@ -87,6 +87,11 @@
<type>boolean</type>
</attribute>
+ <attribute access="read-write" getMethod="getMaxUnreplicatedInterval" setMethod="setMaxUnreplicatedInterval">
+ <name>MaxUnreplicatedInterval</name>
+ <type>int</type>
+ </attribute>
+
<attribute access="read-write" getMethod="getDomain" setMethod="setDomain">
<name>Domain</name>
<type>java.lang.String</type>
More information about the jboss-cvs-commits
mailing list