You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by hx...@apache.org on 2021/03/10 08:08:51 UTC

[iotdb] 01/01: seperate thrift module into 3 parts; extract Node Serialization from Server module into Cluster module

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

hxd pushed a commit to branch seperate_thrift
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 1f5e7b2bda07e8c4d653e5fa327755c8606daeff
Author: xiangdong huang <sa...@gmail.com>
AuthorDate: Wed Mar 10 16:08:16 2021 +0800

    seperate thrift module into 3 parts; extract Node Serialization from Server module into Cluster module
---
 cluster/pom.xml                                    |  15 ++
 .../apache/iotdb/cluster/RemoteTsFileResource.java |   5 +-
 .../org/apache/iotdb/cluster/log/HardState.java    |   6 +-
 .../iotdb/cluster/log/logtypes/AddNodeLog.java     |   6 +-
 .../iotdb/cluster/log/logtypes/RemoveNodeLog.java  |   6 +-
 .../log/snapshot/PullSnapshotTaskDescriptor.java   |   6 +-
 .../iotdb/cluster/partition/slot/SlotManager.java  |   6 +-
 .../cluster/partition/slot/SlotPartitionTable.java |   5 +-
 .../iotdb/cluster/utils/NodeSerializeUtils.java    |  90 ++++++++++
 .../iotdb/cluster/utils/SerializeUtilTest.java     |  13 ++
 grafana/pom.xml                                    |   4 +
 jdbc/pom.xml                                       |   5 -
 pom.xml                                            |   2 +
 server/pom.xml                                     |   5 +
 .../org/apache/iotdb/db/utils/SerializeUtils.java  |  62 -------
 .../apache/iotdb/db/utils/SerializeUtilsTest.java  |  13 --
 service-rpc/pom.xml                                |   7 +
 session/pom.xml                                    |   5 -
 thrift-cluster/README.md                           |  22 +++
 thrift-cluster/pom.xml                             |  44 +++++
 thrift-cluster/rpc-changelist.md                   | 181 +++++++++++++++++++++
 .../src/main/thrift/cluster.thrift                 |   0
 thrift-sync/README.md                              |  22 +++
 thrift-sync/pom.xml                                |  44 +++++
 thrift-sync/rpc-changelist.md                      | 181 +++++++++++++++++++++
 .../src/main/thrift/sync.thrift                    |   0
 thrift/README.md                                   |  22 +++
 27 files changed, 673 insertions(+), 104 deletions(-)

diff --git a/cluster/pom.xml b/cluster/pom.xml
index 1d29693..7347a3c 100644
--- a/cluster/pom.xml
+++ b/cluster/pom.xml
@@ -76,6 +76,21 @@
                     <artifactId>libthrift</artifactId>
                 </exclusion>
             </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.iotdb</groupId>
+            <artifactId>iotdb-thrift-cluster</artifactId>
+            <version>0.12.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.thrift</groupId>
+                    <artifactId>libthrift</artifactId>
+                </exclusion>
+            </exclusions>
             <scope>compile</scope>
         </dependency>
         <dependency>
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/RemoteTsFileResource.java b/cluster/src/main/java/org/apache/iotdb/cluster/RemoteTsFileResource.java
index fdf492a..04fb776 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/RemoteTsFileResource.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/RemoteTsFileResource.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.cluster;
 
 import org.apache.iotdb.cluster.rpc.thrift.Node;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.utils.SerializeUtils;
@@ -82,7 +83,7 @@ public class RemoteTsFileResource extends TsFileResource {
   }
 
   public void serialize(DataOutputStream dataOutputStream) {
-    SerializeUtils.serialize(source, dataOutputStream);
+    NodeSerializeUtils.serialize(source, dataOutputStream);
     try {
       // the path here is only for the remote node to get a download link, so it does not matter
       // if it is absolute
@@ -102,7 +103,7 @@ public class RemoteTsFileResource extends TsFileResource {
 
   public void deserialize(ByteBuffer buffer) {
     source = new Node();
-    SerializeUtils.deserialize(source, buffer);
+    NodeSerializeUtils.deserialize(source, buffer);
     setFile(new File(SerializeUtils.deserializeString(buffer)));
 
     timeIndex =
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/log/HardState.java b/cluster/src/main/java/org/apache/iotdb/cluster/log/HardState.java
index 03e12fc..2e9e172 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/log/HardState.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/log/HardState.java
@@ -20,7 +20,7 @@
 package org.apache.iotdb.cluster.log;
 
 import org.apache.iotdb.cluster.rpc.thrift.Node;
-import org.apache.iotdb.db.utils.SerializeUtils;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -46,7 +46,7 @@ public class HardState {
     int isNull = buffer.get();
     if (isNull == 1) {
       Node node = new Node();
-      SerializeUtils.deserialize(node, buffer);
+      NodeSerializeUtils.deserialize(node, buffer);
       res.setVoteFor(node);
     } else {
       res.setVoteFor(null);
@@ -63,7 +63,7 @@ public class HardState {
         dataOutputStream.writeByte(0);
       } else {
         dataOutputStream.writeByte(1);
-        SerializeUtils.serialize(voteFor, dataOutputStream);
+        NodeSerializeUtils.serialize(voteFor, dataOutputStream);
       }
     } catch (IOException e) {
       // unreachable
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/AddNodeLog.java b/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/AddNodeLog.java
index 75bb8f5..ea41685 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/AddNodeLog.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/AddNodeLog.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.cluster.log.logtypes;
 
 import org.apache.iotdb.cluster.log.Log;
 import org.apache.iotdb.cluster.rpc.thrift.Node;
-import org.apache.iotdb.db.utils.SerializeUtils;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
@@ -50,7 +50,7 @@ public class AddNodeLog extends Log {
       dataOutputStream.writeLong(getCurrLogIndex());
       dataOutputStream.writeLong(getCurrLogTerm());
 
-      SerializeUtils.serialize(newNode, dataOutputStream);
+      NodeSerializeUtils.serialize(newNode, dataOutputStream);
     } catch (IOException e) {
       // ignored
     }
@@ -67,7 +67,7 @@ public class AddNodeLog extends Log {
     setCurrLogTerm(buffer.getLong());
 
     newNode = new Node();
-    SerializeUtils.deserialize(newNode, buffer);
+    NodeSerializeUtils.deserialize(newNode, buffer);
   }
 
   @Override
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/RemoveNodeLog.java b/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/RemoveNodeLog.java
index 19359c2..8a84023 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/RemoveNodeLog.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/log/logtypes/RemoveNodeLog.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.cluster.log.logtypes;
 
 import org.apache.iotdb.cluster.log.Log;
 import org.apache.iotdb.cluster.rpc.thrift.Node;
-import org.apache.iotdb.db.utils.SerializeUtils;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
@@ -41,7 +41,7 @@ public class RemoveNodeLog extends Log {
       dataOutputStream.writeLong(getCurrLogIndex());
       dataOutputStream.writeLong(getCurrLogTerm());
 
-      SerializeUtils.serialize(removedNode, dataOutputStream);
+      NodeSerializeUtils.serialize(removedNode, dataOutputStream);
     } catch (IOException e) {
       // ignored
     }
@@ -54,7 +54,7 @@ public class RemoveNodeLog extends Log {
     setCurrLogTerm(buffer.getLong());
 
     removedNode = new Node();
-    SerializeUtils.deserialize(removedNode, buffer);
+    NodeSerializeUtils.deserialize(removedNode, buffer);
   }
 
   public Node getRemovedNode() {
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/log/snapshot/PullSnapshotTaskDescriptor.java b/cluster/src/main/java/org/apache/iotdb/cluster/log/snapshot/PullSnapshotTaskDescriptor.java
index b811f1f..a2216fd 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/log/snapshot/PullSnapshotTaskDescriptor.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/log/snapshot/PullSnapshotTaskDescriptor.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.cluster.log.snapshot;
 
 import org.apache.iotdb.cluster.partition.PartitionGroup;
 import org.apache.iotdb.cluster.rpc.thrift.Node;
-import org.apache.iotdb.db.utils.SerializeUtils;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -77,7 +77,7 @@ public class PullSnapshotTaskDescriptor {
 
     dataOutputStream.writeInt(previousHolders.size());
     for (Node previousHolder : previousHolders) {
-      SerializeUtils.serialize(previousHolder, dataOutputStream);
+      NodeSerializeUtils.serialize(previousHolder, dataOutputStream);
     }
 
     dataOutputStream.writeBoolean(requireReadOnly);
@@ -94,7 +94,7 @@ public class PullSnapshotTaskDescriptor {
     previousHolders = new PartitionGroup();
     for (int i = 0; i < holderSize; i++) {
       Node node = new Node();
-      SerializeUtils.deserialize(node, dataInputStream);
+      NodeSerializeUtils.deserialize(node, dataInputStream);
       previousHolders.add(node);
     }
 
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotManager.java b/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotManager.java
index 37cc0f2..528119f 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotManager.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotManager.java
@@ -6,8 +6,8 @@ package org.apache.iotdb.cluster.partition.slot;
 
 import org.apache.iotdb.cluster.config.ClusterDescriptor;
 import org.apache.iotdb.cluster.rpc.thrift.Node;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.utils.SerializeUtils;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -298,7 +298,7 @@ public class SlotManager {
     private void serialize(DataOutputStream outputStream) throws IOException {
       outputStream.writeInt(slotStatus.ordinal());
       if (slotStatus == SlotStatus.PULLING || slotStatus == SlotStatus.PULLING_WRITABLE) {
-        SerializeUtils.serialize(source, outputStream);
+        NodeSerializeUtils.serialize(source, outputStream);
       } else if (slotStatus == SlotStatus.SENDING) {
         outputStream.writeInt(snapshotReceivedCount);
       }
@@ -310,7 +310,7 @@ public class SlotManager {
       if (descriptor.slotStatus == SlotStatus.PULLING
           || descriptor.slotStatus == SlotStatus.PULLING_WRITABLE) {
         descriptor.source = new Node();
-        SerializeUtils.deserialize(descriptor.source, buffer);
+        NodeSerializeUtils.deserialize(descriptor.source, buffer);
       } else if (descriptor.slotStatus == SlotStatus.SENDING) {
         descriptor.snapshotReceivedCount = buffer.getInt();
       }
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotPartitionTable.java b/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotPartitionTable.java
index 8c25a63..469e84d 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotPartitionTable.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/partition/slot/SlotPartitionTable.java
@@ -12,6 +12,7 @@ import org.apache.iotdb.cluster.partition.PartitionGroup;
 import org.apache.iotdb.cluster.partition.PartitionTable;
 import org.apache.iotdb.cluster.partition.slot.SlotStrategy.DefaultStrategy;
 import org.apache.iotdb.cluster.rpc.thrift.Node;
+import org.apache.iotdb.cluster.utils.NodeSerializeUtils;
 import org.apache.iotdb.db.utils.SerializeUtils;
 
 import org.slf4j.Logger;
@@ -310,7 +311,7 @@ public class SlotPartitionTable implements PartitionTable {
       dataOutputStream.writeInt(totalSlotNumbers);
       dataOutputStream.writeInt(nodeSlotMap.size());
       for (Entry<Node, List<Integer>> entry : nodeSlotMap.entrySet()) {
-        SerializeUtils.serialize(entry.getKey(), dataOutputStream);
+        NodeSerializeUtils.serialize(entry.getKey(), dataOutputStream);
         SerializeUtils.serializeIntList(entry.getValue(), dataOutputStream);
       }
 
@@ -341,7 +342,7 @@ public class SlotPartitionTable implements PartitionTable {
     for (int i = 0; i < size; i++) {
       Node node = new Node();
       List<Integer> slots = new ArrayList<>();
-      SerializeUtils.deserialize(node, buffer);
+      NodeSerializeUtils.deserialize(node, buffer);
       SerializeUtils.deserializeIntList(slots, buffer);
       nodeSlotMap.put(node, slots);
       idNodeMap.put(node.getNodeIdentifier(), node);
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/utils/NodeSerializeUtils.java b/cluster/src/main/java/org/apache/iotdb/cluster/utils/NodeSerializeUtils.java
new file mode 100644
index 0000000..6e14cc3
--- /dev/null
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/utils/NodeSerializeUtils.java
@@ -0,0 +1,90 @@
+/*
+ * 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.cluster.utils;
+
+import org.apache.iotdb.cluster.rpc.thrift.Node;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class NodeSerializeUtils {
+
+  public static void serialize(Node node, DataOutputStream dataOutputStream) {
+    try {
+      byte[] internalIpBytes = node.internalIp.getBytes();
+      dataOutputStream.writeInt(internalIpBytes.length);
+      dataOutputStream.write(internalIpBytes);
+      dataOutputStream.writeInt(node.metaPort);
+      dataOutputStream.writeInt(node.nodeIdentifier);
+      dataOutputStream.writeInt(node.dataPort);
+      dataOutputStream.writeInt(node.clientPort);
+      byte[] clientIpBytes = node.clientIp.getBytes();
+      dataOutputStream.writeInt(clientIpBytes.length);
+      dataOutputStream.write(clientIpBytes);
+    } catch (IOException e) {
+      // unreachable
+    }
+  }
+
+  public static void deserialize(Node node, ByteBuffer buffer) {
+    int internalIpLength = buffer.getInt();
+    byte[] internalIpBytes = new byte[internalIpLength];
+    buffer.get(internalIpBytes);
+    node.setInternalIp(new String(internalIpBytes));
+    node.setMetaPort(buffer.getInt());
+    node.setNodeIdentifier(buffer.getInt());
+    node.setDataPort(buffer.getInt());
+    node.setClientPort(buffer.getInt());
+    int clientIpLength = buffer.getInt();
+    byte[] clientIpBytes = new byte[clientIpLength];
+    buffer.get(clientIpBytes);
+    node.setClientIp(new String(clientIpBytes));
+  }
+
+  public static void deserialize(Node node, DataInputStream stream) throws IOException {
+    int ipLength = stream.readInt();
+    byte[] ipBytes = new byte[ipLength];
+    int readIpSize = stream.read(ipBytes);
+    if (readIpSize != ipLength) {
+      throw new IOException(
+          String.format(
+              "No sufficient bytes read when deserializing the ip of a node: %d/%d",
+              readIpSize, ipLength));
+    }
+    node.setInternalIp(new String(ipBytes));
+    node.setMetaPort(stream.readInt());
+    node.setNodeIdentifier(stream.readInt());
+    node.setDataPort(stream.readInt());
+    node.setClientPort(stream.readInt());
+
+    int clientIpLength = stream.readInt();
+    byte[] clientIpBytes = new byte[clientIpLength];
+    int readClientIpSize = stream.read(clientIpBytes);
+    if (readClientIpSize != clientIpLength) {
+      throw new IOException(
+          String.format(
+              "No sufficient bytes read when deserializing the clientIp of a node: %d/%d",
+              readClientIpSize, clientIpLength));
+    }
+    node.setClientIp(new String(clientIpBytes));
+  }
+}
diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/utils/SerializeUtilTest.java b/cluster/src/test/java/org/apache/iotdb/cluster/utils/SerializeUtilTest.java
index 8fabcb5..0de5cbb 100644
--- a/cluster/src/test/java/org/apache/iotdb/cluster/utils/SerializeUtilTest.java
+++ b/cluster/src/test/java/org/apache/iotdb/cluster/utils/SerializeUtilTest.java
@@ -34,6 +34,7 @@ import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.utils.Binary;
 
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.io.ByteArrayOutputStream;
@@ -178,4 +179,16 @@ public class SerializeUtilTest {
     Log parsed = LogParser.getINSTANCE().parse(serialized);
     assertEquals(log, parsed);
   }
+
+  @Test
+  public void serdesNodeTest() {
+    Node node = new Node("127.0.0.1", 6667, 1, 6535, 4678, "127.0.0.1");
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    DataOutputStream outputStream = new DataOutputStream(baos);
+    NodeSerializeUtils.serialize(node, outputStream);
+    ByteBuffer buffer = ByteBuffer.wrap(baos.toByteArray());
+    Node anotherNode = new Node("127.0.0.1", 6667, 1, 6535, 4678, "127.0.0.1");
+    NodeSerializeUtils.deserialize(anotherNode, buffer);
+    Assert.assertEquals(node, anotherNode);
+  }
 }
diff --git a/grafana/pom.xml b/grafana/pom.xml
index ac5a8e9..a24ba06 100644
--- a/grafana/pom.xml
+++ b/grafana/pom.xml
@@ -59,6 +59,10 @@
     </dependencyManagement>
     <dependencies>
         <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.iotdb</groupId>
             <artifactId>iotdb-jdbc</artifactId>
             <version>${project.version}</version>
diff --git a/jdbc/pom.xml b/jdbc/pom.xml
index 41e1ffd..dd17752 100644
--- a/jdbc/pom.xml
+++ b/jdbc/pom.xml
@@ -38,11 +38,6 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.iotdb</groupId>
-            <artifactId>tsfile</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.iotdb</groupId>
             <artifactId>service-rpc</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/pom.xml b/pom.xml
index e249644..5cf7914 100644
--- a/pom.xml
+++ b/pom.xml
@@ -82,6 +82,8 @@
         <module>tsfile</module>
         <module>antlr</module>
         <module>thrift</module>
+        <module>thrift-cluster</module>
+        <module>thrift-sync</module>
         <module>service-rpc</module>
         <module>jdbc</module>
         <module>session</module>
diff --git a/server/pom.xml b/server/pom.xml
index a985d6a..dee952f 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -76,6 +76,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.iotdb</groupId>
+            <artifactId>iotdb-thrift-sync</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-collections4</artifactId>
         </dependency>
diff --git a/server/src/main/java/org/apache/iotdb/db/utils/SerializeUtils.java b/server/src/main/java/org/apache/iotdb/db/utils/SerializeUtils.java
index e4f3bda..cb881e0 100644
--- a/server/src/main/java/org/apache/iotdb/db/utils/SerializeUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/utils/SerializeUtils.java
@@ -19,7 +19,6 @@
 
 package org.apache.iotdb.db.utils;
 
-import org.apache.iotdb.cluster.rpc.thrift.Node;
 import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
@@ -30,7 +29,6 @@ import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 import org.apache.iotdb.tsfile.utils.TsPrimitiveType;
 
 import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -119,66 +117,6 @@ public class SerializeUtils {
     }
   }
 
-  public static void serialize(Node node, DataOutputStream dataOutputStream) {
-    try {
-      byte[] internalIpBytes = node.internalIp.getBytes();
-      dataOutputStream.writeInt(internalIpBytes.length);
-      dataOutputStream.write(internalIpBytes);
-      dataOutputStream.writeInt(node.metaPort);
-      dataOutputStream.writeInt(node.nodeIdentifier);
-      dataOutputStream.writeInt(node.dataPort);
-      dataOutputStream.writeInt(node.clientPort);
-      byte[] clientIpBytes = node.clientIp.getBytes();
-      dataOutputStream.writeInt(clientIpBytes.length);
-      dataOutputStream.write(clientIpBytes);
-    } catch (IOException e) {
-      // unreachable
-    }
-  }
-
-  public static void deserialize(Node node, ByteBuffer buffer) {
-    int internalIpLength = buffer.getInt();
-    byte[] internalIpBytes = new byte[internalIpLength];
-    buffer.get(internalIpBytes);
-    node.setInternalIp(new String(internalIpBytes));
-    node.setMetaPort(buffer.getInt());
-    node.setNodeIdentifier(buffer.getInt());
-    node.setDataPort(buffer.getInt());
-    node.setClientPort(buffer.getInt());
-    int clientIpLength = buffer.getInt();
-    byte[] clientIpBytes = new byte[clientIpLength];
-    buffer.get(clientIpBytes);
-    node.setClientIp(new String(clientIpBytes));
-  }
-
-  public static void deserialize(Node node, DataInputStream stream) throws IOException {
-    int ipLength = stream.readInt();
-    byte[] ipBytes = new byte[ipLength];
-    int readIpSize = stream.read(ipBytes);
-    if (readIpSize != ipLength) {
-      throw new IOException(
-          String.format(
-              "No sufficient bytes read when deserializing the ip of a node: %d/%d",
-              readIpSize, ipLength));
-    }
-    node.setInternalIp(new String(ipBytes));
-    node.setMetaPort(stream.readInt());
-    node.setNodeIdentifier(stream.readInt());
-    node.setDataPort(stream.readInt());
-    node.setClientPort(stream.readInt());
-
-    int clientIpLength = stream.readInt();
-    byte[] clientIpBytes = new byte[clientIpLength];
-    int readClientIpSize = stream.read(clientIpBytes);
-    if (readClientIpSize != clientIpLength) {
-      throw new IOException(
-          String.format(
-              "No sufficient bytes read when deserializing the clientIp of a node: %d/%d",
-              readClientIpSize, clientIpLength));
-    }
-    node.setClientIp(new String(clientIpBytes));
-  }
-
   public static void serializeBatchData(BatchData batchData, DataOutputStream outputStream) {
     try {
       int length = batchData.length();
diff --git a/server/src/test/java/org/apache/iotdb/db/utils/SerializeUtilsTest.java b/server/src/test/java/org/apache/iotdb/db/utils/SerializeUtilsTest.java
index ba91d9f..5924589 100644
--- a/server/src/test/java/org/apache/iotdb/db/utils/SerializeUtilsTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/utils/SerializeUtilsTest.java
@@ -18,7 +18,6 @@
  */
 package org.apache.iotdb.db.utils;
 
-import org.apache.iotdb.cluster.rpc.thrift.Node;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
 import org.apache.iotdb.tsfile.read.common.BatchData;
@@ -85,18 +84,6 @@ public class SerializeUtilsTest {
   }
 
   @Test
-  public void serdesNodeTest() {
-    Node node = new Node("127.0.0.1", 6667, 1, 6535, 4678, "127.0.0.1");
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    DataOutputStream outputStream = new DataOutputStream(baos);
-    SerializeUtils.serialize(node, outputStream);
-    ByteBuffer buffer = ByteBuffer.wrap(baos.toByteArray());
-    Node anotherNode = new Node("127.0.0.1", 6667, 1, 6535, 4678, "127.0.0.1");
-    SerializeUtils.deserialize(anotherNode, buffer);
-    Assert.assertEquals(node, anotherNode);
-  }
-
-  @Test
   public void serdesINT32BatchDataTest() {
     BatchData batchData = new BatchData(TSDataType.INT32);
     int ivalue = 0;
diff --git a/service-rpc/pom.xml b/service-rpc/pom.xml
index 83995c8..8c34872 100644
--- a/service-rpc/pom.xml
+++ b/service-rpc/pom.xml
@@ -40,6 +40,13 @@
             <groupId>org.apache.iotdb</groupId>
             <artifactId>tsfile</artifactId>
             <version>${project.version}</version>
+            <!-- we want to reduce the size of JDBC -->
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.iotdb</groupId>
diff --git a/session/pom.xml b/session/pom.xml
index 3e3bb71..bd02c26 100644
--- a/session/pom.xml
+++ b/session/pom.xml
@@ -73,11 +73,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.iotdb</groupId>
-            <artifactId>tsfile</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.iotdb</groupId>
             <artifactId>iotdb-server</artifactId>
             <version>${project.version}</version>
             <type>test-jar</type>
diff --git a/thrift-cluster/README.md b/thrift-cluster/README.md
new file mode 100644
index 0000000..b83e1e1
--- /dev/null
+++ b/thrift-cluster/README.md
@@ -0,0 +1,22 @@
+<!--
+
+    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.
+
+-->
+
+This modules maintains all RPC interfaces among servers for the cluster module.
\ No newline at end of file
diff --git a/thrift-cluster/pom.xml b/thrift-cluster/pom.xml
new file mode 100644
index 0000000..c1c49a3
--- /dev/null
+++ b/thrift-cluster/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.iotdb</groupId>
+        <artifactId>iotdb-parent</artifactId>
+        <version>0.12.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>iotdb-thrift-cluster</artifactId>
+    <name>rpc-thrift-cluster</name>
+    <description>RPC (Thrift) framework among servers.</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.thrift</groupId>
+            <artifactId>libthrift</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.iotdb</groupId>
+            <artifactId>iotdb-thrift</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/thrift-cluster/rpc-changelist.md b/thrift-cluster/rpc-changelist.md
new file mode 100644
index 0000000..797c0b6
--- /dev/null
+++ b/thrift-cluster/rpc-changelist.md
@@ -0,0 +1,181 @@
+<!--
+
+    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.
+
+-->
+# 0.11.x(version-2) -> 0.12.x(version-1)
+
+Last Updated on 2021.01.19 by Xiangwei Wei.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Add timeout in TSFetchResultsReq and TSExecuteStatementReq | Xiangwei Wei | 
+
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+
+
+# 0.10.x (version-2) -> 0.11.x (version-3)
+
+Last Updated on 2020-10-27 by Xiangwei Wei.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+| Remove TSBatchExecuteStatementResp            | Tian Jiang         |
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| set the input/output as TFramedTransport      |  Tian Jiang        |
+| Add timeout(optional) in TSFetchResultsReq and TSExecuteStatementReq | Xiangwei Wei | 
+
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Add sub-status in TSStatus  | Tian Jiang  |
+| Change the result of executeBatchStatement  as   TSStatus    | Tian Jiang  |
+| Change TSDeleteDataReq, delete timestamp and add startTime and endTime   | Wei Shao   |
+| Add zoneId in TSOpenSessionReq | Xiangwei Wei |
+
+
+# 0.9.x (version-1) -> 0.10.x (version-2)
+
+Last Updated on 2020-5-25 by Kaifeng Xue.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+| Remove TS_SessionHandle,TSHandleIdentifier            | Tian Jiang         |
+| Remove TSStatus,TSExecuteInsertRowInBatchResp            | Jialin Qiao|
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers                 |
+| ------------------------------------------------------------ | ---------------------------------- |
+| Add parameter sessionId in getTimeZone, getProperties, setStorageGroup, createTimeseries... | Tian Jiang|
+| Add struct TSQueryNonAlignDataSet                            | Haonan Hou|
+| Add struct TSInsertTabletsReq                            | Jialin Qiao|
+| Add method insertTablets                            | Jialin Qiao|
+| Add method testInsertTablets                            | Xiangdong Huang |
+| add new field `inferType` in TSInsertRecordReq  | Jialin Qiao      |
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Replace TS_SessionHandles with SessionIds, TSOperationHandle with queryIds  | Tian Jiang  |
+| Add optional TSQueryNonAlignDataSet in TSExecuteStatementResp, TSFetchResultsResp and required bool isAlign in TSFetchResultsReq | Haonan Hou |
+| Rename TSStatusType to TSStatus   | Jialin Qiao   |
+| Remove sessionId in TSExecuteBatchStatementResp   | Jialin Qiao   |
+| Rename insertRows to insertReords, insert to insertRecord, insertBatch to insertTablet   | Jialin Qiao   |
+| Use TsDataType and binary rather than string in TSInsertInBatchReq and TSInsertReq  | Kaifeng Xue  |
+
+
+
+# 0.8.x -> 0.9.x (version-1)
+
+Last Updated on 2019-10-27 by Lei Rui.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+| Delete struct TSSetStorageGroupReq | Jialin Qiao        |
+| Remove struct TSDataValue          | Lei Rui            |
+| Remove struct TSRowRecord          | Lei Rui            |
+| Remove optional string version in TSFetchMetadataResp | Genius_pig |
+| Remove optional set<string> childPaths, nodesList, storageGroups, devices in TSFetchMetadataResp | Genius_pig |
+| Remove optional map<string, string> nodeTimeseriesNum in TSFetchMetadataResp | Genius_pig |
+| Remove optional list<list<string>> timeseriesList in TSFetchMetadataResp | Genius_pig |
+| Remove optinoal optional i32 timeseriesNum in TSFetchMetadataResp | Genius_pig |
+| Remove optional i32 nodeLevel in TSFetchMetadataReq | Genius_pig |
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers                 |
+| ------------------------------------------------------------ | ---------------------------------- |
+| Add struct TSBatchInsertionReq                               | qiaojialin                         |
+| Add method TSExecuteBatchStatementResp insertBatch(1:TSBatchInsertionReq req) | qiaojialin                         |
+| Add Struct TSStatusType                                      | Zesong Sun                         |
+| Add TSCreateTimeseriesReq                                    | Zesong Sun                         |
+| Add method TSStatus setStorageGroup(1:string storageGroup)   | Zesong Sun, Jialin Qiao            |
+| Add method TSStatus createTimeseries(1:TSCreateTimeseriesReq req) | Zesong Sun                         |
+| Add struct TSInsertReq                                       | qiaojialin                         |
+| Add method TSRPCResp insertRow(1:TSInsertReq req)            | qiaojialin                         |
+| Add struct TSDeleteDataReq                                   | Jack Tsai, qiaojialin              |
+| Add method TSStatus deleteData(1:TSDeleteDataReq req)        | Jack Tsai, Jialin Qiao, qiaojialin |
+| Add method TSStatus deleteTimeseries(1:list\<string> path)   | qiaojialin                         |
+| Add method TSStatus deleteStorageGroups(1:list\<string> storageGroup) | Yi Tao                             |
+| Add Struct TSExecuteInsertRowInBatchResp                     | Kaifeng Xue |
+| Add method insertRowInBatch(1:TSInsertInBatchReq req);       | Kaifeng Xue |
+| Add method testInsertRowInBatch(1:TSInsertInBatchReq req);   | Kaifeng Xue |
+| Add method testInsertRow(1:TSInsertReq req);                 | Kaifeng Xue |
+| Add method testInsertBatch(1:TSBatchInsertionReq req);       | Kaifeng Xue |
+| Add struct TSCreateMultiTimeseriesReq                        | qiaojialin |
+| Add method createMultiTimeseries(1:TSCreateMultiTimeseriesReq req);       | qiaojialin |
+
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Add required string timestampPrecision in ServerProperties   | 1160300922             |
+| Add optional list\<string\> dataTypeList in TSExecuteStatementResp | suyue                  |
+| Update TSStatus to use TSStatusType, instead of using ~~TS_StatusCode, errorCode and errorMessage~~ | Zesong Sun             |
+| Rename item in enum TSProtocolVersion from ~~TSFILE_SERVICE_PROTOCOL_V1~~ to IOTDB_SERVICE_PROTOCOL_V1 | qiaojialin             |
+| Rename method name from ~~TSExecuteStatementResp executeInsertion(1:TSInsertionReq req)~~ to TSExecuteStatementResp insert(1:TSInsertionReq req) | qiaojialin             |
+| Add required i32 compressor in TSCreateTimeseriesReq         | Jialin Qiao            |
+| Add optional list\<string> nodesList, optional map\<string, string> nodeTimeseriesNum in TSFetchMetadataResp | jack870131             |
+| Add optional i32 nodeLevel in TSFetchMetadataReq             | jack870131, Zesong Sun |
+| Change the following methods' returned type to be TSStatus: <br />TSStatus closeSession(1:TSCloseSessionReq req), <br />TSStatus cancelOperation(1:TSCancelOperationReq req), <br />TSStatus closeOperation(1:TSCloseOperationReq req), <br />TSStatus setTimeZone(1:TSSetTimeZoneReq req), <br />TSStatus setStorageGroup(1:string storageGroup), <br />TSStatus createTimeseries(1:TSCreateTimeseriesReq req), <br />TSStatus insertRow(1:TSInsertReq req), <br />TSStatus deleteData(1:TSDeleteDataReq  [...]
+| Change from ~~required string path~~ to required list\<string> paths in TSDeleteDataReq | qiaojialin             |
+| Add optional set\<string> devices in TSFetchMetadataResp     | Zesong Sun             |
+| Rename some fields in TSFetchMetadataResp: ~~ColumnsList~~ to columnsList, ~~showTimeseriesList~~ to timeseriesList, ~~showStorageGroups~~ to storageGroups | Zesong Sun             |
+| Change struct TSQueryDataSet to eliminate row-wise rpc writing | Lei Rui                |
+| Add optional i32 timeseriesNum in TSFetchMetadataResp        | Jack Tsai              |
+| Add required i64 queryId in TSHandleIdentifier               | Yuan Tian    |
+| Add optional set\<string> childPaths in TSFetchMetadataResp     | Haonan Hou             |
+| Add optional string version in TSFetchMetadataResp           | Genius_pig             |
+| Add required i64 statementId in TSExecuteStatementReq        | Yuan Tian |
+| Add required binary time, required list<binary> valueList, required list<binary> bitmapList and remove required binary values, required i32 rowCount in TSQueryDataSet| Yuan Tian |
+| Add optional i32 fetchSize in TSExecuteStatementReq,<br />Add optional TSQueryDataSet in TSExecuteStatementResp| liutaohua |
+| Add optional map<string, string> props, optional map<string, string> tags, optional map<string, string> attributes and optional string aliasPath in TSCreateTimeseriesReq | Yuan Tian | 
diff --git a/thrift/src/main/thrift/cluster.thrift b/thrift-cluster/src/main/thrift/cluster.thrift
similarity index 100%
rename from thrift/src/main/thrift/cluster.thrift
rename to thrift-cluster/src/main/thrift/cluster.thrift
diff --git a/thrift-sync/README.md b/thrift-sync/README.md
new file mode 100644
index 0000000..94c1de6
--- /dev/null
+++ b/thrift-sync/README.md
@@ -0,0 +1,22 @@
+<!--
+
+    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.
+
+-->
+
+This modules maintains all RPC interfaces for data synchronization among servers.
\ No newline at end of file
diff --git a/thrift-sync/pom.xml b/thrift-sync/pom.xml
new file mode 100644
index 0000000..2108734
--- /dev/null
+++ b/thrift-sync/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.iotdb</groupId>
+        <artifactId>iotdb-parent</artifactId>
+        <version>0.12.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>iotdb-thrift-sync</artifactId>
+    <name>rpc-thrift-sync</name>
+    <description>RPC (Thrift) framework among servers for data synchronization.</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.thrift</groupId>
+            <artifactId>libthrift</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.iotdb</groupId>
+            <artifactId>iotdb-thrift</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/thrift-sync/rpc-changelist.md b/thrift-sync/rpc-changelist.md
new file mode 100644
index 0000000..797c0b6
--- /dev/null
+++ b/thrift-sync/rpc-changelist.md
@@ -0,0 +1,181 @@
+<!--
+
+    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.
+
+-->
+# 0.11.x(version-2) -> 0.12.x(version-1)
+
+Last Updated on 2021.01.19 by Xiangwei Wei.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Add timeout in TSFetchResultsReq and TSExecuteStatementReq | Xiangwei Wei | 
+
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+
+
+# 0.10.x (version-2) -> 0.11.x (version-3)
+
+Last Updated on 2020-10-27 by Xiangwei Wei.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+| Remove TSBatchExecuteStatementResp            | Tian Jiang         |
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| set the input/output as TFramedTransport      |  Tian Jiang        |
+| Add timeout(optional) in TSFetchResultsReq and TSExecuteStatementReq | Xiangwei Wei | 
+
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Add sub-status in TSStatus  | Tian Jiang  |
+| Change the result of executeBatchStatement  as   TSStatus    | Tian Jiang  |
+| Change TSDeleteDataReq, delete timestamp and add startTime and endTime   | Wei Shao   |
+| Add zoneId in TSOpenSessionReq | Xiangwei Wei |
+
+
+# 0.9.x (version-1) -> 0.10.x (version-2)
+
+Last Updated on 2020-5-25 by Kaifeng Xue.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+| Remove TS_SessionHandle,TSHandleIdentifier            | Tian Jiang         |
+| Remove TSStatus,TSExecuteInsertRowInBatchResp            | Jialin Qiao|
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers                 |
+| ------------------------------------------------------------ | ---------------------------------- |
+| Add parameter sessionId in getTimeZone, getProperties, setStorageGroup, createTimeseries... | Tian Jiang|
+| Add struct TSQueryNonAlignDataSet                            | Haonan Hou|
+| Add struct TSInsertTabletsReq                            | Jialin Qiao|
+| Add method insertTablets                            | Jialin Qiao|
+| Add method testInsertTablets                            | Xiangdong Huang |
+| add new field `inferType` in TSInsertRecordReq  | Jialin Qiao      |
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Replace TS_SessionHandles with SessionIds, TSOperationHandle with queryIds  | Tian Jiang  |
+| Add optional TSQueryNonAlignDataSet in TSExecuteStatementResp, TSFetchResultsResp and required bool isAlign in TSFetchResultsReq | Haonan Hou |
+| Rename TSStatusType to TSStatus   | Jialin Qiao   |
+| Remove sessionId in TSExecuteBatchStatementResp   | Jialin Qiao   |
+| Rename insertRows to insertReords, insert to insertRecord, insertBatch to insertTablet   | Jialin Qiao   |
+| Use TsDataType and binary rather than string in TSInsertInBatchReq and TSInsertReq  | Kaifeng Xue  |
+
+
+
+# 0.8.x -> 0.9.x (version-1)
+
+Last Updated on 2019-10-27 by Lei Rui.
+
+
+## 1. Delete Old
+
+| Latest Changes                     | Related Committers |
+| ---------------------------------- | ------------------ |
+| Delete struct TSSetStorageGroupReq | Jialin Qiao        |
+| Remove struct TSDataValue          | Lei Rui            |
+| Remove struct TSRowRecord          | Lei Rui            |
+| Remove optional string version in TSFetchMetadataResp | Genius_pig |
+| Remove optional set<string> childPaths, nodesList, storageGroups, devices in TSFetchMetadataResp | Genius_pig |
+| Remove optional map<string, string> nodeTimeseriesNum in TSFetchMetadataResp | Genius_pig |
+| Remove optional list<list<string>> timeseriesList in TSFetchMetadataResp | Genius_pig |
+| Remove optinoal optional i32 timeseriesNum in TSFetchMetadataResp | Genius_pig |
+| Remove optional i32 nodeLevel in TSFetchMetadataReq | Genius_pig |
+
+
+## 2. Add New
+
+| Latest Changes                                               | Related Committers                 |
+| ------------------------------------------------------------ | ---------------------------------- |
+| Add struct TSBatchInsertionReq                               | qiaojialin                         |
+| Add method TSExecuteBatchStatementResp insertBatch(1:TSBatchInsertionReq req) | qiaojialin                         |
+| Add Struct TSStatusType                                      | Zesong Sun                         |
+| Add TSCreateTimeseriesReq                                    | Zesong Sun                         |
+| Add method TSStatus setStorageGroup(1:string storageGroup)   | Zesong Sun, Jialin Qiao            |
+| Add method TSStatus createTimeseries(1:TSCreateTimeseriesReq req) | Zesong Sun                         |
+| Add struct TSInsertReq                                       | qiaojialin                         |
+| Add method TSRPCResp insertRow(1:TSInsertReq req)            | qiaojialin                         |
+| Add struct TSDeleteDataReq                                   | Jack Tsai, qiaojialin              |
+| Add method TSStatus deleteData(1:TSDeleteDataReq req)        | Jack Tsai, Jialin Qiao, qiaojialin |
+| Add method TSStatus deleteTimeseries(1:list\<string> path)   | qiaojialin                         |
+| Add method TSStatus deleteStorageGroups(1:list\<string> storageGroup) | Yi Tao                             |
+| Add Struct TSExecuteInsertRowInBatchResp                     | Kaifeng Xue |
+| Add method insertRowInBatch(1:TSInsertInBatchReq req);       | Kaifeng Xue |
+| Add method testInsertRowInBatch(1:TSInsertInBatchReq req);   | Kaifeng Xue |
+| Add method testInsertRow(1:TSInsertReq req);                 | Kaifeng Xue |
+| Add method testInsertBatch(1:TSBatchInsertionReq req);       | Kaifeng Xue |
+| Add struct TSCreateMultiTimeseriesReq                        | qiaojialin |
+| Add method createMultiTimeseries(1:TSCreateMultiTimeseriesReq req);       | qiaojialin |
+
+
+## 3. Update
+
+| Latest Changes                                               | Related Committers     |
+| ------------------------------------------------------------ | ---------------------- |
+| Add required string timestampPrecision in ServerProperties   | 1160300922             |
+| Add optional list\<string\> dataTypeList in TSExecuteStatementResp | suyue                  |
+| Update TSStatus to use TSStatusType, instead of using ~~TS_StatusCode, errorCode and errorMessage~~ | Zesong Sun             |
+| Rename item in enum TSProtocolVersion from ~~TSFILE_SERVICE_PROTOCOL_V1~~ to IOTDB_SERVICE_PROTOCOL_V1 | qiaojialin             |
+| Rename method name from ~~TSExecuteStatementResp executeInsertion(1:TSInsertionReq req)~~ to TSExecuteStatementResp insert(1:TSInsertionReq req) | qiaojialin             |
+| Add required i32 compressor in TSCreateTimeseriesReq         | Jialin Qiao            |
+| Add optional list\<string> nodesList, optional map\<string, string> nodeTimeseriesNum in TSFetchMetadataResp | jack870131             |
+| Add optional i32 nodeLevel in TSFetchMetadataReq             | jack870131, Zesong Sun |
+| Change the following methods' returned type to be TSStatus: <br />TSStatus closeSession(1:TSCloseSessionReq req), <br />TSStatus cancelOperation(1:TSCancelOperationReq req), <br />TSStatus closeOperation(1:TSCloseOperationReq req), <br />TSStatus setTimeZone(1:TSSetTimeZoneReq req), <br />TSStatus setStorageGroup(1:string storageGroup), <br />TSStatus createTimeseries(1:TSCreateTimeseriesReq req), <br />TSStatus insertRow(1:TSInsertReq req), <br />TSStatus deleteData(1:TSDeleteDataReq  [...]
+| Change from ~~required string path~~ to required list\<string> paths in TSDeleteDataReq | qiaojialin             |
+| Add optional set\<string> devices in TSFetchMetadataResp     | Zesong Sun             |
+| Rename some fields in TSFetchMetadataResp: ~~ColumnsList~~ to columnsList, ~~showTimeseriesList~~ to timeseriesList, ~~showStorageGroups~~ to storageGroups | Zesong Sun             |
+| Change struct TSQueryDataSet to eliminate row-wise rpc writing | Lei Rui                |
+| Add optional i32 timeseriesNum in TSFetchMetadataResp        | Jack Tsai              |
+| Add required i64 queryId in TSHandleIdentifier               | Yuan Tian    |
+| Add optional set\<string> childPaths in TSFetchMetadataResp     | Haonan Hou             |
+| Add optional string version in TSFetchMetadataResp           | Genius_pig             |
+| Add required i64 statementId in TSExecuteStatementReq        | Yuan Tian |
+| Add required binary time, required list<binary> valueList, required list<binary> bitmapList and remove required binary values, required i32 rowCount in TSQueryDataSet| Yuan Tian |
+| Add optional i32 fetchSize in TSExecuteStatementReq,<br />Add optional TSQueryDataSet in TSExecuteStatementResp| liutaohua |
+| Add optional map<string, string> props, optional map<string, string> tags, optional map<string, string> attributes and optional string aliasPath in TSCreateTimeseriesReq | Yuan Tian | 
diff --git a/thrift/src/main/thrift/sync.thrift b/thrift-sync/src/main/thrift/sync.thrift
similarity index 100%
rename from thrift/src/main/thrift/sync.thrift
rename to thrift-sync/src/main/thrift/sync.thrift
diff --git a/thrift/README.md b/thrift/README.md
new file mode 100644
index 0000000..1d105e8
--- /dev/null
+++ b/thrift/README.md
@@ -0,0 +1,22 @@
+<!--
+
+    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.
+
+-->
+
+This modules maintains all RPC interfaces between clients and the server.
\ No newline at end of file