[jboss-cvs] JBossCache/src/org/jboss/cache/marshall ...
Manik Surtani
msurtani at jboss.com
Mon Jan 15 13:10:56 EST 2007
User: msurtani
Date: 07/01/15 13:10:56
Modified: src/org/jboss/cache/marshall CacheMarshaller200.java
InactiveRegionException.java Marshaller.java
VersionAwareMarshaller.java
Added: src/org/jboss/cache/marshall AbstractMarshaller.java
Log:
Made marshallers pluggable (JBCACHE-870)
Revision Changes Path
1.6 +4 -4 JBossCache/src/org/jboss/cache/marshall/CacheMarshaller200.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: CacheMarshaller200.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/marshall/CacheMarshaller200.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- CacheMarshaller200.java 15 Jan 2007 16:19:09 -0000 1.5
+++ CacheMarshaller200.java 15 Jan 2007 18:10:56 -0000 1.6
@@ -39,7 +39,7 @@
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
*/
-public class CacheMarshaller200 extends Marshaller
+public class CacheMarshaller200 extends AbstractMarshaller
{
// logger
private Log log = LogFactory.getLog(CacheMarshaller200.class);
@@ -93,9 +93,9 @@
return !(o instanceof MethodCall);
}
- // -------- Marshaller interface
+ // -------- AbstractMarshaller interface
- public void objectToStream(Object o, ObjectOutputStream out) throws Exception
+ public void objectToObjectStream(Object o, ObjectOutputStream out) throws Exception
{
if (log.isTraceEnabled()) log.trace("Marshalling object " + o);
Map<Object, Integer> refMap = new HashMap<Object, Integer>();
@@ -135,7 +135,7 @@
marshallObject(o, out, refMap);
}
- public Object objectFromStream(ObjectInputStream in) throws Exception
+ public Object objectFromObjectStream(ObjectInputStream in) throws Exception
{
Object retValue;
Map<Integer, Object> refMap = new HashMap<Integer, Object>();
1.3 +2 -2 JBossCache/src/org/jboss/cache/marshall/InactiveRegionException.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: InactiveRegionException.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/marshall/InactiveRegionException.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- InactiveRegionException.java 11 Dec 2006 21:14:35 -0000 1.2
+++ InactiveRegionException.java 15 Jan 2007 18:10:56 -0000 1.3
@@ -3,7 +3,7 @@
import org.jboss.cache.CacheException;
/**
- * Thrown by a {@link org.jboss.cache.marshall.Marshaller} instance when attempting to perform an operation on an inactive region.
+ * Thrown by a {@link org.jboss.cache.marshall.AbstractMarshaller} instance when attempting to perform an operation on an inactive region.
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
* @since 2.0.0
1.9 +42 -182 JBossCache/src/org/jboss/cache/marshall/Marshaller.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Marshaller.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/marshall/Marshaller.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- Marshaller.java 15 Jan 2007 11:22:39 -0000 1.8
+++ Marshaller.java 15 Jan 2007 18:10:56 -0000 1.9
@@ -1,215 +1,75 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
package org.jboss.cache.marshall;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.GlobalTransaction;
-import org.jboss.cache.Region;
-import org.jboss.cache.RegionManager;
-import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jgroups.blocks.RpcDispatcher;
+import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
/**
- * Abstract Marshaller for JBoss Cache.
+ * A marshaller is a class that is able to marshall and unmarshall objects efficiently.
+ * <p/>
+ * The reason why this is implemented specially in JBoss Cache rather than resorting to
+ * Java serialization or even the more efficient JBoss serialization is that a lot of efficiency
+ * can be gained when a majority of the serialization that occurs has to do with a small set
+ * of known types such as {@link Fqn} or {@link MethodCall}.
+ * <p/>
+ * Unknown types (typically user data} falls back to JBoss serialization.
+ * <p/>
+ * In addition, using a marshaller allows adding additional data to the byte stream, such as context
+ * class loader information on which class loader to use to deserialize the object stream, or versioning
+ * information to allow streams to interoperate between different versions of JBoss Cache (see {@link VersionAwareMarshaller}
+ * <p/>
+ * This interface implements the JGroups building-block interface {@link org.jgroups.blocks.RpcDispatcher.Marshaller} which
+ * is used to marshall {@link MethodCall}s, their parameters and their response values.
+ * <p/>
+ * The interface is also used by the {@link CacheLoader} framework to efficiently serialize data to be persisted, as well as
+ * the {@link org.jboss.cache.statetransfer.StateTransferManager} when serializing the cache for transferring state en-masse.
*
- * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
+ * @author <a href="mailto://manik@jboss.org">Manik Surtani</a>
+ * @since 2.0.0
*/
-public abstract class Marshaller
+public interface Marshaller extends RpcDispatcher.Marshaller
{
- protected boolean useRegionBasedMarshalling;
- protected RegionManager regionManager;
- protected boolean defaultInactive;
- private static Log log = LogFactory.getLog(Marshaller.class);
-
/**
- * Map<GlobalTransaction, Fqn> for prepared tx that have not committed
- */
- private Map<GlobalTransaction, String> transactions = new ConcurrentHashMap<GlobalTransaction, String>(16);
-
- protected void init(RegionManager manager, boolean defaultInactive, boolean useRegionBasedMarshalling)
- {
- this.useRegionBasedMarshalling = useRegionBasedMarshalling;
- this.defaultInactive = defaultInactive;
- this.regionManager = manager;
- }
-
- /**
- * Implementation classes will need to marshall the object passed in and write the object
- * into the given stream.
+ * Marshalls an object to a given ObjectOutputStream
*
- * @param obj
- * @param out
+ * @param obj object to marshall
+ * @param out stream to marshall to
* @throws Exception
*/
- public abstract void objectToStream(Object obj, ObjectOutputStream out) throws Exception;
+ void objectToObjectStream(Object obj, ObjectOutputStream out) throws Exception;
/**
- * Implementation classes will need to parse the given stream and create an object from it.
+ * Unmarshalls an object from a stream
*
- * @param in
+ * @param in stream to unmarshall from
* @throws Exception
*/
- public abstract Object objectFromStream(ObjectInputStream in) throws Exception;
-
-
- /**
- * This is "replicate" call with a single MethodCall argument.
- *
- * @param call
- */
- protected String extractFqnFromMethodCall(MethodCall call)
- {
- MethodCall c0 = (MethodCall) call.getArgs()[0];
- return extractFqn(c0);
- }
+ Object objectFromObjectStream(ObjectInputStream in) throws Exception;
/**
- * This is "replicate" call with a list of MethodCall argument.
+ * Creates an Object from the InputStream passed in
*
- * @param call
+ * @param is stream to unmarshall from
+ * @return Object from stream passed in.
+ * @throws Exception
*/
- protected String extractFqnFromListOfMethodCall(MethodCall call)
- {
- Object[] args = call.getArgs();
- // We simply pick the first one and assume everyone will need to operate under the same region!
- MethodCall c0 = (MethodCall) ((List) args[0]).get(0);
- return extractFqn(c0);
- }
-
- protected String extractFqn(MethodCall methodCall)
- {
- if (methodCall == null)
- {
- throw new NullPointerException("method call is null");
- }
-
- String fqnStr = null;
- Object[] args = methodCall.getArgs();
- switch (methodCall.getMethodId())
- {
- case MethodDeclarations.optimisticPrepareMethod_id:
- case MethodDeclarations.prepareMethod_id:
- // Prepare method has a list of modifications. We will just take the first one and extract.
- List modifications = (List) args[1];
- fqnStr = extractFqn((MethodCall) modifications.get(0));
-
- // the last arg of a prepare call is the one-phase flag
- boolean one_phase_commit = (Boolean) args[args.length - 1];
-
- // If this is two phase commit, map the FQN to the GTX so
- // we can find it when the commit/rollback comes through
- if (!one_phase_commit)
- {
- transactions.put((GlobalTransaction) args[0], fqnStr);
- }
- break;
- case MethodDeclarations.rollbackMethod_id:
- case MethodDeclarations.commitMethod_id:
- // We stored the fqn in the transactions map during the prepare phase
- fqnStr = transactions.remove(args[0]);
- break;
- case MethodDeclarations.getPartialStateMethod_id:
- case MethodDeclarations.dataGravitationMethod_id:
- case MethodDeclarations.evictNodeMethodLocal_id:
- case MethodDeclarations.evictVersionedNodeMethodLocal_id:
- case MethodDeclarations.getChildrenNamesMethodLocal_id:
- case MethodDeclarations.getDataMapMethodLocal_id:
- case MethodDeclarations.getKeysMethodLocal_id:
- case MethodDeclarations.getKeyValueMethodLocal_id:
- Fqn fqn = (Fqn) args[0];
- fqnStr = fqn.toString();
- break;
- case MethodDeclarations.dataGravitationCleanupMethod_id:
- Fqn fqn1 = (Fqn) args[1];
- fqnStr = fqn1.toString();
- break;
- case MethodDeclarations.remoteAnnounceBuddyPoolNameMethod_id:
- case MethodDeclarations.remoteAssignToBuddyGroupMethod_id:
- case MethodDeclarations.remoteRemoveFromBuddyGroupMethod_id:
- break;
- case MethodDeclarations.replicateMethod_id:
- case MethodDeclarations.clusteredGetMethod_id:
- // possible when we have a replication queue.
- fqnStr = extractFqn((MethodCall) args[0]);
- break;
- default:
- if (MethodDeclarations.isCrudMethod(methodCall.getMethodId()))
- {
- Fqn fqn2 = (Fqn) args[1];
- fqnStr = fqn2.toString();
- }
- else
- {
- throw new IllegalArgumentException("Marshaller.extractFqn(): Unknown id in method call: " + methodCall);
- }
- break;
-
- }
-
- if (log.isTraceEnabled())
- {
- log.trace("extract(): received " + methodCall + "extracted fqn: " + fqnStr);
- }
-
- return fqnStr;
- }
+ Object objectFromStream(InputStream is) throws Exception;
/**
- * Retrieves the {@link Region} from the {@link RegionManager} after taking into account that this may be a Buddy Backup FQN
+ * Tests whether a particular Fqn passed in is inactive.
*
- * @param fqnString
- * @return
+ * @param fqn
+ * @return true if the fqn is inactive
*/
- protected Region getRegion(String fqnString)
- {
- Fqn fqn = Fqn.fromString(fqnString);
-
- if (BuddyManager.isBackupFqn(fqn))
- {
- // Strip out the buddy group portion
- fqn = fqn.getFqnChild(2, fqn.size());
- }
- return regionManager.getRegion(fqn, false);
- }
-
- /**
- * Gets the classloader previously registered for <code>fqn</code>.
- *
- * @param fqn the fqn
- * @return the classloader associated with the cache region rooted by
- * <code>fqn</code>, or <code>null</code> if no classloader has
- * been associated with the region.
- */
- public ClassLoader getClassLoader(String fqn)
- {
- ClassLoader result = null;
- Region region = regionManager.getRegion(Fqn.fromString(fqn), false);
- if (region != null) result = region.getClassLoader();
- return result;
- }
+ boolean isInactive(String fqn);
/**
- * Gets whether unmarshalling has been disabled for the region
- * rooted in the given Fqn.
+ * Returns the class loader associated with a particular Fqn.
*
* @param fqn
- * @return <code>true</code> if unmarshalling is disabled;
- * <code>false</code> otherwise.
+ * @return the context class loader associated with the Fqn passed in.
*/
- public boolean isInactive(String fqn)
- {
- Region region = regionManager.getRegion(Fqn.fromString(fqn), false);
- return region == null ? defaultInactive : !region.isActive();
- }
+ ClassLoader getClassLoader(String fqn);
}
1.14 +21 -20 JBossCache/src/org/jboss/cache/marshall/VersionAwareMarshaller.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: VersionAwareMarshaller.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/marshall/VersionAwareMarshaller.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- VersionAwareMarshaller.java 12 Jan 2007 17:02:02 -0000 1.13
+++ VersionAwareMarshaller.java 15 Jan 2007 18:10:56 -0000 1.14
@@ -9,30 +9,29 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.RegionManager;
-import org.jgroups.blocks.RpcDispatcher;
import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
/**
- * A facade to various other marshallers like {@link org.jboss.cache.marshall.CacheMarshaller200}
- * which is version-aware.
+ * A delegate to various other marshallers like {@link org.jboss.cache.marshall.CacheMarshaller200}.
+ * This delegating marshaller adds versioning to the stream.
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
* @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
*/
-public class VersionAwareMarshaller implements RpcDispatcher.Marshaller
+public class VersionAwareMarshaller extends AbstractMarshaller
{
private RegionManager manager;
private boolean defaultInactive, useRegionBasedMarshalling;
private Log log = LogFactory.getLog(VersionAwareMarshaller.class);
- Marshaller defaultMarshaller;
+ AbstractMarshaller defaultMarshaller;
Map<Integer, Marshaller> marshallers = new HashMap<Integer, Marshaller>();
private static final int VERSION_200 = 20;
@@ -109,7 +108,7 @@
}
/**
- * Marshals the object passed in to a byte buffer using an appropriate {@link Marshaller} based on
+ * Marshals the object passed in to a byte buffer using an appropriate {@link AbstractMarshaller} based on
* the version information passed in to this instance upon construction (See {@link #VersionAwareMarshaller(org.jboss.cache.RegionManager,boolean,boolean,String)})
*
* @param obj
@@ -126,7 +125,7 @@
out.writeShort(versionInt);
//now marshall the contents of the object
- defaultMarshaller.objectToStream(obj, out);
+ defaultMarshaller.objectToObjectStream(obj, out);
out.close();
// and return bytes.
@@ -134,7 +133,7 @@
}
/**
- * Creates an Object from the byte buffer passed in, using the appropriate {@link Marshaller} based
+ * Creates an Object from the byte buffer passed in, using the appropriate {@link AbstractMarshaller} based
* on the version headers in the byte stream.
*
* @param buf
@@ -161,18 +160,10 @@
marshaller = getMarshaller(versionId);
- return marshaller.objectFromStream(in);
+ return marshaller.objectFromObjectStream(in);
}
- /**
- * Creates an Object from the InputStream passed in, using the appropriate {@link Marshaller} based
- * on the version headers in the byte stream.
- *
- * @param is
- * @return Object from byte buffer passed in.
- * @throws Exception
- */
- public Object objectFromInputStream(InputStream is) throws Exception
+ public Object objectFromStream(InputStream is) throws Exception
{
Marshaller marshaller;
int versionId;
@@ -192,7 +183,7 @@
marshaller = getMarshaller(versionId);
- return marshaller.objectFromStream(in);
+ return marshaller.objectFromObjectStream(in);
}
/**
@@ -230,6 +221,16 @@
return defaultMarshaller.isInactive(fqn);
}
+ public void objectToObjectStream(Object obj, ObjectOutputStream out) throws Exception
+ {
+ defaultMarshaller.objectToObjectStream(obj, out);
+ }
+
+ public Object objectFromObjectStream(ObjectInputStream in) throws Exception
+ {
+ return objectFromStream(in);
+ }
+
/**
* Returns the class loader associated with a particular Fqn.
*
1.1 date: 2007/01/15 18:10:56; author: msurtani; state: Exp;JBossCache/src/org/jboss/cache/marshall/AbstractMarshaller.java
Index: AbstractMarshaller.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.marshall;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.GlobalTransaction;
import org.jboss.cache.Region;
import org.jboss.cache.RegionManager;
import org.jboss.cache.buddyreplication.BuddyManager;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Abstract AbstractMarshaller for JBoss Cache.
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
*/
public abstract class AbstractMarshaller implements Marshaller
{
protected boolean useRegionBasedMarshalling;
protected RegionManager regionManager;
protected boolean defaultInactive;
private static Log log = LogFactory.getLog(AbstractMarshaller.class);
/**
* Map<GlobalTransaction, Fqn> for prepared tx that have not committed
*/
private Map<GlobalTransaction, String> transactions = new ConcurrentHashMap<GlobalTransaction, String>(16);
protected void init(RegionManager manager, boolean defaultInactive, boolean useRegionBasedMarshalling)
{
this.useRegionBasedMarshalling = useRegionBasedMarshalling;
this.defaultInactive = defaultInactive;
this.regionManager = manager;
}
// implement the basic contract set in RPcDispatcher.AbstractMarshaller
public byte[] objectToByteBuffer(Object obj) throws Exception
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = ObjectSerializationFactory.createObjectOutputStream(baos);
objectToObjectStream(obj, out);
out.close();
return baos.toByteArray();
}
public Object objectFromByteBuffer(byte[] bytes) throws Exception
{
ObjectInputStream in = ObjectSerializationFactory.createObjectInputStream(bytes);
return objectFromObjectStream(in);
}
public Object objectFromStream(InputStream in) throws Exception
{
// by default just create an OIS from this IS and pass in to the relevant method
if (in instanceof ObjectInputStream)
{
return objectFromObjectStream((ObjectInputStream) in);
}
else
{
return objectFromObjectStream(ObjectSerializationFactory.createObjectInputStream(in));
}
}
/**
* This is "replicate" call with a single MethodCall argument.
*
* @param call
*/
protected String extractFqnFromMethodCall(MethodCall call)
{
MethodCall c0 = (MethodCall) call.getArgs()[0];
return extractFqn(c0);
}
/**
* This is "replicate" call with a list of MethodCall argument.
*
* @param call
*/
protected String extractFqnFromListOfMethodCall(MethodCall call)
{
Object[] args = call.getArgs();
// We simply pick the first one and assume everyone will need to operate under the same region!
MethodCall c0 = (MethodCall) ((List) args[0]).get(0);
return extractFqn(c0);
}
protected String extractFqn(MethodCall methodCall)
{
if (methodCall == null)
{
throw new NullPointerException("method call is null");
}
String fqnStr = null;
Object[] args = methodCall.getArgs();
switch (methodCall.getMethodId())
{
case MethodDeclarations.optimisticPrepareMethod_id:
case MethodDeclarations.prepareMethod_id:
// Prepare method has a list of modifications. We will just take the first one and extract.
List modifications = (List) args[1];
fqnStr = extractFqn((MethodCall) modifications.get(0));
// the last arg of a prepare call is the one-phase flag
boolean one_phase_commit = (Boolean) args[args.length - 1];
// If this is two phase commit, map the FQN to the GTX so
// we can find it when the commit/rollback comes through
if (!one_phase_commit)
{
transactions.put((GlobalTransaction) args[0], fqnStr);
}
break;
case MethodDeclarations.rollbackMethod_id:
case MethodDeclarations.commitMethod_id:
// We stored the fqn in the transactions map during the prepare phase
fqnStr = transactions.remove(args[0]);
break;
case MethodDeclarations.getPartialStateMethod_id:
case MethodDeclarations.dataGravitationMethod_id:
case MethodDeclarations.evictNodeMethodLocal_id:
case MethodDeclarations.evictVersionedNodeMethodLocal_id:
case MethodDeclarations.getChildrenNamesMethodLocal_id:
case MethodDeclarations.getDataMapMethodLocal_id:
case MethodDeclarations.getKeysMethodLocal_id:
case MethodDeclarations.getKeyValueMethodLocal_id:
Fqn fqn = (Fqn) args[0];
fqnStr = fqn.toString();
break;
case MethodDeclarations.dataGravitationCleanupMethod_id:
Fqn fqn1 = (Fqn) args[1];
fqnStr = fqn1.toString();
break;
case MethodDeclarations.remoteAnnounceBuddyPoolNameMethod_id:
case MethodDeclarations.remoteAssignToBuddyGroupMethod_id:
case MethodDeclarations.remoteRemoveFromBuddyGroupMethod_id:
break;
case MethodDeclarations.replicateMethod_id:
case MethodDeclarations.clusteredGetMethod_id:
// possible when we have a replication queue.
fqnStr = extractFqn((MethodCall) args[0]);
break;
default:
if (MethodDeclarations.isCrudMethod(methodCall.getMethodId()))
{
Fqn fqn2 = (Fqn) args[1];
fqnStr = fqn2.toString();
}
else
{
throw new IllegalArgumentException("AbstractMarshaller.extractFqn(): Unknown id in method call: " + methodCall);
}
break;
}
if (log.isTraceEnabled())
{
log.trace("extract(): received " + methodCall + "extracted fqn: " + fqnStr);
}
return fqnStr;
}
/**
* Retrieves the {@link Region} from the {@link RegionManager} after taking into account that this may be a Buddy Backup FQN
*
* @param fqnString
* @return
*/
protected Region getRegion(String fqnString)
{
Fqn fqn = Fqn.fromString(fqnString);
if (BuddyManager.isBackupFqn(fqn))
{
// Strip out the buddy group portion
fqn = fqn.getFqnChild(2, fqn.size());
}
return regionManager.getRegion(fqn, false);
}
/**
* Gets the classloader previously registered for <code>fqn</code>.
*
* @param fqn the fqn
* @return the classloader associated with the cache region rooted by
* <code>fqn</code>, or <code>null</code> if no classloader has
* been associated with the region.
*/
public ClassLoader getClassLoader(String fqn)
{
ClassLoader result = null;
Region region = regionManager.getRegion(Fqn.fromString(fqn), false);
if (region != null) result = region.getClassLoader();
return result;
}
/**
* Gets whether unmarshalling has been disabled for the region
* rooted in the given Fqn.
*
* @param fqn
* @return <code>true</code> if unmarshalling is disabled;
* <code>false</code> otherwise.
*/
public boolean isInactive(String fqn)
{
Region region = regionManager.getRegion(Fqn.fromString(fqn), false);
return region == null ? defaultInactive : !region.isActive();
}
}
More information about the jboss-cvs-commits
mailing list