You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ta...@apache.org on 2018/11/13 21:48:53 UTC

[3/3] qpid-proton-j git commit: PROTON-1963 Improve performance of some fast path codec types

PROTON-1963 Improve performance of some fast path codec types

For the fast path types that configure their map type encoding with a
key type use a single lookup for the type to reduce overhead on each
write.

For the map based types do an in-place decode using the known key types
and other structural expectations to improve decode performance.

For the fast path data section type use the known structure of the type
and avoid looking up encodings to improve performance of decodes.

Project: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/commit/589504d7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/tree/589504d7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/diff/589504d7

Branch: refs/heads/master
Commit: 589504d76e0a9567dcacca43695d4af414cd2e58
Parents: c8fd87e
Author: Timothy Bish <ta...@gmail.com>
Authored: Tue Nov 13 16:12:32 2018 -0500
Committer: Timothy Bish <ta...@gmail.com>
Committed: Tue Nov 13 16:12:32 2018 -0500

----------------------------------------------------------------------
 .../FastPathApplicationPropertiesType.java      | 105 ++++++++++++++++--
 .../codec/messaging/FastPathDataType.java       |  31 +++++-
 .../FastPathDeliveryAnnotationsType.java        | 106 +++++++++++++++++--
 .../FastPathMessageAnnotationsType.java         | 106 +++++++++++++++++--
 4 files changed, 327 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/589504d7/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
index 08078f3..5ebb9ea 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
@@ -17,17 +17,26 @@
 package org.apache.qpid.proton.codec.messaging;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
+import org.apache.qpid.proton.ProtonException;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
 import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.ArrayType;
+import org.apache.qpid.proton.codec.DecodeException;
 import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DecoderImpl;
 import org.apache.qpid.proton.codec.EncoderImpl;
 import org.apache.qpid.proton.codec.EncodingCodes;
 import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
 import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.PrimitiveTypeEncoding;
+import org.apache.qpid.proton.codec.ReadableBuffer;
+import org.apache.qpid.proton.codec.StringType;
+import org.apache.qpid.proton.codec.TypeConstructor;
 import org.apache.qpid.proton.codec.TypeEncoding;
 import org.apache.qpid.proton.codec.WritableBuffer;
 
@@ -35,15 +44,16 @@ public class FastPathApplicationPropertiesType implements AMQPType<ApplicationPr
 
     private static final byte DESCRIPTOR_CODE = 0x74;
 
-    private static final Object[] DESCRIPTORS =
-    {
+    private static final Object[] DESCRIPTORS = {
         UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:application-properties:map"),
     };
 
     private final ApplicationPropertiesType propertiesType;
+    private final StringType stringType;
 
     public FastPathApplicationPropertiesType(EncoderImpl encoder) {
         this.propertiesType = new ApplicationPropertiesType(encoder);
+        this.stringType = (StringType) encoder.getTypeFromClass(String.class);
     }
 
     public EncoderImpl getEncoder() {
@@ -81,7 +91,66 @@ public class FastPathApplicationPropertiesType implements AMQPType<ApplicationPr
 
     @Override
     public ApplicationProperties readValue() {
-        return new ApplicationProperties(getDecoder().readMap());
+        DecoderImpl decoder = getDecoder();
+        ReadableBuffer buffer = decoder.getBuffer();
+
+        final int size;
+        final int count;
+
+        byte encodingCode = buffer.get();
+
+        switch (encodingCode) {
+            case EncodingCodes.MAP8:
+                size = buffer.get() & 0xFF;
+                count = buffer.get() & 0xFF;
+                break;
+            case EncodingCodes.MAP32:
+                size = buffer.getInt();
+                count = buffer.getInt();
+                break;
+            case EncodingCodes.NULL:
+                return new ApplicationProperties(null);
+            default:
+                throw new ProtonException("Expected Map type but found encoding: " + encodingCode);
+        }
+
+        if (count > buffer.remaining()) {
+            throw new IllegalArgumentException("Map element count " + count + " is specified to be greater than the " +
+                                               "amount of data available ("+ buffer.remaining() + ")");
+        }
+
+        TypeConstructor<?> valueConstructor = null;
+
+        Map<String, Object> map = new LinkedHashMap<>(count);
+        for (int i = 0; i < count / 2; i++) {
+            String key = decoder.readString(null);
+            if (key == null) {
+                throw new DecodeException("String key in ApplicationProperties cannot be null");
+            }
+
+            boolean arrayType = false;
+            byte code = buffer.get(buffer.position());
+            switch (code)
+            {
+                case EncodingCodes.ARRAY8:
+                case EncodingCodes.ARRAY32:
+                    arrayType = true;
+            }
+
+            valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
+
+            final Object value;
+
+            if (arrayType) {
+                value = ((ArrayType.ArrayEncoding) valueConstructor).readValueArray();
+            } else {
+                value = valueConstructor.readValue();
+            }
+
+            map.put(key, value);
+        }
+
+        return new ApplicationProperties(map);
     }
 
     @Override
@@ -99,17 +168,41 @@ public class FastPathApplicationPropertiesType implements AMQPType<ApplicationPr
 
         MapType mapType = (MapType) getEncoder().getType(val.getValue());
 
-        mapType.setKeyEncoding(getEncoder().getTypeFromClass(String.class));
+        mapType.setKeyEncoding(stringType);
         mapType.write(val.getValue());
         mapType.setKeyEncoding(null);
     }
 
     public static void register(Decoder decoder, EncoderImpl encoder) {
         FastPathApplicationPropertiesType type = new FastPathApplicationPropertiesType(encoder);
-        for(Object descriptor : DESCRIPTORS)
-        {
+        for (Object descriptor : DESCRIPTORS) {
             decoder.register(descriptor, type);
         }
         encoder.register(type);
     }
+
+    private static TypeConstructor<?> findNextDecoder(DecoderImpl decoder, ReadableBuffer buffer, TypeConstructor<?> previousConstructor) {
+        if (previousConstructor == null) {
+            return decoder.readConstructor();
+        } else {
+            byte encodingCode = buffer.get(buffer.position());
+            if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(previousConstructor instanceof PrimitiveTypeEncoding<?>)) {
+                previousConstructor = decoder.readConstructor();
+            } else {
+                PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) previousConstructor;
+                if (encodingCode != primitiveConstructor.getEncodingCode()) {
+                    previousConstructor = decoder.readConstructor();
+                } else {
+                    // consume the encoding code byte for real
+                    encodingCode = buffer.get();
+                }
+            }
+        }
+
+        if (previousConstructor == null) {
+            throw new DecodeException("Unknown constructor found in Map encoding: ");
+        }
+
+        return previousConstructor;
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/589504d7/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
index a3cfb2a..acc6d77 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
@@ -18,6 +18,8 @@ package org.apache.qpid.proton.codec.messaging;
 
 import java.util.Collection;
 
+import org.apache.qpid.proton.ProtonException;
+import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.messaging.Data;
@@ -27,6 +29,7 @@ import org.apache.qpid.proton.codec.DecoderImpl;
 import org.apache.qpid.proton.codec.EncoderImpl;
 import org.apache.qpid.proton.codec.EncodingCodes;
 import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.ReadableBuffer;
 import org.apache.qpid.proton.codec.TypeEncoding;
 import org.apache.qpid.proton.codec.WritableBuffer;
 
@@ -80,7 +83,33 @@ public class FastPathDataType implements AMQPType<Data>, FastPathDescribedTypeCo
 
     @Override
     public Data readValue() {
-        return new Data(getDecoder().readBinary());
+        ReadableBuffer buffer = getDecoder().getBuffer();
+        byte encodingCode = buffer.get();
+
+        int size = 0;
+
+        switch (encodingCode) {
+            case EncodingCodes.VBIN8:
+                size = buffer.get() & 0xFF;
+                break;
+            case EncodingCodes.VBIN32:
+                size = buffer.getInt();
+                break;
+            case EncodingCodes.NULL:
+                return new Data(null);
+            default:
+                throw new ProtonException("Expected Binary type but found encoding: " + encodingCode);
+        }
+
+        if (size > buffer.remaining()) {
+            throw new IllegalArgumentException("Binary data size " + size + " is specified to be greater than the " +
+                                               "amount of data available ("+ buffer.remaining()+")");
+        }
+
+        byte[] data = new byte[size];
+        buffer.get(data, 0, size);
+
+        return new Data(new Binary(data));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/589504d7/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
index acf91dc..1bbc321 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
@@ -17,17 +17,26 @@
 package org.apache.qpid.proton.codec.messaging;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
+import org.apache.qpid.proton.ProtonException;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.messaging.DeliveryAnnotations;
 import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.ArrayType;
+import org.apache.qpid.proton.codec.DecodeException;
 import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DecoderImpl;
 import org.apache.qpid.proton.codec.EncoderImpl;
 import org.apache.qpid.proton.codec.EncodingCodes;
 import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
 import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.PrimitiveTypeEncoding;
+import org.apache.qpid.proton.codec.ReadableBuffer;
+import org.apache.qpid.proton.codec.SymbolType;
+import org.apache.qpid.proton.codec.TypeConstructor;
 import org.apache.qpid.proton.codec.TypeEncoding;
 import org.apache.qpid.proton.codec.WritableBuffer;
 
@@ -35,15 +44,16 @@ public class FastPathDeliveryAnnotationsType implements AMQPType<DeliveryAnnotat
 
     private static final byte DESCRIPTOR_CODE = 0x71;
 
-    private static final Object[] DESCRIPTORS =
-    {
+    private static final Object[] DESCRIPTORS = {
         UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:delivery-annotations:map"),
     };
 
     private final DeliveryAnnotationsType annotationsType;
+    private final SymbolType symbolType;
 
     public FastPathDeliveryAnnotationsType(EncoderImpl encoder) {
         this.annotationsType = new DeliveryAnnotationsType(encoder);
+        this.symbolType = (SymbolType) encoder.getTypeFromClass(Symbol.class);
     }
 
     public EncoderImpl getEncoder() {
@@ -79,10 +89,68 @@ public class FastPathDeliveryAnnotationsType implements AMQPType<DeliveryAnnotat
         return annotationsType.getAllEncodings();
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public DeliveryAnnotations readValue() {
-        return new DeliveryAnnotations(getDecoder().readMap());
+        DecoderImpl decoder = getDecoder();
+        ReadableBuffer buffer = decoder.getBuffer();
+
+        final int size;
+        final int count;
+
+        byte encodingCode = buffer.get();
+
+        switch (encodingCode) {
+            case EncodingCodes.MAP8:
+                size = buffer.get() & 0xFF;
+                count = buffer.get() & 0xFF;
+                break;
+            case EncodingCodes.MAP32:
+                size = buffer.getInt();
+                count = buffer.getInt();
+                break;
+            case EncodingCodes.NULL:
+                return new DeliveryAnnotations(null);
+            default:
+                throw new ProtonException("Expected Map type but found encoding: " + encodingCode);
+        }
+
+        if (count > buffer.remaining()) {
+            throw new IllegalArgumentException("Map element count " + count + " is specified to be greater than the " +
+                                               "amount of data available (" + buffer.remaining() + ")");
+        }
+
+        TypeConstructor<?> valueConstructor = null;
+
+        Map<Symbol, Object> map = new LinkedHashMap<>(count);
+        for(int i = 0; i < count / 2; i++) {
+            Symbol key = decoder.readSymbol(null);
+            if (key == null) {
+                throw new DecodeException("String key in DeliveryAnnotations cannot be null");
+            }
+
+            boolean arrayType = false;
+            byte code = buffer.get(buffer.position());
+            switch (code)
+            {
+                case EncodingCodes.ARRAY8:
+                case EncodingCodes.ARRAY32:
+                    arrayType = true;
+            }
+
+            valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
+
+            final Object value;
+
+            if (arrayType) {
+                value = ((ArrayType.ArrayEncoding) valueConstructor).readValueArray();
+            } else {
+                value = valueConstructor.readValue();
+            }
+
+            map.put(key, value);
+        }
+
+        return new DeliveryAnnotations(map);
     }
 
     @Override
@@ -100,17 +168,41 @@ public class FastPathDeliveryAnnotationsType implements AMQPType<DeliveryAnnotat
 
         MapType mapType = (MapType) getEncoder().getType(val.getValue());
 
-        mapType.setKeyEncoding(getEncoder().getTypeFromClass(Symbol.class));
+        mapType.setKeyEncoding(symbolType);
         mapType.write(val.getValue());
         mapType.setKeyEncoding(null);
     }
 
     public static void register(Decoder decoder, EncoderImpl encoder) {
         FastPathDeliveryAnnotationsType type = new FastPathDeliveryAnnotationsType(encoder);
-        for(Object descriptor : DESCRIPTORS)
-        {
+        for(Object descriptor : DESCRIPTORS) {
             decoder.register(descriptor, type);
         }
         encoder.register(type);
     }
+
+    private static TypeConstructor<?> findNextDecoder(DecoderImpl decoder, ReadableBuffer buffer, TypeConstructor<?> previousConstructor) {
+        if (previousConstructor == null) {
+            return decoder.readConstructor();
+        } else {
+            byte encodingCode = buffer.get(buffer.position());
+            if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(previousConstructor instanceof PrimitiveTypeEncoding<?>)) {
+                previousConstructor = decoder.readConstructor();
+            } else {
+                PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) previousConstructor;
+                if (encodingCode != primitiveConstructor.getEncodingCode()) {
+                    previousConstructor = decoder.readConstructor();
+                } else {
+                    // consume the encoding code byte for real
+                    encodingCode = buffer.get();
+                }
+            }
+        }
+
+        if (previousConstructor == null) {
+            throw new DecodeException("Unknown constructor found in Map encoding: ");
+        }
+
+        return previousConstructor;
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/589504d7/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
index 195e4b5..49cc09e 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
@@ -17,17 +17,26 @@
 package org.apache.qpid.proton.codec.messaging;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
+import org.apache.qpid.proton.ProtonException;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
 import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.ArrayType;
+import org.apache.qpid.proton.codec.DecodeException;
 import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DecoderImpl;
 import org.apache.qpid.proton.codec.EncoderImpl;
 import org.apache.qpid.proton.codec.EncodingCodes;
 import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
 import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.PrimitiveTypeEncoding;
+import org.apache.qpid.proton.codec.ReadableBuffer;
+import org.apache.qpid.proton.codec.SymbolType;
+import org.apache.qpid.proton.codec.TypeConstructor;
 import org.apache.qpid.proton.codec.TypeEncoding;
 import org.apache.qpid.proton.codec.WritableBuffer;
 
@@ -35,15 +44,16 @@ public class FastPathMessageAnnotationsType implements AMQPType<MessageAnnotatio
 
     private static final byte DESCRIPTOR_CODE = 0x72;
 
-    private static final Object[] DESCRIPTORS =
-    {
+    private static final Object[] DESCRIPTORS = {
         UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:message-annotations:map"),
     };
 
     private final MessageAnnotationsType annotationsType;
+    private final SymbolType symbolType;
 
     public FastPathMessageAnnotationsType(EncoderImpl encoder) {
         this.annotationsType = new MessageAnnotationsType(encoder);
+        this.symbolType = (SymbolType) encoder.getTypeFromClass(Symbol.class);
     }
 
     public EncoderImpl getEncoder() {
@@ -79,10 +89,68 @@ public class FastPathMessageAnnotationsType implements AMQPType<MessageAnnotatio
         return annotationsType.getAllEncodings();
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public MessageAnnotations readValue() {
-        return new MessageAnnotations(getDecoder().readMap());
+        DecoderImpl decoder = getDecoder();
+        ReadableBuffer buffer = decoder.getBuffer();
+
+        final int size;
+        final int count;
+
+        byte encodingCode = buffer.get();
+
+        switch (encodingCode) {
+            case EncodingCodes.MAP8:
+                size = buffer.get() & 0xFF;
+                count = buffer.get() & 0xFF;
+                break;
+            case EncodingCodes.MAP32:
+                size = buffer.getInt();
+                count = buffer.getInt();
+                break;
+            case EncodingCodes.NULL:
+                return new MessageAnnotations(null);
+            default:
+                throw new ProtonException("Expected Map type but found encoding: " + encodingCode);
+        }
+
+        if (count > buffer.remaining()) {
+            throw new IllegalArgumentException("Map element count "+count+" is specified to be greater than the amount of data available ("+
+                                               decoder.getByteBufferRemaining()+")");
+        }
+
+        TypeConstructor<?> valueConstructor = null;
+
+        Map<Symbol, Object> map = new LinkedHashMap<>(count);
+        for(int i = 0; i < count / 2; i++) {
+            Symbol key = decoder.readSymbol(null);
+            if (key == null) {
+                throw new DecodeException("String key in DeliveryAnnotations cannot be null");
+            }
+
+            boolean arrayType = false;
+            byte code = buffer.get(buffer.position());
+            switch (code)
+            {
+                case EncodingCodes.ARRAY8:
+                case EncodingCodes.ARRAY32:
+                    arrayType = true;
+            }
+
+            valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
+
+            final Object value;
+
+            if (arrayType) {
+                value = ((ArrayType.ArrayEncoding) valueConstructor).readValueArray();
+            } else {
+                value = valueConstructor.readValue();
+            }
+
+            map.put(key, value);
+        }
+
+        return new MessageAnnotations(map);
     }
 
     @Override
@@ -100,17 +168,41 @@ public class FastPathMessageAnnotationsType implements AMQPType<MessageAnnotatio
 
         MapType mapType = (MapType) getEncoder().getType(val.getValue());
 
-        mapType.setKeyEncoding(getEncoder().getTypeFromClass(Symbol.class));
+        mapType.setKeyEncoding(symbolType);
         mapType.write(val.getValue());
         mapType.setKeyEncoding(null);
     }
 
     public static void register(Decoder decoder, EncoderImpl encoder) {
         FastPathMessageAnnotationsType type = new FastPathMessageAnnotationsType(encoder);
-        for(Object descriptor : DESCRIPTORS)
-        {
+        for(Object descriptor : DESCRIPTORS) {
             decoder.register(descriptor, type);
         }
         encoder.register(type);
     }
+
+    private static TypeConstructor<?> findNextDecoder(DecoderImpl decoder, ReadableBuffer buffer, TypeConstructor<?> previousConstructor) {
+        if (previousConstructor == null) {
+            return decoder.readConstructor();
+        } else {
+            byte encodingCode = buffer.get(buffer.position());
+            if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(previousConstructor instanceof PrimitiveTypeEncoding<?>)) {
+                previousConstructor = decoder.readConstructor();
+            } else {
+                PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) previousConstructor;
+                if (encodingCode != primitiveConstructor.getEncodingCode()) {
+                    previousConstructor = decoder.readConstructor();
+                } else {
+                    // consume the encoding code byte for real
+                    encodingCode = buffer.get();
+                }
+            }
+        }
+
+        if (previousConstructor == null) {
+            throw new DecodeException("Unknown constructor found in Map encoding: ");
+        }
+
+        return previousConstructor;
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org