You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by lq...@apache.org on 2017/05/22 16:22:48 UTC

[6/7] qpid-broker-j git commit: QPID-7723: Optimize evaluation of metadata storable size for AMQP 0-10

QPID-7723: Optimize evaluation of metadata storable size for AMQP 0-10


Project: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/commit/7772251c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/7772251c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/7772251c

Branch: refs/heads/6.1.x
Commit: 7772251c1534c5c6ac1d168ee16f019206d60355
Parents: b192192
Author: Alex Rudyy <or...@apache.org>
Authored: Wed Mar 29 11:13:54 2017 +0000
Committer: Lorenz Quack <lq...@apache.org>
Committed: Mon May 22 16:51:46 2017 +0100

----------------------------------------------------------------------
 .../protocol/v0_10/MessageMetaData_0_10.java    |  28 +-
 .../org/apache/qpid/transport/Acquired.java     |   6 +-
 .../qpid/transport/DeliveryProperties.java      |  48 ++-
 .../qpid/transport/ExchangeBoundResult.java     |   5 +
 .../qpid/transport/ExchangeQueryResult.java     |   5 +
 .../qpid/transport/FragmentProperties.java      |   6 +
 .../apache/qpid/transport/GetTimeoutResult.java |   6 +
 .../qpid/transport/MessageProperties.java       |  47 +++
 .../qpid/transport/MessageResumeResult.java     |   5 +
 .../java/org/apache/qpid/transport/Method.java  |   6 +
 .../apache/qpid/transport/QueueQueryResult.java |   6 +
 .../apache/qpid/transport/RecoverResult.java    |   6 +
 .../java/org/apache/qpid/transport/ReplyTo.java |  19 +
 .../qpid/transport/SessionCommandFragment.java  |   5 +
 .../apache/qpid/transport/SessionHeader.java    |   6 +
 .../java/org/apache/qpid/transport/Struct.java  |   2 +
 .../org/apache/qpid/transport/XaResult.java     |   7 +
 .../java/org/apache/qpid/transport/Xid.java     |   5 +
 .../qpid/transport/codec/AbstractEncoder.java   |  78 +----
 .../apache/qpid/transport/codec/Encoder.java    |   1 -
 .../qpid/transport/codec/EncoderUtils.java      | 343 +++++++++++++++++++
 .../qpid/transport/codec/BBEncoderTest.java     |  72 +++-
 22 files changed, 622 insertions(+), 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
----------------------------------------------------------------------
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
index b308435..403c554 100755
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
@@ -27,6 +27,7 @@ import java.util.List;
 import org.apache.qpid.bytebuffer.QpidByteBuffer;
 import org.apache.qpid.server.message.AMQMessageHeader;
 import org.apache.qpid.server.plugin.MessageMetaDataType;
+import org.apache.qpid.transport.codec.EncoderUtils;
 import org.apache.qpid.server.store.StorableMessageMetaData;
 import org.apache.qpid.transport.DeliveryProperties;
 import org.apache.qpid.transport.Header;
@@ -83,17 +84,32 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData
         return TYPE;
     }
 
-    public synchronized int getStorableSize()
+
+    public int getStorableSize()
     {
-        QpidByteBuffer buf = _encoded;
+        int len = 0;
+
+        len += 8; // arrival time
+        len += 4; // body size
+        len += 4; // headers length
 
-        if(buf == null)
+        if(_header.getDeliveryProperties() != null)
+        {
+            len += EncoderUtils.getStruct32Length(_header.getDeliveryProperties());
+        }
+        if(_header.getMessageProperties() != null)
         {
-            buf = encodeAsBuffer();
-            _encoded = buf;
+            len += EncoderUtils.getStruct32Length(_header.getMessageProperties());
         }
+        if(_header.getNonStandardProperties() != null)
+        {
+            for(Struct header : _header.getNonStandardProperties())
+            {
+                len += EncoderUtils.getStruct32Length(header);
+            }
 
-        return buf.limit();
+        }
+        return len;
     }
 
     private QpidByteBuffer encodeAsBuffer()

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/Acquired.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/Acquired.java b/common/src/main/java/org/apache/qpid/transport/Acquired.java
index 28e6e4c..20c366c 100644
--- a/common/src/main/java/org/apache/qpid/transport/Acquired.java
+++ b/common/src/main/java/org/apache/qpid/transport/Acquired.java
@@ -137,5 +137,9 @@ public final class Acquired extends Struct {
         return result;
     }
 
-
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/DeliveryProperties.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/DeliveryProperties.java b/common/src/main/java/org/apache/qpid/transport/DeliveryProperties.java
index 94e8d06..ee9c13a 100644
--- a/common/src/main/java/org/apache/qpid/transport/DeliveryProperties.java
+++ b/common/src/main/java/org/apache/qpid/transport/DeliveryProperties.java
@@ -520,6 +520,51 @@ public final class DeliveryProperties extends Struct {
 
     }
 
+    public int getEncodedLength()
+    {
+        int len = 0;
+
+        len += 2; // packing_flags
+
+        if ((packing_flags & 2048) != 0)
+        {
+            len += 1; // priority
+        }
+        if ((packing_flags & 4096) != 0)
+        {
+            len += 1; // deliveryMode
+        }
+        if ((packing_flags & 8192) != 0)
+        {
+            len += 8; // ttl
+        }
+        if ((packing_flags & 16384) != 0)
+        {
+            len += 8; // timestamp
+        }
+        if ((packing_flags & 32768) != 0)
+        {
+            len += 8; // expiration
+        }
+        if ((packing_flags & 1) != 0)
+        {
+            len += EncoderUtils.getStr8Length(this.exchange);
+        }
+        if ((packing_flags & 2) != 0)
+        {
+            len += EncoderUtils.getStr8Length(this.routingKey);
+        }
+        if ((packing_flags & 4) != 0)
+        {
+            len += EncoderUtils.getStr16Length(this.resumeId);
+        }
+        if ((packing_flags & 8) != 0)
+        {
+            len += 8; // resumeTtl
+        }
+        return len;
+    }
+
     public void read(Decoder dec)
     {
         packing_flags = (short) dec.readUint16();
@@ -562,6 +607,7 @@ public final class DeliveryProperties extends Struct {
 
     }
 
+
     public Map<String,Object> getFields()
     {
         Map<String,Object> result = new LinkedHashMap<String,Object>();
@@ -618,6 +664,4 @@ public final class DeliveryProperties extends Struct {
 
         return result;
     }
-
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/ExchangeBoundResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/ExchangeBoundResult.java b/common/src/main/java/org/apache/qpid/transport/ExchangeBoundResult.java
index 04d944e..9348a64 100644
--- a/common/src/main/java/org/apache/qpid/transport/ExchangeBoundResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/ExchangeBoundResult.java
@@ -297,5 +297,10 @@ public final class ExchangeBoundResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/ExchangeQueryResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/ExchangeQueryResult.java b/common/src/main/java/org/apache/qpid/transport/ExchangeQueryResult.java
index 9f83a4a..1a4c90c 100644
--- a/common/src/main/java/org/apache/qpid/transport/ExchangeQueryResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/ExchangeQueryResult.java
@@ -264,5 +264,10 @@ public final class ExchangeQueryResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/FragmentProperties.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/FragmentProperties.java b/common/src/main/java/org/apache/qpid/transport/FragmentProperties.java
index 0b97743..d9fffa1 100644
--- a/common/src/main/java/org/apache/qpid/transport/FragmentProperties.java
+++ b/common/src/main/java/org/apache/qpid/transport/FragmentProperties.java
@@ -220,5 +220,11 @@ public final class FragmentProperties extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/GetTimeoutResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/GetTimeoutResult.java b/common/src/main/java/org/apache/qpid/transport/GetTimeoutResult.java
index ebff105..dce8b4d 100644
--- a/common/src/main/java/org/apache/qpid/transport/GetTimeoutResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/GetTimeoutResult.java
@@ -135,5 +135,11 @@ public final class GetTimeoutResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/MessageProperties.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/MessageProperties.java b/common/src/main/java/org/apache/qpid/transport/MessageProperties.java
index 1ddbae8..825d049 100644
--- a/common/src/main/java/org/apache/qpid/transport/MessageProperties.java
+++ b/common/src/main/java/org/apache/qpid/transport/MessageProperties.java
@@ -392,6 +392,52 @@ public final class MessageProperties extends Struct {
 
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        int len = 0;
+
+        len += 2; // packing_flags
+
+        if ((packing_flags & 256) != 0)
+        {
+            len += 8; // contentLength
+        }
+        if ((packing_flags & 512) != 0)
+        {
+            len += 16; // messageId
+        }
+        if ((packing_flags & 1024) != 0)
+        {
+            len += EncoderUtils.getVbin16Length(this.correlationId);
+        }
+        if ((packing_flags & 2048) != 0)
+        {
+            len += EncoderUtils.getStructLength(ReplyTo.TYPE, this.replyTo);
+        }
+        if ((packing_flags & 4096) != 0)
+        {
+            len += EncoderUtils.getStr8Length(this.contentType);
+        }
+        if ((packing_flags & 8192) != 0)
+        {
+            len += EncoderUtils.getStr8Length(this.contentEncoding);
+        }
+        if ((packing_flags & 16384) != 0)
+        {
+            len += EncoderUtils.getVbin16Length(this.userId);
+        }
+        if ((packing_flags & 32768) != 0)
+        {
+            len += EncoderUtils.getVbin16Length(this.appId);
+        }
+        if ((packing_flags & 1) != 0)
+        {
+            len += EncoderUtils.getMapLength(this.applicationHeaders);
+        }
+        return len;
+    }
+
     public void read(Decoder dec)
     {
         packing_flags = (short) dec.readUint16();
@@ -480,4 +526,5 @@ public final class MessageProperties extends Struct {
     }
 
 
+
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/MessageResumeResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/MessageResumeResult.java b/common/src/main/java/org/apache/qpid/transport/MessageResumeResult.java
index 1524b09..93e8d26 100644
--- a/common/src/main/java/org/apache/qpid/transport/MessageResumeResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/MessageResumeResult.java
@@ -135,5 +135,10 @@ public final class MessageResumeResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/Method.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/Method.java b/common/src/main/java/org/apache/qpid/transport/Method.java
index d23ce72..b42c22f 100644
--- a/common/src/main/java/org/apache/qpid/transport/Method.java
+++ b/common/src/main/java/org/apache/qpid/transport/Method.java
@@ -178,6 +178,12 @@ public abstract class Method extends Struct implements ProtocolEvent
         return completionListener != null;
     }
 
+    @Override
+    public final int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
     public String toString()
     {
         StringBuilder str = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/QueueQueryResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/QueueQueryResult.java b/common/src/main/java/org/apache/qpid/transport/QueueQueryResult.java
index ca0c027..ee8042b 100644
--- a/common/src/main/java/org/apache/qpid/transport/QueueQueryResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/QueueQueryResult.java
@@ -425,5 +425,11 @@ public final class QueueQueryResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/RecoverResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/RecoverResult.java b/common/src/main/java/org/apache/qpid/transport/RecoverResult.java
index 7a78f37..6dcd4cf 100644
--- a/common/src/main/java/org/apache/qpid/transport/RecoverResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/RecoverResult.java
@@ -137,5 +137,11 @@ public final class RecoverResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/ReplyTo.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/ReplyTo.java b/common/src/main/java/org/apache/qpid/transport/ReplyTo.java
index 38340db..3800fd1 100644
--- a/common/src/main/java/org/apache/qpid/transport/ReplyTo.java
+++ b/common/src/main/java/org/apache/qpid/transport/ReplyTo.java
@@ -148,6 +148,25 @@ public final class ReplyTo extends Struct {
 
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        int len = 0;
+
+        len += 2; // packing_flags
+
+        if ((packing_flags & 256) != 0)
+        {
+            len += EncoderUtils.getStr8Length(this.exchange);
+        }
+        if ((packing_flags & 512) != 0)
+        {
+            len += EncoderUtils.getStr8Length(this.routingKey);
+        }
+        return len;
+    }
+
+
     public void read(Decoder dec)
     {
         packing_flags = (short) dec.readUint16();

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/SessionCommandFragment.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/SessionCommandFragment.java b/common/src/main/java/org/apache/qpid/transport/SessionCommandFragment.java
index 6ae2d45..4647606 100644
--- a/common/src/main/java/org/apache/qpid/transport/SessionCommandFragment.java
+++ b/common/src/main/java/org/apache/qpid/transport/SessionCommandFragment.java
@@ -134,5 +134,10 @@ public final class SessionCommandFragment extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/SessionHeader.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/SessionHeader.java b/common/src/main/java/org/apache/qpid/transport/SessionHeader.java
index 9287d59..e5915d1 100644
--- a/common/src/main/java/org/apache/qpid/transport/SessionHeader.java
+++ b/common/src/main/java/org/apache/qpid/transport/SessionHeader.java
@@ -141,5 +141,11 @@ public final class SessionHeader extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/Struct.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/Struct.java b/common/src/main/java/org/apache/qpid/transport/Struct.java
index 045939e..bf48c77 100644
--- a/common/src/main/java/org/apache/qpid/transport/Struct.java
+++ b/common/src/main/java/org/apache/qpid/transport/Struct.java
@@ -114,6 +114,8 @@ public abstract class Struct implements Encodable
 
     public abstract Map<String,Object> getFields();
 
+    public abstract int getEncodedLength();
+
     public String toString()
     {
         StringBuilder str = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/XaResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/XaResult.java b/common/src/main/java/org/apache/qpid/transport/XaResult.java
index c9d502f..596390d 100644
--- a/common/src/main/java/org/apache/qpid/transport/XaResult.java
+++ b/common/src/main/java/org/apache/qpid/transport/XaResult.java
@@ -137,5 +137,12 @@ public final class XaResult extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/Xid.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/Xid.java b/common/src/main/java/org/apache/qpid/transport/Xid.java
index 4e14207..57d4418 100644
--- a/common/src/main/java/org/apache/qpid/transport/Xid.java
+++ b/common/src/main/java/org/apache/qpid/transport/Xid.java
@@ -219,5 +219,10 @@ public final class Xid extends Struct {
         return result;
     }
 
+    @Override
+    public int getEncodedLength()
+    {
+        throw new UnsupportedOperationException();
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java b/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
index 070621d..a3947a0 100644
--- a/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
+++ b/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
@@ -24,7 +24,6 @@ import static org.apache.qpid.transport.util.Functions.lsb;
 
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,7 +33,6 @@ import org.apache.qpid.transport.Range;
 import org.apache.qpid.transport.RangeSet;
 import org.apache.qpid.transport.Struct;
 import org.apache.qpid.transport.Type;
-import org.apache.qpid.transport.Xid;
 
 
 /**
@@ -46,24 +44,6 @@ import org.apache.qpid.transport.Xid;
 public abstract class AbstractEncoder implements Encoder
 {
 
-    private static Map<Class<?>,Type> ENCODINGS = new HashMap<Class<?>,Type>();
-    static
-    {
-        ENCODINGS.put(Boolean.class, Type.BOOLEAN);
-        ENCODINGS.put(String.class, Type.STR16);
-        ENCODINGS.put(Long.class, Type.INT64);
-        ENCODINGS.put(Integer.class, Type.INT32);
-        ENCODINGS.put(Short.class, Type.INT16);
-        ENCODINGS.put(Byte.class, Type.INT8);
-        ENCODINGS.put(Map.class, Type.MAP);
-        ENCODINGS.put(List.class, Type.LIST);
-        ENCODINGS.put(Float.class, Type.FLOAT);
-        ENCODINGS.put(Double.class, Type.DOUBLE);
-        ENCODINGS.put(Character.class, Type.CHAR);
-        ENCODINGS.put(byte[].class, Type.VBIN32);
-        ENCODINGS.put(UUID.class, Type.UUID);
-        ENCODINGS.put(Xid.class, Type.STRUCT32);
-    }
 
     private final Map<String,byte[]> str8cache = new LinkedHashMap<String,byte[]>()
     {
@@ -290,58 +270,6 @@ public abstract class AbstractEncoder implements Encoder
         }
     }
 
-    private Type encoding(Object value)
-    {
-        if (value == null)
-        {
-            return Type.VOID;
-        }
-
-        Class klass = value.getClass();
-        Type type = resolve(klass);
-
-        if (type == null)
-        {
-            throw new IllegalArgumentException
-                ("unable to resolve type: " + klass + ", " + value);
-        }
-        else
-        {
-            return type;
-        }
-    }
-
-    static final Type resolve(Class klass)
-    {
-        Type type = ENCODINGS.get(klass);
-        if (type != null)
-        {
-            return type;
-        }
-
-        Class sup = klass.getSuperclass();
-        if (sup != null)
-        {
-            type = resolve(klass.getSuperclass());
-
-            if (type != null)
-            {
-                return type;
-            }
-        }
-
-        for (Class iface : klass.getInterfaces())
-        {
-            type = resolve(iface);
-            if (type != null)
-            {
-                return type;
-            }
-        }
-
-        return null;
-    }
-
     public void writeMap(Map<String,Object> map)
     {
         int pos = beginSize32();
@@ -359,7 +287,7 @@ public abstract class AbstractEncoder implements Encoder
         {
             String key = entry.getKey();
             Object value = entry.getValue();
-            Type type = encoding(value);
+            Type type = EncoderUtils.getEncodingType(value);
             writeStr8(key);
             put(type.getCode());
             write(type, value);
@@ -381,7 +309,7 @@ public abstract class AbstractEncoder implements Encoder
     {
         for (Object value : list)
         {
-            Type type = encoding(value);
+            Type type = EncoderUtils.getEncodingType(value);
             put(type.getCode());
             write(type, value);
         }
@@ -407,7 +335,7 @@ public abstract class AbstractEncoder implements Encoder
         }
         else
         {
-            type = encoding(array.get(0));
+            type = EncoderUtils.getEncodingType(array.get(0));
         }
 
         put(type.getCode());

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java b/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
index b2ca829..86c0ece 100644
--- a/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
+++ b/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
@@ -27,7 +27,6 @@ import java.util.UUID;
 import org.apache.qpid.transport.RangeSet;
 import org.apache.qpid.transport.Struct;
 
-
 /**
  * Encoder interface.
  * Each concrete implementor must specify how to encode given values.

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/main/java/org/apache/qpid/transport/codec/EncoderUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/qpid/transport/codec/EncoderUtils.java b/common/src/main/java/org/apache/qpid/transport/codec/EncoderUtils.java
new file mode 100644
index 0000000..ea06175
--- /dev/null
+++ b/common/src/main/java/org/apache/qpid/transport/codec/EncoderUtils.java
@@ -0,0 +1,343 @@
+/*
+ * 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.qpid.transport.codec;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.Type;
+import org.apache.qpid.transport.Xid;
+
+public class EncoderUtils
+{
+    private static final Map<Class<?>, Type> ENCODINGS = new HashMap<>();
+    static
+    {
+        ENCODINGS.put(Boolean.class, Type.BOOLEAN);
+        ENCODINGS.put(String.class, Type.STR16);
+        ENCODINGS.put(Long.class, Type.INT64);
+        ENCODINGS.put(Integer.class, Type.INT32);
+        ENCODINGS.put(Short.class, Type.INT16);
+        ENCODINGS.put(Byte.class, Type.INT8);
+        ENCODINGS.put(Map.class, Type.MAP);
+        ENCODINGS.put(List.class, Type.LIST);
+        ENCODINGS.put(Float.class, Type.FLOAT);
+        ENCODINGS.put(Double.class, Type.DOUBLE);
+        ENCODINGS.put(Character.class, Type.CHAR);
+        ENCODINGS.put(byte[].class, Type.VBIN32);
+        ENCODINGS.put(UUID.class, Type.UUID);
+        ENCODINGS.put(Xid.class, Type.STRUCT32);
+    }
+
+    public static Type getEncodingType(Object value)
+    {
+        if (value == null)
+        {
+            return Type.VOID;
+        }
+
+        Class klass = value.getClass();
+        Type type = resolve(klass);
+
+        if (type == null)
+        {
+            throw new IllegalArgumentException
+                    ("unable to resolve type: " + klass + ", " + value);
+        }
+        else
+        {
+            return type;
+        }
+    }
+
+    public static int getStruct32Length(Struct s)
+    {
+        if (s == null)
+        {
+            return 4;
+        }
+        else
+        {
+            int len = 0;
+            len += 4; // size
+            len += 2; // encoded type
+            len += s.getEncodedLength();
+
+            return len;
+        }
+    }
+
+    public static int getArrayLength(List<Object> value)
+    {
+        int len = 0;
+        len += 4; // size
+        if (value != null && !value.isEmpty())
+        {
+            len += 1; // type
+            len += 4; // array size
+
+            final Type type = getEncodingType(value.get(0));
+            for (Object v : value)
+            {
+                len += getTypeLength(type, v);
+            }
+
+        }
+
+        return len;
+
+    }
+
+    public static int getListLength(List<Object> value)
+    {
+        int len = 0;
+        len += 4; // size
+        if (value != null && !value.isEmpty())
+        {
+            len += 4; // list size
+            for (Object v : value)
+            {
+                final Type type = getEncodingType(v);
+                len += 1; // type code
+                len += getTypeLength(type, v);
+            }
+        }
+        return len;
+    }
+
+    public static int getStr8Length(String s)
+    {
+        if (s == null)
+        {
+            return 1;
+        }
+        else
+        {
+            int length = s.getBytes(StandardCharsets.UTF_8).length;
+            if (length > 255)
+            {
+                throw new IllegalArgumentException(String.format("String too long (%d) for str8", length));
+            }
+            return 1 + length;
+        }
+    }
+
+    public static int getStr16Length(String s)
+    {
+        if (s == null)
+        {
+            return 2;
+        }
+        else
+        {
+            int length = s.getBytes(StandardCharsets.UTF_8).length;
+            if (length > 65535)
+            {
+                throw new IllegalArgumentException(String.format("String too long (%d) for str16", length));
+            }
+            return 2 + length;
+        }
+    }
+
+    public static int getVbin16Length(byte[] bytes)
+    {
+        if (bytes == null)
+        {
+            return 2;
+        }
+        else
+        {
+            return 2 + bytes.length;
+        }
+    }
+
+    public static int getStructLength(int type, Struct s)
+    {
+        int len = 0;
+
+        if (s == null)
+        {
+            s = Struct.create(type);
+        }
+
+        int width = s.getSizeWidth();
+
+        if (width > 0)
+        {
+            switch (width)
+            {
+                case 1:
+                case 2:
+                case 4:
+                    len += width;
+                    break;
+                default:
+                    throw new IllegalStateException("illegal width: " + width);
+            }
+        }
+
+        if (type > 0)
+        {
+            len += 2; // type
+        }
+
+        len += s.getEncodedLength();
+
+        return len;
+
+
+    }
+
+    public static int getMapLength(Map<String, Object> map)
+    {
+        int len = 0;
+
+        len += 4; // size
+        if (map != null)
+        {
+            len += 4; // map size
+            for (Map.Entry<String,Object> entry : map.entrySet())
+            {
+                String key = entry.getKey();
+                Object value = entry.getValue();
+                len += getStr8Length(key);
+                len += 1; // type code
+                Type type = getEncodingType(value);
+                len += getTypeLength(type, value);
+            }
+        }
+
+        return len;
+    }
+
+    private static Type resolve(Class klass)
+    {
+        Type type = ENCODINGS.get(klass);
+        if (type != null)
+        {
+            return type;
+        }
+
+        Class sup = klass.getSuperclass();
+        if (sup != null)
+        {
+            type = resolve(klass.getSuperclass());
+
+            if (type != null)
+            {
+                return type;
+            }
+        }
+
+        for (Class iface : klass.getInterfaces())
+        {
+            type = resolve(iface);
+            if (type != null)
+            {
+                return type;
+            }
+        }
+
+        return null;
+    }
+
+    private static int getTypeLength(Type t, Object value)
+    {
+        switch (t)
+        {
+            case VOID:
+                return 0;
+
+            case BIN8:
+            case UINT8:
+            case INT8:
+            case CHAR:
+            case BOOLEAN:
+                return 1;
+
+            case BIN16:
+            case UINT16:
+            case INT16:
+                return 2;
+
+            case BIN32:
+            case UINT32:
+            case CHAR_UTF32:
+            case INT32:
+            case FLOAT:
+                return 4;
+
+            case BIN64:
+            case UINT64:
+            case INT64:
+            case DATETIME:
+            case DOUBLE:
+                return 8;
+
+            case UUID:
+                return 16;
+
+            case STR8:
+                return getStr8Length((String) value);
+
+            case STR16:
+                return getStr16Length((String) value);
+
+            case STR8_LATIN:
+            case STR8_UTF16:
+            case STR16_LATIN:
+            case STR16_UTF16:
+                String str = (String) value;
+                return t.getWidth() + (str == null ? 0 : str.getBytes(StandardCharsets.UTF_8).length);
+
+            case MAP:
+                return getMapLength((Map<String, Object>) value);
+
+            case LIST:
+                return getListLength((List<Object>) value);
+
+            case ARRAY:
+                return getArrayLength((List<Object>) value);
+
+            case STRUCT32:
+                return getStruct32Length((Struct) value);
+
+            case BIN40:
+            case DEC32:
+            case BIN72:
+            case DEC64:
+                return t.getWidth() + (value == null ? 0 : ((byte[])value).length);
+
+            default:
+                if (!(value instanceof byte[]))
+                {
+                    throw new IllegalArgumentException("Expecting byte array was " + (value == null
+                            ? "null"
+                            : value.getClass()));
+                }
+                return t.getWidth() + (value == null ? 0 : ((byte[])value).length);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7772251c/common/src/test/java/org/apache/qpid/transport/codec/BBEncoderTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/qpid/transport/codec/BBEncoderTest.java b/common/src/test/java/org/apache/qpid/transport/codec/BBEncoderTest.java
index 5d6d406..f4cedc4 100644
--- a/common/src/test/java/org/apache/qpid/transport/codec/BBEncoderTest.java
+++ b/common/src/test/java/org/apache/qpid/transport/codec/BBEncoderTest.java
@@ -20,14 +20,17 @@
  */
 package org.apache.qpid.transport.codec;
 
-import org.apache.qpid.test.utils.QpidTestCase;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertArrayEquals;
 
 import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
 
-/**
- * BBEncoderTest
- *
- */
+import org.apache.qpid.test.utils.QpidTestCase;
 
 public class BBEncoderTest extends QpidTestCase
 {
@@ -44,4 +47,63 @@ public class BBEncoderTest extends QpidTestCase
         assertEquals(0xBEEFDEAD, buf.getInt(4));
     }
 
+
+    public void testReadWriteStruct()
+    {
+        BBEncoder encoder = new BBEncoder(4);
+
+        ReplyTo replyTo = new ReplyTo("amq.direct", "test");
+        encoder.writeStruct(ReplyTo.TYPE, replyTo);
+
+        ByteBuffer buffer = encoder.buffer();
+
+        assertEquals("Unexpected size", EncoderUtils.getStructLength(ReplyTo.TYPE, replyTo), buffer.remaining());
+
+        BBDecoder decoder = new BBDecoder();
+        decoder.init(buffer);
+
+        ReplyTo decoded = (ReplyTo)decoder.readStruct(ReplyTo.TYPE);
+
+        assertEquals("Unexpected exchange", replyTo.getExchange(), decoded.getExchange());
+        assertEquals("Unexpected routing key", replyTo.getRoutingKey(), decoded.getRoutingKey());
+    }
+
+    public void testReadWriteStruct32()
+    {
+        BBEncoder encoder = new BBEncoder(4);
+        Map<String, Object> applicationHeaders = new HashMap<>();
+        applicationHeaders.put("testProperty", "testValue");
+        applicationHeaders.put("list", Arrays.asList("a", 1, 2.0));
+        applicationHeaders.put("map", Collections.singletonMap("mapKey", "mapValue"));
+        MessageProperties messageProperties = new MessageProperties(10,
+                                                                    UUID.randomUUID(),
+                                                                    "abc".getBytes(UTF_8),
+                                                                    new ReplyTo("amq.direct", "test"),
+                                                                    "text/plain",
+                                                                    "identity",
+                                                                    "cba".getBytes(UTF_8),
+                                                                    "app".getBytes(UTF_8),
+                                                                    applicationHeaders);
+
+        encoder.writeStruct32(messageProperties);
+
+        ByteBuffer buffer = encoder.buffer();
+
+        assertEquals("Unexpected size", EncoderUtils.getStruct32Length(messageProperties), buffer.remaining());
+
+        BBDecoder decoder = new BBDecoder();
+        decoder.init(buffer);
+
+        MessageProperties decoded = (MessageProperties)decoder.readStruct32();
+
+        assertEquals("Unexpected content length", messageProperties.getContentLength(), decoded.getContentLength());
+        assertEquals("Unexpected message id", messageProperties.getMessageId(), decoded.getMessageId());
+        assertArrayEquals("Unexpected correlation id", messageProperties.getCorrelationId(), decoded.getCorrelationId());
+        assertEquals("Unexpected reply to", messageProperties.getReplyTo(), decoded.getReplyTo());
+        assertEquals("Unexpected content type", messageProperties.getContentType(), decoded.getContentType());
+        assertEquals("Unexpected content encoding", messageProperties.getContentEncoding(), decoded.getContentEncoding());
+        assertArrayEquals("Unexpected user id", messageProperties.getUserId(), decoded.getUserId());
+        assertArrayEquals("Unexpected application id", messageProperties.getAppId(), decoded.getAppId());
+        assertEquals("Unexpected application headers", messageProperties.getApplicationHeaders(), decoded.getApplicationHeaders());
+    }
 }


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