[jboss-cvs] JBossAS SVN: r106467 - in branches/Session_Ownership: cluster and 6 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Jul 6 14:57:13 EDT 2010
Author: bstansberry at jboss.com
Date: 2010-07-06 14:57:12 -0400 (Tue, 06 Jul 2010)
New Revision: 106467
Removed:
branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheCluster.java
branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheClusterMBean.java
Modified:
branches/Session_Ownership/build/build.xml
branches/Session_Ownership/cluster/pom.xml
branches/Session_Ownership/component-matrix/pom.xml
branches/Session_Ownership/testsuite/build.xml
branches/Session_Ownership/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java
branches/Session_Ownership/tomcat/pom.xml
branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java
branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheManager.java
branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/persistent/PersistentStoreDistributedCacheManager.java
Log:
[JBAS-7844][JBAS-7852] Distributed locking, session ownership and failover detection
Modified: branches/Session_Ownership/build/build.xml
===================================================================
--- branches/Session_Ownership/build/build.xml 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/build/build.xml 2010-07-06 18:57:12 UTC (rev 106467)
@@ -2211,7 +2211,7 @@
<mkdir dir="${install.all.lib}"/>
<copy todir="${install.all.lib}" filtering="no">
<fileset refid="jacorb:jacorb:jar"/>
- <fileset refid="jgroups:jgroups:jar"/>
+ <fileset refid="org.jgroups:jgroups:jar"/>
<fileset refid="net.jcip:jcip-annotations:jar"/>
<fileset refid="org.hibernate:hibernate-jbosscache:jar"/>
<fileset refid="org.jboss.cache:jbosscache-core:jar"/>
Modified: branches/Session_Ownership/cluster/pom.xml
===================================================================
--- branches/Session_Ownership/cluster/pom.xml 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/cluster/pom.xml 2010-07-06 18:57:12 UTC (rev 106467)
@@ -157,7 +157,7 @@
</dependency>
<dependency>
- <groupId>jgroups</groupId>
+ <groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
</dependency>
Modified: branches/Session_Ownership/component-matrix/pom.xml
===================================================================
--- branches/Session_Ownership/component-matrix/pom.xml 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/component-matrix/pom.xml 2010-07-06 18:57:12 UTC (rev 106467)
@@ -78,7 +78,7 @@
<version.jboss.osgi.webconsole>1.0.3</version.jboss.osgi.webconsole>
<version.jboss.osgi.xml.binding>2.0.2.Beta4.SP1</version.jboss.osgi.xml.binding>
<version.jboss.web>3.0.0-beta-6</version.jboss.web>
- <version.jgroups>2.10.0.Beta2</version.jgroups>
+ <version.jgroups>2.10.0.CR1</version.jgroups>
<version.jsr181.api>1.0-MR1</version.jsr181.api>
<version.junit>4.6</version.junit>
<version.ops4j.pax.web>0.7.2</version.ops4j.pax.web>
@@ -97,11 +97,11 @@
<version.org.jboss.cache.pojo>3.0.0.GA</version.org.jboss.cache.pojo>
<version.org.jboss.cl>2.2.0.Alpha7</version.org.jboss.cl>
<version.org.jboss.classpool>1.0.0.Alpha6</version.org.jboss.classpool>
- <version.org.jboss.cluster.cache.jbc>2.4.0.Alpha2</version.org.jboss.cluster.cache.jbc>
- <version.org.jboss.cluster.cache.spi>2.2.0.Final</version.org.jboss.cluster.cache.spi>
+ <version.org.jboss.cluster.cache.jbc>0.0.1-SNAPSHOT</version.org.jboss.cluster.cache.jbc>
+ <version.org.jboss.cluster.cache.spi>0.0.1-SNAPSHOT</version.org.jboss.cluster.cache.spi>
<version.org.jboss.cluster.client>1.1.1.GA</version.org.jboss.cluster.client>
- <version.org.jboss.cluster.server.api>2.0.0.Alpha5</version.org.jboss.cluster.server.api>
- <version.org.jboss.cluster.server.core>1.0.0.Alpha2</version.org.jboss.cluster.server.core>
+ <version.org.jboss.cluster.server.api>0.0.1-SNAPSHOT</version.org.jboss.cluster.server.api>
+ <version.org.jboss.cluster.server.core>1.0.0-SNAPSHOT</version.org.jboss.cluster.server.core>
<version.org.jboss.common.core>2.2.17.GA</version.org.jboss.common.core>
<version.org.jboss.deployers>2.2.0.Alpha6</version.org.jboss.deployers>
<version.org.jboss.ejb3.bom>0.2.0-alpha-2</version.org.jboss.ejb3.bom>
@@ -1588,7 +1588,7 @@
</dependency>
<dependency>
- <groupId>jgroups</groupId>
+ <groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
<version>${version.jgroups}</version>
</dependency>
Modified: branches/Session_Ownership/testsuite/build.xml
===================================================================
--- branches/Session_Ownership/testsuite/build.xml 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/testsuite/build.xml 2010-07-06 18:57:12 UTC (rev 106467)
@@ -233,7 +233,7 @@
<fileset refid="javax.inject:javax.inject:jar"/>
<fileset refid="org.jboss.cache:jbosscache-core:jar"/>
<fileset refid="org.jboss.cache:jbosscache-pojo:jar"/>
- <fileset refid="jgroups:jgroups:jar"/>
+ <fileset refid="org.jgroups:jgroups:jar"/>
<fileset refid="joesnmp:joesnmp:jar"/>
<fileset refid="junit:junit:jar"/>
<fileset refid="org.easymock:easymock:jar"/>
@@ -1163,9 +1163,9 @@
<exclude name="org/jboss/test/classloader/leak/test/AopPreparedClassesClassloaderLeakUnitTestCase.class" if="sun-vm"/>
<exclude name="org/jboss/test/cluster/classloader/leak/test/*Field*TestCase.class" if="sun-vm"/>
- <!-- The FarmedClusterHugeDeploymentUnitTestCase will fail on slaves with inadequate network buffers
+ <!-- The FarmedClusterHugeDeploymentUnitTestCase will fail on slaves with inadequate network buffers -->
<exclude name="org/jboss/test/cluster/defaultcfg/profileservice/test/FarmedClusterHugeDeploymentUnitTestCase.class"/>
- -->
+
<!-- JBAS-7569 -->
<exclude name="org/jboss/test/console/jbas3861/JBAS3861UnitTestCase.class"/>
Modified: branches/Session_Ownership/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java
===================================================================
--- branches/Session_Ownership/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java 2010-07-06 18:57:12 UTC (rev 106467)
@@ -26,10 +26,12 @@
import java.util.Map;
import java.util.Set;
+import org.jboss.ha.framework.server.lock.TimeoutException;
import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager.LockResult;
/**
* @author Brian Stansberry
@@ -166,6 +168,21 @@
{
// no-op
}
+
+ public boolean getSupportsSessionOwnership()
+ {
+ return false;
+ }
+
+ public DistributedCacheManager.LockResult acquireSessionOwnership(String realId, boolean newLock) throws TimeoutException, InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void relinquishSessionOwnership(String realId, boolean remove)
+ {
+ // no-op
+ }
private static class MockBatchingManager implements BatchingManager
{
Modified: branches/Session_Ownership/tomcat/pom.xml
===================================================================
--- branches/Session_Ownership/tomcat/pom.xml 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/tomcat/pom.xml 2010-07-06 18:57:12 UTC (rev 106467)
@@ -217,7 +217,7 @@
<artifactId>jasper-jdt</artifactId>
</dependency>
<dependency>
- <groupId>jgroups</groupId>
+ <groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
</dependency>
<dependency>
Modified: branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java
===================================================================
--- branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java 2010-07-06 18:57:12 UTC (rev 106467)
@@ -40,6 +40,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
@@ -61,12 +63,14 @@
import org.apache.catalina.session.StandardSessionFacade;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.StringManager;
+import org.jboss.ha.framework.server.lock.TimeoutException;
import org.jboss.logging.Logger;
import org.jboss.metadata.web.jboss.ReplicationTrigger;
import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager.LockResult;
import org.jboss.web.tomcat.service.session.notification.ClusteredSessionManagementStatus;
import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationCause;
import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationPolicy;
@@ -385,6 +389,9 @@
/** End of period when we do full replication */
private transient long fullReplicationWindow = -1;
+ /** Coordinate updates from the cluster */
+ private transient ReentrantLock ownershipLock = new ReentrantLock();
+
// ------------------------------------------------------------ Constructors
/**
@@ -558,6 +565,12 @@
public void access()
{
+ boolean canOwn = this.distributedCacheManager.getSupportsSessionOwnership();
+ if (canOwn)
+ {
+ acquireSessionOwnership();
+ }
+
this.lastAccessedTime = this.thisAccessedTime;
this.thisAccessedTime = System.currentTimeMillis();
@@ -575,6 +588,8 @@
public void endAccess()
{
+ try
+ {
isNew = false;
if (ACTIVITY_CHECK) {
@@ -591,6 +606,14 @@
// So, we fix that
isNew = true;
}
+ }
+ finally
+ {
+ if (this.distributedCacheManager.getSupportsSessionOwnership())
+ {
+ this.distributedCacheManager.relinquishSessionOwnership(getRealId(), false);
+ }
+ }
}
public boolean isNew()
@@ -640,7 +663,7 @@
*/
public void invalidate()
{
- if (!isValid())
+ if (!isValid(true))
throw new IllegalStateException(sm.getString("clusteredSession.invalidate.ise"));
// Cause this session to expire globally
@@ -658,22 +681,6 @@
expire(notify, localCall, localOnly, ClusteredSessionNotificationCause.INVALIDATE);
}
- /**
- * Expires the session, but in such a way that other cluster nodes
- * are unaware of the expiration.
- *
- * @param notify true if notifications should be to sent to registered listeners;
- * false otherwise
- *
- * @deprecated Will be removed in AS 6
- */
- public void expire(boolean notify)
- {
- boolean localCall = true;
- boolean localOnly = true;
- expire(notify, localCall, localOnly, ClusteredSessionNotificationCause.TIMEOUT);
- }
-
public void recycle()
{
if (!isValid)
@@ -824,7 +831,7 @@
public Object getAttribute(String name)
{
- if (!isValid())
+ if (!isValid(true))
throw new IllegalStateException
(sm.getString("clusteredSession.getAttribute.ise"));
@@ -834,7 +841,7 @@
@SuppressWarnings("unchecked")
public Enumeration<String> getAttributeNames()
{
- if (!isValid())
+ if (!isValid(true))
throw new IllegalStateException
(sm.getString("clusteredSession.getAttributeNames.ise"));
@@ -1365,6 +1372,43 @@
}
+ private void acquireSessionOwnership()
+ {
+ boolean locked = false;
+ try
+ {
+ ownershipLock.lockInterruptibly();
+ locked = true;
+ LockResult res = this.distributedCacheManager.acquireSessionOwnership(getRealId(), needNewLock());
+ if (res == LockResult.ACQUIRED_FROM_CLUSTER)
+ {
+ // We may be out of date re: the distributed cache
+ update(this.distributedCacheManager.getSessionData(getRealId(), false));
+ }
+ }
+ catch (TimeoutException e)
+ {
+ throw new RuntimeException("Caught " + e.getClass().getSimpleName() + " acquiring ownership of " + getRealId(), e);
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("Interrupted acquiring ownership of " + getRealId(), e);
+ }
+ finally
+ {
+ if (locked)
+ {
+ ownershipLock.unlock();
+ }
+ }
+ }
+
+ private boolean needNewLock()
+ {
+ return firstAccess && isNew;
+ }
+
/**
* Expires the session, notifying listeners and possibly the manager.
* <p>
@@ -1416,8 +1460,15 @@
// SRV.10.6 (2.5) 11.6 (3.0) Propagate listener exceptions
RuntimeException listenerException = null;
+ boolean acquiredLock = false;
try
{
+ if (localCall)
+ {
+ acquireSessionOwnership();
+ acquiredLock = true;
+ }
+
// Notify interested application event listeners
// FIXME - Assumes we call listeners in reverse order
Context context = (Context) manager.getContainer();
@@ -1516,7 +1567,11 @@
{
// We have completed expire of this session
setValid(false);
- expiring = false;
+ expiring = false;
+ if (acquiredLock)
+ {
+ this.distributedCacheManager.relinquishSessionOwnership(getRealId(), true);
+ }
}
}
}
@@ -1997,7 +2052,7 @@
*/
public boolean isValidInternal()
{
- return (this.isValid || this.expiring);
+ return (this.isValid || this.expiring);
}
/**
Deleted: branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheCluster.java
===================================================================
--- branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheCluster.java 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheCluster.java 2010-07-06 18:57:12 UTC (rev 106467)
@@ -1,861 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.web.tomcat.service.session;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URL;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.apache.catalina.Container;
-import org.apache.catalina.Engine;
-import org.apache.catalina.Host;
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.Manager;
-import org.apache.catalina.core.ContainerBase;
-import org.apache.catalina.util.LifecycleSupport;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.tomcat.util.modeler.Registry;
-import org.jboss.metadata.web.jboss.ReplicationGranularity;
-import org.jboss.metadata.web.jboss.ReplicationTrigger;
-import org.jboss.metadata.web.jboss.SnapshotMode;
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManagerFactoryFactory;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.TomcatClusterConfig;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.TomcatClusterDistributedCacheManagerFactory;
-
-/**
- * A Tomcat <code>Cluster</code> implementation that uses a JBoss
- * <code>TreeCache</code> to support intra-cluster session replication.
- * <p>
- * This class registers a <code>TreeCache</code> in JMX, making it
- * available to other users who wish to replicate data within the cluster.
- * </p>
- *
- * @author Brian Stansberry
- * @version $Revision$
- */
-public class JBossCacheCluster
- implements TomcatClusterConfig, JBossCacheClusterMBean, Lifecycle
-{
- // ------------------------------------------------------- Static Fields
-
- protected static final String info = "JBossCacheCluster/2.1";
-
- public static Log log = LogFactory.getLog(JBossCacheCluster.class);
-
- public static final String DEFAULT_CACHE_CONFIG_PATH = "conf/cluster-cache.xml";
-
- // ------------------------------------------------------- Instance Fields
-
- /** Parent container of this cluster. */
- private Container container = null;
-
- /** Our JMX Server. */
- private MBeanServer mserver = null;
-
- /** Name under which we are registered in JMX */
- private ObjectName objectName = null;
-
- /** The factory we use to create our DistributedCacheManager */
- private TomcatClusterDistributedCacheManagerFactory factory = null;
-
- /** Are we started? */
- private boolean started = false;
-
- /** The lifecycle event support for this component. */
- private LifecycleSupport lifecycle = new LifecycleSupport(this);
-
- /** Name under which our TreeCache is registered in JMX */
- private String pojoCacheObjectName = "jboss.cache:service=TomcatClusteringCache";
-
- /** Name of the tree cache's JGroups channel */
- private String clusterName = null;
-
- /** File name, URL or String to use to configure JGroups. */
- private String cacheConfigPath = null;
-
- /**
- * Implementation of Manager to instantiate when
- * createManager() is called.
- */
- private String managerClassName = JBossCacheManager.class.getName();
-
- /** Does the Engine in which we are running use mod_jk? */
- private boolean useJK = false;
-
- /** Whether our Managers should use a local cache. */
- private boolean useLocalCache = false;
-
- /**
- * Default replication trigger to assign to our
- * Managers that haven't had this property set.
- */
- private ReplicationTrigger defaultReplicationTrigger = null;
-
- /**
- * Default replication granularity to assign to our Managers
- * that haven't had this property set.
- */
- private ReplicationGranularity defaultReplicationGranularity = null;
-
- /**
- * JBossCacheManager's snapshot mode.
- */
- private SnapshotMode snapshotMode = null;
-
- /**
- * JBossCacheManager's snapshot interval.
- */
- private int snapshotInterval = 0;
-
- /** Whether we use batch mode replication for field level granularity */
- private boolean replicationFieldBatchMode = true;
-
- // ---------------------------------------------------------- Constructors
-
- /**
- * Default constructor.
- */
- public JBossCacheCluster()
- {
- super();
- }
-
- // ------------------------------------------------------------ Properties
-
- /**
- * Gets a String representation of the JMX <code>ObjectName</code> under
- * which our <code>TreeCache</code> is registered.
- * <p>
- * If this property is not explicitly set, the <code>TreeCache</code> will
- * be registered under
- * @{@link Tomcat6.DEFAULT_CACHE_NAME the default name used in
- * embedded JBoss/Tomcat}.
- * </p>
- *
- * @jmx.managed-attribute
- */
- public String getCacheObjectName()
- {
- return pojoCacheObjectName;
- }
-
- /**
- * Sets the JMX <code>ObjectName</code> under which our
- * <code>TreeCache</code> is registered, if already created, or under
- * which it should be registered if this object creates it.
- *
- * @jmx.managed-attribute
- */
- public void setCacheObjectName(String objectName)
- {
- this.pojoCacheObjectName = objectName;
- }
-
- /**
- * Sets the name of the <code>TreeCache</code>'s JGroups channel.
- * <p>
- * This property is ignored if a <code>TreeCache</code> is already
- * registered under the provided
- * {@link #setCacheObjectName cache object name}.
- * </p>
- *
- * @jmx.managed-attribute
- */
- public void setClusterName(String clusterName)
- {
- this.clusterName = clusterName;
- }
-
- /**
- * Gets the filesystem path, which can either be absolute or a path
- * relative to <code>$CATALINA_BASE</code>, where a
- * a JBossCache configuration file can be found.
- *
- * @return a path, either absolute or relative to
- * <code>$CATALINA_BASE</code>. Will return
- * <code>null</code> if no such path was configured.
- *
- * @jmx.managed-attribute
- */
- public String getCacheConfigPath()
- {
- return cacheConfigPath;
- }
-
- /**
- * Sets the filesystem path, which can either be absolute or a path
- * relative to <code>$CATALINA_BASE</code>, where a
- * a JBossCache configuration file can be found.
- * <p>
- * This property is ignored if a <code>TreeCache</code> is already
- * registered under the provided
- * {@link #setCacheObjectName cache object name}.
- * </p>
- *
- * @param cacheConfigPath a path, absolute or relative to
- * <code>$CATALINA_BASE</code>,
- * pointing to a JBossCache configuration file.
- *
- * @jmx.managed-attribute
- */
- public void setCacheConfigPath(String cacheConfigPath)
- {
- this.cacheConfigPath = cacheConfigPath;
- }
-
- /**
- * Get the current Catalina MBean Server.
- *
- * @return the mbean server
- */
- public MBeanServer getMBeanServer()
- {
- if (mserver == null)
- {
- mserver = Registry.getRegistry(null, null).getMBeanServer();
- }
- return mserver;
- }
-
- /**
- * Gets the name of the implementation of Manager to instantiate when
- * createManager() is called.
- *
- * @jmx.managed-attribute
- */
- public String getManagerClassName()
- {
- return managerClassName;
- }
-
- /**
- * Sets the name of the implementation of Manager to instantiate when
- * createManager() is called.
- * <p>
- * This should be {@link JBossCacheManager} (the default) or a subclass
- * of it.
- * </p>
- *
- * @jmx.managed-attribute
- */
- public void setManagerClassName(String managerClassName)
- {
- this.managerClassName = managerClassName;
- }
-
- public void registerManager(Manager arg0)
- {
- // TODO tie this into the managerClassName
- }
-
- public void removeManager(Manager arg0)
- {
- // TODO tie this into the managerClassName
- }
-
- /**
- * Gets whether the <code>Engine</code> in which we are running
- * uses <code>mod_jk</code>.
- *
- * @jmx.managed-attribute
- */
- public boolean isUseJK()
- {
- return useJK;
- }
-
- /**
- * Sets whether the <code>Engine</code> in which we are running
- * uses <code>mod_jk</code>.
- *
- * @jmx.managed-attribute
- */
- public void setUseJK(boolean useJK)
- {
- this.useJK = useJK;
- }
-
- /**
- * Gets the <code>JBossCacheManager</code>'s <code>useLocalCache</code>
- * property.
- *
- * @jmx.managed-attribute
- */
- public boolean isUseLocalCache()
- {
- return useLocalCache;
- }
-
- /**
- * Sets the <code>JBossCacheManager</code>'s <code>useLocalCache</code>
- * property.
- *
- * @jmx.managed-attribute
- */
- public void setUseLocalCache(boolean useLocalCache)
- {
- this.useLocalCache = useLocalCache;
- }
-
- /**
- * Gets the default granularity of session data replicated across the
- * cluster; i.e. whether the entire session should be replicated when
- * replication is triggered, or only modified attributes.
- * <p>
- * The value of this property is applied to <code>Manager</code> instances
- * that did not have an equivalent property explicitly set in
- * <code>context.xml</code> or <code>server.xml</code>.
- * </p>
- *
- * @jmx.managed-attribute
- */
- public String getDefaultReplicationGranularity()
- {
- return defaultReplicationGranularity == null ? null : defaultReplicationGranularity.toString();
- }
-
- /**
- * Sets the granularity of session data replicated across the cluster.
- * Valid values are:
- * <ul>
- * <li>SESSION</li>
- * <li>ATTRIBUTE</li>
- * <li>FIELD</li>
- * </ul>
- * @jmx.managed-attribute
- */
- public void setDefaultReplicationGranularity(
- String defaultReplicationGranularity)
- {
- this.defaultReplicationGranularity = (defaultReplicationGranularity == null ? null : ReplicationGranularity.fromString(defaultReplicationGranularity.toUpperCase()));
- }
-
- /**
- * Gets the type of operations on a <code>HttpSession</code> that
- * trigger replication.
- * <p>
- * The value of this property is applied to <code>Manager</code> instances
- * that did not have an equivalent property explicitly set in
- * <code>context.xml</code> or <code>server.xml</code>.
- * </p>
- *
- * @jmx.managed-attribute
- */
- public String getDefaultReplicationTrigger()
- {
- return defaultReplicationTrigger == null ? null : defaultReplicationTrigger.toString();
- }
-
- /**
- * Sets the type of operations on a <code>HttpSession</code> that
- * trigger replication. Valid values are:
- * <ul>
- * <li>SET_AND_GET</li>
- * <li>SET_AND_NON_PRIMITIVE_GET</li>
- * <li>SET</li>
- * </ul>
- *
- * @jmx.managed-attribute
- */
- public void setDefaultReplicationTrigger(String defaultTrigger)
- {
- this.defaultReplicationTrigger = (defaultTrigger == null ? null : ReplicationTrigger.fromString(defaultTrigger.toUpperCase()));
- }
-
- /**
- * Gets whether Managers should use batch mode replication.
- * Only meaningful if replication granularity is set to <code>FIELD</code>.
- *
- * @jmx.managed-attribute
- */
- public boolean getDefaultReplicationFieldBatchMode()
- {
- return replicationFieldBatchMode;
- }
-
- /**
- * Sets whether Managers should use batch mode replication.
- * Only meaningful if replication granularity is set to <code>FIELD</code>.
- *
- * @jmx.managed-attribute
- */
- public void setDefaultReplicationFieldBatchMode(boolean replicationFieldBatchMode)
- {
- this.replicationFieldBatchMode = replicationFieldBatchMode;
- }
-
- /**
- * Gets when sessions are replicated to the other nodes.
- * The default value, "instant", synchronously replicates changes
- * to the other nodes. In this case, the "SnapshotInterval" attribute
- * is not used.
- * The "interval" mode, in association with the "SnapshotInterval"
- * attribute, indicates that Tomcat will only replicate modified
- * sessions every "SnapshotInterval" miliseconds at most.
- *
- * @see #getSnapshotInterval()
- *
- * @jmx.managed-attribute
- */
- public String getSnapshotMode()
- {
- return snapshotMode == null ? null : snapshotMode.toString();
- }
-
- /**
- * Sets when sessions are replicated to the other nodes. Valid values are:
- * <ul>
- * <li>instant</li>
- * <li>interval</li>
- * </ul>
- *
- * @jmx.managed-attribute
- */
- public void setSnapshotMode(String snapshotMode)
- {
- this.snapshotMode = (snapshotMode == null ? null : SnapshotMode.fromString(snapshotMode.toUpperCase()));
- }
-
- /**
- * Gets how often session changes should be replicated to other nodes.
- * Only relevant if property {@link #getSnapshotMode() snapshotMode} is
- * set to <code>interval</code>.
- *
- * @return the number of milliseconds between session replications.
- *
- * @jmx.managed-attribute
- */
- public int getSnapshotInterval()
- {
- return snapshotInterval;
- }
-
- /**
- * Sets how often session changes should be replicated to other nodes.
- *
- * @param snapshotInterval the number of milliseconds between
- * session replications.
- * @jmx.managed-attribute
- */
- public void setSnapshotInterval(int snapshotInterval)
- {
- this.snapshotInterval = snapshotInterval;
- }
-
- // ---------------------------------------------------------------- Cluster
-
- /**
- * Gets the name of the <code>TreeCache</code>'s JGroups channel.
- *
- * @see org.apache.catalina.Cluster#getClusterName()
- */
- public String getClusterName()
- {
- return clusterName;
- }
-
- /* (non-javadoc)
- * @see org.apache.catalina.Cluster#getContainer()
- */
- public Container getContainer()
- {
- return container;
- }
-
- /* (non-javadoc)
- * @see org.apache.catalina.Cluster#setContainer()
- */
- public void setContainer(Container container)
- {
- this.container = container;
- }
-
- /**
- * @see org.apache.catalina.Cluster#getInfo()
- *
- * @jmx.managed-attribute access="read-only"
- */
- public String getInfo()
- {
- return info;
- }
-
- /**
- * @see org.apache.catalina.Cluster#createManager(java.lang.String)
- */
- @SuppressWarnings("unchecked")
- public Manager createManager(String name)
- {
- if (log.isDebugEnabled())
- log.debug("Creating ClusterManager for context " + name
- + " using class " + getManagerClassName());
- Manager manager = null;
-
- String mgrClass = getManagerClassName();
- if (mgrClass != null && !JBossCacheManager.class.getName().equals(mgrClass))
- {
- try
- {
- manager = (Manager) getClass().getClassLoader().loadClass(mgrClass).newInstance();
- }
- catch (Exception x)
- {
- log.error("Unable to load class " + mgrClass + " for replication manager; using JBossCacheManager", x);
- }
- }
-
- if (manager == null)
- {
- if (factory == null)
- throw new IllegalStateException("PojoCache not initialized");
- manager = new JBossCacheManager(factory);
- }
-
- manager.setDistributable(true);
-
- if (manager instanceof JBossCacheManager)
- {
- configureManager((JBossCacheManager) manager);
- }
-
- return manager;
- }
-
- /**
- * Does nothing; tracking the status of other members of the cluster is
- * provided by the JGroups layer.
- *
- * @see org.apache.catalina.Cluster#backgroundProcess()
- */
- public void backgroundProcess()
- {
- ; // no-op
- }
-
- // --------------------------------------------- Deprecated Cluster Methods
-
- /**
- * Returns <code>null</code>; method is deprecated.
- *
- * @return <code>null</code>, always.
- *
- * @see org.apache.catalina.Cluster#getProtocol()
- */
- public String getProtocol()
- {
- return null;
- }
-
- /**
- * Does nothing; method is deprecated.
- *
- * @see org.apache.catalina.Cluster#setProtocol(java.lang.String)
- */
- public void setProtocol(String protocol)
- {
- ; // no-op
- }
-
- /**
- * Does nothing; method is deprecated.
- *
- * @see org.apache.catalina.Cluster#startContext(java.lang.String)
- */
- public void startContext(String contextPath) throws IOException
- {
- ; // no-op
- }
-
- /**
- * Does nothing; method is deprecated.
- *
- * @see org.apache.catalina.Cluster#installContext(java.lang.String, java.net.URL)
- */
- public void installContext(String contextPath, URL war)
- {
- ; // no-op
- }
-
- /**
- * Does nothing; method is deprecated.
- *
- * @see org.apache.catalina.Cluster#stop(java.lang.String)
- */
- public void stop(String contextPath) throws IOException
- {
- ; // no-op
- }
-
- // --------------------------------------------------------- Public Methods
-
- /**
- * Sets the cluster-wide properties of a <code>Manager</code> to
- * match those of this cluster. Does not override
- * <code>Manager</code>-specific properties with cluster-wide defaults
- * if the <code>Manager</code>-specfic properties have already been set.
- */
- public void configureManager(JBossCacheManager<? extends OutgoingDistributableSessionData> manager)
- {
- manager.setSnapshotMode(snapshotMode);
- manager.setSnapshotInterval(snapshotInterval);
- manager.setUseJK(useJK);
-
- // Only set replication attributes if they were not
- // already set via a <Manager> element in an XML config file
-
- if (manager.getReplicationGranularity() == null)
- {
- manager.setReplicationGranularity(defaultReplicationGranularity);
- }
-
- if (manager.getReplicationTrigger() == null)
- {
- manager.setReplicationTrigger(defaultReplicationTrigger);
- }
-
- if (manager.isReplicationFieldBatchMode() == null)
- {
- manager.setReplicationFieldBatchMode(replicationFieldBatchMode);
- }
- }
-
- // --------------------------------------------------------------- Lifecyle
-
- /**
- * Finds or creates a {@link TreeCache}; if created, starts the
- * cache and registers it with our JMX server.
- *
- * @see org.apache.catalina.Lifecycle#start()
- */
- public void start() throws LifecycleException
- {
- if (started)
- {
- throw new LifecycleException("Cluster already started");
- }
-
- // Notify our interested LifecycleListeners
- lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, this);
-
- try
- {
- // Tell the JBoss MBeanServerLocator utility
- // that Tomcat's MBean server is 'jboss'
- // JBAS-4623 Only do this if there isn't already a 'jboss' server
- try
- {
- MBeanServerLocator.locateJBoss();
- }
- catch (IllegalStateException ise)
- {
- // This is the expected condition when running in standalone Tomcat
- MBeanServerLocator.setJBoss(getMBeanServer());
- }
-
- // Initialize the tree cache
-
- factory = DistributedCacheManagerFactoryFactory.getInstance().getTomcatClusterDistributedCacheManagerFactory(this);
-
- registerMBeans();
-
- factory.start();
-
- started = true;
-
- // Notify our interested LifecycleListeners
- lifecycle.fireLifecycleEvent(AFTER_START_EVENT, this);
-
- }
- catch (LifecycleException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- log.error("Unable to start cluster.", e);
- throw new LifecycleException(e);
- }
- }
-
- /**
- * If this object created its own {@link TreeCache}, stops it
- * and unregisters it with JMX.
- *
- * @see org.apache.catalina.Lifecycle#stop()
- */
- public void stop() throws LifecycleException
- {
- if (!started)
- {
- throw new IllegalStateException("Cluster not started");
- }
-
- // Notify our interested LifecycleListeners
- lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, this);
-
- try
- {
- factory.stop();
- }
- catch (Exception e)
- {
- throw new LifecycleException("Failed to stop DistributedCacheManagerFactory", e);
- }
-
- started = false;
- // Notify our interested LifecycleListeners
- lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, this);
-
- unregisterMBeans();
- }
-
- /* (non-javadoc)
- * @see org.apache.catalina.Lifecycle#addLifecycleListener()
- */
- public void addLifecycleListener(LifecycleListener listener)
- {
- lifecycle.addLifecycleListener(listener);
- }
-
- /* (non-javadoc)
- * @see org.apache.catalina.Lifecycle#findLifecycleListeners()
- */
- public LifecycleListener[] findLifecycleListeners()
- {
- return lifecycle.findLifecycleListeners();
- }
-
- /* (non-javadoc)
- * @see org.apache.catalina.Lifecycle#removeLifecycleListener()
- */
- public void removeLifecycleListener(LifecycleListener listener)
- {
- lifecycle.removeLifecycleListener(listener);
- }
-
- // -------------------------------------------------------- Private Methods
-
-
-
- public File getCacheConfigFile() throws FileNotFoundException
- {
- boolean useDefault = (this.cacheConfigPath == null);
- String path = (useDefault) ? DEFAULT_CACHE_CONFIG_PATH : cacheConfigPath;
- // See if clusterProperties points to a file relative
- // to $CATALINA_BASE
- File file = new File(path);
- if (!file.isAbsolute())
- {
- file = new File(System.getProperty("catalina.base"), path);
- }
-
- if (file.exists())
- {
- return file;
- }
- else
- {
- // User provided config was invalid; throw the exception
- String msg = "No tree cache config file found at " +
- file.getAbsolutePath();
- log.error(msg);
- throw new IllegalStateException(msg);
- }
- }
-
- /**
- * Registers this object and the tree cache (if we created it) with JMX.
- */
- private void registerMBeans()
- {
- try
- {
- MBeanServer server = getMBeanServer();
-
- String domain;
- if (container instanceof ContainerBase)
- {
- domain = ((ContainerBase) container).getDomain();
- }
- else
- {
- domain = server.getDefaultDomain();
- }
-
- String name = ":type=Cluster";
- if (container instanceof Host) {
- name += ",host=" + container.getName();
- }
- else if (container instanceof Engine)
- {
- name += ",engine=" + container.getName();
- }
-
- ObjectName clusterName = new ObjectName(domain + name);
-
- if (server.isRegistered(clusterName))
- {
- log.warn("MBean " + clusterName + " already registered");
- }
- else
- {
- this.objectName = clusterName;
- server.registerMBean(this, objectName);
- }
-
- }
- catch (Exception ex)
- {
- log.error(ex.getMessage(), ex);
- }
- }
-
- /**
- * Unregisters this object and the tree cache (if we created it) with JMX.
- */
- private void unregisterMBeans()
- {
- if (mserver != null)
- {
- try
- {
- if (objectName != null) {
- mserver.unregisterMBean(objectName);
- }
- }
- catch (Exception e)
- {
- log.error(e);
- }
- }
- }
-
-}
Deleted: branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheClusterMBean.java
===================================================================
--- branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheClusterMBean.java 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheClusterMBean.java 2010-07-06 18:57:12 UTC (rev 106467)
@@ -1,80 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.web.tomcat.service.session;
-
-import org.apache.catalina.Cluster;
-import org.apache.catalina.LifecycleException;
-
-/**
- * The MBean interface for the JBossCacheCluster.
- *
- * @see org.jboss.web.tomcat.service.JBossCacheCluster
- *
- * @author Brian Stansberry
- * @version $Revision$
- */
-public interface JBossCacheClusterMBean extends Cluster
-{
- public abstract boolean isUseJK();
-
- public abstract void setUseJK(boolean useJK);
-
- public abstract boolean isUseLocalCache();
-
- public abstract void setUseLocalCache(boolean useLocalCache);
-
- public abstract String getManagerClassName();
-
- public abstract void setManagerClassName(String managerClassName);
-
- public abstract String getDefaultReplicationGranularity();
-
- public abstract void setDefaultReplicationGranularity(String defaultGran);
-
- public abstract String getDefaultReplicationTrigger();
-
- public abstract void setDefaultReplicationTrigger(String defaultTrigger);
-
- public boolean getDefaultReplicationFieldBatchMode();
-
- public void setDefaultReplicationFieldBatchMode(boolean replicationFieldBatchMode);
-
- public abstract int getSnapshotInterval();
-
- public abstract void setSnapshotInterval(int snapshotInterval);
-
- public abstract String getSnapshotMode();
-
- public abstract void setSnapshotMode(String snapshotMode);
-
- public abstract String getCacheObjectName();
-
- public abstract void setCacheObjectName(String objectName);
-
- public abstract void start() throws LifecycleException;
-
- /**
- * Does nothing.
- */
- public abstract void stop() throws LifecycleException;
-
-}
\ No newline at end of file
Modified: branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheManager.java
===================================================================
--- branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheManager.java 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/JBossCacheManager.java 2010-07-06 18:57:12 UTC (rev 106467)
@@ -312,7 +312,7 @@
"session with id " + session.getIdInternal());
}
- if (session.isValid() &&
+ if (session.isValid(true) &&
(session.isSessionDirty() || session.getMustReplicateTimestamp()))
{
String realId = session.getRealId();
@@ -1813,26 +1813,29 @@
// the local copy has timed out. If found, refresh the
// session from the cache in case that might change the timeout
likelyExpired = (session.isValid(false) == false);
- if (likelyExpired && this.outdatedSessionChecker.isSessionOutdated(session))
- {
- // With JBC, every time we get a notification from the distributed
- // cache of an update, we get the latest timestamp. So
- // we shouldn't need to do a full session load here. A load
- // adds a risk of an unintended data gravitation. However,
- // with a database instead of JBC we don't get notifications
-
- // JBAS-2792 don't assign the result of loadSession to session
- // just update the object from the cache or fall through if
- // the session has been removed from the cache
- loadSession(session.getRealId());
- }
-
- // Do a normal invalidation check that will expire the
- // session if it has timed out
- // DON'T SYNCHRONIZE on session here -- isValid() and
- // expire() are meant to be multi-threaded and synchronize
- // properly internally; synchronizing externally can lead
- // to deadlocks!!
+// if (likelyExpired && this.outdatedSessionChecker.isSessionOutdated(session))
+// {
+// // With JBC, every time we get a notification from the distributed
+// // cache of an update, we get the latest timestamp. So
+// // we shouldn't need to do a full session load here. A load
+// // adds a risk of an unintended data gravitation. However,
+// // with a database instead of JBC we don't get notifications
+//
+// // JBAS-2792 don't assign the result of loadSession to session
+// // just update the object from the cache or fall through if
+// // the session has been removed from the cache
+// loadSession(session.getRealId());
+// }
+//
+// // Do a normal invalidation check that will expire the
+// // session if it has timed out
+// // DON'T SYNCHRONIZE on session here -- isValid() and
+// // expire() are meant to be multi-threaded and synchronize
+// // properly internally; synchronizing externally can lead
+// // to deadlocks!!
+// if (!session.isValid(true)) continue;
+
+ // This call will take ownership and ensure the session is up to date
if (!session.isValid()) continue;
likelyExpired = false;
@@ -1902,7 +1905,7 @@
Session session = findSession(realId);
if (session != null)
{
- session.isValid(); // will expire
+ session.isValid(); // will take ownership and expire
continue;
}
}
@@ -2071,7 +2074,7 @@
{
// TODO -- why are we doing this check? The request checks session
// validity and will expire the session; this seems redundant
- if (!session.isValid())
+ if (!session.isValid(true))
{
// Not an error; this can happen if a failover request pulls in an
// outdated session from the distributed cache (see TODO above)
@@ -2482,26 +2485,26 @@
protected void configureUnembedded() throws LifecycleException
{
- if (snapshotMode_ == null)
- {
- // We were not instantiated by a JBossCacheCluster, so we need to
- // find one and let it configure our cluster-wide properties
- try
- {
- JBossCacheCluster cluster = (JBossCacheCluster) container_.getCluster();
- if (cluster == null)
- {
- cluster = new JBossCacheCluster();
- }
- cluster.configureManager(this);
- }
- catch (ClassCastException e)
- {
- String msg = "Cluster is not an instance of JBossCacheCluster";
- log_.error(msg, e);
- throw new LifecycleException(msg, e);
- }
- }
+// if (snapshotMode_ == null)
+// {
+// // We were not instantiated by a JBossCacheCluster, so we need to
+// // find one and let it configure our cluster-wide properties
+// try
+// {
+// JBossCacheCluster cluster = (JBossCacheCluster) container_.getCluster();
+// if (cluster == null)
+// {
+// cluster = new JBossCacheCluster();
+// }
+// cluster.configureManager(this);
+// }
+// catch (ClassCastException e)
+// {
+// String msg = "Cluster is not an instance of JBossCacheCluster";
+// log_.error(msg, e);
+// throw new LifecycleException(msg, e);
+// }
+// }
}
private void synthesizeReplicationConfig()
@@ -2594,7 +2597,7 @@
{
// if session passivation is enabled, passivate sessions instead of expiring them which means
// they'll be available to the manager for activation after a restart.
- if(passivation && ses.isValid())
+ if(passivation && ses.isValid(true))
{
processSessionPassivation(ses.getRealId());
}
Modified: branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/persistent/PersistentStoreDistributedCacheManager.java
===================================================================
--- branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/persistent/PersistentStoreDistributedCacheManager.java 2010-07-06 18:42:31 UTC (rev 106466)
+++ branches/Session_Ownership/tomcat/src/main/java/org/jboss/web/tomcat/service/session/persistent/PersistentStoreDistributedCacheManager.java 2010-07-06 18:57:12 UTC (rev 106467)
@@ -25,6 +25,7 @@
import java.util.Map;
import java.util.Set;
+import org.jboss.ha.framework.server.lock.TimeoutException;
import org.jboss.metadata.web.jboss.ReplicationGranularity;
import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
@@ -279,4 +280,21 @@
}
+ public boolean getSupportsSessionOwnership()
+ {
+ return false;
+ }
+
+ public org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager.LockResult acquireSessionOwnership(
+ String realId, boolean newLock) throws TimeoutException, InterruptedException
+ {
+ // FIXME -- re-evaluate
+ return LockResult.UNSUPPORTED;
+ }
+
+ public void relinquishSessionOwnership(String realId, boolean remove)
+ {
+ // no-op
+ }
+
}
More information about the jboss-cvs-commits
mailing list