Merge "Bug 2327: Handle binary data in NormalizedNode streaming"
authorMoiz Raja <moraja@cisco.com>
Sun, 25 Jan 2015 19:58:35 +0000 (19:58 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sun, 25 Jan 2015 19:58:35 +0000 (19:58 +0000)
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeOutputStreamWriter.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ValueTypes.java
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeStreamReaderWriterTest.java
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test.yang

index 9201a94de326111856ad7d4d5246264cb9edfe46..8cd428bdcca45cf30ac719b2a87b954727b8ac1e 100644 (file)
@@ -12,6 +12,18 @@ package org.opendaylight.controller.cluster.datastore.node.utils.stream;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.Node;
@@ -29,18 +41,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * NormalizedNodeInputStreamReader reads the byte stream and constructs the normalized node including its children nodes.
@@ -67,6 +67,8 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
     private NormalizedNodeAttrBuilder<NodeWithValue, Object,
                                       LeafSetEntryNode<Object>> leafSetEntryBuilder;
 
+    private final StringBuilder reusableStringBuilder = new StringBuilder(50);
+
     public NormalizedNodeInputStreamReader(InputStream stream) throws IOException {
         Preconditions.checkNotNull(stream);
         input = new DataInputStream(stream);
@@ -147,7 +149,6 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
 
             case NodeTypes.ANY_XML_NODE :
                 LOG.debug("Read xml node");
-                Node<?> value = (Node<?>) readObject();
                 return Builders.anyXmlBuilder().withValue((Node<?>) readObject()).build();
 
             case NodeTypes.MAP_NODE :
@@ -196,14 +197,16 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
         String namespace = readCodedString();
         String revision = readCodedString();
 
-        // Not using stringbuilder as compiler optimizes string concatenation of +
         String qName;
         if(!Strings.isNullOrEmpty(revision)) {
-            qName = "(" + namespace + REVISION_ARG + revision + ")" +localName;
+            qName = reusableStringBuilder.append('(').append(namespace).append(REVISION_ARG).
+                        append(revision).append(')').append(localName).toString();
         } else {
-            qName = "(" + namespace + ")" + localName;
+            qName = reusableStringBuilder.append('(').append(namespace).append(')').
+                        append(localName).toString();
         }
 
+        reusableStringBuilder.delete(0, reusableStringBuilder.length());
         return QNameFactory.create(qName);
     }
 
@@ -213,7 +216,7 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
         if(valueType == NormalizedNodeOutputStreamWriter.IS_CODE_VALUE) {
             return codedStringMap.get(input.readInt());
         } else if(valueType == NormalizedNodeOutputStreamWriter.IS_STRING_VALUE) {
-            String value = input.readUTF();
+            String value = input.readUTF().intern();
             codedStringMap.put(Integer.valueOf(codedStringMap.size()), value);
             return value;
         }
@@ -249,22 +252,22 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
                 return readObjSet();
 
             case ValueTypes.BOOL_TYPE :
-                return input.readBoolean();
+                return Boolean.valueOf(input.readBoolean());
 
             case ValueTypes.BYTE_TYPE :
-                return input.readByte();
+                return Byte.valueOf(input.readByte());
 
             case ValueTypes.INT_TYPE :
-                return input.readInt();
+                return Integer.valueOf(input.readInt());
 
             case ValueTypes.LONG_TYPE :
-                return input.readLong();
+                return Long.valueOf(input.readLong());
 
             case ValueTypes.QNAME_TYPE :
                 return readQName();
 
             case ValueTypes.SHORT_TYPE :
-                return input.readShort();
+                return Short.valueOf(input.readShort());
 
             case ValueTypes.STRING_TYPE :
                 return input.readUTF();
@@ -275,6 +278,11 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
             case ValueTypes.BIG_INTEGER_TYPE :
                 return new BigInteger(input.readUTF());
 
+            case ValueTypes.BINARY_TYPE :
+                byte[] bytes = new byte[input.readInt()];
+                input.readFully(bytes);
+                return bytes;
+
             case ValueTypes.YANG_IDENTIFIER_TYPE :
             return readYangInstanceIdentifier();
 
index 46768d5112425effba48a8a8513f288f20aaf71a..c76a254b53ffcdb8f8e64594faa7e93864d4b0ab 100644 (file)
@@ -12,11 +12,6 @@ package org.opendaylight.controller.cluster.datastore.node.utils.stream;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import java.io.DataOutput;
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -24,6 +19,11 @@ import java.io.OutputStream;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * NormalizedNodeOutputStreamWriter will be used by distributed datastore to send normalized node in
@@ -339,6 +339,11 @@ public class NormalizedNodeOutputStreamWriter implements NormalizedNodeStreamWri
             case ValueTypes.BITS_TYPE:
                 writeObjSet((Set<?>) value);
                 break;
+            case ValueTypes.BINARY_TYPE:
+                byte[] bytes = (byte[]) value;
+                output.writeInt(bytes.length);
+                output.write(bytes);
+                break;
             case ValueTypes.YANG_IDENTIFIER_TYPE:
                 writeYangInstanceIdentifier((YangInstanceIdentifier) value);
                 break;
index 80fa527b4613e54d942aa14cc121c3cf234dd410..e75a454d394294795c633a1d57d83ccc5661ce98 100644 (file)
@@ -9,14 +9,13 @@
 package org.opendaylight.controller.cluster.datastore.node.utils.stream;
 
 import com.google.common.base.Preconditions;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 public class ValueTypes {
     public static final byte SHORT_TYPE = 1;
@@ -30,6 +29,7 @@ public class ValueTypes {
     public static final byte STRING_TYPE = 9;
     public static final byte BIG_INTEGER_TYPE = 10;
     public static final byte BIG_DECIMAL_TYPE = 11;
+    public static final byte BINARY_TYPE = 12;
 
     private static Map<Class<?>, Byte> types = new HashMap<>();
 
@@ -45,6 +45,7 @@ public class ValueTypes {
         types.put(Short.class, Byte.valueOf(SHORT_TYPE));
         types.put(BigInteger.class, Byte.valueOf(BIG_INTEGER_TYPE));
         types.put(BigDecimal.class, Byte.valueOf(BIG_DECIMAL_TYPE));
+        types.put(byte[].class, Byte.valueOf(BINARY_TYPE));
     }
 
     public static final byte getSerializableType(Object node){
index 8854fc73b5ebffb656f07ea83b4a7443ba69d81e..f3df8f0c577a8484ac55cce6752a3058cc02b7f7 100644 (file)
@@ -17,13 +17,17 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.util.TestModel;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public class NormalizedNodeStreamReaderWriterTest {
@@ -31,7 +35,7 @@ public class NormalizedNodeStreamReaderWriterTest {
     @Test
     public void testNormalizedNodeStreamReaderWriter() throws IOException {
 
-        testNormalizedNodeStreamReaderWriter(TestModel.createTestContainer());
+        testNormalizedNodeStreamReaderWriter(createTestContainer());
 
         QName toaster = QName.create("http://netconfcentral.org/ns/toaster","2009-11-20","toaster");
         QName darknessFactor = QName.create("http://netconfcentral.org/ns/toaster","2009-11-20","darknessFactor");
@@ -44,6 +48,25 @@ public class NormalizedNodeStreamReaderWriterTest {
                 withChild(toasterNode).build());
     }
 
+    private NormalizedNode<?, ?> createTestContainer() {
+        byte[] bytes1 = {1,2,3};
+        LeafSetEntryNode<Object> entry1 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+                new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes1)).
+                withValue(bytes1).build();
+
+        byte[] bytes2 = {};
+        LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+                new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
+                withValue(bytes2).build();
+
+        return TestModel.createBaseTestContainerBuilder().
+                withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
+                        new YangInstanceIdentifier.NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
+                        withChild(entry1).withChild(entry2).build()).
+                withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATE_QNAME, new byte[]{1,2,3,4})).
+                        build();
+    }
+
     private void testNormalizedNodeStreamReaderWriter(NormalizedNode<?, ?> input) throws IOException {
 
         byte[] byteData = null;
index d3abd38153968ca3c66430e6887b5b80c7220afb..8720f3bd8839a02391968700fac55c5dce40b2b0 100644 (file)
 
 package org.opendaylight.controller.cluster.datastore.util;
 
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
 import com.google.common.collect.ImmutableSet;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
@@ -36,18 +46,6 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
 public class TestModel {
 
   public static final QName TEST_QNAME = QName.create(
@@ -66,6 +64,7 @@ public class TestModel {
   public static final QName DESC_QNAME = QName.create(TEST_QNAME, "desc");
   public static final QName POINTER_QNAME = QName.create(TEST_QNAME, "pointer");
   public static final QName SOME_BINARY_DATE_QNAME = QName.create(TEST_QNAME, "some-binary-data");
+  public static final QName BINARY_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "binary_leaf_list");
   public static final QName SOME_REF_QNAME = QName.create(TEST_QNAME,
       "some-ref");
   public static final QName MYIDENTITY_QNAME = QName.create(TEST_QNAME,
index a1fbc1fdad1f897d265bbd6813d7a36962b70a3f..c720d5e0cdcc099026b545357c1edc8edb92de41 100644 (file)
@@ -74,6 +74,10 @@ module odl-datastore-test {
             type uint8;
         }
 
+        leaf-list binary_leaf_list {
+            type binary;
+        }
+
         leaf pointer {
             type leafref {
                 path "/network-topology/topology/node/termination-point/tp-id";