You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by ka...@apache.org on 2013/11/11 23:15:30 UTC

git commit: [HELIX-292] ZNRecordStreamingSerializer should not assume id comes first

Updated Branches:
  refs/heads/master 00ff8c06c -> ec3611238


[HELIX-292] ZNRecordStreamingSerializer should not assume id comes first


Project: http://git-wip-us.apache.org/repos/asf/incubator-helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-helix/commit/ec361123
Tree: http://git-wip-us.apache.org/repos/asf/incubator-helix/tree/ec361123
Diff: http://git-wip-us.apache.org/repos/asf/incubator-helix/diff/ec361123

Branch: refs/heads/master
Commit: ec36112386c527cb7cdeeb2e2b7d14069a5fec3e
Parents: 00ff8c0
Author: Kanak Biscuitwala <ka...@apache.org>
Authored: Mon Nov 11 14:15:09 2013 -0800
Committer: Kanak Biscuitwala <ka...@apache.org>
Committed: Mon Nov 11 14:15:09 2013 -0800

----------------------------------------------------------------------
 .../manager/zk/ZNRecordStreamingSerializer.java | 31 +++++--
 .../zk/TestZNRecordStreamingSerializer.java     | 92 ++++++++++++++++++++
 2 files changed, 115 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/ec361123/helix-core/src/main/java/org/apache/helix/manager/zk/ZNRecordStreamingSerializer.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZNRecordStreamingSerializer.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZNRecordStreamingSerializer.java
index f97774e..bd37d42 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZNRecordStreamingSerializer.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZNRecordStreamingSerializer.java
@@ -37,6 +37,7 @@ import org.codehaus.jackson.JsonParser;
 import org.codehaus.jackson.JsonToken;
 import org.restlet.engine.util.Base64;
 
+import com.google.common.collect.Maps;
 
 public class ZNRecordStreamingSerializer implements ZkSerializer {
   private static Logger LOG = Logger.getLogger(ZNRecordStreamingSerializer.class);
@@ -173,7 +174,13 @@ public class ZNRecordStreamingSerializer implements ZkSerializer {
     }
 
     ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+
     ZNRecord record = null;
+    String id = null;
+    Map<String, String> simpleFields = Maps.newHashMap();
+    Map<String, List<String>> listFields = Maps.newHashMap();
+    Map<String, Map<String, String>> mapFields = Maps.newHashMap();
+    byte[] rawPayload = null;
 
     try {
       JsonFactory f = new JsonFactory();
@@ -185,24 +192,24 @@ public class ZNRecordStreamingSerializer implements ZkSerializer {
         jp.nextToken(); // move to value, or START_OBJECT/START_ARRAY
         if ("id".equals(fieldname)) {
           // contains an object
-          record = new ZNRecord(jp.getText());
+          id = jp.getText();
         } else if ("simpleFields".equals(fieldname)) {
           while (jp.nextToken() != JsonToken.END_OBJECT) {
             String key = jp.getCurrentName();
             jp.nextToken(); // move to value
-            record.setSimpleField(key, jp.getText());
+            simpleFields.put(key, jp.getText());
           }
         } else if ("mapFields".equals(fieldname)) {
           // user.setVerified(jp.getCurrentToken() == JsonToken.VALUE_TRUE);
           while (jp.nextToken() != JsonToken.END_OBJECT) {
             String key = jp.getCurrentName();
-            record.setMapField(key, new TreeMap<String, String>());
+            mapFields.put(key, new TreeMap<String, String>());
             jp.nextToken(); // move to value
 
             while (jp.nextToken() != JsonToken.END_OBJECT) {
               String mapKey = jp.getCurrentName();
               jp.nextToken(); // move to value
-              record.getMapField(key).put(mapKey, jp.getText());
+              mapFields.get(key).put(mapKey, jp.getText());
             }
           }
 
@@ -210,25 +217,33 @@ public class ZNRecordStreamingSerializer implements ZkSerializer {
           // user.setUserImage(jp.getBinaryValue());
           while (jp.nextToken() != JsonToken.END_OBJECT) {
             String key = jp.getCurrentName();
-            record.setListField(key, new ArrayList<String>());
+            listFields.put(key, new ArrayList<String>());
             jp.nextToken(); // move to value
             while (jp.nextToken() != JsonToken.END_ARRAY) {
-              record.getListField(key).add(jp.getText());
+              listFields.get(key).add(jp.getText());
             }
 
           }
 
         } else if ("rawPayload".equals(fieldname)) {
-          record.setRawPayload(Base64.decode(jp.getText()));
+          rawPayload = Base64.decode(jp.getText());
         } else {
           throw new IllegalStateException("Unrecognized field '" + fieldname + "'!");
         }
       }
       jp.close(); // ensure resources get cleaned up timely and properly
+
+      if (id == null) {
+        throw new IllegalStateException("ZNRecord id field is required!");
+      }
+      record = new ZNRecord(id);
+      record.setSimpleFields(simpleFields);
+      record.setListFields(listFields);
+      record.setMapFields(mapFields);
+      record.setRawPayload(rawPayload);
     } catch (Exception e) {
       LOG.error("Exception during deserialization of bytes: " + new String(bytes), e);
     }
-
     return record;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/ec361123/helix-core/src/test/java/org/apache/helix/manager/zk/TestZNRecordStreamingSerializer.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/manager/zk/TestZNRecordStreamingSerializer.java b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZNRecordStreamingSerializer.java
new file mode 100644
index 0000000..e4b0b25
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZNRecordStreamingSerializer.java
@@ -0,0 +1,92 @@
+package org.apache.helix.manager.zk;
+
+import org.apache.helix.ZNRecord;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/*
+ * 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.
+ */
+
+public class TestZNRecordStreamingSerializer {
+  /**
+   * Test the normal case of serialize/deserialize where ZNRecord is well-formed
+   */
+  @Test
+  public void basicTest() {
+    ZNRecord record = new ZNRecord("testId");
+    record.setMapField("k1", ImmutableMap.of("a", "b", "c", "d"));
+    record.setMapField("k2", ImmutableMap.of("e", "f", "g", "h"));
+    record.setListField("k3", ImmutableList.of("a", "b", "c", "d"));
+    record.setListField("k4", ImmutableList.of("d", "e", "f", "g"));
+    record.setSimpleField("k5", "a");
+    record.setSimpleField("k5", "b");
+    ZNRecordStreamingSerializer serializer = new ZNRecordStreamingSerializer();
+    ZNRecord result = (ZNRecord) serializer.deserialize(serializer.serialize(record));
+    Assert.assertEquals(result, record);
+  }
+
+  /**
+   * Check that the ZNRecord is not constructed if there is no id in the json
+   */
+  @Test
+  public void noIdTest() {
+    StringBuilder jsonString =
+        new StringBuilder("{\n").append("  \"simpleFields\": {},\n")
+            .append("  \"listFields\": {},\n").append("  \"mapFields\": {}\n").append("}\n");
+    ZNRecordStreamingSerializer serializer = new ZNRecordStreamingSerializer();
+    ZNRecord result = (ZNRecord) serializer.deserialize(jsonString.toString().getBytes());
+    Assert.assertNull(result);
+  }
+
+  /**
+   * Test that the json still deserizalizes correctly if id is not first
+   */
+  @Test
+  public void idNotFirstTest() {
+    StringBuilder jsonString =
+        new StringBuilder("{\n").append("  \"simpleFields\": {},\n")
+            .append("  \"listFields\": {},\n").append("  \"mapFields\": {},\n")
+            .append("\"id\": \"myId\"\n").append("}");
+    ZNRecordStreamingSerializer serializer = new ZNRecordStreamingSerializer();
+    ZNRecord result = (ZNRecord) serializer.deserialize(jsonString.toString().getBytes());
+    Assert.assertNotNull(result);
+    Assert.assertEquals(result.getId(), "myId");
+  }
+
+  /**
+   * Test that simple, list, and map fields are initialized as empty even when not in json
+   */
+  @Test
+  public void fieldAutoInitTest() {
+    StringBuilder jsonString = new StringBuilder("{\n").append("\"id\": \"myId\"\n").append("}");
+    ZNRecordStreamingSerializer serializer = new ZNRecordStreamingSerializer();
+    ZNRecord result = (ZNRecord) serializer.deserialize(jsonString.toString().getBytes());
+    Assert.assertNotNull(result);
+    Assert.assertEquals(result.getId(), "myId");
+    Assert.assertNotNull(result.getSimpleFields());
+    Assert.assertTrue(result.getSimpleFields().isEmpty());
+    Assert.assertNotNull(result.getListFields());
+    Assert.assertTrue(result.getListFields().isEmpty());
+    Assert.assertNotNull(result.getMapFields());
+    Assert.assertTrue(result.getMapFields().isEmpty());
+  }
+}