[jboss-cvs] JBossAS SVN: r72946 - in trunk: tomcat/src/main/org/jboss/web/tomcat/service/session and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu May 1 12:36:50 EDT 2008
Author: bstansberry at jboss.com
Date: 2008-05-01 12:36:49 -0400 (Thu, 01 May 2008)
New Revision: 72946
Added:
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossSerializationObjectStreamSource.java
Modified:
trunk/testsuite/src/main/org/jboss/test/cluster/web/CacheHelper.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/AttributeBasedClusteredSession.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheWrapper.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionBasedClusteredSession.java
trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionSerializationFactory.java
Log:
[JBAS-5448] Move ha-client to 1.1.0.Beta1
[JBAS-5449] Move ha-server-api to 1.1.0.Beta1
[JBAS-4639] Optimized replication of ClusteredSession metadata
Modified: trunk/testsuite/src/main/org/jboss/test/cluster/web/CacheHelper.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/web/CacheHelper.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/web/CacheHelper.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -39,6 +39,7 @@
import org.jboss.ha.framework.server.PojoCacheManagerLocator;
import org.jboss.mx.util.ObjectNameFactory;
import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.web.tomcat.service.session.JBossCacheService;
/**
* Helper class to locate and invoke methods on the cache mbeans used by JBossWeb.
@@ -58,7 +59,7 @@
public static final ObjectName OBJECT_NAME =
ObjectNameFactory.create("jboss.test:service=WebTestCacheHelper");
- private static final String VERSION_KEY = "VERSION";
+ private static final String VERSION_KEY = JBossCacheService.VERSION_KEY;
private String cacheConfigName;
private Cache cache;
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/AttributeBasedClusteredSession.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/AttributeBasedClusteredSession.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/AttributeBasedClusteredSession.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -26,7 +26,6 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import java.util.Map.Entry;
/**
* Implementation of a clustered session for the JBossCacheManager. The replication granularity
@@ -62,7 +61,7 @@
protected static final String info = "AttributeBasedClusteredSession/1.0";
// Transient map to store attr changes for replication.
- private transient Map attrModifiedMap_ = new HashMap();
+ private transient Map<Object, Object> attrModifiedMap_ = new HashMap<Object, Object>();
// Note that the removed attr is intentionally stored in a map
// instead of a Set so it is faster to lookup and remove.
private transient Map attrRemovedMap_ = new HashMap();
@@ -126,15 +125,14 @@
// Go thru the attribute change list
- if (getSessionAttributesDirty())
+ if (isSessionAttributeMapDirty())
{
// Go thru the modified attr list first
int modCount = attrModifiedMap_.size();
if (modCount == 1)
{
- for (Iterator it = attrModifiedMap_.entrySet().iterator(); it.hasNext(); )
+ for (Map.Entry entry : attrModifiedMap_.entrySet())
{
- Map.Entry entry = (Entry) it.next();
proxy_.putAttribute(realId, (String) entry.getKey(), entry.getValue());
}
}
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -97,14 +97,6 @@
protected ReplicationTrigger invalidationPolicy;
/**
- * If true, means the local in-memory session data contains
- * changes that have not been published to the distributed cache.
- *
- * @deprecated not used
- */
- protected transient boolean isSessionModifiedSinceLastSave;
-
- /**
* If true, means the local in-memory session data contains metadata
* changes that have not been published to the distributed cache.
*/
@@ -116,6 +108,20 @@
*/
protected transient boolean sessionAttributesDirty;
+ /**
+ * Object wrapping thisAccessedTime. Create once and mutate so
+ * we can store it in JBoss Cache w/o concern that a transaction
+ * rollback will revert the cached ref to an older object.
+ */
+ protected transient SessionTimestamp timestamp = new SessionTimestamp();
+
+ /**
+ * Object wrapping other metadata for this session. Create once and mutate so
+ * we can store it in JBoss Cache w/o concern that a transaction
+ * rollback will revert the cached ref to an older object.
+ */
+ protected transient SessionMetadata metadata = new SessionMetadata();
+
/**
* The last version that was passed to {@link #setOutdatedVersion} or
* <code>0</code> if <code>setIsOutdated(false)</code> was subsequently called.
@@ -213,22 +219,6 @@
{
return thisAccessedTime < outdatedTime;
}
-
- /**
- * Marks this session as outdated or up-to-date vis-a-vis the distributed
- * cache.
- *
- * @param outdated
- *
- * @deprecated use {@link #setOutdatedVersion(int)} and {@link #clearOutdated()}
- */
- public void setIsOutdated(boolean outdated)
- {
- if (outdated)
- outdatedTime = System.currentTimeMillis();
- else
- clearOutdated();
- }
public void setOutdatedVersion(int version)
{
@@ -415,9 +405,9 @@
public boolean getExceedsMaxUnreplicatedInterval()
{
- boolean result = false;
+ boolean result = (invalidationPolicy == ReplicationTrigger.ACCESS);
- if (maxUnreplicatedInterval > 0) // -1 means ignore; 0 means expire now
+ if (!result && maxUnreplicatedInterval > 0) // -1 means ignore; 0 means expire now
{
result = ((System.currentTimeMillis() - lastReplicated) >= maxUnreplicatedInterval);
}
@@ -435,6 +425,29 @@
maxUnreplicatedInterval = maxInactiveInterval * maxUnreplicatedFactor * 10;
}
}
+
+ public SessionTimestamp getSessionTimestamp()
+ {
+ this.timestamp.timestamp = this.thisAccessedTime;
+ return this.timestamp;
+ }
+
+ public SessionMetadata getSessionMetadata()
+ {
+ this.metadata.id = id;
+ this.metadata.creationTime = creationTime;
+ this.metadata.maxInactiveInterval = maxInactiveInterval;
+ this.metadata.invalidationPolicy = invalidationPolicy;
+ this.metadata.isNew = isNew;
+ this.metadata.isValid = isValid;
+
+ return this.metadata;
+ }
+
+ public Map<String, Object> getSessionAttributeMap()
+ {
+ return null;
+ }
/**
* This is called after loading a session to initialize the transient values.
@@ -464,18 +477,13 @@
public void access()
{
super.access();
-
+
// JBAS-3528. If it's not the first access, make sure
// the 'new' flag is correct
if (!firstAccess && isNew)
{
setNew(false);
- }
-
- if (invalidationPolicy == ReplicationTrigger.ACCESS)
- {
- this.sessionMetadataDirty();
- }
+ }
}
@@ -1238,70 +1246,63 @@
return excluded;
}
- /**
- * Reads all non-transient state from the ObjectOutput <i>except
- * the attribute map</i>. Subclasses that wish the attribute map
- * to be read should override this method and
- * {@link #writeExternal(ObjectOutput) writeExternal()}.
- *
- * <p>
- * This method is deliberately public so it can be used to reset
- * the internal state of a session object using serialized
- * contents replicated from another JVM via JBossCache.
- * </p>
- *
- * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
- */
- protected void update(ClusteredSession replicated)
+ protected void update(Integer version, SessionTimestamp timestamp,
+ SessionMetadata metadata, Map attributes)
{
- synchronized (this)
- {
- // From StandardSession
- id = replicated.id;
- creationTime = replicated.creationTime;
- lastAccessedTime = replicated.lastAccessedTime;
- maxInactiveInterval = replicated.maxInactiveInterval;
- isNew = replicated.isNew;
- isValid = replicated.isValid;
- thisAccessedTime = replicated.thisAccessedTime;
-
- // From ClusteredSession
- invalidationPolicy = replicated.invalidationPolicy;
- version = replicated.version;
+ assert version != null : "version is null";
+ assert timestamp != null : "timestamp is null";
+ assert metadata != null : "metadata is null";
+
+ this.version = version.intValue();
+
+ this.lastAccessedTime = this.thisAccessedTime = timestamp.timestamp;
+ this.timestamp = timestamp;
+
+ this.id = metadata.id;
+ this.creationTime = metadata.creationTime;
+ this.maxInactiveInterval = metadata.maxInactiveInterval;
+ this.isNew = metadata.isNew;
+ this.isValid = metadata.isValid;
+ this.invalidationPolicy = metadata.invalidationPolicy;
+ this.metadata = metadata;
+
+ // Get our id without any jvmRoute appended
+ parseRealId(id);
+
+ // We no longer know if we have an activationListener
+ hasActivationListener = null;
+
+ // If the session has been replicated, any subsequent
+ // access cannot be the first.
+ this.firstAccess = false;
+
+ // 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
+// // We use the superclass set/removeNote calls here to bypass
+// // the custom logic we've added
+// String username = (String) in.readObject();
+// if (username != null)
+// {
+// super.setNote(Constants.SESS_USERNAME_NOTE, username);
+// }
+// else
+// {
+// super.removeNote(Constants.SESS_USERNAME_NOTE);
+// }
+// String password = (String) in.readObject();
+// if (password != null)
+// {
+// super.setNote(Constants.SESS_PASSWORD_NOTE, password);
+// }
+// else
+// {
+// super.removeNote(Constants.SESS_PASSWORD_NOTE);
+// }
+
+ // we ignore the attributes
+ }
- // Get our id without any jvmRoute appended
- parseRealId(id);
-
- // We no longer know if we have an activationListener
- hasActivationListener = null;
-
- // 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
-// // We use the superclass set/removeNote calls here to bypass
-// // the custom logic we've added
-// String username = (String) in.readObject();
-// if (username != null)
-// {
-// super.setNote(Constants.SESS_USERNAME_NOTE, username);
-// }
-// else
-// {
-// super.removeNote(Constants.SESS_USERNAME_NOTE);
-// }
-// String password = (String) in.readObject();
-// if (password != null)
-// {
-// super.setNote(Constants.SESS_PASSWORD_NOTE, password);
-// }
-// else
-// {
-// super.removeNote(Constants.SESS_PASSWORD_NOTE);
-// }
- }
- }
-
-
// -------------------------------------- Internal protected method override
/**
@@ -1318,6 +1319,7 @@
* @param name the attribute name
* @param notify <code>true</code> if listeners should be notified
*/
+ @Override
protected void removeAttributeInternal(String name, boolean notify)
{
boolean localCall = true;
@@ -1459,16 +1461,11 @@
protected void sessionAttributesDirty()
{
if (!sessionAttributesDirty && log.isTraceEnabled())
- log.trace("Marking session attributes dirty" + id);
+ log.trace("Marking session attributes dirty " + id);
sessionAttributesDirty = true;
}
- protected boolean getSessionAttributesDirty()
- {
- return sessionAttributesDirty;
- }
-
protected void sessionMetadataDirty()
{
if (!sessionMetadataDirty && !isNew && log.isTraceEnabled())
@@ -1476,31 +1473,19 @@
sessionMetadataDirty = true;
}
- protected boolean getSessionMetadataDirty()
+ public boolean isSessionMetadataDirty()
{
return sessionMetadataDirty;
}
-
- /**
- * Calls {@link #sessionAttributesDirty()} and
- * {@link #sessionMetadataDirty()}.
- *
- * @deprecated use one of the more fine-grained methods.
- */
- protected void sessionDirty()
- {
- sessionAttributesDirty();
- sessionMetadataDirty();
- }
public boolean isSessionDirty()
{
return sessionAttributesDirty || sessionMetadataDirty;
}
- public boolean getReplicateSessionBody()
+ public boolean isSessionAttributeMapDirty()
{
- return sessionMetadataDirty || getExceedsMaxUnreplicatedInterval();
+ return sessionAttributesDirty;
}
protected boolean isGetDirty(Object attribute)
@@ -1528,5 +1513,40 @@
attribute instanceof Character ||
attribute instanceof Boolean);
}
+
+ /**
+ * Encapsulates the "thisAccessedTime" timestamp. The wrapped timestamp long
+ * can be mutated, allowing the same object to always be stored in
+ * JBoss Cache. Always storing the same object avoids an earlier, no
+ * longer accurate, object being reverted into the cache during a
+ * transaction rollback.
+ */
+ public static class SessionTimestamp implements Serializable
+ {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 2317131983552715467L;
+
+ public long timestamp = 0L;
+ }
+
+ /**
+ * Encapsulates the replicated metadata for a session. The wrapped data
+ * can be mutated, allowing the same object to always be stored in
+ * JBoss Cache. Always storing the same object avoids an earlier, no
+ * longer accurate, object being reverted into the cache during a
+ * transaction rollback.
+ */
+ public static class SessionMetadata implements Serializable
+ {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = -6845914023373746866L;
+
+ public String id;
+ public long creationTime;
+ public int maxInactiveInterval;
+ public boolean isNew;
+ public boolean isValid;
+ public ReplicationTrigger invalidationPolicy;
+ }
}
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -958,12 +958,13 @@
// createEmptyClusteredSession to avoid a cast
public Session createEmptySession()
{
+ log_.trace("Creating an empty ClusteredSession");
+
return createEmptyClusteredSession();
}
private ClusteredSession createEmptyClusteredSession()
- {
- log_.trace("Creating an empty ClusteredSession");
+ {
ClusteredSession session = null;
switch (replicationGranularity_)
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -21,10 +21,8 @@
*/
package org.jboss.web.tomcat.service.session;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -44,9 +42,12 @@
import org.jboss.cache.config.CacheLoaderConfig;
import org.jboss.cache.pojo.impl.InternalConstant;
import org.jboss.cache.transaction.BatchModeTransactionManager;
-import org.jboss.invocation.MarshalledValue;
+import org.jboss.ha.framework.interfaces.CachableMarshalledValue;
+import org.jboss.ha.framework.server.MarshalledValueHelper;
+import org.jboss.ha.framework.server.SimpleCachableMarshalledValue;
import org.jboss.logging.Logger;
-import org.jboss.serial.io.MarshalledObject;
+import org.jboss.web.tomcat.service.session.ClusteredSession.SessionMetadata;
+import org.jboss.web.tomcat.service.session.ClusteredSession.SessionTimestamp;
/**
* A wrapper class to JBossCache. This is currently needed to handle various operations such as
@@ -66,7 +67,11 @@
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 = "V";
+ public static final String TIMESTAMP_KEY = "T";
+ public static final String METADATA_KEY = "M";
+ public static final String ATTRIBUTE_KEY = "A";
+
static final String FQN_DELIMITER = "/";
private Cache plainCache_;
@@ -264,83 +269,53 @@
public ClusteredSession loadSession(String realId, ClusteredSession toLoad)
{
Fqn fqn = getSessionFqn(realId);
- Object sessionData = cacheWrapper_.get(fqn, realId, true);
+ Map sessionData = cacheWrapper_.getData(fqn, true);
if (sessionData == null) {
// Requested session is no longer in the cache; return null
return null;
}
- boolean firstLoad = (toLoad.getVersion() == 0);
+ Integer version = (Integer) sessionData.get(VERSION_KEY);
+ SessionTimestamp timestamp = (SessionTimestamp) sessionData.get(TIMESTAMP_KEY);
+ SessionMetadata metadata = (SessionMetadata) sessionData.get(METADATA_KEY);
+ Map attrs = (Map) getUnMarshalledValue(sessionData.get(ATTRIBUTE_KEY));
+ toLoad.update(version, timestamp, metadata, attrs);
-// if (useTreeCacheMarshalling_)
-// {
-// toLoad.update((ClusteredSession) sessionData);
-// }
-// else
-// {
- byte[] sessionBytes = (byte[]) sessionData;
-
- // Swap in/out the webapp classloader so we can deserialize
- // attributes whose classes are only available to the webapp
- ClassLoader prevTCL = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(manager_.getWebappClassLoader());
- try
- {
- // JBAS-2921 - replaced MarshalledValue calls with SessionSerializationFactory calls
- // ByteArrayInputStream bais = new ByteArrayInputStream(sessionBytes);
- // Use MarshalledValueInputStream instead of superclass ObjectInputStream
- // or else there are problems finding classes with scoped loaders
- // MarshalledValueInputStream input = new MarshalledValueInputStream(bais);
- ObjectInputStream input = SessionSerializationFactory.createObjectInputStream(sessionBytes);
- toLoad.readExternal(input);
- input.close();
- }
- catch (Exception e)
- {
- log_.error("loadSession(): id: " + realId + " exception occurred during deserialization", e);
- return null;
- }
- finally {
- Thread.currentThread().setContextClassLoader(prevTCL);
- }
-// }
-
- // The internal version of the serialized session may be less than the
- // real one due to not replicating metadata. If our listener hasn't
- // been keeping the outdatedVersion of the session up to date because
- // the session has never been loaded into the JBCManager cache, we
- // need to fix the version
- if (firstLoad)
- {
- Integer ver = (Integer) cacheWrapper_.get(fqn, VERSION_KEY);
- if (ver != null)
- toLoad.setVersion(ver.intValue());
- }
-
return toLoad;
}
public void putSession(String realId, ClusteredSession session)
- {
- Fqn fqn = getSessionFqn(realId);
-
- if (session.getReplicateSessionBody())
+ {
+ if (log_.isTraceEnabled())
{
- Map map = new HashMap();
-// if (useTreeCacheMarshalling_)
-// map.put(realId, session);
-// else
- map.put(realId, externalizeSession(session));
- // Put in (VERSION_KEY, version) after the real put for cache invalidation
- map.put(VERSION_KEY, new Integer(session.getVersion()));
- cacheWrapper_.put(fqn, map);
+ log_.trace("putSession(): putting session " + session.getIdInternal());
+ }
+
+ Map map = new HashMap();
+ map.put(VERSION_KEY, new Integer(session.getVersion()));
+ map.put(TIMESTAMP_KEY, session.getSessionTimestamp());
+
+ if (session.isSessionMetadataDirty())
+ {
+ map.put(METADATA_KEY, session.getSessionMetadata());
}
- else
+
+ if (session.isSessionAttributeMapDirty())
{
- // Invalidate the remote caches
- cacheWrapper_.put(fqn, VERSION_KEY, new Integer(session.getVersion()));
+ Map attrs = session.getSessionAttributeMap();
+ // May be null if the session type doesn't use this mechanism to store
+ // attributes (i.e. isn't SessionBasedClusteredSession)
+ if (attrs != null)
+ {
+// if (useTreeCacheMarshalling_)
+// map.put(ATTRIBUTE_KEY, attrs);
+// else
+ map.put(ATTRIBUTE_KEY, getMarshalledValue(attrs));
+ }
}
+
+ cacheWrapper_.put(getSessionFqn(realId), map);
}
public void removeSession(String realId)
@@ -630,42 +605,31 @@
// }
// else
// {
- try
+
+ // JBAS-2921 - replaced MarshalledValue calls with SessionSerializationFactory calls
+ // to allow for switching between JBossSerialization and JavaSerialization using
+ // system property -D=session.serialization.jboss=true / false
+ // MarshalledValue mv = new MarshalledValue(value);
+ if (MarshalledValueHelper.isTypeExcluded(value.getClass()))
{
- // JBAS-2921 - replaced MarshalledValue calls with SessionSerializationFactory calls
- // to allow for switching between JBossSerialization and JavaSerialization using
- // system property -D=session.serialization.jboss=true / false
- // MarshalledValue mv = new MarshalledValue(value);
- if (SessionSerializationFactory.useJBossSerialization())
+ return value;
+ }
+ else
+ {
+ try
{
- MarshalledObject mo = SessionSerializationFactory.createMarshalledObject(value);
- if (log_.isTraceEnabled())
- {
- log_.trace("JBoss Marshalled Object to size ");
- }
- return mo;
-
+ CachableMarshalledValue mv = SessionSerializationFactory.createMarshalledValue((Serializable) value);
+ return mv;
}
- else
+ catch (ClassCastException e)
{
- MarshalledValue mv = SessionSerializationFactory.createMarshalledValue(value);
- if (log_.isTraceEnabled())
- {
- log_.trace("marshalled object to size " + mv.size() + " bytes");
- }
- return mv;
+ throw new IllegalArgumentException(value + " does not implement java.io.Serializable");
}
-
}
- catch (IOException e)
- {
- log_.error("IOException occurred marshalling value ", e);
- return null;
- }
// }
}
- private Object getUnMarshalledValue(Object mv)
+ private Object getUnMarshalledValue(Object obj)
{
// JBAS-2920. For now, continue using MarshalledValue, as
// it allows lazy deserialization of the attribute on remote nodes
@@ -677,24 +641,17 @@
// }
// else
// {
- if (mv == null) return null;
+ if (!(obj instanceof SimpleCachableMarshalledValue))
+ return obj;
+
// Swap in/out the tcl for this web app. Needed only for un marshalling.
ClassLoader prevTCL = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(manager_.getWebappClassLoader());
try
{
- // JBAS-2921 - replaced MarshalledValue calls with SessionSerializationFactory calls
- // to allow for switching between JBossSerialization and JavaSerialization using
- // system property -D=session.serialization.jboss=true / false
-
- if (SessionSerializationFactory.useJBossSerialization())
- {
- return ((MarshalledObject)mv).get();
- }
- else
- {
- return ((MarshalledValue) mv).get();
- }
+ SimpleCachableMarshalledValue mv = (SimpleCachableMarshalledValue) obj;
+ mv.setObjectStreamSource(SessionSerializationFactory.getObjectStreamSource());
+ return mv.get();
}
catch (IOException e)
{
@@ -713,40 +670,4 @@
// }
}
- private byte[] externalizeSession(ClusteredSession session)
- {
- try
- {
- // Write the contents of session to a byte array and store that
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- // Use MarshalledValueOutputStream instead of superclass ObjectOutputStream
- // or else there are problems finding classes with scoped loaders
-
- // JBAS-2921 - replaced MarshalledValue calls with SessionSerializationFactory calls
- // to allow for switching between JBossSerialization and JavaSerialization using
- // system property -D=session.serialization.jboss=true / false
-
- // MarshalledValueOutputStream oos = new MarshalledValueOutputStream(baos);
-
- ObjectOutputStream oos = SessionSerializationFactory.createObjectOutputStream(baos);
- session.writeExternal(oos);
- oos.close(); // flushes bytes to baos
-
- byte[] bytes = baos.toByteArray();
-
- if (log_.isTraceEnabled())
- {
- log_.trace("Serialized Object to size " + bytes.length + " bytes");
- }
-
- return bytes;
- }
- catch (Exception e)
- {
- log_.error("externalizeSession(): exception occurred externalizing session " + session, e);
- return null;
- }
-
- }
-
}
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheWrapper.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheWrapper.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheWrapper.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -42,6 +42,28 @@
{
plainCache_ = cache;
}
+
+ Map getData(Fqn fqn, boolean gravitate)
+ {
+ TimeoutException ex = null;
+ for (int i = 0; i < RETRY; i++)
+ {
+ try
+ {
+ if (gravitate)
+ {
+ plainCache_.getInvocationContext().getOptionOverrides()
+ .setForceDataGravitation(true);
+ }
+ return plainCache_.getData(fqn);
+ }
+ catch (TimeoutException e)
+ {
+ ex = e;
+ }
+ }
+ throw new RuntimeException(RETRY_FAIL_MSG, ex);
+ }
/**
* Wrapper to embed retry logic.
@@ -69,18 +91,12 @@
{
try
{
- Object value = null;
if (gravitate)
{
plainCache_.getInvocationContext().getOptionOverrides()
.setForceDataGravitation(true);
- value = plainCache_.get(fqn, id);
}
- else
- {
- value = plainCache_.get(fqn, id);
- }
- return value;
+ return plainCache_.get(fqn, id);
}
catch (TimeoutException e)
{
Added: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossSerializationObjectStreamSource.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossSerializationObjectStreamSource.java (rev 0)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossSerializationObjectStreamSource.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -0,0 +1,54 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OutputStream;
+
+import org.jboss.ha.framework.interfaces.ObjectStreamSource;
+import org.jboss.serial.io.JBossObjectInputStreamSharedTree;
+import org.jboss.serial.io.JBossObjectOutputStreamSharedTree;
+
+/**
+ * {@link ObjectStreamSource} implementation that provides
+ * {@link JBossObjectInputStreamSharedTree} and {@link JBossObjectOutputStreamSharedTree}.
+ *
+ * @author Brian Stansberry
+ */
+public class JBossSerializationObjectStreamSource implements ObjectStreamSource
+{
+
+ public ObjectInput getObjectInput(InputStream input) throws IOException
+ {
+ return new JBossObjectInputStreamSharedTree(input);
+ }
+
+ public ObjectOutput getObjectOutput(OutputStream output) throws IOException
+ {
+ return new JBossObjectOutputStreamSharedTree(output);
+ }
+
+}
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionBasedClusteredSession.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionBasedClusteredSession.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionBasedClusteredSession.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -24,6 +24,7 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.util.HashMap;
import java.util.Map;
@@ -133,6 +134,14 @@
return attributes.put(name, value);
}
+ @Override
+ public Map<String, Object> getSessionAttributeMap()
+ {
+ Map attrs = new HashMap(attributes);
+ removeExcludedAttributes(attrs);
+ return attrs;
+ }
+
/**
* Overrides the superclass version by additionally reading the
* attributes map.
@@ -149,6 +158,10 @@
{
synchronized (this)
{
+
+ // If the session has been replicated, any subsequent
+ // access cannot be the first.
+ this.firstAccess = false;
// Let superclass read in everything but the attribute map
super.readExternal(in);
@@ -178,27 +191,25 @@
// Restore any excluded attributes
if (excluded != null)
attributes.putAll(excluded);
- }
-
+ }
}
- protected void update(ClusteredSession replicated)
+ protected void update(Integer version, SessionTimestamp timestamp,
+ SessionMetadata metadata, Map updatedAttrs)
{
- SessionBasedClusteredSession other = (SessionBasedClusteredSession) replicated;
+ // A new session may not have sent over any attributes
+ if (updatedAttrs == null)
+ {
+ updatedAttrs = new HashMap();
+ }
+
+ super.update(version, timestamp, metadata, updatedAttrs);
- super.update(other);
+ Map excluded = removeExcludedAttributes(attributes);
+ if (excluded != null)
+ updatedAttrs.putAll(excluded);
- attributes = other.attributes;
+ this.attributes = updatedAttrs;
}
-
- /**
- * Overrides the superclass version to return <code>true</code> if either
- * the metadata or the attributes are dirty.
- */
- public boolean getReplicateSessionBody()
- {
- return isSessionDirty() || getExceedsMaxUnreplicatedInterval();
- }
-
}
Modified: trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionSerializationFactory.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionSerializationFactory.java 2008-05-01 16:35:25 UTC (rev 72945)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/service/session/SessionSerializationFactory.java 2008-05-01 16:36:49 UTC (rev 72946)
@@ -21,20 +21,13 @@
*/
package org.jboss.web.tomcat.service.session;
-import org.jboss.invocation.MarshalledValueInputStream;
-import org.jboss.invocation.MarshalledValueOutputStream;
-import org.jboss.invocation.MarshalledValue;
+import java.io.Serializable;
+
+import org.jboss.ha.framework.interfaces.ObjectStreamSource;
+import org.jboss.ha.framework.server.MarshalledValueObjectStreamSource;
+import org.jboss.ha.framework.server.SimpleCachableMarshalledValue;
import org.jboss.logging.Logger;
-import org.jboss.serial.io.JBossObjectInputStreamSharedTree;
-import org.jboss.serial.io.JBossObjectOutputStreamSharedTree;
-import org.jboss.serial.io.MarshalledObject;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-
/**
* Factory class for creating object output and input streams,
* switching between JDK Serialization and JBoss Serialization classes.
@@ -44,16 +37,25 @@
*
*
* @author <a href="hmesha at novell.com">Hany Mesha</a>
+ * @author Brian Stansberry
*/
public class SessionSerializationFactory
{
- static Logger log_ = Logger.getLogger(SessionSerializationFactory.class);
- static boolean useJBossSerialization = false;
+ /**
+ * System property that, if set to <code>true</code>, indicates that
+ * JBoss Serialization should be used for session serialization.
+ */
+ public static final String JBOSS_SERIALIZATION_SYS_PROP = "session.serialization.jboss";
+ private static Logger log_ = Logger.getLogger(SessionSerializationFactory.class);
+ private static boolean useJBossSerialization = false;
+ private static ObjectStreamSource objectStreamSource;
static
{
- String useJBossSerializationStr = System.getProperty("session.serialization.jboss", "false");
+ String useJBossSerializationStr = System.getProperty(JBOSS_SERIALIZATION_SYS_PROP, "false");
useJBossSerialization = Boolean.valueOf(useJBossSerializationStr).booleanValue();
+ objectStreamSource = useJBossSerialization ? new JBossSerializationObjectStreamSource()
+ : new MarshalledValueObjectStreamSource();
try
{
if (useJBossSerialization)
@@ -66,26 +68,15 @@
// we don't fail a static initializer due to a debug log stmt
}
}
-
- public static ObjectOutputStream createObjectOutputStream(OutputStream out) throws IOException
- {
- return useJBossSerialization ? new JBossObjectOutputStreamSharedTree(out) : new MarshalledValueOutputStream(out);
- }
-
- public static ObjectInputStream createObjectInputStream(byte[] bytes) throws IOException
- {
- ByteArrayInputStream in = new ByteArrayInputStream(bytes);
- return useJBossSerialization ? new JBossObjectInputStreamSharedTree(in) : new MarshalledValueInputStream(in);
- }
- public static MarshalledValue createMarshalledValue(Object o) throws IOException
+ public static SimpleCachableMarshalledValue createMarshalledValue(Serializable o)
{
- return new MarshalledValue (o);
+ return new SimpleCachableMarshalledValue(o, objectStreamSource);
}
- public static MarshalledObject createMarshalledObject(Object o) throws IOException
+ public static ObjectStreamSource getObjectStreamSource()
{
- return new MarshalledObject(o);
+ return objectStreamSource;
}
public static boolean useJBossSerialization()
More information about the jboss-cvs-commits
mailing list