Author: mircea.markus
Date: 2009-02-11 07:53:09 -0500 (Wed, 11 Feb 2009)
New Revision: 7682
Added:
core/branches/flat/src/test/java/org/horizon/interceptors/
core/branches/flat/src/test/java/org/horizon/interceptors/MarshalledValueInterceptorTest.java
core/branches/flat/src/test/java/org/horizon/marshall/
core/branches/flat/src/test/java/org/horizon/marshall/MarshalledValueTest.java
Removed:
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueHelper.java
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueMap.java
Modified:
core/branches/flat/src/main/java/org/horizon/Cache.java
core/branches/flat/src/main/java/org/horizon/CacheDelegate.java
core/branches/flat/src/main/java/org/horizon/config/GlobalConfiguration.java
core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java
core/branches/flat/src/main/java/org/horizon/interceptors/MarshalledValueInterceptor.java
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValue.java
core/branches/flat/src/main/resources/config-samples/all.xml
core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd
core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java
core/branches/flat/src/test/java/org/horizon/config/parsing/XmlFileParsingTest.java
core/branches/flat/src/test/resources/configs/named-cache-test.xml
Log:
added support for lazy deserialization
Modified: core/branches/flat/src/main/java/org/horizon/Cache.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/Cache.java 2009-02-11 11:09:31 UTC (rev
7681)
+++ core/branches/flat/src/main/java/org/horizon/Cache.java 2009-02-11 12:53:09 UTC (rev
7682)
@@ -140,5 +140,14 @@
AdvancedCache<K, V> getAdvancedCache();
+ /**
+ * Method that releases object references of cached objects held in the cache by
serializing them to byte buffers.
+ * Cached objects are lazily deserialized when accessed again, based on the calling
thread's context class loader.
+ * <p/>
+ * This can be expensive, based on the effort required to serialize cached objects.
+ * <p/>
+ */
+ void compact();
+
ComponentStatus getStatus();
}
Modified: core/branches/flat/src/main/java/org/horizon/CacheDelegate.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/CacheDelegate.java 2009-02-11 11:09:31
UTC (rev 7681)
+++ core/branches/flat/src/main/java/org/horizon/CacheDelegate.java 2009-02-11 12:53:09
UTC (rev 7682)
@@ -50,6 +50,7 @@
import org.horizon.logging.Log;
import org.horizon.logging.LogFactory;
import org.horizon.manager.CacheManager;
+import org.horizon.marshall.MarshalledValue;
import org.horizon.marshall.Marshaller;
import org.horizon.notifications.cachelistener.CacheNotifier;
import org.horizon.remoting.RPCManager;
@@ -432,4 +433,23 @@
public AdvancedCache<K, V> getAdvancedCache() {
return this;
}
+
+ public void compact() {
+ for (Object key : dataContainer.keySet())
+ {
+ // get the key first, before attempting to serialize stuff since data.get() may
deserialize the key if doing
+ // a hashcode() or equals().
+
+ Object value = dataContainer.get(key);
+ if (key instanceof MarshalledValue)
+ {
+ ((MarshalledValue) key).compact(true, true);
+ }
+
+ if (value instanceof MarshalledValue)
+ {
+ ((MarshalledValue) value).compact(true, true);
+ }
+ }
+ }
}
Modified: core/branches/flat/src/main/java/org/horizon/config/GlobalConfiguration.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/config/GlobalConfiguration.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/main/java/org/horizon/config/GlobalConfiguration.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -31,23 +31,23 @@
*/
public static final short DEFAULT_MARSHALL_VERSION = Version.getVersionShort();
- String asyncListenerExecutorFactoryClass = DefaultExecutorFactory.class.getName();
- TypedProperties asyncListenerExecutorProperties = EMPTY_PROPERTIES;
- String asyncSerializationExecutorFactoryClass =
DefaultExecutorFactory.class.getName();
- TypedProperties asyncSerializationExecutorProperties = EMPTY_PROPERTIES;
- String evictionScheduledExecutorFactoryClass =
DefaultScheduledExecutorFactory.class.getName();
- TypedProperties evictionScheduledExecutorProperties = EMPTY_PROPERTIES;
- String replicationQueueScheduledExecutorFactoryClass =
DefaultScheduledExecutorFactory.class.getName();
- TypedProperties replicationQueueScheduledExecutorProperties = EMPTY_PROPERTIES;
- String marshallerClass = VersionAwareMarshaller.class.getName(); // the default
- int objectInputStreamPoolSize = 50; // defaults
- int objectOutputStreamPoolSize = 50; // defaults
- String transportClass = null; // this defaults to a non-clustered cache.
- TypedProperties transportProperties = EMPTY_PROPERTIES;
- Configuration defaultConfiguration;
- String clusterName = "Horizon-Cluster";
- ShutdownHookBehavior shutdownHookBehavior = ShutdownHookBehavior.DEFAULT;
- short marshallVersion = DEFAULT_MARSHALL_VERSION;
+ private String asyncListenerExecutorFactoryClass =
DefaultExecutorFactory.class.getName();
+ private TypedProperties asyncListenerExecutorProperties = EMPTY_PROPERTIES;
+ private String asyncSerializationExecutorFactoryClass =
DefaultExecutorFactory.class.getName();
+ private TypedProperties asyncSerializationExecutorProperties = EMPTY_PROPERTIES;
+ private String evictionScheduledExecutorFactoryClass =
DefaultScheduledExecutorFactory.class.getName();
+ private TypedProperties evictionScheduledExecutorProperties = EMPTY_PROPERTIES;
+ private String replicationQueueScheduledExecutorFactoryClass =
DefaultScheduledExecutorFactory.class.getName();
+ private TypedProperties replicationQueueScheduledExecutorProperties =
EMPTY_PROPERTIES;
+ private String marshallerClass = VersionAwareMarshaller.class.getName(); // the
default
+ private int objectInputStreamPoolSize = 50; // defaults
+ private int objectOutputStreamPoolSize = 50; // defaults
+ private String transportClass = null; // this defaults to a non-clustered cache.
+ private TypedProperties transportProperties = EMPTY_PROPERTIES;
+ private Configuration defaultConfiguration;
+ private String clusterName = "Horizon-Cluster";
+ private ShutdownHookBehavior shutdownHookBehavior = ShutdownHookBehavior.DEFAULT;
+ private short marshallVersion = DEFAULT_MARSHALL_VERSION;
private GlobalComponentRegistry gcr;
Modified:
core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -151,6 +151,7 @@
configureLocking(getSingleElementInCoreNS("locking", e), c);
configureTransaction(getSingleElementInCoreNS("transaction", e), c);
configureJmxStatistics(getSingleElementInCoreNS("jmxStatistics", e), c);
+
configureLazyDeserialization(getSingleElementInCoreNS("lazyDeserialization", e),
c);
configureInvocationBatching(getSingleElementInCoreNS("invocationBatching", e),
c);
configureClustering(getSingleElementInCoreNS("clustering", e), c);
configureEviction(getSingleElementInCoreNS("eviction", e), c);
@@ -293,6 +294,15 @@
}
}
+ void configureLazyDeserialization(Element element, Configuration config) {
+ if (element != null) {
+ String enabled = getAttributeValue(element, "enabled");
+ if (existsAttribute(enabled)) {
+ config.setUseLazyDeserialization(getBoolean(enabled));
+ }
+ }
+ }
+
void configureInvalidation(Element element, Configuration config) {
if (element == null) return; //might be replication
Element async = getSingleElement("async");
Modified:
core/branches/flat/src/main/java/org/horizon/interceptors/MarshalledValueInterceptor.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/interceptors/MarshalledValueInterceptor.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/main/java/org/horizon/interceptors/MarshalledValueInterceptor.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -28,7 +28,6 @@
import org.horizon.context.InvocationContext;
import org.horizon.interceptors.base.CommandInterceptor;
import org.horizon.marshall.MarshalledValue;
-import org.horizon.marshall.MarshalledValueHelper;
import java.io.IOException;
import java.io.NotSerializableException;
@@ -47,6 +46,7 @@
* representations.
*
* @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @author Mircea.Markus(a)jboss.com
* @see org.horizon.marshall.MarshalledValue
* @since 1.0
*/
@@ -54,59 +54,68 @@
@Override
public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws
Throwable {
Set<MarshalledValue> marshalledValues = new
HashSet<MarshalledValue>();
-
- command.setMap(wrapMap(command.getMap(), marshalledValues, ctx));
+ Map map = wrapMap(command.getMap(), marshalledValues, ctx);
+ command.setMap(map);
Object retVal = invokeNextInterceptor(ctx, command);
return compactAndProcessRetVal(marshalledValues, retVal);
}
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand
command) throws Throwable {
- Set<MarshalledValue> marshalledValues = new
HashSet<MarshalledValue>();
- if (!MarshalledValueHelper.isTypeExcluded(command.getKey().getClass())) {
- Object newKey = createAndAddMarshalledValue(command.getKey(), marshalledValues,
ctx);
- command.setKey(newKey);
+ MarshalledValue key = null;
+ MarshalledValue value = null;
+ if (!MarshalledValue.isTypeExcluded(command.getKey().getClass())) {
+ key = createMarshalledValue(command.getKey(), ctx);
+ command.setKey(key);
}
- if (!MarshalledValueHelper.isTypeExcluded(command.getValue().getClass())) {
- Object value = createAndAddMarshalledValue(command.getValue(), marshalledValues,
ctx);
+ if (!MarshalledValue.isTypeExcluded(command.getValue().getClass())) {
+ value = createMarshalledValue(command.getValue(), ctx);
command.setValue(value);
}
Object retVal = invokeNextInterceptor(ctx, command);
- return compactAndProcessRetVal(marshalledValues, retVal);
+ compact(key);
+ compact(value);
+ return processRetVal(retVal);
}
@Override
public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws
Throwable {
- Set<MarshalledValue> marshalledValues = new
HashSet<MarshalledValue>();
- if (!MarshalledValueHelper.isTypeExcluded(command.getKey().getClass())) {
- Object value = createAndAddMarshalledValue(command.getKey(), marshalledValues,
ctx);
+ MarshalledValue value = null;
+ if (!MarshalledValue.isTypeExcluded(command.getKey().getClass())) {
+ value = createMarshalledValue(command.getKey(), ctx);
command.setKey(value);
}
Object retVal = invokeNextInterceptor(ctx, command);
- return compactAndProcessRetVal(marshalledValues, retVal);
+ compact(value);
+ return processRetVal(retVal);
}
@Override
public Object visitGetKeyValueCommand(InvocationContext ctx, GetKeyValueCommand
command) throws Throwable {
- Set<MarshalledValue> marshalledValues = new
HashSet<MarshalledValue>();
- if (!MarshalledValueHelper.isTypeExcluded(command.getKey().getClass())) {
- Object value = createAndAddMarshalledValue(command.getKey(), marshalledValues,
ctx);
- command.setKey(value);
+ MarshalledValue mv = null;
+ if (!MarshalledValue.isTypeExcluded(command.getKey().getClass())) {
+ mv = createMarshalledValue(command.getKey(), ctx);
+ command.setKey(mv);
+ compact(mv);
}
Object retVal = invokeNextInterceptor(ctx, command);
- return compactAndProcessRetVal(marshalledValues, retVal);
+ compact(mv);
+ return processRetVal(retVal);
}
private Object compactAndProcessRetVal(Set<MarshalledValue> marshalledValues,
Object retVal)
throws IOException, ClassNotFoundException {
if (trace) log.trace("Compacting MarshalledValues created");
- for (MarshalledValue mv : marshalledValues) mv.compact(false, false);
-
+ for (MarshalledValue mv : marshalledValues) compact(mv);
return processRetVal(retVal);
}
- private Object processRetVal(Object retVal)
- throws IOException, ClassNotFoundException {
+ private void compact(MarshalledValue mv) {
+ if (mv == null) return;
+ mv.compact(false, false);
+ }
+
+ private Object processRetVal(Object retVal) throws IOException, ClassNotFoundException
{
if (retVal instanceof MarshalledValue) {
if (trace) log.trace("Return value is a MarshalledValue.
Unwrapping.");
retVal = ((MarshalledValue) retVal).get();
@@ -125,16 +134,16 @@
for (Map.Entry me : m.entrySet()) {
Object key = me.getKey();
Object value = me.getValue();
- copy.put((key == null || MarshalledValueHelper.isTypeExcluded(key.getClass())) ?
key : createAndAddMarshalledValue(key, marshalledValues, ctx),
- (value == null ||
MarshalledValueHelper.isTypeExcluded(value.getClass())) ? value :
createAndAddMarshalledValue(value, marshalledValues, ctx));
+ Object newKey = (key == null || MarshalledValue.isTypeExcluded(key.getClass()))
? key : createMarshalledValue(key, ctx);
+ Object newValue = (value == null ||
MarshalledValue.isTypeExcluded(value.getClass())) ? value : createMarshalledValue(value,
ctx);
+ if (newKey instanceof MarshalledValue) marshalledValues.add((MarshalledValue)
newKey);
+ if (newValue instanceof MarshalledValue) marshalledValues.add((MarshalledValue)
newValue);
+ copy.put(newKey, newValue);
}
return copy;
}
- protected MarshalledValue createAndAddMarshalledValue(Object toWrap,
Set<MarshalledValue> marshalledValues, InvocationContext ctx) throws
NotSerializableException {
- MarshalledValue mv = new MarshalledValue(toWrap);
- marshalledValues.add(mv);
- if (!ctx.isOriginLocal()) mv.setEqualityPreferenceForInstance(false);
- return mv;
+ protected MarshalledValue createMarshalledValue(Object toWrap, InvocationContext ctx)
throws NotSerializableException {
+ return new MarshalledValue(toWrap, ctx.isOriginLocal());
}
}
Modified: core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValue.java 2009-02-11
11:09:31 UTC (rev 7681)
+++ core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValue.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -22,6 +22,9 @@
package org.horizon.marshall;
import org.horizon.CacheException;
+import org.horizon.commands.ReplicableCommand;
+import org.horizon.remoting.transport.Address;
+import org.horizon.transaction.GlobalTransaction;
import org.jboss.util.stream.MarshalledValueInputStream;
import java.io.*;
@@ -35,6 +38,7 @@
* <p/>
*
* @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @author Mircea.Markus(a)jboss.com
* @see org.horizon.interceptors.MarshalledValueInterceptor
* @since 1.0
*/
@@ -45,23 +49,20 @@
// by default equals() will test on the istance rather than the byte array if
conversion is required.
private transient boolean equalityPreferenceForInstance = true;
- public MarshalledValue(Object instance) throws NotSerializableException {
+ public MarshalledValue(Object instance, boolean equalityPreferenceForInstance) throws
NotSerializableException {
if (instance == null) throw new NullPointerException("Null values cannot be
wrapped as MarshalledValues!");
if (instance instanceof Serializable)
this.instance = instance;
else
throw new NotSerializableException("Marshalled values can only wrap Objects
that are serializable! Instance of " + instance.getClass() + " won't
Serialize.");
+ this.equalityPreferenceForInstance = equalityPreferenceForInstance;
}
public MarshalledValue() {
// empty ctor for serialization
}
- public void setEqualityPreferenceForInstance(boolean equalityPreferenceForInstance) {
- this.equalityPreferenceForInstance = equalityPreferenceForInstance;
- }
-
public synchronized void serialize() {
if (raw == null) {
try {
@@ -72,7 +73,6 @@
baos.close();
// Do NOT set instance to null over here, since it may be used elsewhere
(e.g., in a cache listener).
// this will be compacted by the MarshalledValueInterceptor when the call
returns.
-// instance = null;
raw = baos.toByteArray();
}
catch (Exception e) {
@@ -90,7 +90,6 @@
instance = ois.readObject();
ois.close();
bais.close();
-// raw = null;
}
catch (Exception e) {
throw new CacheException("Unable to unmarshall value", e);
@@ -123,13 +122,17 @@
// need to lose one representation!
if (preferSerializedRepresentation) {
- instance = null;
+ nullifyInstance();
} else {
raw = null;
}
}
}
+ private synchronized void nullifyInstance() {
+ instance = null;
+ }
+
public void writeExternal(ObjectOutput out) throws IOException {
if (raw == null) serialize();
out.writeInt(raw.length);
@@ -145,7 +148,13 @@
cachedHashCode = in.readInt();
}
- public Object get() throws IOException, ClassNotFoundException {
+ /**
+ * Returns the 'cached' instance.
+ * Impl note: this method is synchronized so that it synchronizez with the code that
nullifies the instance.
+ *
+ * @see #nullifyInstance()
+ */
+ public synchronized Object get() throws IOException, ClassNotFoundException {
if (instance == null) deserialize();
return instance;
}
@@ -191,4 +200,19 @@
public String toString() {
return "MarshalledValue(cachedHashCode=" + cachedHashCode + ";
serialized=" + (raw != null) + ")";
}
+
+ /**
+ * Tests whether the type should be excluded from MarshalledValue wrapping.
+ *
+ * @param type type to test. Should not be null.
+ * @return true if it should be excluded from MarshalledValue wrapping.
+ */
+ public static boolean isTypeExcluded(Class type) {
+ return type.equals(String.class) || type.isPrimitive() ||
+ type.equals(Void.class) || type.equals(Boolean.class) ||
type.equals(Character.class) ||
+ type.equals(Byte.class) || type.equals(Short.class) ||
type.equals(Integer.class) ||
+ type.equals(Long.class) || type.equals(Float.class) ||
type.equals(Double.class) ||
+ (type.isArray() && isTypeExcluded(type.getComponentType())) ||
type.equals(GlobalTransaction.class) || Address.class.isAssignableFrom(type) ||
+ ReplicableCommand.class.isAssignableFrom(type) ||
type.equals(MarshalledValue.class);
+ }
}
Deleted: core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueHelper.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueHelper.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueHelper.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -1,53 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 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.horizon.marshall;
-
-import org.horizon.commands.ReplicableCommand;
-import org.horizon.remoting.transport.Address;
-import org.horizon.transaction.GlobalTransaction;
-
-/**
- * Common functionality used by the {@link
org.horizon.interceptors.MarshalledValueInterceptor} and the {@link
- * MarshalledValueMap}.
- *
- * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
- * @see MarshalledValue
- * @see org.horizon.interceptors.MarshalledValueInterceptor
- * @see MarshalledValueMap
- * @since 1.0
- */
-public class MarshalledValueHelper {
- /**
- * Tests whether the type should be excluded from MarshalledValue wrapping.
- *
- * @param type type to test. Should not be null.
- * @return true if it should be excluded from MarshalledValue wrapping.
- */
- public static boolean isTypeExcluded(Class type) {
- return type.equals(String.class) || type.isPrimitive() ||
- type.equals(Void.class) || type.equals(Boolean.class) ||
type.equals(Character.class) ||
- type.equals(Byte.class) || type.equals(Short.class) ||
type.equals(Integer.class) ||
- type.equals(Long.class) || type.equals(Float.class) ||
type.equals(Double.class) ||
- (type.isArray() && isTypeExcluded(type.getComponentType())) ||
type.equals(GlobalTransaction.class) || Address.class.isAssignableFrom(type) ||
- ReplicableCommand.class.isAssignableFrom(type) ||
type.equals(MarshalledValue.class);
- }
-}
Deleted: core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueMap.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueMap.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/main/java/org/horizon/marshall/MarshalledValueMap.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -1,155 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 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.horizon.marshall;
-
-import net.jcip.annotations.Immutable;
-import org.horizon.CacheException;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A Map that is able to wrap/unwrap MarshalledValues in keys or values. Note that
calling keySet(), entrySet() or
- * values() could be expensive if this map is large!!
- * <p/>
- * Also note that this is an immutable Map.
- * <p/>
- *
- * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
- * @see MarshalledValue
- * @since 1.0
- */
-@Immutable
-public class MarshalledValueMap implements Map, Externalizable {
- Map delegate;
- Map<Object, Object> unmarshalled;
-
- public MarshalledValueMap() {
- // for externalization
- }
-
- public MarshalledValueMap(Map delegate) {
- this.delegate = delegate;
- }
-
- @SuppressWarnings("unchecked")
- protected synchronized Map getUnmarshalledMap() {
- if (unmarshalled == null) unmarshalled = unmarshalledMap(delegate.entrySet());
- return unmarshalled;
- }
-
- public int size() {
- return delegate.size();
- }
-
- public boolean isEmpty() {
- return delegate.isEmpty();
- }
-
- public boolean containsKey(Object key) {
- return getUnmarshalledMap().containsKey(key);
- }
-
- public boolean containsValue(Object value) {
- return getUnmarshalledMap().containsValue(value);
- }
-
- public Object get(Object key) {
- return getUnmarshalledMap().get(key);
- }
-
- public Object put(Object key, Object value) {
- throw new UnsupportedOperationException("This is an immutable map!");
- }
-
- public Object remove(Object key) {
- throw new UnsupportedOperationException("This is an immutable map!");
- }
-
- public void putAll(Map t) {
- throw new UnsupportedOperationException("This is an immutable map!");
- }
-
- public void clear() {
- throw new UnsupportedOperationException("This is an immutable map!");
- }
-
- public Set keySet() {
- return getUnmarshalledMap().keySet();
- }
-
- public Collection values() {
- return getUnmarshalledMap().values();
- }
-
- public Set entrySet() {
- return getUnmarshalledMap().entrySet();
- }
-
- @SuppressWarnings("unchecked")
- protected Map unmarshalledMap(Set entries) {
- if (entries == null || entries.isEmpty()) return Collections.emptyMap();
- Map map = new HashMap(entries.size());
- for (Object e : entries) {
- Map.Entry entry = (Map.Entry) e;
- map.put(getUnmarshalledValue(entry.getKey()),
getUnmarshalledValue(entry.getValue()));
- }
- return map;
- }
-
- private Object getUnmarshalledValue(Object o) {
- try {
- return o instanceof MarshalledValue ? ((MarshalledValue) o).get() : o;
- }
- catch (Exception e) {
- throw new CacheException("Unable to unmarshall value", e);
- }
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof Map) {
- return getUnmarshalledMap().equals(other);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return getUnmarshalledMap().hashCode();
- }
-
- public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(delegate);
- }
-
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- delegate = (Map) in.readObject();
- }
-}
Modified: core/branches/flat/src/main/resources/config-samples/all.xml
===================================================================
--- core/branches/flat/src/main/resources/config-samples/all.xml 2009-02-11 11:09:31 UTC
(rev 7681)
+++ core/branches/flat/src/main/resources/config-samples/all.xml 2009-02-11 12:53:09 UTC
(rev 7682)
@@ -77,6 +77,8 @@
-->
<jmxStatistics enabled="false"/>
+ <lazyDeserialization enabled="false"/>
+
<!--
Used to enable invocation batching and allow the use of
Cache.startBatch()/endBatch() methods.
-->
Modified: core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd
===================================================================
--- core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd 2009-02-11
11:09:31 UTC (rev 7681)
+++ core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd 2009-02-11
12:53:09 UTC (rev 7682)
@@ -47,6 +47,7 @@
<xs:element name="locking" type="tns:lockingType"
minOccurs="0" maxOccurs="1"/>
<xs:element name="transaction" type="tns:transactionType"
minOccurs="0" maxOccurs="1"/>
<xs:element name="jmxStatistics"
type="tns:jmxStatisticsType" minOccurs="0"
maxOccurs="1"/>
+ <xs:element name="lazyDeserialization"
type="tns:lazyDeserialization" minOccurs="0"
maxOccurs="1"/>
<xs:element name="invocationBatching"
type="tns:invocationBatchingType" minOccurs="0"
maxOccurs="1"/>
<xs:element name="eviction" type="tns:evictionType"
minOccurs="0" maxOccurs="1"/>
<xs:element name="loaders" type="tns:loadersType"
minOccurs="0" maxOccurs="1"/>
@@ -108,10 +109,6 @@
</xs:attribute>
</xs:complexType>
- <xs:complexType name="serializationType">
- <xs:attribute name="useLazyDeserialization"
type="tns:booleanType"/>
- </xs:complexType>
-
<xs:simpleType name="booleanType">
<xs:restriction base="xs:string">
<xs:pattern
value="\$\{.*\}|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]"/>
@@ -128,6 +125,10 @@
<xs:attribute name="enabled" type="tns:booleanType"/>
</xs:complexType>
+ <xs:complexType name="lazyDeserialization">
+ <xs:attribute name="enabled" type="tns:booleanType"/>
+ </xs:complexType>
+
<xs:complexType name="invocationBatchingType">
<xs:attribute name="enabled" type="tns:booleanType"/>
</xs:complexType>
Modified:
core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java
===================================================================
---
core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -75,6 +75,17 @@
assert c.isExposeManagementStatistics();
}
+ public void testLazyDeserialization() throws Exception {
+ XmlConfigurationParserImpl parser = new XmlConfigurationParserImpl();
+ String xml = "<lazyDeserialization enabled=\"true\"/>";
+ Element e = XmlConfigHelper.stringToElement(xml);
+
+ Configuration c = new Configuration();
+ parser.configureLazyDeserialization(e, c);
+
+ assert c.isExposeManagementStatistics();
+ }
+
public void testJmxStatisticsDefaults() throws Exception {
XmlConfigurationParserImpl parser = new XmlConfigurationParserImpl();
String xml = "<jmxStatistics />";
Modified:
core/branches/flat/src/test/java/org/horizon/config/parsing/XmlFileParsingTest.java
===================================================================
---
core/branches/flat/src/test/java/org/horizon/config/parsing/XmlFileParsingTest.java 2009-02-11
11:09:31 UTC (rev 7681)
+++
core/branches/flat/src/test/java/org/horizon/config/parsing/XmlFileParsingTest.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -87,6 +87,10 @@
assert c.getLockAcquisitionTimeout() == 20000;
assert c.getConcurrencyLevel() == 1000;
assert c.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
+ assert !c.isUseLazyDeserialization();
+
+ c = namedCaches.get("lazyDeserialization");
+ assert c.isUseLazyDeserialization();
}
public void testConfigurationMerging() throws IOException {
Added:
core/branches/flat/src/test/java/org/horizon/interceptors/MarshalledValueInterceptorTest.java
===================================================================
---
core/branches/flat/src/test/java/org/horizon/interceptors/MarshalledValueInterceptorTest.java
(rev 0)
+++
core/branches/flat/src/test/java/org/horizon/interceptors/MarshalledValueInterceptorTest.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -0,0 +1,135 @@
+package org.horizon.interceptors;
+
+import org.horizon.Cache;
+import org.horizon.config.Configuration;
+import org.horizon.config.GlobalConfiguration;
+import org.horizon.manager.CacheManager;
+import org.horizon.manager.DefaultCacheManager;
+import org.horizon.marshall.MarshalledValue;
+import org.horizon.util.TestingUtil;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik
AT jboss DOT org</a>)
+ * @author Mircea.Markus(a)jboss.com
+ * @since 1.0
+ */
+@Test(groups = "functional", sequential = true, testName =
"interceptors.MarshalledValueInterceptorTest")
+public class MarshalledValueInterceptorTest {
+ CacheManager cm;
+
+ @BeforeTest
+ public void setUp() {
+ cm = new DefaultCacheManager(GlobalConfiguration.getNonClusteredDefault());
+ }
+
+ @AfterTest
+ public void tearDown() {
+ TestingUtil.killCacheManagers(cm);
+ }
+
+ public void testDefaultInterceptorStack() {
+ assert TestingUtil.findInterceptor(cm.getCache(), MarshalledValueInterceptor.class)
== null;
+
+ Configuration configuration = new Configuration();
+ configuration.setUseLazyDeserialization(true);
+ cm.defineCache("someCache", configuration);
+ Cache c = cm.getCache("someCache");
+
+ assert TestingUtil.findInterceptor(c, MarshalledValueInterceptor.class) != null;
+ TestingUtil.killCaches(c);
+ }
+
+ public void testDisabledInterceptorStack() {
+ Configuration cfg = new Configuration();
+ cfg.setUseLazyDeserialization(false);
+ cm.defineCache("a", cfg);
+ Cache c = cm.getCache("a");
+ assert TestingUtil.findInterceptor(c, MarshalledValueInterceptor.class) == null;
+ }
+
+ public void testExcludedTypes() {
+ // Strings
+ assert MarshalledValue.isTypeExcluded(String.class);
+ assert MarshalledValue.isTypeExcluded(String[].class);
+ assert MarshalledValue.isTypeExcluded(String[][].class);
+ assert MarshalledValue.isTypeExcluded(String[][][].class);
+
+ // primitives
+ assert MarshalledValue.isTypeExcluded(void.class);
+ assert MarshalledValue.isTypeExcluded(boolean.class);
+ assert MarshalledValue.isTypeExcluded(char.class);
+ assert MarshalledValue.isTypeExcluded(byte.class);
+ assert MarshalledValue.isTypeExcluded(short.class);
+ assert MarshalledValue.isTypeExcluded(int.class);
+ assert MarshalledValue.isTypeExcluded(long.class);
+ assert MarshalledValue.isTypeExcluded(float.class);
+ assert MarshalledValue.isTypeExcluded(double.class);
+
+ assert MarshalledValue.isTypeExcluded(boolean[].class);
+ assert MarshalledValue.isTypeExcluded(char[].class);
+ assert MarshalledValue.isTypeExcluded(byte[].class);
+ assert MarshalledValue.isTypeExcluded(short[].class);
+ assert MarshalledValue.isTypeExcluded(int[].class);
+ assert MarshalledValue.isTypeExcluded(long[].class);
+ assert MarshalledValue.isTypeExcluded(float[].class);
+ assert MarshalledValue.isTypeExcluded(double[].class);
+
+ assert MarshalledValue.isTypeExcluded(boolean[][].class);
+ assert MarshalledValue.isTypeExcluded(char[][].class);
+ assert MarshalledValue.isTypeExcluded(byte[][].class);
+ assert MarshalledValue.isTypeExcluded(short[][].class);
+ assert MarshalledValue.isTypeExcluded(int[][].class);
+ assert MarshalledValue.isTypeExcluded(long[][].class);
+ assert MarshalledValue.isTypeExcluded(float[][].class);
+ assert MarshalledValue.isTypeExcluded(double[][].class);
+
+ assert MarshalledValue.isTypeExcluded(Void.class);
+ assert MarshalledValue.isTypeExcluded(Boolean.class);
+ assert MarshalledValue.isTypeExcluded(Character.class);
+ assert MarshalledValue.isTypeExcluded(Byte.class);
+ assert MarshalledValue.isTypeExcluded(Short.class);
+ assert MarshalledValue.isTypeExcluded(Integer.class);
+ assert MarshalledValue.isTypeExcluded(Long.class);
+ assert MarshalledValue.isTypeExcluded(Float.class);
+ assert MarshalledValue.isTypeExcluded(Double.class);
+
+ assert MarshalledValue.isTypeExcluded(Boolean[].class);
+ assert MarshalledValue.isTypeExcluded(Character[].class);
+ assert MarshalledValue.isTypeExcluded(Byte[].class);
+ assert MarshalledValue.isTypeExcluded(Short[].class);
+ assert MarshalledValue.isTypeExcluded(Integer[].class);
+ assert MarshalledValue.isTypeExcluded(Long[].class);
+ assert MarshalledValue.isTypeExcluded(Float[].class);
+ assert MarshalledValue.isTypeExcluded(Double[].class);
+
+ assert MarshalledValue.isTypeExcluded(Boolean[][].class);
+ assert MarshalledValue.isTypeExcluded(Character[][].class);
+ assert MarshalledValue.isTypeExcluded(Byte[][].class);
+ assert MarshalledValue.isTypeExcluded(Short[][].class);
+ assert MarshalledValue.isTypeExcluded(Integer[][].class);
+ assert MarshalledValue.isTypeExcluded(Long[][].class);
+ assert MarshalledValue.isTypeExcluded(Float[][].class);
+ assert MarshalledValue.isTypeExcluded(Double[][].class);
+ }
+
+ public void testNonExcludedTypes() {
+ assert !MarshalledValue.isTypeExcluded(Object.class);
+ assert !MarshalledValue.isTypeExcluded(List.class);
+ assert !MarshalledValue.isTypeExcluded(Collection.class);
+ assert !MarshalledValue.isTypeExcluded(Map.class);
+ assert !MarshalledValue.isTypeExcluded(Date.class);
+ assert !MarshalledValue.isTypeExcluded(Thread.class);
+ assert !MarshalledValue.isTypeExcluded(Collection.class);
+ assert !MarshalledValue.isTypeExcluded(new Object() {
+ String blah;
+ }.getClass());
+ }
+}
Property changes on:
core/branches/flat/src/test/java/org/horizon/interceptors/MarshalledValueInterceptorTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: core/branches/flat/src/test/java/org/horizon/marshall/MarshalledValueTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/marshall/MarshalledValueTest.java
(rev 0)
+++
core/branches/flat/src/test/java/org/horizon/marshall/MarshalledValueTest.java 2009-02-11
12:53:09 UTC (rev 7682)
@@ -0,0 +1,373 @@
+package org.horizon.marshall;
+
+import org.horizon.AdvancedCache;
+import org.horizon.BaseClusteredTest;
+import org.horizon.Cache;
+import org.horizon.CacheException;
+import org.horizon.commands.write.PutKeyValueCommand;
+import org.horizon.config.CacheLoaderManagerConfig;
+import org.horizon.config.Configuration;
+import org.horizon.container.DataContainer;
+import org.horizon.context.InvocationContext;
+import org.horizon.interceptors.InterceptorChain;
+import org.horizon.interceptors.MarshalledValueInterceptor;
+import org.horizon.interceptors.base.CommandInterceptor;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.dummy.DummyInMemoryCacheLoader;
+import org.horizon.manager.CacheManager;
+import org.horizon.notifications.Listener;
+import org.horizon.notifications.cachelistener.annotation.CacheEntryModified;
+import org.horizon.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.horizon.util.TestingUtil;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+
+/**
+ * Tests implicit marshalled values
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik
AT jboss DOT org</a>)
+ * @author Mircea.Markus(a)jboss.com
+ * @since 1.0
+ */
+@Test(groups = "functional", testName =
"marshall.MarshalledValueTest")
+public class MarshalledValueTest extends BaseClusteredTest {
+ private Cache cache1, cache2;
+ private MarshalledValueListenerInterceptor mvli;
+ String k = "key", v = "value";
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() {
+ CacheManager cm1 = addClusterEnabledCacheManager();
+ CacheManager cm2 = addClusterEnabledCacheManager();
+
+ Configuration replSync = new Configuration();
+ replSync.setCacheMode(Configuration.CacheMode.REPL_SYNC);
+ replSync.setUseLazyDeserialization(true);
+
+ defineCacheOnAllManagers("replSync", replSync);
+
+ cache1 = cm1.getCache("replSync");
+ cache2 = cm2.getCache("replSync");
+
+ assertMarshalledValueInterceptorPresent(cache1);
+ assertMarshalledValueInterceptorPresent(cache2);
+
+ mvli = new MarshalledValueListenerInterceptor();
+ ((AdvancedCache)cache1).addInterceptorAfter(mvli,
MarshalledValueInterceptor.class);
+
+ TestingUtil.blockUntilViewsReceived(60000, true, cm1, cm2);
+ }
+
+ private void assertMarshalledValueInterceptorPresent(Cache c) {
+ InterceptorChain ic1 = TestingUtil.extractComponent(c, InterceptorChain.class);
+ assert ic1.containsInterceptorType(MarshalledValueInterceptor.class);
+ }
+
+ @AfterMethod
+ public void tearDown() {
+ TestingUtil.killCaches(cache1, cache2);
+ Pojo.serializationCount = 0;
+ Pojo.deserializationCount = 0;
+ }
+
+ private void assertOnlyOneRepresentationExists(MarshalledValue mv) {
+ assert (mv.instance != null && mv.raw == null) || (mv.instance == null
&& mv.raw != null) : "Only instance or raw representations should exist in a
MarshalledValue; never both";
+ }
+
+ private void assertSerialized(MarshalledValue mv) {
+ assert mv.raw != null : "Should be serialized";
+ }
+
+ private void assertDeserialized(MarshalledValue mv) {
+ assert mv.instance != null : "Should be deserialized";
+ }
+
+ private void assertSerializationCounts(int serializationCount, int
deserializationCount) {
+ assert Pojo.serializationCount == serializationCount : "Serialization count:
expected " + serializationCount + " but was " + Pojo.serializationCount;
+ assert Pojo.deserializationCount == deserializationCount : "Deserialization
count: expected " + deserializationCount + " but was " +
Pojo.deserializationCount;
+ }
+
+ public void testNonSerializable() {
+ try {
+ cache1.put("Hello", new Object());
+ assert false : "Should have failed";
+ }
+ catch (CacheException expected) {
+
+ }
+
+ assert mvli.invocationCount == 0 : "Call should not have gone beyond the
MarshalledValueInterceptor";
+
+ try {
+ cache1.put(new Object(), "Hello");
+ assert false : "Should have failed";
+ }
+ catch (CacheException expected) {
+
+ }
+
+ assert mvli.invocationCount == 0 : "Call should not have gone beyond the
MarshalledValueInterceptor";
+ }
+
+ public void testNodeReleaseObjectValueReferences() {
+ Pojo value = new Pojo();
+ cache1.put("key", value);
+ assertSerializationCounts(1, 0);
+
+ DataContainer dc1 = TestingUtil.extractComponent(cache1, DataContainer.class);
+
+ Object o = dc1.get("key");
+ assert o instanceof MarshalledValue;
+ MarshalledValue mv = (MarshalledValue) o;
+ assertDeserialized(mv);
+ assert cache1.get("key").equals(value);
+ assertDeserialized(mv);
+ assertSerializationCounts(1, 0);
+ cache1.compact();
+ assertSerializationCounts(2, 0);
+ assertOnlyOneRepresentationExists(mv);
+ assertSerialized(mv);
+
+ // now on cache 2
+ DataContainer dc2 = TestingUtil.extractComponent(cache2, DataContainer.class);
+ o = dc2.get("key");
+ assert o instanceof MarshalledValue;
+ mv = (MarshalledValue) o;
+ assertSerialized(mv); // this proves that unmarshalling on the recipient cache
instance is lazy
+
+ assert cache2.get("key").equals(value);
+ assertDeserialized(mv);
+ assertSerializationCounts(2, 1);
+ cache2.compact();
+ assertSerializationCounts(2, 1);
+ assertOnlyOneRepresentationExists(mv);
+ assertSerialized(mv);
+ }
+
+ public void testNodeReleaseObjectKeyReferences() throws IOException,
ClassNotFoundException {
+ Pojo key = new Pojo();
+ cache1.put(key, "value");
+
+ assertSerializationCounts(1, 0);
+
+ DataContainer dc1 = TestingUtil.extractComponent(cache1, DataContainer.class);
+
+ Object o = dc1.keySet().iterator().next();
+ assert o instanceof MarshalledValue;
+ MarshalledValue mv = (MarshalledValue) o;
+ assertDeserialized(mv);
+
+ assert cache1.get(key).equals("value");
+ assertDeserialized(mv);
+ assertSerializationCounts(1, 0);
+
+ cache1.compact();
+ assertSerializationCounts(2, 0);
+ assertOnlyOneRepresentationExists(mv);
+ assertSerialized(mv);
+
+
+ // now on cache 2
+ DataContainer dc2 = TestingUtil.extractComponent(cache2, DataContainer.class);
+ o = dc2.keySet().iterator().next();
+ assert o instanceof MarshalledValue;
+ mv = (MarshalledValue) o;
+ assertSerialized(mv);
+ assert cache2.get(key).equals("value");
+ assertSerializationCounts(2, 1);
+ assertDeserialized(mv);
+ cache2.compact();
+
+ assertOnlyOneRepresentationExists(mv);
+ assertSerialized(mv);
+ assertSerializationCounts(2, 1);
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ Pojo pojo = new Pojo();
+ MarshalledValue mv = new MarshalledValue(pojo, true);
+ assertDeserialized(mv);
+ int oldHashCode = mv.hashCode();
+
+ mv.serialize();
+ assertSerialized(mv);
+ assert oldHashCode == mv.hashCode();
+
+ MarshalledValue mv2 = new MarshalledValue(pojo, true);
+ assertSerialized(mv);
+ assertDeserialized(mv2);
+
+ assert mv2.hashCode() == oldHashCode;
+ assert mv.equals(mv2);
+ }
+
+ public void assertUseOfMagicNumbers() throws Exception {
+ Pojo pojo = new Pojo();
+ MarshalledValue mv = new MarshalledValue(pojo, true);
+
+ Configuration c = new Configuration();
+// ComponentRegistry cr = new ComponentRegistry(c, new
CacheDelegate("aaa"));
+
+ HorizonMarshaller marshaller = new HorizonMarshaller();
+// cr.registerComponent(marshaller, Marshaller.class);
+
+ // Wire the marshaller
+// cr.start();
+
+ // start the test
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(bout);
+ marshaller.objectToObjectStream(mv, out);
+ out.close();
+ bout.close();
+
+ // check that the rest just contains a byte stream which a MarshalledValue will be
able to deserialize.
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bin);
+
+ assert in.read() == HorizonMarshaller.MAGICNUMBER_MARSHALLEDVALUE;
+ MarshalledValue recreated = new MarshalledValue();
+ recreated.readExternal(in);
+
+ // there should be nothing more
+ assert in.available() == 0;
+ in.close();
+ bin.close();
+
+ assertSerialized(recreated);
+ assert recreated.equals(mv);
+
+ // since both objects being compared are serialized, the equals() above should just
compare byte arrays.
+ assertSerialized(recreated);
+ assertOnlyOneRepresentationExists(recreated);
+ }
+
+ public void testCacheLoaders() throws CloneNotSupportedException {
+ tearDown();
+
+ Configuration cacheCofig = new Configuration();
+ cacheCofig.setCacheMode(Configuration.CacheMode.REPL_SYNC);
+ cacheCofig.setUseLazyDeserialization(true);
+ CacheLoaderManagerConfig clmc = new CacheLoaderManagerConfig();
+ DummyInMemoryCacheLoader.Cfg clc = new DummyInMemoryCacheLoader.Cfg();
+ clc.setStore(getClass().getSimpleName());
+
clmc.setIndividualCacheLoaderConfigs(Collections.singletonList((CacheLoaderConfig)clc));
+ cacheCofig.setCacheLoaderConfig(clmc);
+
+ defineCacheOnAllManagers("replSync2", cacheCofig);
+ cache1 = getCacheManagers().get(0).getCache("replSync2");
+ cache2 = getCacheManagers().get(1).getCache("replSync2");
+
+ TestingUtil.blockUntilViewsReceived(60000, cache1, cache2);
+
+ Pojo pojo = new Pojo();
+ cache1.put("key", pojo);
+
+ assertMarshalledValueInterceptorPresent(cache1);
+ assertMarshalledValueInterceptorPresent(cache2);
+ assertSerializationCounts(1, 0);
+
+ cache2.get("key");
+
+ assertSerializationCounts(1, 1);
+ }
+
+ public void testCallbackValues() {
+ MockListener l = new MockListener();
+ cache1.addListener(l);
+ Pojo pojo = new Pojo();
+ cache1.put("key", pojo);
+
+ assert l.newValue != null;
+ assert l.newValue instanceof MarshalledValue;
+ MarshalledValue mv = (MarshalledValue) l.newValue;
+ assert mv.instance instanceof Pojo;
+ assertSerializationCounts(1, 0);
+ }
+
+ public void testRemoteCallbackValues() throws Exception {
+ MockListener l = new MockListener();
+ cache2.addListener(l);
+ Pojo pojo = new Pojo();
+ cache1.put("key", pojo);
+
+ assert l.newValue != null;
+ assert l.newValue instanceof MarshalledValue;
+ MarshalledValue mv = (MarshalledValue) l.newValue;
+ assert mv.get() instanceof Pojo;
+ assertSerializationCounts(1, 1);
+ }
+
+ @Listener
+ public static class MockListener {
+ Object newValue;
+
+ @CacheEntryModified
+ public void nodeModified(CacheEntryModifiedEvent e) {
+ if (!e.isPre()) newValue = e.getValue();
+ }
+ }
+
+ class MarshalledValueListenerInterceptor extends CommandInterceptor {
+ int invocationCount = 0;
+ public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand
command) throws Throwable {
+ invocationCount++;
+ if (command.getKey() instanceof MarshalledValue)
+ assertOnlyOneRepresentationExists((MarshalledValue) command.getKey());
+ if (command.getValue() instanceof MarshalledValue)
+ assertOnlyOneRepresentationExists((MarshalledValue) command.getValue());
+ Object retval = invokeNextInterceptor(ctx, command);
+ if (retval instanceof MarshalledValue)
assertOnlyOneRepresentationExists((MarshalledValue) retval);
+ return retval;
+ }
+
+ }
+
+ public static class Pojo implements Externalizable {
+ int i;
+ boolean b;
+ static int serializationCount, deserializationCount;
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Pojo pojo = (Pojo) o;
+
+ if (b != pojo.b) return false;
+ if (i != pojo.i) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = i;
+ result = 31 * result + (b ? 1 : 0);
+ return result;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeInt(i);
+ out.writeBoolean(b);
+ serializationCount++;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
+ i = in.readInt();
+ b = in.readBoolean();
+ deserializationCount++;
+ }
+ }
+}
Property changes on:
core/branches/flat/src/test/java/org/horizon/marshall/MarshalledValueTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: core/branches/flat/src/test/resources/configs/named-cache-test.xml
===================================================================
--- core/branches/flat/src/test/resources/configs/named-cache-test.xml 2009-02-11 11:09:31
UTC (rev 7681)
+++ core/branches/flat/src/test/resources/configs/named-cache-test.xml 2009-02-11 12:53:09
UTC (rev 7682)
@@ -69,4 +69,9 @@
<locking isolationLevel="REPEATABLE_READ"
concurrencyLevel="1000" lockAcquisitionTimeout="20000" />
</namedCache>
+ <namedCache name="lazyDeserialization">
+ <locking isolationLevel="REPEATABLE_READ"
concurrencyLevel="1000" lockAcquisitionTimeout="20000" />
+ <lazyDeserialization enabled="true"/>
+ </namedCache>
+
</horizon>