Improvements to JaCObs Jackson serializer/deserializer - deserialization of channel proxies is now using public Jackson APIs only. - Channel garbage collection implemented. - HashSets replaced by LinkedHashSets in order to make the serialized form more deterministic.
Project: http://git-wip-us.apache.org/repos/asf/ode-jacob/repo Commit: http://git-wip-us.apache.org/repos/asf/ode-jacob/commit/9c05eb2c Tree: http://git-wip-us.apache.org/repos/asf/ode-jacob/tree/9c05eb2c Diff: http://git-wip-us.apache.org/repos/asf/ode-jacob/diff/9c05eb2c Branch: refs/heads/master Commit: 9c05eb2c37abdb33365bb44cdd259b56df553ceb Parents: 8736076 Author: Tammo van Lessen <[email protected]> Authored: Fri May 3 01:36:23 2013 +0200 Committer: Tammo van Lessen <[email protected]> Committed: Fri May 3 01:39:00 2013 +0200 ---------------------------------------------------------------------- .../org/apache/ode/jacob/CompositeProcess.java | 4 +- .../java/org/apache/ode/jacob/ReceiveProcess.java | 4 +- .../jacob/soup/jackson/ChannelProxySerializer.java | 14 ++- .../jackson/ContinuationValueInstantiator.java | 52 ------- .../soup/jackson/JacksonExecutionQueueImpl.java | 81 +++++++++- .../JacobJacksonAnnotationIntrospector.java | 2 +- .../soup/jackson/JacobTypeResolverBuilder.java | 34 +--- .../ode/jacob/soup/jackson/NullJsonGenerator.java | 118 +++++++++++++++ .../apache/ode/jacob/vpu/ExecutionQueueImpl.java | 30 +++- .../ode/jacob/examples/helloworld/HelloWorld.java | 18 ++- 10 files changed, 254 insertions(+), 103 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/CompositeProcess.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/CompositeProcess.java b/src/main/java/org/apache/ode/jacob/CompositeProcess.java index c1e5843..785fed0 100644 --- a/src/main/java/org/apache/ode/jacob/CompositeProcess.java +++ b/src/main/java/org/apache/ode/jacob/CompositeProcess.java @@ -20,13 +20,13 @@ package org.apache.ode.jacob; import java.lang.reflect.Method; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; @SuppressWarnings("serial") public final class CompositeProcess extends ChannelListener { - private Set<ChannelListener> processes = new HashSet<ChannelListener>(); + private Set<ChannelListener> processes = new LinkedHashSet<ChannelListener>(); public CompositeProcess() { } http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/ReceiveProcess.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/ReceiveProcess.java b/src/main/java/org/apache/ode/jacob/ReceiveProcess.java index eccfd09..70f9191 100644 --- a/src/main/java/org/apache/ode/jacob/ReceiveProcess.java +++ b/src/main/java/org/apache/ode/jacob/ReceiveProcess.java @@ -20,7 +20,7 @@ package org.apache.ode.jacob; import java.lang.reflect.Method; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; @@ -53,7 +53,7 @@ public abstract class ReceiveProcess extends ChannelListener { public Set<Method> getImplementedMethods() { if (_implementedMethods == null) { - Set<Method> implementedMethods = new HashSet<Method>(); + Set<Method> implementedMethods = new LinkedHashSet<Method>(); ClassUtil.getImplementedMethods(implementedMethods, receiver.getClass()); _implementedMethods = Collections.unmodifiableSet(implementedMethods); } http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java b/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java index 0817461..a3cee06 100644 --- a/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java +++ b/src/main/java/org/apache/ode/jacob/soup/jackson/ChannelProxySerializer.java @@ -19,6 +19,8 @@ package org.apache.ode.jacob.soup.jackson; import java.io.IOException; +import java.util.LinkedHashSet; +import java.util.Set; import org.apache.ode.jacob.Channel; import org.apache.ode.jacob.ChannelProxy; @@ -34,6 +36,8 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; public class ChannelProxySerializer extends StdSerializer<ChannelProxy>{ + private final Set<Integer> serializedChannels = new LinkedHashSet<Integer>(); + protected ChannelProxySerializer() { super(ChannelProxy.class); } @@ -61,8 +65,16 @@ public class ChannelProxySerializer extends StdSerializer<ChannelProxy>{ SerializerProvider provider) throws JsonGenerationException, IOException { CommChannel commChannel = (CommChannel) ChannelFactory.getBackend((Channel)value); ClassNameIdResolver idResolver = new ClassNameIdResolver(provider.constructType(commChannel.getType()), provider.getTypeFactory()); + Integer cid = (Integer)commChannel.getId(); jgen.writeStringField("channelType", idResolver.idFromBaseType()); - jgen.writeNumberField("channelId", (Integer)commChannel.getId()); + jgen.writeNumberField("channelId", cid); + + // save channel id for garbage collection + serializedChannels.add(cid); + } + + public Set<Integer> getSerializedChannels() { + return serializedChannels; } } http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java b/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java deleted file mode 100644 index d770ad1..0000000 --- a/src/main/java/org/apache/ode/jacob/soup/jackson/ContinuationValueInstantiator.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.ode.jacob.soup.jackson; - -import java.lang.reflect.Method; - -import org.apache.ode.jacob.JacobObject; -import org.apache.ode.jacob.soup.Continuation; - -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.deser.CreatorProperty; -import com.fasterxml.jackson.databind.deser.SettableBeanProperty; -import com.fasterxml.jackson.databind.deser.ValueInstantiator; - -public class ContinuationValueInstantiator extends ValueInstantiator { - - @Override - public String getValueTypeDesc() { - return Continuation.class.getName(); - } - - @Override - public boolean canCreateFromObjectWith() { - return true; - } - - @Override - public SettableBeanProperty[] getFromObjectArguments( - DeserializationConfig config) { - return new CreatorProperty[] { - new CreatorProperty("_closure", config.constructType(JacobObject.class), null, null, null, 0, null), - new CreatorProperty("_method", config.constructType(Method.class), null, null, null, 1, null), - new CreatorProperty("_args", config.constructType(Object[].class), null, null, null, 2, null)}; - - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java b/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java index e0892df..fb08f10 100644 --- a/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java +++ b/src/main/java/org/apache/ode/jacob/soup/jackson/JacksonExecutionQueueImpl.java @@ -19,14 +19,19 @@ package org.apache.ode.jacob.soup.jackson; import java.io.IOException; +import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; import org.apache.ode.jacob.Channel; import org.apache.ode.jacob.ChannelProxy; import org.apache.ode.jacob.soup.Continuation; import org.apache.ode.jacob.vpu.ExecutionQueueImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; @@ -35,11 +40,16 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -51,20 +61,40 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; */ public class JacksonExecutionQueueImpl extends ExecutionQueueImpl { + private static final Logger LOG = LoggerFactory.getLogger(JacksonExecutionQueueImpl.class); + public JacksonExecutionQueueImpl() { super(null); } public static void configureMapper(ObjectMapper om) { - SimpleModule sm = new SimpleModule("jacobmodule"); - sm.addSerializer(ChannelProxy.class, new ChannelProxySerializer()); + SimpleModule sm = new SimpleModule("jacob", Version.unknownVersion()); + + final ChannelProxySerializer cps = new ChannelProxySerializer(); + + sm.addSerializer(ChannelProxy.class, cps); sm.addSerializer(Continuation.class, new ContinuationSerializer()); - sm.addSerializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplSerializer()); + sm.addSerializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplSerializer(cps)); sm.addDeserializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplDeserializer()); sm.addDeserializer(Continuation.class, new ContinuationDeserializer()); sm.addDeserializer(Channel.class, new ChannelProxyDeserializer()); + sm.setDeserializerModifier(new BeanDeserializerModifier() { + + public JsonDeserializer<?> modifyDeserializer( + DeserializationConfig config, BeanDescription beanDesc, + JsonDeserializer<?> deserializer) { + + // use channel proxy deserializer for channels. + if (Channel.class.isAssignableFrom(beanDesc.getBeanClass()) && beanDesc.getBeanClass().isInterface()) { + return new ChannelProxyDeserializer(); + } + + return super.modifyDeserializer(config, beanDesc, deserializer); + } + }); + om.registerModule(sm); om.disable(MapperFeature.AUTO_DETECT_CREATORS); om.disable(MapperFeature.AUTO_DETECT_GETTERS); @@ -82,8 +112,11 @@ public class JacksonExecutionQueueImpl extends ExecutionQueueImpl { public static class ExecutionQueueImplSerializer extends StdSerializer<JacksonExecutionQueueImpl> { - public ExecutionQueueImplSerializer() { + private ChannelProxySerializer channelProxySerializer; + + public ExecutionQueueImplSerializer(ChannelProxySerializer cps) { super(JacksonExecutionQueueImpl.class); + this.channelProxySerializer = cps; } @Override @@ -108,11 +141,44 @@ public class JacksonExecutionQueueImpl extends ExecutionQueueImpl { private void serializeContents(JacksonExecutionQueueImpl value, JsonGenerator jgen, SerializerProvider provider) throws JsonGenerationException, IOException { - jgen.writeNumberField("objIdCounter", value._objIdCounter); + channelProxySerializer.getSerializedChannels().clear(); + + // write metadata + jgen.writeNumberField("objIdCounter", value._objIdCounter); jgen.writeNumberField("currentCycle", value._currentCycle); + // write continuations jgen.writeObjectField("continuations", value._reactions.toArray(new Continuation[] {})); + + + // channel garbage collection + // - traverse whole object graph and record referenced channel proxies. + // - first, regularily serialize continuations. + // - second, serialize channels to a null serializer in order to record channel references + // without writing them to the stream. + // - remove unused channels. + // - serialize remaining channels. + + // write channels to null serializer + JsonGenerator nullgen = new NullJsonGenerator(null, 0, jgen.getCodec()); + nullgen.writeObjectField("channels", value._channels.values().toArray(new ChannelFrame[] {})); + + // remove unreferenced channels (and keep those which have been exported using export()). + Set<Integer> referencedChannels = channelProxySerializer.getSerializedChannels(); + for (Iterator<ChannelFrame> i = value._channels.values().iterator(); i.hasNext();) { + ChannelFrame cframe = i.next(); + if (referencedChannels.contains(cframe.getId()) || cframe.getRefCount() > 0) { + // skip + } else { + LOG.debug("GC Channel: {}", cframe); + i.remove(); + } + } + + // write channels jgen.writeObjectField("channels", value._channels.values().toArray(new ChannelFrame[] {})); + + // write global data jgen.writeObjectField("global", value._gdata); } } @@ -152,13 +218,12 @@ public class JacksonExecutionQueueImpl extends ExecutionQueueImpl { for (ChannelFrame f : frames) { soup._channels.put(f.getId(), f); } + } else if ("global".equals(fieldname)) { + soup._gdata = jp.readValueAs(Serializable.class); } } - // Garbage collection - // TODO - return soup; } http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java index 0cb3a73..ba8b7b1 100644 --- a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java +++ b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobJacksonAnnotationIntrospector.java @@ -15,5 +15,5 @@ public class JacobJacksonAnnotationIntrospector extends public ObjectIdInfo findObjectIdInfo(Annotated ann) { return new ObjectIdInfo("@id", Object.class, ObjectIdGenerators.IntSequenceGenerator.class); } - + } http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java index b477fcd..8a14a71 100644 --- a/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java +++ b/src/main/java/org/apache/ode/jacob/soup/jackson/JacobTypeResolverBuilder.java @@ -40,7 +40,6 @@ import com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.fasterxml.jackson.databind.util.ClassUtil; public class JacobTypeResolverBuilder extends StdTypeResolverBuilder { @@ -65,7 +64,15 @@ public class JacobTypeResolverBuilder extends StdTypeResolverBuilder { return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null; } + + @Override + public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, + JavaType baseType, Collection<NamedType> subtypes) { + + return (useForType(baseType)) ? super.buildTypeDeserializer(config, baseType, subtypes) : null; + } + private boolean useForType(JavaType t) { if (JacobObject.class.isAssignableFrom(t.getRawClass())) { return true; @@ -82,18 +89,6 @@ public class JacobTypeResolverBuilder extends StdTypeResolverBuilder { return false; } - @Override - public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, - JavaType baseType, Collection<NamedType> subtypes) { - - if (useForType(baseType)) { - // set Channel as the default impl. - defaultImpl(Channel.class); - return super.buildTypeDeserializer(config, baseType, subtypes); - } - - return null; - } public static class ChannelAwareTypeIdResolver extends TypeIdResolverBase { @@ -119,18 +114,7 @@ public class JacobTypeResolverBuilder extends StdTypeResolverBuilder { } public JavaType typeFromId(String id) { - try { - Class<?> cls = ClassUtil.findClass(id); - if (Channel.class.isAssignableFrom(cls) && cls.isInterface()) { - // return null to force Jackson to use default deserializer (which is the ChannelProxyDeserializer) - return null; - } - return _typeFactory.constructSpecializedType(_baseType, cls); - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): no such class found"); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): "+e.getMessage(), e); - } + return delegate.typeFromId(id); } public Id getMechanism() { http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java b/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java new file mode 100644 index 0000000..08cd96a --- /dev/null +++ b/src/main/java/org/apache/ode/jacob/soup/jackson/NullJsonGenerator.java @@ -0,0 +1,118 @@ +package org.apache.ode.jacob.soup.jackson; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import com.fasterxml.jackson.core.Base64Variant; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.core.io.IOContext; +import com.fasterxml.jackson.core.json.JsonGeneratorImpl; + +/** + * No-op Json generator. + * + * @author vanto + * + */ +public class NullJsonGenerator extends JsonGeneratorImpl { + + public NullJsonGenerator(IOContext ctxt, int features, ObjectCodec codec) { + super(ctxt, features, codec); + } + + public void flush() throws IOException { + } + + protected void _releaseBuffers() { + } + + protected void _verifyValueWrite(String typeMsg) throws IOException, + JsonGenerationException { + } + + public void writeStartArray() throws IOException, JsonGenerationException { + } + + public void writeEndArray() throws IOException, JsonGenerationException { + } + + public void writeStartObject() throws IOException, JsonGenerationException { + } + + public void writeEndObject() throws IOException, JsonGenerationException { + } + + public void writeFieldName(String name) throws IOException, + JsonGenerationException { + } + + public void writeString(String text) throws IOException, + JsonGenerationException { + } + + public void writeString(char[] text, int offset, int len) + throws IOException, JsonGenerationException { + } + + public void writeRawUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException { + } + + public void writeUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException { + } + + public void writeRaw(String text) throws IOException, + JsonGenerationException { + } + + public void writeRaw(String text, int offset, int len) throws IOException, + JsonGenerationException { + } + + public void writeRaw(char[] text, int offset, int len) throws IOException, + JsonGenerationException { + } + + public void writeRaw(char c) throws IOException, JsonGenerationException { + } + + public void writeBinary(Base64Variant b64variant, byte[] data, int offset, + int len) throws IOException, JsonGenerationException { + } + + public void writeNumber(int v) throws IOException, JsonGenerationException { + } + + public void writeNumber(long v) throws IOException, JsonGenerationException { + } + + public void writeNumber(BigInteger v) throws IOException, + JsonGenerationException { + } + + public void writeNumber(double d) throws IOException, + JsonGenerationException { + } + + public void writeNumber(float f) throws IOException, + JsonGenerationException { + } + + public void writeNumber(BigDecimal dec) throws IOException, + JsonGenerationException { + } + + public void writeNumber(String encodedValue) throws IOException, + JsonGenerationException, UnsupportedOperationException { + } + + public void writeBoolean(boolean state) throws IOException, + JsonGenerationException { + } + + public void writeNull() throws IOException, JsonGenerationException { + } +} http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java b/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java index fff2ae1..a6c0837 100644 --- a/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java +++ b/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java @@ -30,9 +30,10 @@ import java.io.OutputStream; import java.io.PrintStream; import java.io.Serializable; import java.lang.reflect.Method; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -80,9 +81,9 @@ public class ExecutionQueueImpl implements ExecutionQueue { * forward progress; this scenario would occur if a maximum processign * time-per-instance policy were in effect. */ - protected Set<Continuation> _reactions = new HashSet<Continuation>(); + protected Set<Continuation> _reactions = new LinkedHashSet<Continuation>(); - protected Map<Integer, ChannelFrame> _channels = new HashMap<Integer, ChannelFrame>(); + protected Map<Integer, ChannelFrame> _channels = new LinkedHashMap<Integer, ChannelFrame>(); /** * The "expected" cycle counter, use to detect database serialization @@ -96,7 +97,7 @@ public class ExecutionQueueImpl implements ExecutionQueue { protected Serializable _gdata; - private Map<Object, LinkedList<IndexedObject>> _index = new HashMap<Object, LinkedList<IndexedObject>>(); + private Map<Object, LinkedList<IndexedObject>> _index = new LinkedHashMap<Object, LinkedList<IndexedObject>>(); public ExecutionQueueImpl(ClassLoader classLoader) { _classLoader = classLoader; @@ -454,9 +455,9 @@ public class ExecutionQueueImpl implements ExecutionQueue { boolean replicatedRecv; - Set<ObjectFrame> objFrames = new HashSet<ObjectFrame>(); + Set<ObjectFrame> objFrames = new LinkedHashSet<ObjectFrame>(); - Set<MessageFrame> msgFrames = new HashSet<MessageFrame>(); + Set<MessageFrame> msgFrames = new LinkedHashSet<MessageFrame>(); public String description; @@ -473,6 +474,18 @@ public class ExecutionQueueImpl implements ExecutionQueue { public Integer getId() { return Integer.valueOf(id); } + + public int getRefCount() { + return refCount; + } + + public Set<ObjectFrame> getObjFrames() { + return objFrames; + } + + public Set<MessageFrame> getMsgFrames() { + return msgFrames; + } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { type = (Class<?>)in.readObject(); @@ -535,7 +548,7 @@ public class ExecutionQueueImpl implements ExecutionQueue { @SuppressWarnings("serial") protected static class CommGroupFrame implements Serializable { boolean replicated; - public Set<CommFrame> commFrames = new HashSet<CommFrame>(); + public Set<CommFrame> commFrames = new LinkedHashSet<CommFrame>(); // default constructor for deserialization public CommGroupFrame() {} @@ -593,14 +606,13 @@ public class ExecutionQueueImpl implements ExecutionQueue { } } - private static class MessageFrame extends CommFrame implements Externalizable { + protected static class MessageFrame extends CommFrame implements Externalizable { private static final long serialVersionUID = -1112437852498126297L; String method; Object[] args; // Used for deserialization - @SuppressWarnings("unused") public MessageFrame() { } http://git-wip-us.apache.org/repos/asf/ode-jacob/blob/9c05eb2c/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java b/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java index 524d350..053d049 100644 --- a/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java +++ b/src/test/java/org/apache/ode/jacob/examples/helloworld/HelloWorld.java @@ -30,6 +30,8 @@ import org.apache.ode.jacob.vpu.JacobVPU; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.smile.SmileFactory; +import com.fasterxml.jackson.dataformat.smile.SmileGenerator; /** * Simple Hello World example to showcase different @@ -254,13 +256,23 @@ public class HelloWorld extends JacobRunnable { public static void main(String args[]) throws Exception { // enable logging //BasicConfigurator.configure(); - long start = System.currentTimeMillis(); - ObjectMapper mapper = new ObjectMapper(); + + SmileFactory sf = null; + // // enable smile: + // sf = new SmileFactory(); + // sf.enable(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES); + // sf.enable(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT); + + ObjectMapper mapper = new ObjectMapper(sf); + + JacksonExecutionQueueImpl.configureMapper(mapper); JacobVPU vpu = new JacobVPU(); JacksonExecutionQueueImpl queue = new JacksonExecutionQueueImpl(); vpu.setContext(queue); + + long start = System.currentTimeMillis(); vpu.inject(new HelloWorld()); while (vpu.execute()) { queue = loadAndRestoreQueue(mapper, (JacksonExecutionQueueImpl)vpu.getContext()); @@ -268,8 +280,8 @@ public class HelloWorld extends JacobRunnable { System.out.println(vpu.isComplete() ? "<0>" : "."); //vpu.dumpState(); } - vpu.dumpState(); System.out.println("Runtime in ms: " + (System.currentTimeMillis() - start)); + vpu.dumpState(); } public static JacksonExecutionQueueImpl loadAndRestoreQueue(ObjectMapper mapper, JacksonExecutionQueueImpl in) throws Exception {
