BUG 4589 : Handle writing and reading large strings 63/29563/1
authorMoiz Raja <moraja@cisco.com>
Tue, 10 Nov 2015 01:56:32 +0000 (17:56 -0800)
committerTom Pantelis <tpanteli@brocade.com>
Wed, 11 Nov 2015 19:30:23 +0000 (19:30 +0000)
Change-Id: If81926757aef3c1275ba43a7cf8c7adf94d86e08
Signed-off-by: Moiz Raja <moraja@cisco.com>
(cherry picked from commit 28484d59aa626dd4b32cdeb2d10dbc2c47cc051a)

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/node/utils/stream/ValueTypesTest.java [new file with mode: 0644]

index 8bb059c..8c95397 100644 (file)
@@ -16,6 +16,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -291,6 +292,9 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
             case ValueTypes.STRING_TYPE :
                 return input.readUTF();
 
+            case ValueTypes.STRING_BYTES_TYPE:
+                return readStringBytes();
+
             case ValueTypes.BIG_DECIMAL_TYPE :
                 return new BigDecimal(input.readUTF());
 
@@ -310,6 +314,12 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeStreamRead
         }
     }
 
+    private String readStringBytes() throws IOException {
+        byte[] bytes = new byte[input.readInt()];
+        input.readFully(bytes);
+        return new String(bytes, StandardCharsets.UTF_8);
+    }
+
     public YangInstanceIdentifier readYangInstanceIdentifier() throws IOException {
         readSignatureMarkerAndVersionIfNeeded();
         return readYangInstanceIdentifierInternal();
index 3a56335..b155b5a 100644 (file)
@@ -13,6 +13,7 @@ import java.io.DataOutput;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -387,6 +388,11 @@ public class NormalizedNodeOutputStreamWriter implements NormalizedNodeStreamWri
                 break;
             case ValueTypes.NULL_TYPE :
                 break;
+            case ValueTypes.STRING_BYTES_TYPE:
+                final byte[] valueBytes = value.toString().getBytes(StandardCharsets.UTF_8);
+                output.writeInt(valueBytes.length);
+                output.write(valueBytes);
+                break;
             default:
                 output.writeUTF(value.toString());
                 break;
index f107ce7..1afc73a 100644 (file)
@@ -18,6 +18,9 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 final class ValueTypes {
+    // The String length threshold beyond which a String should be encoded as bytes
+    public static final int STRING_BYTES_LENGTH_THRESHOLD = Short.MAX_VALUE / 4;
+
     public static final byte SHORT_TYPE = 1;
     public static final byte BYTE_TYPE = 2;
     public static final byte INT_TYPE = 3;
@@ -31,6 +34,7 @@ final class ValueTypes {
     public static final byte BIG_DECIMAL_TYPE = 11;
     public static final byte BINARY_TYPE = 12;
     public static final byte NULL_TYPE = 13;
+    public static final byte STRING_BYTES_TYPE = 14;
 
     private static final Map<Class<?>, Byte> TYPES;
 
@@ -62,6 +66,9 @@ final class ValueTypes {
 
         final Byte type = TYPES.get(node.getClass());
         if (type != null) {
+            if(type == STRING_TYPE && ((String) node).length() >= STRING_BYTES_LENGTH_THRESHOLD ){
+                return STRING_BYTES_TYPE;
+            }
             return type;
         }
 
index f468264..6dbb0f8 100644 (file)
@@ -43,9 +43,12 @@ public class NormalizedNodeStreamReaderWriterTest {
 
         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");
+        QName description = QName.create("http://netconfcentral.org/ns/toaster","2009-11-20","description");
         ContainerNode toasterNode = Builders.containerBuilder().
                 withNodeIdentifier(new NodeIdentifier(toaster)).
-                withChild(ImmutableNodes.leafNode(darknessFactor, "1000")).build();
+                withChild(ImmutableNodes.leafNode(darknessFactor, "1000")).
+                withChild(ImmutableNodes.leafNode(description, largeString(20)))
+                .build();
 
         ContainerNode toasterContainer = Builders.containerBuilder().
                 withNodeIdentifier(new NodeIdentifier(SchemaContext.NAME)).
@@ -172,4 +175,14 @@ public class NormalizedNodeStreamReaderWriterTest {
         Assert.assertEquals(input, clone.getInput());
 
     }
+
+    private String largeString(int pow){
+        String s = "X";
+        for(int i=0;i<pow;i++){
+            StringBuilder b = new StringBuilder();
+            b.append(s).append(s);
+            s = b.toString();
+        }
+        return s;
+    }
 }
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ValueTypesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ValueTypesTest.java
new file mode 100644 (file)
index 0000000..be521ef
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.cluster.datastore.node.utils.stream;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class ValueTypesTest {
+    @Test
+    public void testStringType(){
+        assertEquals(ValueTypes.STRING_TYPE, ValueTypes.getSerializableType("foobar"));
+        final String largeString = largeString(ValueTypes.STRING_BYTES_LENGTH_THRESHOLD);
+        assertEquals(ValueTypes.STRING_BYTES_TYPE, ValueTypes.getSerializableType(largeString));
+    }
+
+    private String largeString(int minSize){
+        final int pow = (int) (Math.log(minSize * 2) / Math.log(2));
+        String s = "X";
+        for(int i=0;i<pow;i++){
+            StringBuilder b = new StringBuilder();
+            b.append(s).append(s);
+            s = b.toString();
+        }
+        return s;
+    }
+
+}
\ No newline at end of file