This is an automated email from the ASF dual-hosted git repository.

jiangtian pushed a commit to branch cluster_new
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git


The following commit(s) were added to refs/heads/cluster_new by this push:
     new 96cbb3a  [IOTDB-781] Support AlterTimeSeriesPlan in distributed version
     new 1030519  Merge pull request #1405 from neuyilan/cluster_new_IOTDB-781
96cbb3a is described below

commit 96cbb3ab6e83a19287181fa13660ead6cc4b0163
Author: HouliangQi <[email protected]>
AuthorDate: Mon Jun 22 15:37:56 2020 +0800

    [IOTDB-781] Support AlterTimeSeriesPlan in distributed version
---
 .../iotdb/cluster/query/ClusterPlanRouter.java     |  16 ++-
 .../apache/iotdb/cluster/utils/PartitionUtils.java |   6 +-
 .../apache/iotdb/db/qp/physical/PhysicalPlan.java  |   7 +-
 .../db/qp/physical/sys/AlterTimeSeriesPlan.java    | 136 ++++++++++++++++++--
 .../iotdb/tsfile/utils/ReadWriteIOUtils.java       | 100 +++++++--------
 .../iotdb/tsfile/utils/ReadWriteIOUtilsTest.java   | 142 +++++++++++++++++++++
 6 files changed, 337 insertions(+), 70 deletions(-)

diff --git 
a/cluster/src/main/java/org/apache/iotdb/cluster/query/ClusterPlanRouter.java 
b/cluster/src/main/java/org/apache/iotdb/cluster/query/ClusterPlanRouter.java
index 8403d24..fb5d814 100644
--- 
a/cluster/src/main/java/org/apache/iotdb/cluster/query/ClusterPlanRouter.java
+++ 
b/cluster/src/main/java/org/apache/iotdb/cluster/query/ClusterPlanRouter.java
@@ -37,6 +37,7 @@ import org.apache.iotdb.db.qp.physical.PhysicalPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
 import org.apache.iotdb.db.qp.physical.crud.UpdatePlan;
+import org.apache.iotdb.db.qp.physical.sys.AlterTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.CountPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowChildPathsPlan;
@@ -115,6 +116,8 @@ public class ClusterPlanRouter {
       return splitAndRoutePlan((CreateTimeSeriesPlan) plan);
     } else if (plan instanceof InsertPlan) {
       return splitAndRoutePlan((InsertPlan) plan);
+    } else if (plan instanceof AlterTimeSeriesPlan) {
+      return splitAndRoutePlan((AlterTimeSeriesPlan) plan);
     }
     //the if clause can be removed after the program is stable
     if (PartitionUtils.isLocalNonQueryPlan(plan)) {
@@ -135,6 +138,13 @@ public class ClusterPlanRouter {
     return Collections.singletonMap(plan, partitionGroup);
   }
 
+  public Map<PhysicalPlan, PartitionGroup> 
splitAndRoutePlan(AlterTimeSeriesPlan plan)
+      throws MetadataException {
+    PartitionGroup partitionGroup =
+        partitionTable.partitionByPathTime(plan.getPath().getFullPath(), 0);
+    return Collections.singletonMap(plan, partitionGroup);
+  }
+
   public Map<PhysicalPlan, PartitionGroup> 
splitAndRoutePlan(CreateTimeSeriesPlan plan)
       throws MetadataException {
     PartitionGroup partitionGroup =
@@ -151,7 +161,8 @@ public class ClusterPlanRouter {
     if (times.length == 0) {
       return Collections.emptyMap();
     }
-    long startTime = (times[0] / StorageEngine.getTimePartitionInterval()) * 
StorageEngine.getTimePartitionInterval();//included
+    long startTime = (times[0] / StorageEngine.getTimePartitionInterval()) * 
StorageEngine
+        .getTimePartitionInterval();//included
     long endTime = startTime + 
StorageEngine.getTimePartitionInterval();//excluded
     int startLoc = 0; //included
 
@@ -168,7 +179,8 @@ public class ClusterPlanRouter {
         startLoc = i;
         startTime = endTime;
         endTime =
-            (times[i] / StorageEngine.getTimePartitionInterval() + 1)  * 
StorageEngine.getTimePartitionInterval();
+            (times[i] / StorageEngine.getTimePartitionInterval() + 1) * 
StorageEngine
+                .getTimePartitionInterval();
       }
     }
     //the final range
diff --git 
a/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java 
b/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
index b0813e9..58c9fe6 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
@@ -103,8 +103,10 @@ public class PartitionUtils {
    * @return is globalDataPlan or not
    */
   public static boolean isGlobalDataPlan(PhysicalPlan plan) {
-    return plan instanceof DeletePlan  // because deletePlan has an infinite 
time range.
-        || plan instanceof DeleteTimeSeriesPlan;
+    return
+        // because deletePlan has an infinite time range.
+        plan instanceof DeletePlan
+            || plan instanceof DeleteTimeSeriesPlan;
   }
 
   public static int calculateStorageGroupSlotByTime(String storageGroupName, 
long timestamp,
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
index 5d30f66..39daae5 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
 import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
 import org.apache.iotdb.db.qp.physical.crud.DeletePlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
+import org.apache.iotdb.db.qp.physical.sys.AlterTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.DataAuthPlan;
@@ -257,6 +258,10 @@ public abstract class PhysicalPlan {
           plan = new LoadConfigurationPlan();
           plan.deserialize(buffer);
           break;
+        case ALTER_TIMESERIES:
+          plan = new AlterTimeSeriesPlan();
+          plan.deserialize(buffer);
+          break;
         default:
           throw new IOException("unrecognized log type " + type);
       }
@@ -267,7 +272,7 @@ public abstract class PhysicalPlan {
   public enum PhysicalPlanType {
     INSERT, DELETE, BATCHINSERT, SET_STORAGE_GROUP, CREATE_TIMESERIES, TTL, 
GRANT_WATERMARK_EMBEDDING, REVOKE_WATERMARK_EMBEDDING,
     CREATE_ROLE, DELETE_ROLE, CREATE_USER, REVOKE_USER_ROLE, 
REVOKE_ROLE_PRIVILEGE, REVOKE_USER_PRIVILEGE, GRANT_ROLE_PRIVILEGE, 
GRANT_USER_PRIVILEGE, GRANT_USER_ROLE, MODIFY_PASSWORD, DELETE_USER,
-    DELETE_STORAGE_GROUP, SHOW_TIMESERIES, DELETE_TIMESERIES, 
LOAD_CONFIGURATION
+    DELETE_STORAGE_GROUP, SHOW_TIMESERIES, DELETE_TIMESERIES, 
LOAD_CONFIGURATION, ALTER_TIMESERIES
   }
 
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AlterTimeSeriesPlan.java
 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AlterTimeSeriesPlan.java
index e8020e3..814b7cb 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AlterTimeSeriesPlan.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AlterTimeSeriesPlan.java
@@ -19,32 +19,48 @@
 
 package org.apache.iotdb.db.qp.physical.sys;
 
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import org.apache.iotdb.db.qp.logical.Operator;
+import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
 import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator;
 import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator.AlterType;
 import org.apache.iotdb.db.qp.physical.PhysicalPlan;
 import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 public class AlterTimeSeriesPlan extends PhysicalPlan {
 
-  private final Path path;
+  private Path path;
 
-  private final AlterTimeSeriesOperator.AlterType alterType;
+  private AlterType alterType;
 
-  // used when the alterType is RENAME, SET, DROP, ADD_TAGS, ADD_ATTRIBUTES
-  // when the alterType is RENAME, alterMap has only one entry, key is the 
beforeName, value is the
-  // currentName
-  // when the alterType is DROP, only the keySet of alterMap is useful, it 
contains all the key
-  // names needed to be removed
-  private final Map<String, String> alterMap;
+  /**
+   * used when the alterType is RENAME, SET, DROP, ADD_TAGS, ADD_ATTRIBUTES. 
when the alterType is
+   * RENAME, alterMap has only one entry, key is the beforeName, value is the 
currentName. when the
+   * alterType is DROP, only the keySet of alterMap is useful, it contains all 
the key names needed
+   * to be removed
+   */
+  private Map<String, String> alterMap;
 
-  // used when the alterType is UPSERT
-  private final String alias;
-  private final Map<String, String> tagsMap;
-  private final Map<String, String> attributesMap;
+  /**
+   * used when the alterType is UPSERT
+   */
+  private String alias;
+  private Map<String, String> tagsMap;
+  private Map<String, String> attributesMap;
+
+  /**
+   * used only for deserialize
+   */
+  public AlterTimeSeriesPlan() {
+    super(false, OperatorType.ALTER_TIMESERIES);
+  }
 
   public AlterTimeSeriesPlan(Path path, AlterType alterType, Map<String, 
String> alterMap,
       String alias, Map<String, String> tagsMap, Map<String, String> 
attributesMap) {
@@ -85,4 +101,100 @@ public class AlterTimeSeriesPlan extends PhysicalPlan {
   public List<Path> getPaths() {
     return Collections.singletonList(path);
   }
+
+  @Override
+  public void serialize(DataOutputStream stream) throws IOException {
+    stream.writeByte((byte) PhysicalPlanType.ALTER_TIMESERIES.ordinal());
+    byte[] bytes = path.getFullPath().getBytes();
+    stream.writeInt(bytes.length);
+    stream.write(bytes);
+
+    stream.write(alterType.ordinal());
+
+    // alias
+    if (alias != null) {
+      stream.write(1);
+      ReadWriteIOUtils.write(alias, stream);
+    } else {
+      stream.write(0);
+    }
+
+    // alterMap
+    if (alterMap != null && !alterMap.isEmpty()) {
+      stream.write(1);
+      ReadWriteIOUtils.write(alterMap, stream);
+    } else {
+      stream.write(0);
+    }
+
+    // tagsMap
+    if (tagsMap != null && !tagsMap.isEmpty()) {
+      stream.write(1);
+      ReadWriteIOUtils.write(tagsMap, stream);
+    } else {
+      stream.write(0);
+    }
+
+    // attributesMap
+    if (attributesMap != null && !attributesMap.isEmpty()) {
+      stream.write(1);
+      ReadWriteIOUtils.write(attributesMap, stream);
+    } else {
+      stream.write(0);
+    }
+  }
+
+  @Override
+  public void deserialize(ByteBuffer buffer) {
+    int length = buffer.getInt();
+    byte[] bytes = new byte[length];
+    buffer.get(bytes);
+    path = new Path(new String(bytes));
+
+    alterType = AlterType.values()[buffer.get()];
+
+    // alias
+    if (buffer.get() == 1) {
+      alias = ReadWriteIOUtils.readString(buffer);
+    }
+
+    // alterMap
+    if (buffer.get() == 1) {
+      alterMap = ReadWriteIOUtils.readMap(buffer);
+    }
+
+    // tagsMap
+    if (buffer.get() == 1) {
+      tagsMap = ReadWriteIOUtils.readMap(buffer);
+    }
+
+    // attributesMap
+    if (buffer.get() == 1) {
+      attributesMap = ReadWriteIOUtils.readMap(buffer);
+    }
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    AlterTimeSeriesPlan that = (AlterTimeSeriesPlan) o;
+
+    return Objects.equals(path, that.path) &&
+        alterType != that.alterType &&
+        Objects.equals(alterMap, that.alterMap) &&
+        Objects.equals(alias, that.alias) &&
+        Objects.equals(tagsMap, that.tagsMap) &&
+        Objects.equals(attributesMap, that.attributesMap);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(path, alias, alterType, alterMap, attributesMap, 
tagsMap);
+  }
 }
diff --git 
a/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java 
b/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java
index 4d55f16..6810abc 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java
@@ -93,7 +93,7 @@ public class ReadWriteIOUtils {
    * read bytes array in given size
    *
    * @param buffer buffer
-   * @param size size
+   * @param size   size
    * @return bytes array
    */
   public static byte[] readBytes(ByteBuffer buffer, int size) {
@@ -136,22 +136,12 @@ public class ReadWriteIOUtils {
     stream.writeInt(map.size());
     length += 4;
     for (Entry<String, String> entry : map.entrySet()) {
-      bytes = entry.getKey().getBytes();
-      stream.writeInt(bytes.length);
-      length += 4;
-      stream.write(bytes);
-      length += bytes.length;
-      bytes = entry.getValue().getBytes();
-      stream.writeInt(bytes.length);
-      length += 4;
-      stream.write(bytes);
-      length += bytes.length;
+      length += write(entry.getKey(), stream);
+      length += write(entry.getValue(), stream);
     }
     return length;
   }
 
-
-
   /**
    * write a int value to outputStream according to flag. If flag is true, 
write 1, else write 0.
    */
@@ -244,8 +234,6 @@ public class ReadWriteIOUtils {
     return INT_LEN;
   }
 
-
-
   /**
    * write the size (int) of the binary and then the bytes in binary
    */
@@ -331,6 +319,11 @@ public class ReadWriteIOUtils {
    */
   public static int write(String s, OutputStream outputStream) throws 
IOException {
     int len = 0;
+    if (s == null) {
+      len += write(0, outputStream);
+      return len;
+    }
+
     byte[] bytes = s.getBytes();
     len += write(bytes.length, outputStream);
     outputStream.write(bytes);
@@ -370,7 +363,8 @@ public class ReadWriteIOUtils {
   /**
    * write byteBuffer.array to outputStream without capacity.
    */
-  public static int writeWithoutSize(ByteBuffer byteBuffer, OutputStream 
outputStream) throws IOException {
+  public static int writeWithoutSize(ByteBuffer byteBuffer, OutputStream 
outputStream)
+      throws IOException {
     byte[] bytes = byteBuffer.array();
     outputStream.write(bytes);
     return bytes.length;
@@ -566,7 +560,7 @@ public class ReadWriteIOUtils {
    */
   public static String readString(ByteBuffer buffer) {
     int strLength = readInt(buffer);
-    if (strLength < 0) {
+    if (strLength <= 0) {
       return null;
     }
     byte[] bytes = new byte[strLength];
@@ -668,7 +662,7 @@ public class ReadWriteIOUtils {
   /**
    * read bytes from byteBuffer, this method makes sure that you can read 
length bytes or reach to
    * the end of the buffer.
-   *
+   * <p>
    * read a int + buffer
    */
   public static ByteBuffer readByteBufferWithSelfDescriptionLength(ByteBuffer 
buffer) {
@@ -823,8 +817,8 @@ public class ReadWriteIOUtils {
 
 
   /**
-   * to check whether the byte buffer is reach the magic string
-   * this method doesn't change the position of the byte buffer
+   * to check whether the byte buffer is reach the magic string this method 
doesn't change the
+   * position of the byte buffer
    *
    * @param byteBuffer byte buffer
    * @return whether the byte buffer is reach the magic string
@@ -837,8 +831,8 @@ public class ReadWriteIOUtils {
   }
 
   /**
-   * to check whether the inputStream is reach the magic string
-   * this method doesn't change the position of the inputStream
+   * to check whether the inputStream is reach the magic string this method 
doesn't change the
+   * position of the inputStream
    *
    * @param inputStream inputStream
    * @return whether the inputStream is reach the magic string
@@ -852,38 +846,38 @@ public class ReadWriteIOUtils {
   }
 
   public static void writeObject(Object value, DataOutputStream outputStream) {
-      try {
-        if (value instanceof Long) {
-          outputStream.write(LONG.ordinal());
-          outputStream.writeLong((Long) value);
-        } else if (value instanceof Double) {
-          outputStream.write(DOUBLE.ordinal());
-          outputStream.writeDouble((Double) value);
-        } else if (value instanceof Integer) {
-          outputStream.write(INTEGER.ordinal());
-          outputStream.writeInt((Integer) value);
-        } else if (value instanceof Float) {
-          outputStream.write(FLOAT.ordinal());
-          outputStream.writeFloat((Float) value);
-        } else if (value instanceof Binary) {
-          outputStream.write(BINARY.ordinal());
-          byte[] bytes = ((Binary) value).getValues();
-          outputStream.writeInt(bytes.length);
-          outputStream.write(bytes);
-        } else if (value instanceof Boolean) {
-          outputStream.write(BOOLEAN.ordinal());
-          outputStream.write(((Boolean) value) ? 1 : 0);
-        } else if (value == null) {
-          outputStream.write(NULL.ordinal());
-        } else {
-          outputStream.write(STRING.ordinal());
-          byte[] bytes = value.toString().getBytes();
-          outputStream.writeInt(bytes.length);
-          outputStream.write(bytes);
-        }
-      } catch (IOException ignored) {
-        // ignored
+    try {
+      if (value instanceof Long) {
+        outputStream.write(LONG.ordinal());
+        outputStream.writeLong((Long) value);
+      } else if (value instanceof Double) {
+        outputStream.write(DOUBLE.ordinal());
+        outputStream.writeDouble((Double) value);
+      } else if (value instanceof Integer) {
+        outputStream.write(INTEGER.ordinal());
+        outputStream.writeInt((Integer) value);
+      } else if (value instanceof Float) {
+        outputStream.write(FLOAT.ordinal());
+        outputStream.writeFloat((Float) value);
+      } else if (value instanceof Binary) {
+        outputStream.write(BINARY.ordinal());
+        byte[] bytes = ((Binary) value).getValues();
+        outputStream.writeInt(bytes.length);
+        outputStream.write(bytes);
+      } else if (value instanceof Boolean) {
+        outputStream.write(BOOLEAN.ordinal());
+        outputStream.write(((Boolean) value) ? 1 : 0);
+      } else if (value == null) {
+        outputStream.write(NULL.ordinal());
+      } else {
+        outputStream.write(STRING.ordinal());
+        byte[] bytes = value.toString().getBytes();
+        outputStream.writeInt(bytes.length);
+        outputStream.write(bytes);
       }
+    } catch (IOException ignored) {
+      // ignored
+    }
   }
 
   public static Object readObject(ByteBuffer buffer) {
diff --git 
a/tsfile/src/test/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtilsTest.java 
b/tsfile/src/test/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtilsTest.java
new file mode 100644
index 0000000..20cde42
--- /dev/null
+++ 
b/tsfile/src/test/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtilsTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.iotdb.tsfile.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReadWriteIOUtilsTest {
+
+  protected static final int DEFAULT_BUFFER_SIZE = 4096;
+
+  @Test
+  public void readStringBufferTest() {
+    // 1. not null value
+    String str = "string";
+    ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
+    DataOutputStream stream = new DataOutputStream(byteArrayOutputStream);
+    try {
+      ReadWriteIOUtils.write(str, stream);
+    } catch (IOException e) {
+      Assert.assertEquals("why failed?", e.toString());
+    }
+
+    String result = null;
+    result = 
ReadWriteIOUtils.readString(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));
+    Assert.assertNotNull(result);
+    Assert.assertEquals(str, result);
+
+    //2. null value
+    str = null;
+    byteArrayOutputStream = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
+    stream = new DataOutputStream(byteArrayOutputStream);
+    try {
+      ReadWriteIOUtils.write(str, stream);
+    } catch (IOException e) {
+      Assert.assertEquals("why failed?", e.toString());
+    }
+
+    result = null;
+    result = 
ReadWriteIOUtils.readString(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));
+    Assert.assertNull(result);
+    Assert.assertEquals(str, result);
+  }
+
+  @Test
+  public void readMapTest() {
+    // 1. key: not null; value: not null
+    String key = "string";
+    String value = "string";
+    Map map = new HashMap<String, String>();
+    map.put(key, value);
+    ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
+    DataOutputStream stream = new DataOutputStream(byteArrayOutputStream);
+    try {
+      ReadWriteIOUtils.write(map, stream);
+    } catch (IOException e) {
+      Assert.assertEquals("why failed?", e.toString());
+    }
+
+    Map result = null;
+    result = 
ReadWriteIOUtils.readMap(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));
+    Assert.assertNotNull(result);
+    Assert.assertEquals(map, result);
+
+    // 2. key: not null; value: null
+    key = "string";
+    value = null;
+    map.clear();
+    map.put(key, value);
+    byteArrayOutputStream = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
+    stream = new DataOutputStream(byteArrayOutputStream);
+    try {
+      ReadWriteIOUtils.write(map, stream);
+    } catch (IOException e) {
+      Assert.assertEquals("why failed?", e.toString());
+    }
+
+    result = null;
+    result = 
ReadWriteIOUtils.readMap(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));
+    Assert.assertNotNull(result);
+    Assert.assertEquals(map, result);
+
+    // 3. key: null; value: not null
+    key = null;
+    value = "string";
+    map.clear();
+    map.put(key, value);
+    byteArrayOutputStream = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
+    stream = new DataOutputStream(byteArrayOutputStream);
+    try {
+      ReadWriteIOUtils.write(map, stream);
+    } catch (IOException e) {
+      Assert.assertEquals("why failed?", e.toString());
+    }
+
+    result = null;
+    result = 
ReadWriteIOUtils.readMap(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));
+    Assert.assertNotNull(result);
+    Assert.assertEquals(map, result);
+
+    // 4. key: null; value: null
+    key = null;
+    value = null;
+    map.clear();
+    map.put(key, value);
+    byteArrayOutputStream = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
+    stream = new DataOutputStream(byteArrayOutputStream);
+    try {
+      ReadWriteIOUtils.write(map, stream);
+    } catch (IOException e) {
+      Assert.assertEquals("why failed?", e.toString());
+    }
+
+    result = null;
+    result = 
ReadWriteIOUtils.readMap(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));
+    Assert.assertNotNull(result);
+    Assert.assertEquals(map, result);
+
+  }
+}

Reply via email to