You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tsfile.apache.org by ja...@apache.org on 2024/06/17 08:41:14 UTC

(tsfile) 09/20: init tsfile for cpp.

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

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

commit ca2f942b8ccbb1aa85cd5a8c1cba6be6cdb97ab4
Author: RkGrit <G1...@gmail.com>
AuthorDate: Thu May 23 15:17:38 2024 +0800

    init tsfile for cpp.
---
 cpp/examples/src/demo_read.cpp                     |   92 +
 cpp/tsfile/src/CMakeLists.txt                      |    4 +
 cpp/tsfile/src/common/CMakeLists.txt               |   20 +
 cpp/tsfile/src/common/allocator/CMakeLists.txt.bak |   16 +
 cpp/tsfile/src/common/allocator/alloc_base.h       |  128 +
 cpp/tsfile/src/common/allocator/byte_stream.h      | 1111 ++++++++
 cpp/tsfile/src/common/allocator/mem_alloc.cc       |  236 ++
 cpp/tsfile/src/common/allocator/my_string.h        |  143 +
 cpp/tsfile/src/common/allocator/object_pool.h      |  104 +
 cpp/tsfile/src/common/allocator/page_arena.cc      |   52 +
 cpp/tsfile/src/common/allocator/page_arena.h       |   90 +
 cpp/tsfile/src/common/allocator/stl_allocator.h    |   68 +
 cpp/tsfile/src/common/allocator/util_define.h      |  136 +
 cpp/tsfile/src/common/config/CMakeLists.txt        |    2 +
 cpp/tsfile/src/common/config/config.h              |   52 +
 cpp/tsfile/src/common/container/CMakeLists.txt     |   12 +
 cpp/tsfile/src/common/container/array.h            |  312 +++
 cpp/tsfile/src/common/container/bit_map.cc         |   32 +
 cpp/tsfile/src/common/container/bit_map.h          |   71 +
 cpp/tsfile/src/common/container/blocking_queue.cc  |   47 +
 cpp/tsfile/src/common/container/blocking_queue.h   |   32 +
 cpp/tsfile/src/common/container/byte_buffer.h      |  114 +
 cpp/tsfile/src/common/container/hash_func.h        |  102 +
 cpp/tsfile/src/common/container/hash_node.h        |   90 +
 cpp/tsfile/src/common/container/hash_segm.h        |   41 +
 cpp/tsfile/src/common/container/hash_table.h       |  685 +++++
 cpp/tsfile/src/common/container/list.h             |  147 ++
 cpp/tsfile/src/common/container/murmur_hash3.cc    |  126 +
 cpp/tsfile/src/common/container/murmur_hash3.h     |   67 +
 cpp/tsfile/src/common/container/simple_vector.h    |   48 +
 cpp/tsfile/src/common/container/slice.h            |  142 +
 cpp/tsfile/src/common/container/sorted_array.h     |  333 +++
 cpp/tsfile/src/common/datatype/CMakeLists.txt      |   13 +
 cpp/tsfile/src/common/datatype/value.h             |  216 ++
 cpp/tsfile/src/common/db_common.h                  |  168 ++
 cpp/tsfile/src/common/db_utils.h                   |  457 ++++
 cpp/tsfile/src/common/errno_define.h               |   64 +
 cpp/tsfile/src/common/global.cc                    |  201 ++
 cpp/tsfile/src/common/global.h                     |   28 +
 cpp/tsfile/src/common/injection.h                  |   53 +
 cpp/tsfile/src/common/mutex/CMakeLists.txt         |    2 +
 cpp/tsfile/src/common/mutex/mutex.h                |   64 +
 cpp/tsfile/src/common/tsblock/CMakeLists.txt       |   11 +
 cpp/tsfile/src/common/tsblock/tsblock.cc           |  293 +++
 cpp/tsfile/src/common/tsblock/tsblock.h            |  291 +++
 cpp/tsfile/src/common/tsblock/tuple_desc.cc        |   76 +
 cpp/tsfile/src/common/tsblock/tuple_desc.h         |  116 +
 .../common/tsblock/vector/fixed_length_vector.h    |   76 +
 .../common/tsblock/vector/variable_length_vector.h |   77 +
 cpp/tsfile/src/common/tsblock/vector/vector.h      |   75 +
 cpp/tsfile/src/common/util_define.h                |  133 +
 cpp/tsfile/src/tsfile.cpp                          |   29 -
 cpp/tsfile/src/tsfile/CMakeLists.txt               |  118 +
 cpp/tsfile/src/tsfile/Makefile                     | 1281 +++++++++
 cpp/tsfile/src/tsfile/bloom_filter.cc              |  254 ++
 cpp/tsfile/src/tsfile/bloom_filter.h               |  120 +
 cpp/tsfile/src/tsfile/chunk_reader                 |    0
 cpp/tsfile/src/tsfile/chunk_reader.cc              |  425 +++
 cpp/tsfile/src/tsfile/chunk_reader.h               |  128 +
 cpp/tsfile/src/tsfile/chunk_writer.cc              |  140 +
 cpp/tsfile/src/tsfile/chunk_writer.h               |  116 +
 cpp/tsfile/src/tsfile/compress/CMakeLists.txt      |   14 +
 cpp/tsfile/src/tsfile/compress/Makefile            |  285 ++
 cpp/tsfile/src/tsfile/compress/compressor.c        |    0
 cpp/tsfile/src/tsfile/compress/compressor.h        |   42 +
 .../src/tsfile/compress/compressor_factory.h       |   62 +
 cpp/tsfile/src/tsfile/compress/gzip_compressor.cc  |  271 ++
 cpp/tsfile/src/tsfile/compress/gzip_compressor.h   |  137 +
 cpp/tsfile/src/tsfile/compress/lz4.c               | 2751 ++++++++++++++++++++
 cpp/tsfile/src/tsfile/compress/lz4.h               |  861 ++++++
 cpp/tsfile/src/tsfile/compress/lz4_compressor.cc   |  132 +
 cpp/tsfile/src/tsfile/compress/lz4_compressor.h    |   59 +
 .../src/tsfile/compress/uncompressed_compressor.h  |   56 +
 .../tsfile/data_dir/smoke_test.write_record.dat    |  Bin 0 -> 1273 bytes
 cpp/tsfile/src/tsfile/encode/CMakeLists.txt        |   14 +
 cpp/tsfile/src/tsfile/encode/Makefile              |  189 ++
 cpp/tsfile/src/tsfile/encode/bitpack_decoder.h     |  164 ++
 cpp/tsfile/src/tsfile/encode/bitpack_encoder.h     |  170 ++
 cpp/tsfile/src/tsfile/encode/decoder.h             |   30 +
 cpp/tsfile/src/tsfile/encode/decoder_factory.h     |   89 +
 cpp/tsfile/src/tsfile/encode/dictionary_decoder.h  |   69 +
 cpp/tsfile/src/tsfile/encode/dictionary_encoder.h  |   96 +
 cpp/tsfile/src/tsfile/encode/encode_utils.h        |  138 +
 cpp/tsfile/src/tsfile/encode/encoder.h             |   33 +
 cpp/tsfile/src/tsfile/encode/encoder_factory.h     |  105 +
 cpp/tsfile/src/tsfile/encode/gorilla_decoder.h     |  311 +++
 cpp/tsfile/src/tsfile/encode/gorilla_encoder.h     |  388 +++
 cpp/tsfile/src/tsfile/encode/intpacker.h           |  144 +
 cpp/tsfile/src/tsfile/encode/plain_decoder.h       |   45 +
 cpp/tsfile/src/tsfile/encode/plain_encoder.h       |   56 +
 cpp/tsfile/src/tsfile/encode/ts2diff_decoder.h     |  214 ++
 cpp/tsfile/src/tsfile/encode/ts2diff_encoder.h     |  273 ++
 cpp/tsfile/src/tsfile/encode/zigzag_decoder.h      |  206 ++
 cpp/tsfile/src/tsfile/encode/zigzag_encoder.h      |  172 ++
 cpp/tsfile/src/tsfile/expression.cc                |  180 ++
 cpp/tsfile/src/tsfile/expression.h                 |  132 +
 cpp/tsfile/src/tsfile/filter/and_filter.h          |   79 +
 cpp/tsfile/src/tsfile/filter/between.h             |  107 +
 cpp/tsfile/src/tsfile/filter/binary_filter.h       |   31 +
 cpp/tsfile/src/tsfile/filter/eq.h                  |   63 +
 cpp/tsfile/src/tsfile/filter/filter.h              |   32 +
 cpp/tsfile/src/tsfile/filter/filter_type.h         |   42 +
 cpp/tsfile/src/tsfile/filter/gt.h                  |   59 +
 cpp/tsfile/src/tsfile/filter/gt_eq.h               |   60 +
 cpp/tsfile/src/tsfile/filter/in.h                  |   42 +
 cpp/tsfile/src/tsfile/filter/lt.h                  |   59 +
 cpp/tsfile/src/tsfile/filter/lt_eq.h               |   60 +
 cpp/tsfile/src/tsfile/filter/not_eq.h              |   60 +
 cpp/tsfile/src/tsfile/filter/object.h              |   78 +
 cpp/tsfile/src/tsfile/filter/or_filter.h           |   81 +
 cpp/tsfile/src/tsfile/filter/time_filter.cc        |   30 +
 cpp/tsfile/src/tsfile/filter/time_filter.h         |   39 +
 cpp/tsfile/src/tsfile/filter/time_operator.cc      |  295 +++
 cpp/tsfile/src/tsfile/filter/time_operator.h       |  207 ++
 cpp/tsfile/src/tsfile/filter/unary_filter.h        |   42 +
 cpp/tsfile/src/tsfile/open_file.cc                 |   99 +
 cpp/tsfile/src/tsfile/open_file.h                  |  123 +
 cpp/tsfile/src/tsfile/page_writer.cc               |  191 ++
 cpp/tsfile/src/tsfile/page_writer.h                |  156 ++
 cpp/tsfile/src/tsfile/path.h                       |   37 +
 cpp/tsfile/src/tsfile/qds_with_timegenerator.cc    |  377 +++
 cpp/tsfile/src/tsfile/qds_with_timegenerator.h     |  127 +
 cpp/tsfile/src/tsfile/qds_without_timegenerator.cc |  149 ++
 cpp/tsfile/src/tsfile/qds_without_timegenerator.h  |   52 +
 cpp/tsfile/src/tsfile/query_data_set.h             |   23 +
 cpp/tsfile/src/tsfile/query_executor.h             |   50 +
 cpp/tsfile/src/tsfile/read_file.cc                 |  106 +
 cpp/tsfile/src/tsfile/read_file.h                  |   51 +
 cpp/tsfile/src/tsfile/record.h                     |  144 +
 cpp/tsfile/src/tsfile/row_record.h                 |  194 ++
 cpp/tsfile/src/tsfile/scan_iterator.cc             |  238 ++
 cpp/tsfile/src/tsfile/scan_iterator.h              |  190 ++
 cpp/tsfile/src/tsfile/schema.h                     |   63 +
 cpp/tsfile/src/tsfile/seq_tvlist.h                 |  176 ++
 cpp/tsfile/src/tsfile/seq_tvlist.inc               |  159 ++
 cpp/tsfile/src/tsfile/statistic.h                  |  792 ++++++
 cpp/tsfile/src/tsfile/storage_utils.h              |   80 +
 cpp/tsfile/src/tsfile/tablet.cc                    |  154 ++
 cpp/tsfile/src/tsfile/tablet.h                     |   82 +
 cpp/tsfile/src/tsfile/tablet_iterator.h            |   59 +
 cpp/tsfile/src/tsfile/tsfile_common.cc             |  230 ++
 cpp/tsfile/src/tsfile/tsfile_common.h              |  812 ++++++
 cpp/tsfile/src/tsfile/tsfile_executor.cc           |  107 +
 cpp/tsfile/src/tsfile/tsfile_executor.h            |   42 +
 cpp/tsfile/src/tsfile/tsfile_io_reader.cc          |  495 ++++
 cpp/tsfile/src/tsfile/tsfile_io_reader.h           |  158 ++
 cpp/tsfile/src/tsfile/tsfile_io_writer.cc          |  716 +++++
 cpp/tsfile/src/tsfile/tsfile_io_writer.h           |  190 ++
 cpp/tsfile/src/tsfile/tsfile_mgr.cc                |  130 +
 cpp/tsfile/src/tsfile/tsfile_mgr.h                 |   89 +
 cpp/tsfile/src/tsfile/tsfile_reader.cc             |   53 +
 cpp/tsfile/src/tsfile/tsfile_reader.h              |   45 +
 .../src/tsfile/tsfile_series_scan_iterator.cc      |  102 +
 .../src/tsfile/tsfile_series_scan_iterator.h       |   93 +
 cpp/tsfile/src/tsfile/tsfile_writer.cc             |  438 ++++
 cpp/tsfile/src/tsfile/tsfile_writer.h              |  120 +
 cpp/tsfile/src/tsfile/write_file.cc                |  116 +
 cpp/tsfile/src/tsfile/write_file.h                 |   49 +
 158 files changed, 26862 insertions(+), 29 deletions(-)

diff --git a/cpp/examples/src/demo_read.cpp b/cpp/examples/src/demo_read.cpp
new file mode 100644
index 00000000..a80ff801
--- /dev/null
+++ b/cpp/examples/src/demo_read.cpp
@@ -0,0 +1,92 @@
+#include <iostream>
+#include <vector>
+#include <string>
+#include "tsfile/path.h"
+#include "tsfile/filter/filter.h"
+#include "tsfile/expression.h"
+#include "tsfile/tsfile_reader.h"
+#include "tsfile/qds_with_timegenerator.h"
+#include "tsfile/qds_without_timegenerator.h"
+#include "tsfile/row_record.h"
+
+using namespace std;
+
+std::string field_to_string(timecho::storage::Field *value)
+{
+  if (value->type_ == timecho::common::TEXT) {
+    return std::string(value->value_.sval_);
+  } else {
+    std::stringstream ss;
+    switch (value->type_) {
+      case timecho::common::BOOLEAN:
+        ss << (value->value_.bval_ ? "true" : "false");
+        break;
+      case timecho::common::INT32:
+        ss << value->value_.ival_;
+        break;
+      case timecho::common::INT64:
+        ss << value->value_.lval_;
+        break;
+      case timecho::common::FLOAT:
+        ss << value->value_.fval_;
+        break;
+      case timecho::common::DOUBLE:
+        ss << value->value_.dval_;
+        break;
+      case timecho::common::NULL_TYPE:
+        ss << "NULL";
+        break;
+      default:
+        ASSERT(false);
+        break;
+    }
+    return ss.str();
+  }
+}
+
+int main (int argc, char **argv)
+{
+    std::cout<<"begin to read tsfile from /tmp/t1" << std::endl;
+    std::string device_name = "root.db001.dev001";
+    std::string measurement_name = "m001";
+    timecho::storage::Path p1(device_name, measurement_name);
+    std::vector<timecho::storage::Path> select_list;
+    select_list.push_back(p1);
+    timecho::storage::QueryExpression *query_expr =
+            timecho::storage::QueryExpression::create(select_list, nullptr);
+
+    timecho::common::init_config_value();
+    timecho::storage::TsFileReader reader;
+    int ret = reader.open("/tmp/t1");
+    std::cout <<"open file return " << ret<< std::endl;
+
+    std::cout << "begin to query expr" << std::endl;
+    ASSERT(ret == 0);
+    timecho::storage::QueryDataSet *qds = nullptr;
+    ret = reader.query(query_expr, qds);
+
+
+    timecho::storage::RowRecord *record;
+    std::cout << "begin to dump data from tsfile ---" << std::endl;
+    int row_cout = 0;
+    do {
+        record = qds->get_next();
+        if (record) {
+            std::cout<< "dump QDS :  " << record->get_timestamp() << ",";
+            if (record) {
+                int size = record->get_fields()->size();
+                for (int i = 0; i < size; ++i) {
+                    std::cout << field_to_string(record->get_field(i)) << ",";
+                }
+                std::cout<< std::endl;
+                row_cout++;
+            }
+        } else {
+            break;
+        }
+    } while (true);
+    std::cout << "dump tsfile finish" << std::endl;
+    std::cout << "total row count = " << row_cout<<std::endl;
+
+    return  (0);
+}
diff --git a/cpp/tsfile/src/CMakeLists.txt b/cpp/tsfile/src/CMakeLists.txt
new file mode 100644
index 00000000..78ad85c6
--- /dev/null
+++ b/cpp/tsfile/src/CMakeLists.txt
@@ -0,0 +1,4 @@
+message("Running in src diectory")
+include(${PROJECT_SOURCE_DIR}/cmake/build_function.cmake)
+add_subdirectory(tsfile)
+add_subdirectory(common)
\ No newline at end of file
diff --git a/cpp/tsfile/src/common/CMakeLists.txt b/cpp/tsfile/src/common/CMakeLists.txt
new file mode 100644
index 00000000..20249ab5
--- /dev/null
+++ b/cpp/tsfile/src/common/CMakeLists.txt
@@ -0,0 +1,20 @@
+message("Running in src/common directory")
+
+add_subdirectory(allocator)
+add_subdirectory(config)
+add_subdirectory(container)
+add_subdirectory(mutex)
+add_subdirectory(tsblock)
+add_subdirectory(datatype)
+
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} common_SRC_LIST)
+set(common_INC_LIST )
+set(common_DEFINE_OPTIONS )
+set(common_COMPILE_OPTIONS )
+set(common_LINK_OPTIONS )
+
+add_statis_objtarget(common common_SRC_LIST common_INC_LIST
+                     "${common_DEFINE_OPTIONS}"
+                     "${common_COMPILE_OPTIONS}"
+                     "${common_LINK_OPTIONS}")
+
diff --git a/cpp/tsfile/src/common/allocator/CMakeLists.txt.bak b/cpp/tsfile/src/common/allocator/CMakeLists.txt.bak
new file mode 100644
index 00000000..94b845f4
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/CMakeLists.txt.bak
@@ -0,0 +1,16 @@
+
+message("Running in src/common/allocator directory")
+
+message("CMAKE_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}")
+
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} common_allocator_SRC_LIST)
+set(common_allocator_INC_LIST)
+set(common_allocator_DEFINE_OPTIONS)
+set(common_allocator_COMPILE_OPTIONS)
+set(common_allocator_LINK_OPTIONS)
+
+add_statis_objtarget(common_allocator common_allocator_SRC_LIST common_allocator_INC_LIST
+                     "${common_allocator_DEFINE_OPTIONS}"
+                     "${common_allocator_COMPILE_OPTIONS}"
+                     "${common_allocator_LINK_OPTIONS}")
+
diff --git a/cpp/tsfile/src/common/allocator/alloc_base.h b/cpp/tsfile/src/common/allocator/alloc_base.h
new file mode 100644
index 00000000..953a34a9
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/alloc_base.h
@@ -0,0 +1,128 @@
+
+#ifndef COMMON_ALLOCATOR_ALLOC_BASE_H
+#define COMMON_ALLOCATOR_ALLOC_BASE_H
+
+#include <cstring>
+#include <stddef.h>
+#include "../util_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+enum AllocModID
+{
+  __FIRST_MOD_ID = 0,
+  // if you are sure you will not consume too much memory, you can use MOD_DEFAULT.
+  MOD_DEFAULT = 0,
+  MOD_MEMTABLE = 1,
+  MOD_SCHEMA = 2,
+  MOD_SQL = 3,
+  MOD_NET = 4,
+  MOD_NET_DATA = 5,
+  MOD_TVLIST_DATA = 6,
+  MOD_TVLIST_OBJ = 7,
+  MOD_TSBLOCK = 8,
+  MOD_CONTAINER = 9,
+  MOD_TSSTORE_OBJ = 10,
+  MOD_FLUSH_TASK_OBJ = 11,
+  MOD_PAGE_WRITER_OUTPUT_STREAM = 12,
+  MOD_CW_PAGES_DATA = 13,
+  MOD_CHUNK_WRITER_OBJ = 14,
+  MOD_STATISTIC_OBJ = 15,
+  MOD_ENCODER_OBJ = 16,
+  MOD_DECODER_OBJ = 17,
+  MOD_TSFILE_WRITER_META = 18,
+  MOD_TSFILE_WRITE_STREAM = 19,
+  MOD_TIMESERIES_INDEX_OBJ = 20,
+  MOD_BLOOM_FILTER = 21,
+  MOD_OPEN_FILE_OBJ = 22,
+  MOD_TSFILE_READER = 23,
+  MOD_CHUNK_READER = 24,
+  MOD_COMPRESSOR_OBJ = 25,
+  MOD_ARRAY = 26,
+  MOD_HASH_TABLE = 27,
+  MOD_WRITER_INDEX_NODE = 28,
+  MOD_TS2DIFF_OBJ = 29,
+  MOD_BITENCODE_OBJ = 30,
+  MOD_DICENCODE_OBJ = 31,
+  MOD_ZIGZAG_OBJ = 32,
+  __LAST_MOD_ID = 33, // prev + 1,
+  __MAX_MOD_ID = 127, // leave 1 bit to detect header size
+};
+
+extern const char *g_mod_names[__LAST_MOD_ID];
+
+/* very basic alloc/free interface in C style */
+void *mem_alloc(uint32_t size, AllocModID mid);
+void mem_free(void *ptr);
+void *mem_realloc(void *ptr, uint32_t size);
+
+class ModStat
+{
+public:
+  ModStat() : stat_arr_(NULL) {}
+
+  static ModStat &get_instance()
+  {
+    /*
+     * This is the singleton of Mod Memory Statistic.
+     * gms is short for Global Mod Statistic
+     */
+    static ModStat gms;
+    return gms;
+  }
+  void init();
+  void destroy();
+  INLINE void update_alloc(AllocModID mid, int32_t size)
+  {
+//    ASSERT(mid < __LAST_MOD_ID);
+//     ATOMIC_FAA(get_item(mid), size);
+  }
+  void update_free(AllocModID mid, uint32_t size)
+  {
+//    ASSERT(mid < __LAST_MOD_ID);
+//    ATOMIC_FAA(get_item(mid), 0 - size);
+  }
+  void print_stat();
+
+#ifdef ENABLE_TEST
+  int32_t TEST_get_stat(int8_t mid) { return ATOMIC_FAA(get_item(mid), 0); }
+#endif
+
+private:
+  INLINE int32_t *get_item(int8_t mid)
+  { 
+    return &(stat_arr_[mid * (ITEM_SIZE/sizeof(int32_t))]); 
+  }
+
+private:
+  static const int32_t ITEM_SIZE = CACHE_LINE_SIZE;
+  static const int32_t ITEM_COUNT = __LAST_MOD_ID;
+  int32_t *stat_arr_;
+
+  STATIC_ASSERT((ITEM_SIZE % sizeof(int32_t) == 0), ModStat_ITEM_SIZE_ERROR);
+};
+
+/* base allocator */
+class BaseAllocator
+{
+public:
+  void *alloc(uint32_t size, AllocModID mid)
+  {
+    return mem_alloc(size, mid);
+  }
+  void free(void *ptr)
+  {
+    mem_free(ptr);
+  }
+};
+
+extern BaseAllocator g_base_allocator;
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_ALLOCATOR_ALLOC_BASE_H
+
diff --git a/cpp/tsfile/src/common/allocator/byte_stream.h b/cpp/tsfile/src/common/allocator/byte_stream.h
new file mode 100644
index 00000000..5dd56ebc
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/byte_stream.h
@@ -0,0 +1,1111 @@
+
+#ifndef COMMON_ALLOCATOR_BYTE_STREAM_H
+#define COMMON_ALLOCATOR_BYTE_STREAM_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <iostream>
+
+#include "common/allocator/alloc_base.h"
+#include "common/allocator/my_string.h"
+#include "common/errno_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+template<typename T>
+class OptionalAtomic
+{
+public:
+  OptionalAtomic(T t, bool enable_atomic = false)
+    : val_(t), enable_atomic_(enable_atomic) {}
+
+  FORCE_INLINE T load() const
+  {
+    if (UNLIKELY(enable_atomic_)) {
+      return ATOMIC_LOAD(&val_);
+    } else {
+      return val_;
+    }
+  }
+
+  FORCE_INLINE void store(const T t)
+  {
+    if (UNLIKELY(enable_atomic_)) {
+      ATOMIC_STORE(&val_, t);
+    } else {
+      val_ = t;
+    }
+  }
+
+  FORCE_INLINE T atomic_faa(const T increament)
+  {
+    if (UNLIKELY(enable_atomic_)) {
+      return ATOMIC_FAA(&val_, increament);
+    } else {
+      T old_val = val_;
+      val_ = val_ + increament;
+      return old_val;
+    }
+  }
+
+  FORCE_INLINE T atomic_aaf(const T increament)
+  {
+    if (UNLIKELY(enable_atomic_)) {
+      return ATOMIC_AAF(&val_, increament);
+    } else {
+      val_ = val_ + increament;
+      return val_;
+    }
+  }
+
+  FORCE_INLINE bool enable_atomic() const { return enable_atomic_; }
+
+private:
+  T val_;
+  bool enable_atomic_;
+};
+
+FORCE_INLINE int32_t float_to_int(float f)
+{
+  // return *((int32_t*)(&f));
+  // return *(reinterpret_cast<int32_t*>(&f));
+  union fi
+  {
+    int i_;
+    float f_;
+  };
+
+  fi my_fi;
+  my_fi.f_ = f;
+  return my_fi.i_;  // By mimicking the java jdk's implementation, it's essentially the same as line 75.
+}
+
+FORCE_INLINE float int_to_float(int32_t i)
+{
+  // return *((float *)(&i));
+  union fi
+  {
+    int i_;
+    float f_;
+  };
+
+  fi my_fi;
+  my_fi.i_ = i;
+  return my_fi.f_;
+}
+
+FORCE_INLINE void float_to_bytes(float f, uint8_t bytes[4])
+{
+  /*
+   * See:
+   * floatToBytes in BytesUtils.java of IoTDB project and
+   * Java_java_lang_Float_intBitsToFloat in JDK project
+   */
+  if (UNLIKELY(f != f)) { // this is NaN
+    // IEEE754: 0x7FC00000 for NanN
+    bytes[0] = 0x7F;
+    bytes[1] = 0xC0;
+    bytes[2] = 0x00;
+    bytes[3] = 0x00;
+    return;
+  }
+
+  // follow jdk implementation style.
+  union {
+    int i;
+    float f;
+  } u;
+
+  u.f = f;
+  
+  bytes[3] = (uint8_t)(u.i);
+  bytes[2] = (uint8_t)(u.i >>  8);
+  bytes[1] = (uint8_t)(u.i >> 16);
+  bytes[0] = (uint8_t)(u.i >> 24);
+}
+
+FORCE_INLINE float bytes_to_float(uint8_t bytes[4])
+{
+  int32_t i = bytes[3];
+  i &= 0xFF;
+  i |= bytes[2] << 8;
+  i &= 0xFFFF;
+  i |= bytes[1] << 16;
+  i &= 0xFFFFFF;
+  i |= bytes[0] << 24;
+  
+  union {
+    int i;
+    float f;
+  } u;
+
+  u.i = i;
+  return u.f;
+}
+
+FORCE_INLINE int64_t double_to_long(double d)
+{
+  // return *((int64_t*)(&d));
+  union dl
+  {
+    double d_;
+    int64_t l_;
+  };
+  dl my_dl;
+  my_dl.d_ = d;
+  return my_dl.l_;
+}
+
+FORCE_INLINE double long_to_double(int64_t l)
+{
+  // return *((double *)(&l));
+  union dl
+  {
+    double d_;
+    int64_t l_;
+  };
+  dl my_dl;
+  my_dl.l_ = l;
+  return my_dl.d_;
+}
+
+FORCE_INLINE void double_to_bytes(double d, uint8_t bytes[8])
+{
+  if (UNLIKELY(d != d)) {
+    // NaN, 0x7FF8000000000000L
+    memset(bytes, 0, 8);
+    bytes[0] = 0x7F;
+    bytes[1] = 0xF8;
+    return;
+  }
+  // follow jdk implementation style.
+  union {
+    long long l;
+    double d;
+  } u;
+
+  u.d = d;
+
+  bytes[7] = (uint8_t)u.l;
+  bytes[6] = (uint8_t)(u.l >>  8);
+  bytes[5] = (uint8_t)(u.l >> 16);
+  bytes[4] = (uint8_t)(u.l >> 24);
+  bytes[3] = (uint8_t)(u.l >> 32);
+  bytes[2] = (uint8_t)(u.l >> 40);
+  bytes[1] = (uint8_t)(u.l >> 48);
+  bytes[0] = (uint8_t)(u.l >> 56);
+}
+
+FORCE_INLINE double bytes_to_double(uint8_t bytes[8])
+{
+  int64_t value = bytes[7];
+  value &= 0xFFl;
+  value |= ((int64_t)bytes[6]) <<  8;
+  value &= 0xFFFFl;
+  value |= ((int64_t)bytes[5]) << 16;
+  value &= 0xFFFFFFl;
+  value |= ((int64_t)bytes[4]) << 24;
+  value &= 0xFFFFFFFFl;
+  value |= ((int64_t)bytes[3]) << 32;
+  value &= 0xFFFFFFFFFFl;
+  value |= ((int64_t)bytes[2]) << 40;
+  value &= 0xFFFFFFFFFFFFl;
+  value |= ((int64_t)bytes[1]) << 48;
+  value &= 0xFFFFFFFFFFFFFFl;
+  value |= ((int64_t)bytes[0]) << 56;
+
+  // follow jdk implementation style.
+  union {
+    long l;
+    double d;
+  } u;
+
+  u.l = value;
+  return u.d;
+}
+
+// TODO define a WrappedByteStream class
+
+// auto extend buffer for serialization
+class ByteStream
+{
+private:
+  struct Page
+  {
+    OptionalAtomic<Page*> next_;  // 9 bytes
+    uint8_t *buf_;  // 8 bytes
+
+    explicit Page(bool enable_atomic) : next_(nullptr, enable_atomic)
+    {
+      buf_ = (uint8_t*)(this + 1);  // I think it should add 17, because the Page class is 9+8=17 bytes. No, adding one to a pointer is not adding a byte, but adding the length of the byte corresponding to the type pointed to by the pointer, and adding one here is actually adding 17 bytes. No problem.
+    }
+    Page(bool enable_atomic, uint8_t *wrapped_buf)
+      : next_(nullptr, enable_atomic),
+        buf_(wrapped_buf) {}
+  };
+
+public:
+  ByteStream(uint32_t page_size,
+             AllocModID mid,
+             bool enable_atomic = false,
+             BaseAllocator &allocator = g_base_allocator)
+    : allocator_(allocator),
+      head_(nullptr, enable_atomic),
+      tail_(nullptr, enable_atomic),
+      read_page_(nullptr),
+      total_size_(0, enable_atomic),
+      read_pos_(0),
+      marked_read_pos_(0),
+      page_size_(page_size),
+      mid_(mid),
+      wrapped_page_(false, nullptr)
+  {
+    // assert(page_size >= 16);  // commented out by gxh on 2023.03.09
+      std::cout<<"page size when created is " << page_size << std::endl;
+  }
+
+  // TODO use a specific construct function to mark it as wrapped use.
+  // for wrap plain buffer to ByteStream
+  ByteStream() : allocator_(g_base_allocator),
+                 head_(nullptr, false),
+                 tail_(nullptr, false),
+                 read_page_(nullptr),
+                 total_size_(0, false),
+                 read_pos_(0),
+                 marked_read_pos_(0),
+                 page_size_(0),
+                 mid_(MOD_DEFAULT),
+                 wrapped_page_(false, nullptr) {}
+
+  ~ByteStream() { destroy(); }
+
+  /* ================ Part 0: wrap from outside buffer ================ */
+  // if you wrap a buffer as a ByteStream, you should
+  // manage the outside buffer yourself.
+  void wrap_from(const char *buf, int32_t buf_len)
+  {
+    wrapped_page_.next_.store(nullptr);
+    wrapped_page_.buf_ = (uint8_t*)buf;
+
+    page_size_ = buf_len;
+    std::cout<<"page_size when wrap from" << page_size_ << std::endl;
+    head_.store(&wrapped_page_);
+    tail_.store(&wrapped_page_);
+    total_size_.store(buf_len);
+    marked_read_pos_ = 0;
+    read_pos_ = 0;
+    read_page_ = nullptr;
+  }
+  FORCE_INLINE bool is_wrapped() const { return head_.load() == &wrapped_page_; }
+  char* get_wrapped_buf() { return (char*)wrapped_page_.buf_; }
+  void clear_wrapped_buf() { wrapped_page_.buf_ = nullptr; }
+
+  /* ================ Part 1: basic ================ */
+  FORCE_INLINE uint32_t remaining_size() const
+  {
+    ASSERT(total_size_.load() >= read_pos_);
+    return total_size_.load() - read_pos_;
+  }
+  FORCE_INLINE bool has_remaining() const { return remaining_size() > 0; }
+
+  FORCE_INLINE void mark_read_pos() { marked_read_pos_ = read_pos_; }
+  FORCE_INLINE uint32_t get_mark_len() const
+  {
+    ASSERT(marked_read_pos_ <= read_pos_);
+    return read_pos_ - marked_read_pos_;
+  }
+
+  void destroy() { reset(); }
+  void reset()
+  {
+    // if this ByteStream is wrapped from a plain buffer
+    // do not free the outside buffer.
+    if (!is_wrapped()) {
+      Page *p = head_.load();
+      while (p) {
+        p = head_.load()->next_.load();
+        allocator_.free(head_.load());
+        head_.store(p);
+      }
+    }
+    head_.store(nullptr);
+    tail_.store(nullptr);
+    read_page_ = nullptr;
+    total_size_.store(0);
+    read_pos_ = 0;
+  }
+
+  // never used TODO
+  void shallow_clone_from(ByteStream &other)
+  {
+    this->page_size_ = other.page_size_ ;
+    std::cout << "page size after clone" << this->page_size_ << std::endl;
+    this->mid_ = other.mid_ ;
+    this->head_.store(other.head_.load());
+    this->tail_.store(other.tail_.load());
+    this->total_size_.store(other.total_size_.load());
+  }
+
+  FORCE_INLINE uint32_t total_size() const { return total_size_.load(); }
+  FORCE_INLINE uint32_t read_pos() const { return read_pos_; };
+  FORCE_INLINE void wrapped_buf_advance_read_pos(uint32_t size)
+  {
+    if (size + read_pos_ > total_size_.load()) {
+      read_pos_ = total_size_.load();
+    } else {
+      read_pos_ += size;
+    }
+  }
+
+  /* ================ Part 2: write_xxx and read_xxx ================ */
+  // write @buf with length @len into this bytestream
+  int write_buf(const uint8_t *buf, const uint32_t len)
+  {
+    int ret = common::E_OK;
+    uint32_t write_len = 0;
+    while (write_len < len) {
+      if (RET_FAIL(prepare_space())) {
+          std::cout<<"write_buf error "<< ret <<std::endl;
+        return ret;
+      }
+      uint32_t remainder = page_size_ - (total_size_.load() % page_size_);
+      uint32_t copy_len = remainder < (len - write_len) ? remainder : (len - write_len);
+      memcpy(tail_.load()->buf_ + total_size_.load() % page_size_, buf + write_len, copy_len);
+      total_size_.atomic_aaf(copy_len);
+      write_len += copy_len;
+    }
+    return ret;
+  }
+
+  // read @want_len bytes to @buf, @read_len indicates real len we read.
+  // if ByteStream do not have so many bytes, it will return E_PARTIAL_READ if
+  // no other error occure.
+  int read_buf(uint8_t *buf, const uint32_t want_len, uint32_t &read_len)
+  {
+    int ret = common::E_OK;
+    bool partial_read = (read_pos_ + want_len > total_size_.load());
+    uint32_t want_len_limited = partial_read ? (total_size_.load() - read_pos_) : want_len;
+    read_len = 0;
+    while (read_len < want_len_limited) {
+      if (RET_FAIL(check_space())) {
+        return ret;
+      }
+      uint32_t remainder = page_size_ - (read_pos_ % page_size_);
+      uint32_t copy_len = remainder < want_len_limited - read_len ? remainder : want_len_limited - read_len;
+      memcpy(buf + read_len, read_page_->buf_ + (read_pos_ % page_size_), copy_len);
+      read_len += copy_len;
+      read_pos_ += copy_len;
+    }
+    return partial_read ? common::E_PARTIAL_READ : common::E_OK;
+  }
+
+  FORCE_INLINE int write_buf(const char *buf, const uint32_t len)
+  {
+    return write_buf((const uint8_t*)buf, len);
+  }
+  FORCE_INLINE int read_buf(char *buf, const uint32_t want_len, uint32_t &read_len)
+  {
+    return read_buf((uint8_t*)buf, want_len, read_len);
+  }
+  FORCE_INLINE int read_buf(char *buf, const int32_t want_len, int32_t &read_len)
+  {
+    return read_buf((uint8_t*)buf, (uint32_t&)want_len, (uint32_t&)read_len);
+  }
+
+  void purge_prev_pages(int purge_page_count = INT32_MAX)
+  {
+    Page *cur = head_.load();
+    while (cur != tail_.load() && purge_page_count-- > 0) {
+      Page *next = cur->next_.load();
+      allocator_.free(cur);
+      cur = next;
+    }
+    head_.store(cur);
+  }
+
+  /* ================ Part 3: writing internal buffers ================ */
+  /*
+   * use @acquire_buf function to get a buf, caller will fill the buf, and
+   * after filling, caller use @buffer_used to notice ByteStream to update
+   * internal variables.
+   *
+   * Note: it should be used in single thread.
+   */
+  struct Buffer
+  {
+    char *buf_;
+    uint32_t len_;
+
+    Buffer() : buf_(nullptr), len_(0) {}
+  };
+
+  Buffer acquire_buf()
+  {
+    Buffer b;
+    if (common::E_OK != prepare_space()) {
+      return b;
+    }
+    b.buf_ = (char*)(tail_.load()->buf_ + (total_size_.load() % page_size_));
+    b.len_ = page_size_ - (total_size_.load() % page_size_);
+    return b;
+  }
+
+  void buffer_used(uint32_t used_bytes)
+  {
+    ASSERT(used_bytes >= 1);
+    // would not span page
+    ASSERT((total_size_.load() / page_size_) == ((total_size_.load() + used_bytes - 1) / page_size_));
+    total_size_.atomic_aaf(used_bytes);
+  }
+
+  /* ================ Part 4: reading internal buffers ================ */
+  /*
+   * one-shot read iterator
+   * Do not use it if the host_ is still writing
+   */
+  struct BufferIterator
+  {
+    const ByteStream &host_;
+    Page *cur_;
+    Page *end_;
+    int64_t total_size_;
+    BufferIterator(const ByteStream &bs) : host_(bs)
+    {
+      cur_ = bs.head_.load();
+      end_ = bs.tail_.load();
+      total_size_ = bs.total_size_.load();
+    }
+
+    Buffer get_next_buf()
+    {
+      Buffer b;
+      if (cur_ != nullptr) {
+        b.buf_ = (char*)cur_->buf_;
+        if (cur_ == end_ && host_.total_size_.load() % host_.page_size_ != 0) {
+          b.len_ = host_.total_size_.load() % host_.page_size_;
+        } else {
+          b.len_ = host_.page_size_;
+        }
+        ASSERT(b.len_ > 0);
+        cur_ = cur_->next_.load();
+      }
+      return b;
+    }
+  };
+  BufferIterator init_buffer_iterator() const { return BufferIterator(*this); }
+
+  /*
+   * producer-consumer mode read iterator
+   * Note:
+   * the host ByteStream should be configured as atomically.
+   */
+  struct Consumer
+  {
+    const ByteStream &host_;
+    Page *cur_;
+    uint32_t read_offset_within_cur_page_;
+    int64_t total_end_offset_; // for DEBUG
+
+    Consumer(const ByteStream &bs) : host_(bs)
+    {
+      ASSERT(bs.head_.enable_atomic());
+      cur_ = nullptr;
+      read_offset_within_cur_page_ = 0;
+      total_end_offset_ = 0;
+    }
+
+    Buffer get_next_buf(ByteStream &host)
+    {
+      Buffer b;
+      if (UNLIKELY(host.head_.load() == nullptr)) {
+        // host is empty, return empty buffer.
+        return b;
+      }
+      if (UNLIKELY(cur_ == nullptr)) {
+        // this consumer did not initialiazed.
+        cur_ = host_.head_.load();
+        read_offset_within_cur_page_ = 0;
+      }
+
+      // get tail position <tail_, total_size_> atomically
+      Page *host_end = nullptr;
+      uint32_t host_total_size = 0;
+      while (true) {
+        host_end = host_.tail_.load();
+        host_total_size = host_.total_size_.load();
+        if (host_end == host_.tail_.load()) {
+          break;
+        }
+      }
+
+      while (true) {
+        if (cur_ == host_end) {
+          if (host_total_size % host_.page_size_ == 0) {
+            if (read_offset_within_cur_page_ == host_.page_size_) { 
+              return b;
+            } else {
+              b.buf_ = ((char*)(cur_->buf_)) + read_offset_within_cur_page_;
+              b.len_ = host_.page_size_ - read_offset_within_cur_page_;
+              read_offset_within_cur_page_ = host_.page_size_;
+              total_end_offset_ += b.len_;
+              return b;
+            }
+          } else {
+            if (read_offset_within_cur_page_ == (host_total_size % host_.page_size_)) {
+              return b;
+            } else {
+              b.buf_ = ((char*)(cur_->buf_)) + read_offset_within_cur_page_;
+              b.len_ = (host_total_size % host_.page_size_) - read_offset_within_cur_page_;
+              read_offset_within_cur_page_ = (host_total_size % host_.page_size_);
+              total_end_offset_ += b.len_;
+              return b;
+            }
+          }
+        } else {
+          if (read_offset_within_cur_page_ == host_.page_size_) {
+            cur_ = cur_->next_.load();
+            read_offset_within_cur_page_ = 0;
+          } else {
+            b.buf_ = ((char*)(cur_->buf_)) + read_offset_within_cur_page_;
+            b.len_ = host_.page_size_ - read_offset_within_cur_page_;
+            cur_ = cur_->next_.load();
+            read_offset_within_cur_page_ = 0;
+            total_end_offset_ += b.len_;
+            return b;
+          }
+        }
+      }
+      ASSERT(b.len_ < (1<<30));
+      return b;
+    }
+  };
+
+private:
+  FORCE_INLINE int prepare_space()
+  {
+    int ret = common::E_OK;
+    if (UNLIKELY(tail_.load() == nullptr || total_size_.load() % page_size_ == 0)) {
+      Page *p = nullptr;
+      if (RET_FAIL(alloc_page(p))) {
+        return ret;
+      }
+    } else {
+      // do nothing
+    }
+    return ret;
+  }
+
+  FORCE_INLINE int check_space()
+  {
+    if (UNLIKELY(read_pos_ >= total_size_.load())) {
+      return common::E_OUT_OF_RANGE;
+    }
+    if (UNLIKELY(read_page_ == nullptr)) {
+      read_page_ = head_.load();
+    } else if (UNLIKELY(read_pos_ % page_size_ == 0)) {
+      read_page_ = read_page_->next_.load();
+    }
+    if (UNLIKELY(read_page_ == nullptr)) {
+      return common::E_OUT_OF_RANGE;
+    }
+    return common::E_OK;
+  }
+
+  FORCE_INLINE int alloc_page(Page *&p)
+  {
+    int ret = common::E_OK;
+    char *buf = (char*)allocator_.alloc(page_size_ + sizeof(Page), mid_);
+    if (UNLIKELY(buf == nullptr)) {
+      ret = common::E_OOM;
+    } else {
+      p = new (buf) Page(head_.enable_atomic());
+      p->next_.store(nullptr);
+      if (head_.load()) {
+        tail_.load()->next_.store(p);
+        tail_.store(p);
+      } else {
+        head_.store(p);
+        tail_.store(p);
+      }
+    }
+    // printf("\nByteStream alloc_page, this=%p, new_page=%p\n", this, p);
+    return ret;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(ByteStream);
+private:
+  BaseAllocator &allocator_;
+  OptionalAtomic<Page*> head_;
+  OptionalAtomic<Page*> tail_;
+  Page* read_page_; // only one thread is allow to read this ByteStream
+  OptionalAtomic<uint32_t> total_size_; // total size in byte
+  uint32_t read_pos_; // current read position
+  uint32_t marked_read_pos_; // current read position
+  uint32_t page_size_;
+  AllocModID mid_;
+  Page wrapped_page_;
+};
+
+FORCE_INLINE int merge_byte_stream(ByteStream &sea, ByteStream &river, bool purge_river = false)
+{
+  int ret = common::E_OK;
+  ByteStream::BufferIterator buf_iter = river.init_buffer_iterator();
+  while (true) {
+    ByteStream::Buffer buf = buf_iter.get_next_buf();
+    if (buf.buf_ == nullptr) {
+      break;
+    } else {
+      if (RET_FAIL(sea.write_buf(buf.buf_, buf.len_))) {
+        break;
+      }
+    }
+    if (purge_river) {
+      river.purge_prev_pages(1);
+    }
+  }
+  return ret;
+}
+
+FORCE_INLINE uint32_t get_var_uint_size(uint32_t ui32)  // return: the length of usigned number after varint encoding.
+{
+  uint32_t bytes = 0;
+  while ((ui32 & 0xFFFFFF80) != 0) {
+    bytes++;
+    ui32 = ui32 >> 7;
+  }
+  return ++bytes;
+}
+
+#if DEBUG_SE
+FORCE_INLINE void DEBUG_print_byte_stream(const char *print_tag, ByteStream &b)
+{
+  const int32_t WRAP_COUNT = 16;
+  int32_t print_char_count = 0;
+  ByteStream::BufferIterator buf_iter = b.init_buffer_iterator();
+  while (true) {
+    ByteStream::Buffer buf = buf_iter.get_next_buf();
+    if (buf.buf_ == nullptr) {
+      break;
+    } else {
+      // print_hex(buf.buf_, buf.len_);
+      printf("\n %s: buf.buf_=%p, buf.len_=%u\n", print_tag, buf.buf_, buf.len_);
+      for (uint32_t i = 0; i < buf.len_; i++) {
+        if (print_char_count++ % WRAP_COUNT == 0) {
+          printf("\n %s offset=0x%05x :  ", print_tag, print_char_count - 1);
+        }
+        printf("%02x ", (uint8_t)buf.buf_[i]);
+      }
+    }
+  }
+  printf("\n\n");
+}
+
+FORCE_INLINE void DEBUG_hex_dump_buf(const char *print_tag, const char *buf, int32_t len)
+{
+  const int32_t WRAP_COUNT = 16;
+  for (int i = 0; i < len; i++) {
+    if (i % WRAP_COUNT == 0) {
+      printf("\n%s", print_tag);
+    }
+    printf("%02x ", (uint8_t)(buf[i]));
+  }
+  printf("\n");
+}
+#endif // ifndef NDEBUG
+
+class SerializationUtil
+{
+public:
+  FORCE_INLINE static int write_ui8(uint8_t ui8, ByteStream &out)
+  {
+    return out.write_buf(&ui8, 1);
+  }
+  FORCE_INLINE static int write_ui16(uint16_t ui16, ByteStream &out)
+  {
+    uint8_t buf[2];
+    buf[0] = (uint8_t)((ui16 >> 8) & 0xFF);
+    buf[1] = (uint8_t)((ui16     ) & 0xFF);
+    return out.write_buf(buf, 2);
+  }
+  FORCE_INLINE static int write_ui32(uint32_t ui32, ByteStream &out)
+  {
+    uint8_t buf[4];
+    buf[0] = (uint8_t)((ui32 >> 24) & 0xFF);
+    buf[1] = (uint8_t)((ui32 >> 16) & 0xFF);
+    buf[2] = (uint8_t)((ui32 >>  8) & 0xFF);
+    buf[3] = (uint8_t)((ui32      ) & 0xFF);
+    return out.write_buf(buf, 4);
+  }
+  FORCE_INLINE static int write_ui64(uint64_t ui64, ByteStream &out)
+  {
+    // big-endian: most signification byte at smaller address
+    // refer to tsfile.utils.BytesUtil
+    uint8_t buf[8];
+    buf[0] = (uint8_t)((ui64 >> 56) & 0xFF);
+    buf[1] = (uint8_t)((ui64 >> 48) & 0xFF);
+    buf[2] = (uint8_t)((ui64 >> 40) & 0xFF);
+    buf[3] = (uint8_t)((ui64 >> 32) & 0xFF);
+    buf[4] = (uint8_t)((ui64 >> 24) & 0xFF);
+    buf[5] = (uint8_t)((ui64 >> 16) & 0xFF);
+    buf[6] = (uint8_t)((ui64 >>  8) & 0xFF);
+    buf[7] = (uint8_t)((ui64      ) & 0xFF);
+    return out.write_buf(buf, 8);
+  }
+
+  FORCE_INLINE static int read_ui8(uint8_t &ui8, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    char buf[1];
+    uint32_t read_len = 0;
+    ret = in.read_buf(buf, 1, read_len);
+    ui8 = (uint8_t)buf[0];
+    return ret;
+  }
+  FORCE_INLINE static int read_ui16(uint16_t &ui16, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    uint8_t buf[2];
+    uint32_t read_len = 0;
+    if (RET_FAIL(in.read_buf(buf, 2, read_len))) {
+      return ret;
+    }
+    ui16 = buf[0];
+    ui16 = (ui16 << 8) | buf[1];
+    return ret;
+  }
+  FORCE_INLINE static int read_ui32(uint32_t &ui32, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    uint8_t buf[4];
+    uint32_t read_len = 0;
+    if (RET_FAIL(in.read_buf(buf, 4, read_len))) {
+      return ret;
+    }
+    ui32 = buf[0];
+    ui32 = (ui32 << 8) | (buf[1] & 0xFF);
+    ui32 = (ui32 << 8) | (buf[2] & 0xFF);
+    ui32 = (ui32 << 8) | (buf[3] & 0xFF);
+    return ret;
+  }
+  FORCE_INLINE static int read_ui64(uint64_t &ui64, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    uint8_t buf[8];
+    uint32_t read_len = 0;
+    if (RET_FAIL(in.read_buf(buf, 8, read_len))) {
+      return ret;
+    }
+    ui64 = buf[0];
+    ui64 = (ui64 << 8) | (buf[1] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[2] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[3] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[4] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[5] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[6] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[7] & 0xFF);
+    return ret;
+  }
+  // caller guarantee buffer has at least 1 byte
+  FORCE_INLINE static uint8_t read_ui8(char *buffer)
+  {
+    return *(uint8_t*)buffer;
+  }
+
+  // caller guarantee buffer has at least 2 bytes
+  FORCE_INLINE static uint16_t read_ui16(char *buffer)
+  {
+    uint8_t *buf = (uint8_t*)buffer;
+    uint16_t ui16 = buf[0];
+    ui16 = (ui16 << 8) | (buf[1] & 0xFF);
+    return ui16;
+  }
+  // caller guarantee buffer has at least 4 bytes
+  FORCE_INLINE static uint32_t read_ui32(char *buffer)
+  {
+    uint8_t *buf = (uint8_t*)buffer;
+    uint32_t ui32 = buf[0];
+    ui32 = (ui32 << 8) | (buf[1] & 0xFF);
+    ui32 = (ui32 << 8) | (buf[2] & 0xFF);
+    ui32 = (ui32 << 8) | (buf[3] & 0xFF);
+    return ui32;
+  }
+  // caller guarantee buffer has at least 8 bytes
+  FORCE_INLINE static uint64_t read_ui64(char *buffer)
+  {
+    uint8_t *buf = (uint8_t*)buffer;
+    uint64_t ui64 = buf[0];
+    ui64 = (ui64 << 8) | (buf[1] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[2] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[3] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[4] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[5] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[6] & 0xFF);
+    ui64 = (ui64 << 8) | (buf[7] & 0xFF);
+    return ui64;
+  }
+
+  FORCE_INLINE static int write_float(float f, ByteStream &out)
+  {
+    uint8_t bytes[4];
+    float_to_bytes(f, bytes);
+    return out.write_buf(bytes, 4);
+  }
+  FORCE_INLINE static int read_float(float &f, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    uint8_t bytes[4];
+    uint32_t read_len = 0;
+    if (RET_FAIL(in.read_buf(bytes, 4, read_len))) {
+    } else if (read_len != 4) {
+      ret = common::E_BUF_NOT_ENOUGH;
+    } else {
+      f = bytes_to_float(bytes);
+    }
+    return ret;
+  }
+  FORCE_INLINE static float read_float(char *buffer)
+  {
+    uint8_t *buf = (uint8_t*)buffer;
+    return bytes_to_float(buf);
+  }
+  FORCE_INLINE static int write_double(double d, ByteStream &out)
+  {
+    uint8_t bytes[8];
+    double_to_bytes(d, bytes);
+    return out.write_buf(bytes, 8);
+  }
+  FORCE_INLINE static int read_double(double &d, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    uint32_t read_len = 0;
+    uint8_t bytes[8];
+    if (RET_FAIL(in.read_buf(bytes, 8, read_len))) {
+    } else if (read_len != 8) {
+      ret = common::E_BUF_NOT_ENOUGH;
+    } else {
+      d = bytes_to_double(bytes);
+    }
+    return ret;
+  }
+  FORCE_INLINE static double read_double(char *buffer)
+  {
+    uint8_t *buf = (uint8_t*)buffer;
+    return bytes_to_double(buf);
+  }
+
+  FORCE_INLINE static int write_i8(int8_t i8, ByteStream &out) { return write_ui8((uint8_t)i8, out); }
+  FORCE_INLINE static int write_i16(int16_t i16, ByteStream &out) { return write_ui16((uint16_t)i16, out); }
+  FORCE_INLINE static int write_i32(int32_t i32, ByteStream &out) { return write_ui32((uint32_t)i32, out); }
+  FORCE_INLINE static int write_i64(int64_t i64, ByteStream &out) { return write_ui64((uint64_t)i64, out); }
+
+  FORCE_INLINE static int read_i8(int8_t &i8, ByteStream &in) { return read_ui8((uint8_t&)i8, in); }
+  FORCE_INLINE static int read_i16(int16_t &i16, ByteStream &in) { return read_ui16((uint16_t&)i16, in); }
+  FORCE_INLINE static int read_i32(int32_t &i32, ByteStream &in) { return read_ui32((uint32_t&)i32, in); }
+  FORCE_INLINE static int read_i64(int64_t &i64, ByteStream &in) { return read_ui64((uint64_t&)i64, in); }
+
+  // TODO more test on var_xxx
+  FORCE_INLINE static int do_write_var_uint(uint32_t ui32, ByteStream &out)
+  {
+    int ret = common::E_OK;
+    while ((ui32 & 0xFFFFFF80) != 0) {
+      if (RET_FAIL(write_ui8((ui32 & 0x7F) | 0x80, out))) {
+        return ret;
+      }
+      ui32 = ui32 >> 7;
+    }
+    return write_ui8(ui32 & 0x7F, out);
+  }
+  FORCE_INLINE static int do_write_var_uint(uint32_t ui32, char *out_buf, const uint32_t out_buf_len)
+  {
+    uint32_t offset = 0;
+    while ((ui32 & 0xFFFFFF80) != 0) {
+      if (offset >= out_buf_len) {
+        return common::E_BUF_NOT_ENOUGH;
+      }
+      *(out_buf + offset) = (ui32 & 0x7F) | 0x80;
+      ui32 = ui32 >> 7;
+      offset++;
+    }
+    if (offset >= out_buf_len) {
+      return common::E_BUF_NOT_ENOUGH;
+    }
+    *(out_buf + offset) = (ui32 & 0x7F);
+    return common::E_OK;
+  }
+  FORCE_INLINE static int do_read_var_uint(uint32_t &ui32, ByteStream &in)
+  {
+    // Follow readUnsignedVarInt in ReadWriteForEncodingUtils.java
+    int ret = common::E_OK;
+    ui32 = 0;
+    int i = 0;
+    uint8_t ui8 = 0;
+    if (RET_FAIL(read_ui8(ui8, in))) {
+      return ret;
+    }
+    while (ui8 != 0xF && (ui8 & 0x80) != 0) {
+      ui32 = ui32 | ((ui8 &0x7F) << i);
+      i = i + 7;
+      if (RET_FAIL(read_ui8(ui8, in))) {
+        return ret;
+      }
+    }
+    ui32 = ui32 | (ui8 << i);
+    return ret;
+  }
+  FORCE_INLINE static int do_read_var_uint(uint32_t &ui32, char *in_buf, int in_buf_len, int *ret_offset)
+  {
+    ui32 = 0;
+    int i = 0;
+    uint8_t ui8 = 0;
+    int offset = 0;
+    if (offset < in_buf_len) {
+      ui8 = *(uint8_t*)(in_buf + offset);
+      offset++;
+    } else {
+      return common::E_BUF_NOT_ENOUGH;
+    }
+    while (ui8 != 0xF && (ui8 & 0x80) != 0) {
+      ui32 = ui32 | ((ui8 &0x7F) << i);
+      i = i + 7;
+      if (offset < in_buf_len) {
+        ui8 = *(uint8_t*)(in_buf + offset);
+        offset++;
+      } else {
+        return common::E_BUF_NOT_ENOUGH;
+      }
+    }
+    ui32 = ui32 | (ui8 << i);
+    if (ret_offset != nullptr) {
+      *ret_offset = offset;
+    }
+    return common::E_OK;
+  }
+  FORCE_INLINE static int write_var_int(int32_t i32, ByteStream &out)
+  {
+    // TODO 8byte to 4byte.
+    // but in IoTDB java, it has only write_var_uint(i32)
+    i32 = i32 << 1;
+    return do_write_var_uint((uint32_t)i32, out);
+  }
+  FORCE_INLINE static int read_var_int(int32_t &i32, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    uint32_t ui32;
+    if (RET_FAIL(do_read_var_uint(ui32, in))) {
+    } else {
+      i32 = (int32_t)(ui32 >> 1);
+    }
+    return ret;
+  }
+  FORCE_INLINE static int write_var_uint(uint32_t ui32, ByteStream &out) { return do_write_var_uint(ui32, out); } 
+  FORCE_INLINE static int write_var_uint(uint32_t ui32, char *out_buf, const uint32_t out_buf_len)
+  {
+    return do_write_var_uint(ui32, out_buf, out_buf_len);
+  }
+  FORCE_INLINE static int read_var_uint(uint32_t &ui32, ByteStream &in) { return do_read_var_uint(ui32, in); }
+  FORCE_INLINE static int read_var_uint(uint32_t &ui32, char *in_buf, int in_buf_len, int *ret_offset = nullptr)
+  {
+    return do_read_var_uint(ui32, in_buf, in_buf_len, ret_offset);
+  }
+
+  FORCE_INLINE static int write_str(const std::string &str, ByteStream &out)
+  {
+    int ret = common::E_OK;
+    if (RET_FAIL(write_var_int(((int32_t)str.size()), out))) {
+    } else if (RET_FAIL(out.write_buf(str.c_str(), str.size()))) {
+    }
+    return ret;
+  }
+  FORCE_INLINE static int read_str(std::string &str, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    int32_t len = 0;
+    int32_t read_len = 0;
+    if (RET_FAIL(read_var_int(len, in))) {
+    } else {
+      char *tmp_buf = (char*)malloc(len + 1);
+      tmp_buf[len] = '\0';
+      if (RET_FAIL(in.read_buf(tmp_buf, len, read_len))) {
+      } else if (len != read_len) {
+        ret = E_BUF_NOT_ENOUGH;
+      } else {
+        str = std::string(tmp_buf);
+      }
+      free(tmp_buf);
+    }
+    return ret;
+  }
+  FORCE_INLINE static int write_mystring(const String &str, ByteStream &out)
+  {
+    int ret = common::E_OK;
+    if (RET_FAIL(write_var_int(str.len_, out))) {
+    } else if (RET_FAIL(out.write_buf(str.buf_, str.len_))) {
+    }
+    return ret;
+  }
+  FORCE_INLINE static int read_mystring(String &str, common::PageArena *pa, ByteStream &in)
+  {
+    int ret = common::E_OK;
+    int32_t len = 0;
+    int32_t read_len = 0;
+    if (RET_FAIL(read_var_int(len, in))) {
+    } else {
+      char *buf = (char*)pa->alloc(len);
+      if (IS_NULL(buf)) {
+        ret = common::E_OOM;
+      } else {
+        if (RET_FAIL(in.read_buf(buf, len, read_len))) {
+        } else if (len != read_len) {
+          ret = E_BUF_NOT_ENOUGH;
+        } else {
+          str.buf_ = buf;
+          str.len_ = len;
+        }
+      }
+    }
+    return ret;
+  }
+  FORCE_INLINE static int write_char(char ch, ByteStream &out) { return write_ui8(ch, out); }
+  FORCE_INLINE static int read_char(char &ch, ByteStream &in)  { return read_ui8((uint8_t&)ch, in); }
+};
+
+FORCE_INLINE bool deserialize_buf_not_enough(int ret)
+{
+  return ret == E_OUT_OF_RANGE || ret == E_PARTIAL_READ;
+}
+FORCE_INLINE char *get_bytes_from_bytestream(ByteStream &bs)
+{
+  if (bs.total_size() == 0) {
+    return nullptr;
+  }
+  uint32_t size = bs.total_size();
+  char *ret_buf = (char*)malloc(size);
+  if (ret_buf == nullptr) {
+    return nullptr;
+  }
+
+  ByteStream::BufferIterator buf_iter = bs.init_buffer_iterator();
+  uint32_t offset = 0;
+  while (true) {
+    ByteStream::Buffer buf = buf_iter.get_next_buf();
+    if (buf.buf_ == nullptr) {
+      break;
+    } else {
+      assert(offset + buf.len_ <= size);
+      memcpy(ret_buf + offset, buf.buf_, buf.len_);
+      offset += buf.len_;
+    }
+  }
+  assert(offset == size);
+  return ret_buf;
+}
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_ALLOCATOR_BYTE_STREAM_H
+
diff --git a/cpp/tsfile/src/common/allocator/mem_alloc.cc b/cpp/tsfile/src/common/allocator/mem_alloc.cc
new file mode 100644
index 00000000..5f1a16e2
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/mem_alloc.cc
@@ -0,0 +1,236 @@
+
+#include <iostream>
+#include <string.h>
+#include <execinfo.h>
+
+
+#include "stdlib.h"
+#include "stdio.h"
+#include "alloc_base.h"
+#include "../util_define.h"
+#include "../logger/elog.h"
+
+namespace timecho
+{
+namespace common
+{
+
+const char *g_mod_names[__LAST_MOD_ID] = {
+  /*  0 */ "DEFAULT",
+  /*  1 */ "MEMTABLE",
+  /*  2 */ "SCHEMA",
+  /*  3 */ "SQL",
+  /*  4 */ "NET",
+  /*  5 */ "NET_DATA",
+  /*  6 */ "TVLIST_DATA",
+  /*  7 */ "TVLIST_OBJ",
+  /*  8 */ "TSBLOCK",
+  /*  9 */ "CONTAINER",
+  /* 10 */ "TSSTORE_OBJ",
+  /* 11 */ "FLUSH_TASK_OBJ",
+  /* 12 */ "PAGE_WRITER_OUTPUT_STREAM",
+  /* 13 */ "CW_PAGES_DATA",
+  /* 14 */ "CHUNK_WRITER_OBJ",
+  /* 15 */ "STATISTIC_OBJ",
+  /* 16 */ "ENCODER_OBJ",
+  /* 17 */ "DECODER_OBJ",
+  /* 18 */ "TSFILE_WRITER_META",
+  /* 19 */ "TSFILE_WRITE_STREAM",
+  /* 20 */ "TIMESERIES_INDEX_OBJ",
+  /* 21 */ "BLOOM_FILTER",
+  /* 22 */ "OPEN_FILE_OBJ",
+  /* 23 */ "TSFILE_READER",
+  /* 24 */ "CHUNK_READER",
+  /* 25 */ "COMPRESSOR_OBJ",
+  /* 26 */ "ARRAY",
+  /* 27 */ "HASH_TABLE",
+};
+
+const uint32_t HEADER_SIZE_4B = 4;
+const uint32_t HEADER_SIZE_8B = 8;
+
+void *mem_alloc(uint32_t size, AllocModID mid)
+{
+  // use 7bit at most
+  ASSERT(mid <= 127);
+
+  if (size <= 0xFFFFFF) {
+    // use 3B size + 1B mod
+    char *p = (char*)malloc(size + HEADER_SIZE_4B);
+    if (UNLIKELY(p == nullptr)) {
+      std::cout<<"alloc filed for size " << size + HEADER_SIZE_4B << std::endl;
+      return nullptr;
+    } else {
+      uint32_t header = (size << 8) | ((uint32_t)mid);
+      *((uint32_t*)p) = header;
+      ModStat::get_instance().update_alloc(mid, size);
+      // cppcheck-suppress memleak
+      // cppcheck-suppress unmatchedSuppression
+      return p + HEADER_SIZE_4B;
+    }
+  } else {
+    char *p = (char*)malloc(size + HEADER_SIZE_8B);
+    if (UNLIKELY(p == nullptr)) {
+        std::cout<<"alloc big filed for size " << size + HEADER_SIZE_4B << std::endl;
+      return nullptr;
+    } else {
+      uint64_t large_size = size;
+      uint64_t header = ((large_size) << 8) | (((uint32_t)mid) | (0x80));
+      uint32_t low4b = (uint32_t)(header & 0xFFFFFFFF);
+      uint32_t high4b = (uint32_t)(header >> 32);
+      *(uint32_t*)p = high4b;
+      *(uint32_t*)(p + 4) = low4b;
+      ModStat::get_instance().update_alloc(mid, size);
+      // cppcheck-suppress unmatchedSuppression
+      // cppcheck-suppress memleak
+      return p + HEADER_SIZE_8B;
+    }
+  }
+}
+
+void printCallers()
+{
+  int layers = 0, i = 0;
+  char **symbols = NULL;
+
+  const int64_t MAX_FRAMES = 32;
+
+  void *frames[MAX_FRAMES];
+  memset(frames, 0, sizeof(frames));
+  layers = backtrace(frames, MAX_FRAMES);
+  for (i = 0; i < layers; i++) {
+    printf("Layer %d: %p\n", i, frames[i]);
+  }
+  printf("------------------\n");
+
+  symbols = backtrace_symbols(frames, layers);
+  if (symbols) {
+    for (i = 0; i < layers; i++) {
+      printf("SYMBOL layer %d: %s\n", i, symbols[i]);
+    }
+    free(symbols);
+  } else {
+    printf("Failed to parse function names\n");
+  }
+}
+
+void mem_free(void *ptr)
+{
+  // try as 4Byte header
+  char *p = (char*)ptr;
+  uint32_t header = *(uint32_t*)(p - HEADER_SIZE_4B);
+  if ((header & 0x80) == 0) {
+    // 4Byte header
+    uint32_t size = header >> 8;
+    AllocModID mid = (AllocModID)(header & 0x7F);
+    ModStat::get_instance().update_free(mid, size);
+    ::free(p - HEADER_SIZE_4B);
+  } else {
+    // 8Byte header
+    uint64_t header8b = ((uint64_t)(*(uint32_t*)(p - 4))) | ((uint64_t)(*(uint32_t*)(p - 8)) << 32);
+    AllocModID mid = (AllocModID)(header8b & 0x7F);
+    uint32_t size = (uint32_t)(header8b >> 8);
+    ModStat::get_instance().update_free(mid, size);
+    ::free(p - HEADER_SIZE_8B);
+  }
+}
+
+void *mem_realloc(void *ptr, uint32_t size)
+{
+  AllocModID mid_org;
+  uint32_t size_org;
+  char *p = (char*)ptr;
+  uint32_t header_org = *(uint32_t*)(p - HEADER_SIZE_4B);// try as 4Byte header
+  if ((header_org & 0x80) == 0) {
+    // header_org is 4byte 
+    size_org = header_org >> 8;
+    mid_org = (AllocModID)(header_org & 0x7F);
+    if (size <= 0xFFFFFF) {
+      p = (char *) realloc(p - HEADER_SIZE_4B, size + HEADER_SIZE_4B);
+      if (UNLIKELY(p == nullptr)) {
+        return nullptr;
+      } else {
+        uint32_t header = (size << 8) | ((uint32_t)mid_org); //size changed
+        *((uint32_t*)p) = header;
+        ModStat::get_instance().update_alloc(mid_org, int32_t(size) - int32_t(size_org));
+        return p + HEADER_SIZE_4B;
+      }
+    } else { // size > 0xFFFFFF, realloc(os_p, size + header_len)
+      p = (char *) realloc(p - HEADER_SIZE_4B, size + HEADER_SIZE_8B);
+      if (UNLIKELY(p == nullptr)) { 
+        return nullptr;
+      } else {
+        std::memmove(p + HEADER_SIZE_8B, p + HEADER_SIZE_4B, size_org);
+        // reconstruct 8-byte header
+        uint64_t large_size = size;
+        uint64_t header = ((large_size) << 8) | (((uint32_t)mid_org) | (0x80));
+        uint32_t low4b = (uint32_t)(header & 0xFFFFFFFF);
+        uint32_t high4b = (uint32_t)(header >> 32);
+        *(uint32_t*)p = high4b;
+        *(uint32_t*)(p + 4) = low4b;
+        ModStat::get_instance().update_alloc(mid_org, int32_t(size) - int32_t(size_org));  
+        return p + HEADER_SIZE_8B;
+      }
+    }
+  } else { // header_org is 8byte
+    uint64_t header = ((uint64_t)(*(uint32_t*)(p - 4))) | ((uint64_t)(*(uint32_t*)(p - 8)) << 32); // 8Byte header
+    mid_org = (AllocModID)(header & 0x7F);
+    size_org = (uint32_t)(header >> 8);
+    if (size <= 0xFFFFFF) {
+      uint32_t save_data = *(uint32_t*)(p  - HEADER_SIZE_8B + HEADER_SIZE_4B + size);
+      p = (char *) realloc(p - HEADER_SIZE_8B, size + HEADER_SIZE_4B);
+      if (UNLIKELY(p == nullptr)) {
+        return nullptr;
+      } else {
+        std::memmove(p + HEADER_SIZE_4B, p + HEADER_SIZE_8B, size - HEADER_SIZE_4B);
+        // reconstruct 4-byte header
+        uint32_t header4b = (size << 8) | (((uint32_t)mid_org));
+        *((uint32_t*)p) = header4b;
+        // reconstruct data
+        *(uint32_t*)((char*)p + size - 4) = save_data;
+        ModStat::get_instance().update_alloc(mid_org, int32_t(size) - int32_t(size_org));  
+        return p + HEADER_SIZE_4B;
+      }
+    } else {
+      p = (char *) realloc(p - HEADER_SIZE_8B, size + HEADER_SIZE_8B);
+      if (UNLIKELY(p == nullptr)) {
+        return nullptr;
+      } else {
+        uint64_t large_size = size;
+        uint64_t header8b = ((large_size) << 8) | (((uint32_t)mid_org) | (0x80));
+        uint32_t low4b = (uint32_t)(header8b & 0xFFFFFFFF);
+        uint32_t high4b = (uint32_t)(header8b >> 32);
+        *(uint32_t*)p = high4b;
+        *(uint32_t*)(p + 4) = low4b;
+        ModStat::get_instance().update_alloc(mid_org, int32_t(size) - int32_t(size_org));
+        return p + HEADER_SIZE_8B;
+      }
+    }
+  }
+}
+
+void ModStat::init()
+{
+  stat_arr_ = (int32_t*)(::malloc(ITEM_SIZE * ITEM_COUNT));
+  for (int8_t i = 0; i < __LAST_MOD_ID; i++) {
+    int32_t *item = get_item(i);
+    *item = 0;
+  }
+}
+
+void ModStat::destroy()
+{
+  ::free(stat_arr_);
+}
+
+// TODO return to SQL
+void ModStat::print_stat()
+{
+  //
+}
+
+BaseAllocator g_base_allocator;
+
+} // end namespace common
+} // end namespace timecho
+
diff --git a/cpp/tsfile/src/common/allocator/my_string.h b/cpp/tsfile/src/common/allocator/my_string.h
new file mode 100644
index 00000000..4deaafd2
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/my_string.h
@@ -0,0 +1,143 @@
+#ifndef COMMON_ALLOCATOR_MY_STRING_H
+#define COMMON_ALLOCATOR_MY_STRING_H
+
+#include <string.h>
+#include <iostream>
+
+#include "common/allocator/page_arena.h"
+#include "common/errno_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+// String that use PageArena
+struct String
+{
+  char *buf_;
+  uint32_t len_;
+
+  String() : buf_(nullptr), len_(0) {}
+  String(char *buf, uint32_t len) : buf_(buf), len_(len) {}
+  FORCE_INLINE bool is_null() const
+  {
+    return buf_ == nullptr && len_ == 0;
+  }
+  FORCE_INLINE void reset()
+  {
+    len_ = 0;
+    buf_ = nullptr;
+  }
+  FORCE_INLINE int dup_from(const std::string &str, common::PageArena &pa)
+  {
+    len_ = str.size();
+    if (UNLIKELY(len_ == 0)) {
+      return common::E_OK;
+    }
+    buf_ = pa.alloc(len_);
+    if (IS_NULL(buf_)) {
+      return common::E_OOM;
+    }
+    memcpy(buf_, str.c_str(), len_);
+    return common::E_OK;
+  }
+  FORCE_INLINE int dup_from(const String &str, common::PageArena &pa)
+  {
+    len_ = str.len_;
+    if (UNLIKELY(len_ == 0)) {
+      return common::E_OK;
+    }
+    buf_ = pa.alloc(len_);
+    if (IS_NULL(buf_)) {
+      return common::E_OOM;
+    }
+    memcpy(buf_, str.buf_, len_);
+    return common::E_OK;
+  }
+  FORCE_INLINE int build_from(const String &s1, const String &s2, common::PageArena &pa)
+  {
+    len_ = s1.len_ + s2.len_;
+    buf_ = pa.alloc(len_);
+    if (IS_NULL(buf_)) {
+      return common::E_OOM;
+    }
+    memcpy(buf_, s1.buf_, s1.len_);
+    memcpy(buf_ + s1.len_, s2.buf_, s2.len_);
+    return common::E_OK;
+  }
+  FORCE_INLINE void shallow_copy_from(const String &src)
+  {
+    buf_ = src.buf_;
+    len_ = src.len_;
+  }
+  FORCE_INLINE bool equal_to(const String &that) const
+  {
+    return  (len_ == 0 && that.len_ == 0)
+            || ((len_ == that.len_) && (0 == memcmp(buf_, that.buf_, len_)));
+  }
+
+  // FORCE_INLINE bool equal_to(const std::string &that)
+  // {
+  //   return (len_ == 0 && that.size() == 0)
+  //          || ((len_ == that.len_) && (0 == memcmp(buf_, that.c_str(), len_)));
+  // }
+
+  // strict less than. If @this equals to @that, return false.
+  FORCE_INLINE bool less_than(const String &that) const
+  {
+    if (len_ == 0 || that.len_ == 0) {
+      return false;
+    }
+    uint32_t min_len = std::min(len_, that.len_);
+    int cmp_res = memcmp(buf_, that.buf_, min_len);
+    if (cmp_res < 0) {
+      return true;
+    } else if (cmp_res > 0) {
+      return false;
+    } else {
+      return len_ < that.len_;
+    }
+  }
+
+  // return = 0, if this = that
+  // return < 0, if this < that
+  // return > 0, if this > that
+  FORCE_INLINE int compare(const String &that) const
+  {
+    if (len_ == 0 || that.len_ == 0) {
+      return 0;
+    }
+    uint32_t min_len = std::min(len_, that.len_);
+    int cmp_res = memcmp(buf_, that.buf_, min_len);
+    if (cmp_res == 0) {
+      return len_ - that.len_;
+    } else {
+      return cmp_res;
+    }
+  }
+
+#ifndef NDEBUG
+  friend std::ostream& operator << (std::ostream &os, const String &s)
+  {
+    os << s.len_ << "@";
+    for (uint32_t i = 0; i < s.len_; i++) {
+      os << s.buf_[i];
+    }
+    return os;
+  }
+#endif // ifndef NDEBUG
+};
+
+struct StringLessThan
+{
+  FORCE_INLINE bool operator()(const String &s1, const String &s2) const
+  {
+    return s1.less_than(s2);
+  }
+};
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_ALLOCATOR_MY_STRING_H
diff --git a/cpp/tsfile/src/common/allocator/object_pool.h b/cpp/tsfile/src/common/allocator/object_pool.h
new file mode 100644
index 00000000..c60ae558
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/object_pool.h
@@ -0,0 +1,104 @@
+
+#ifndef COMMON_ALLOCTOR_OBJECT_POOL_H
+#define COMMON_ALLOCTOR_OBJECT_POOL_H
+
+#include "common/allocator/alloc_base.h"
+#include "common/mutex/mutex.h"
+
+namespace timecho
+{
+namespace common
+{
+
+template<class T>
+class ObjectPool
+{
+private:
+  struct ObjectPoolNode
+  {
+    T data_;
+    ObjectPoolNode *next_;
+
+    ObjectPoolNode() : data_(), next_(nullptr) {}
+  };
+
+public:
+  /*
+   * max_cache_count is a soft limitation:
+   */
+  ObjectPool(const uint32_t max_cache_count,
+             const AllocModID mid,
+             BaseAllocator &allocator = g_base_allocator)
+    : max_cache_count_(max_cache_count),
+      cur_alloc_count_(0),
+      mid_(mid),
+      allocator_(allocator),
+      mutex_(),
+      head_(nullptr)
+  {
+    assert(max_cache_count > 1);
+  }
+
+  ~ObjectPool() { destroy(); }
+
+  void destroy()
+  {
+    ObjectPoolNode *cur = head_;
+    while (cur) {
+      head_ = cur->next_;
+      allocator_.free(cur);
+      cur = head_;
+      cur_alloc_count_--;
+    }
+    ASSERT(cur_alloc_count_ == 0);
+  }
+
+  T *alloc()
+  {
+    T *ret_obj = nullptr;
+    common::MutexGuard g(mutex_);
+    if (head_) {
+      ret_obj = &(head_->data_);
+      head_ = head_->next_;
+      return ret_obj;
+    } else {
+      void *buf = allocator_.alloc(sizeof(ObjectPoolNode), mid_);
+      if (UNLIKELY(buf == nullptr)) {
+        return nullptr;
+      }
+      cur_alloc_count_++;
+      ret_obj = &(new (buf) ObjectPoolNode)->data_;
+      return ret_obj;
+    }
+  }
+
+  void free(T* obj)
+  {
+    ASSERT(obj != nullptr);
+    common::MutexGuard g(mutex_);
+    if (cur_alloc_count_ > max_cache_count_) {
+      allocator_.free(obj);
+      cur_alloc_count_--;
+      ASSERT(cur_alloc_count_ >= 0);
+    } else {
+      ObjectPoolNode *n = (ObjectPoolNode*)obj;
+      n->next_ = head_;
+      head_ = n;
+    }
+  }
+
+  uint32_t get_cur_alloc_count() const { return cur_alloc_count_; }
+private:
+  uint32_t max_cache_count_;
+  uint32_t cur_alloc_count_;
+  AllocModID mid_;
+  BaseAllocator allocator_;
+  common::Mutex mutex_;
+  ObjectPoolNode *head_; // freelist head
+};
+
+} // end namspace common
+} // end namespace timecho
+
+#endif // COMMON_ALLOCTOR_OBJECT_POOL_H
+
diff --git a/cpp/tsfile/src/common/allocator/page_arena.cc b/cpp/tsfile/src/common/allocator/page_arena.cc
new file mode 100644
index 00000000..b43bc790
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/page_arena.cc
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include "page_arena.h"
+#include <new> 
+
+namespace timecho
+{
+namespace common
+{
+
+char *PageArena::alloc(uint32_t size)
+{
+  if (LIKELY(size <= page_size_)) {
+    Page *cur_page = dummy_head_.next_;
+    if (LIKELY(cur_page != nullptr)) {
+      char *ret_ptr = cur_page->alloc(size);
+      if (LIKELY(ret_ptr != nullptr)) {
+        return ret_ptr;
+      }
+    }
+
+    /*
+     * cur_page is null OR can not alloc @size from cur_page,
+     * then alloc new page
+     */
+    void *ptr = base_allocator_.alloc(page_size_ + sizeof(Page), mid_);
+    if (UNLIKELY(ptr == nullptr)) {
+      return nullptr;
+    }
+    Page *new_page = new(ptr) Page(page_size_, cur_page);
+    dummy_head_.next_ = new_page;
+    return new_page->alloc(size);
+  } else {
+    void *ptr = base_allocator_.alloc(size + sizeof(Page), mid_);
+    Page *new_page = new(ptr) Page(dummy_head_.next_);
+    dummy_head_.next_ = new_page;
+    return reinterpret_cast<char*>(new_page) + sizeof(Page);
+  }
+}
+
+void PageArena::reset()
+{
+  Page *p = dummy_head_.next_;
+  while (p) {
+    dummy_head_.next_ = p->next_;
+    base_allocator_.free(p);
+    p = dummy_head_.next_;
+  }
+}
+
+} // end namespace common
+} // end namespace timecho
+
diff --git a/cpp/tsfile/src/common/allocator/page_arena.h b/cpp/tsfile/src/common/allocator/page_arena.h
new file mode 100644
index 00000000..d2115411
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/page_arena.h
@@ -0,0 +1,90 @@
+
+#ifndef COMMON_ALLOCATOR_PAGE_ARENA_H
+#define COMMON_ALLOCATOR_PAGE_ARENA_H
+
+#include "alloc_base.h"
+
+namespace timecho
+{
+namespace common
+{
+
+/*
+ * Not Thread Safe
+ */
+class PageArena
+{
+public:
+  explicit PageArena(BaseAllocator &base_allocator = g_base_allocator)
+    : page_size_(0),
+      mid_(__FIRST_MOD_ID),
+      base_allocator_(base_allocator),
+      dummy_head_() {}
+  ~PageArena() { destroy(); }
+  void init(uint32_t page_size, AllocModID mid)
+  {
+    page_size_ = page_size;
+    mid_ = mid;
+  }
+
+  char *alloc(uint32_t size);
+  FORCE_INLINE void destroy() { reset(); }
+  void reset();
+
+#ifdef ENABLE_TEST
+  int TEST_get_page_count() const
+  {
+    int count = 0;
+    Page *p = dummy_head_.next_;
+    while (p) {
+      p = p->next_;
+      count++;
+    }
+    return count;
+  }
+#endif
+
+private:
+  class Page 
+  {
+  public:
+    Page() : next_(nullptr), page_end_(nullptr), cur_alloc_(nullptr) {}
+    explicit Page(Page *next_page) : next_(next_page), page_end_(nullptr), cur_alloc_(nullptr) {}
+    Page(uint32_t page_size, Page *next_page)
+    {
+      next_ = next_page;
+      cur_alloc_ = (char*)this + sizeof(Page);  // equals to (char*)(this+1)
+      page_end_ = cur_alloc_ + page_size;
+    }
+    INLINE char *alloc(uint32_t size)
+    {
+      if (cur_alloc_ + size > page_end_) {
+        return nullptr;
+      } else {
+        char *ret = cur_alloc_;
+        cur_alloc_ += size;
+        int address = reinterpret_cast<uintptr_t>(cur_alloc_);
+        int new_addr = (address + 3) & (~3);
+        cur_alloc_ = reinterpret_cast<char *>(new_addr);
+        return ret;
+      }
+    }
+
+  public:
+    Page *next_;
+    char *page_end_;
+    char *cur_alloc_;  // buf_'s current offset
+  };
+
+private:
+  uint32_t page_size_;
+  AllocModID mid_;
+  BaseAllocator &base_allocator_;
+  Page dummy_head_;
+};
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_ALLOCATOR_PAGE_ARENA_H
+
diff --git a/cpp/tsfile/src/common/allocator/stl_allocator.h b/cpp/tsfile/src/common/allocator/stl_allocator.h
new file mode 100644
index 00000000..5be4cb59
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/stl_allocator.h
@@ -0,0 +1,68 @@
+
+#ifndef COMMON_ALLOCATOR_STL_ALLOCATOR_H
+#define  COMMON_ALLOCATOR_STL_ALLOCATOR_H
+
+#include "alloc_base.h"
+
+namespace timecho
+{
+namespace common
+{
+
+template<class T, AllocModID Mid, class TAllocator=BaseAllocator>
+class StlAllocator
+{
+public:
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef T* pointer;
+  typedef const T* const_pointer;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef T value_type;
+
+  /* 
+   * rebind provides a way to obtain an allocator for a different type. 
+   * For example, std::list will alloc object Node<T> beside alloc object T.
+   */
+  template<class U>
+  struct rebind { typedef StlAllocator<U, Mid, TAllocator> other; };
+
+  StlAllocator() {}
+  StlAllocator(const StlAllocator&) {}
+
+  template<class T2, AllocModID Mid2>
+  StlAllocator(const StlAllocator<T2, Mid2, TAllocator>&) {}
+
+  StlAllocator(TAllocator base_allocator) : base_allocator_(base_allocator) {}
+
+  pointer address(reference x) const { return &x; }
+  const_pointer address(const_reference x) { return &x; }
+
+  pointer allocate(size_type n, const void *hint = 0) { return (pointer)base_allocator_.alloc(n * sizeof(T), Mid); };
+  void deallocate(void *p, size_type) {  base_allocator_.free(p); }
+  size_type max_size() const { return uint32_t(-1); }
+
+  void construct(pointer p, const T& val) { new ((T*)p) T(val); }
+  void destroy(pointer p) { p->~T(); }
+
+private:
+  TAllocator base_allocator_;
+};
+
+/*
+ * According to the manual, allocator is stateless.
+ * Although we define a base_allocator_ here, but base_allocator_ is also stateless.
+ * so '==' is always true and '!=' is always false.
+ * refer to https://en.cppreference.com/w/cpp/memory/allocator/operator_cmp.
+ */
+template<class T1, AllocModID Mid1, class T2, AllocModID Mid2>
+bool operator==(const StlAllocator<T1, Mid1> &a1, const StlAllocator<T2, Mid2> &a2) { return true; }
+
+template<class T1, AllocModID Mid1, class T2, AllocModID Mid2>
+bool operator!=(const StlAllocator<T1, Mid1> &a1, const StlAllocator<T2, Mid2> &a2) { return false; }
+ 
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_ALLOCATOR_STL_ALLOCATOR_H
diff --git a/cpp/tsfile/src/common/allocator/util_define.h b/cpp/tsfile/src/common/allocator/util_define.h
new file mode 100644
index 00000000..4d85ef52
--- /dev/null
+++ b/cpp/tsfile/src/common/allocator/util_define.h
@@ -0,0 +1,136 @@
+
+/*
+ * This file defines some basic macros
+ */
+
+#ifndef COMMON_UTIL_DEFINE_H
+#define COMMON_UTIL_DEFINE_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+
+/* ======== cmake config define ======== */
+
+/* ======== unsued ======== */
+#define UNUSED(v) ((void)(v))
+
+
+/* ======== inline ======== */
+#ifdef __GNUC__
+#define FORCE_INLINE inline __attribute__((always_inline))
+#else
+#define FORCE_INLINE inline
+#endif // __GNUC__
+
+#ifdef BUILD_FOR_SMALL_BINARY
+#define INLINE FORCE_INLINE
+#else
+#define INLINE
+#endif // BUILD_FOR_SMALL_BINARY
+
+
+/* ======== likely ======== */
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LIKELY(x)   (__builtin_expect((x), 1))
+#define UNLIKELY(x) (__builtin_expect((x), 0))
+#else
+#define LIKELY(x)   (x)
+#define UNLIKELY(x) (x)
+#endif // __GNUC__ >= 4
+
+
+/* ======== nullptr ======== */
+#if __cplusplus < 201103L
+#ifndef nullptr
+#define nullptr NULL
+#endif
+#define OVERRIDE 
+#else
+#define OVERRIDE override
+#endif // __cplusplus < 201103L
+
+
+/* ======== cache line ======== */
+#ifndef CACHE_LINE_SIZE
+#define CACHE_LINE_SIZE 64
+#endif // CACHE_LINE_SIZE
+
+
+/* ======== assert ======== */
+#ifdef NDEBUG
+#define ASSERT(condition) ((void)0)
+#else
+#define ASSERT(condition) assert((condition))
+#endif  // NDEBUG
+
+/* ======== statis assert ======== */
+/*
+ * To be compatible with C++ before C++11,
+ * @msg should be a single word (use -/_ to concat)
+ * such as This_should_be_TRUE
+ */
+#if __cplusplus < 201103L
+// TODO only define this when DEBUG
+#define STATIC_ASSERT(cond, msg) typedef char static_assertion_##msg[(cond) ? 1 : -1] __attribute__((unused))
+#else
+#define STATIC_ASSERT(cond, msg) static_assert((cond), #msg)
+#endif // __cplusplus < 201103L
+
+
+/* ======== atomic operation ======== */
+#define ATOMIC_FAA(val_addr, addv)  __atomic_fetch_add((val_addr), (addv), __ATOMIC_SEQ_CST)
+#define ATOMIC_AAF(val_addr, addv)  __atomic_add_fetch((val_addr), (addv), __ATOMIC_SEQ_CST)
+/*
+ * It implements an atomic compare and exchange operation.
+ * This compares the contents of *ptr with the contents of *expected.
+ * - If equal, the operation is a read-modify-write operation that writes desired into *ptr.
+ * - If they are not equal, the operation is a read and the current contents of *ptr are written into *expected
+ */
+#define ATOMIC_CAS(val_addr, expected, desired) \
+  __atomic_compare_exchange_n((val_addr), (expected),(desired), \
+                              /* weak = */ false, \
+                              /* success_memorder = */ __ATOMIC_SEQ_CST, \
+                              /* failure_memorder = */ __ATOMIC_SEQ_CST)
+#define ATOMIC_LOAD(val_addr)  __atomic_load_n((val_addr), __ATOMIC_SEQ_CST)
+#define ATOMIC_STORE(val_addr, val) __atomic_store_n((val_addr), (val), __ATOMIC_SEQ_CST)
+
+/* ======== align ======== */
+#define ALIGNED(a) __attribute__((aligned(a)))
+#define ALIGNED_4 ALIGNED(4)
+#define ALIGNED_8 ALIGNED(8)
+
+/* ======== disallow copy and assign ======== */
+#if __cplusplus < 201103L
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+#else
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete; \
+  TypeName& operator=(const TypeName&) = delete;
+#endif
+
+/* ======== return value check ======== */
+#define RET_FAIL(expr) UNLIKELY(common::E_OK != (ret = (expr)))
+#define RFAIL(expr) UNLIKELY(common::E_OK != (ret = (expr)))
+#define RET_SUCC(expr) LIKELY(common::E_OK != (ret = (exprt)))
+#define RSUCC(expr) LIKELY(common::E_OK != (ret = (exprt)))
+#define IS_SUCC(ret) LIKELY(common::E_OK == (ret))
+#define IS_FAIL(ret) UNLIKELY(common::E_OK != (ret))
+
+#define IS_NULL(ptr) UNLIKELY((ptr) == nullptr)
+
+/* ======== min/max ======== */
+#define UTIL_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define UTIL_MIN(a, b) ((a) > (b) ? (b) : (a))
+
+/*
+ * int64_max < 10^20
+ * consider +/- and the '\0' tail. 24 is enough
+ */
+#define INT64_TO_BASE10_MAX_LEN 24
+
+#endif // COMMON_UTIL_DEFINE_H
+
diff --git a/cpp/tsfile/src/common/config/CMakeLists.txt b/cpp/tsfile/src/common/config/CMakeLists.txt
new file mode 100644
index 00000000..139597f9
--- /dev/null
+++ b/cpp/tsfile/src/common/config/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+
diff --git a/cpp/tsfile/src/common/config/config.h b/cpp/tsfile/src/common/config/config.h
new file mode 100644
index 00000000..5c4754e9
--- /dev/null
+++ b/cpp/tsfile/src/common/config/config.h
@@ -0,0 +1,52 @@
+#ifndef COMMON_CONFIG_CONFIG_H
+#define COMMON_CONFIG_CONFIG_H
+
+#include <stdint.h>
+
+#include "common/util_define.h"
+#include "common/mutex/mutex.h"
+#include "common/db_utils.h"
+
+namespace timecho
+{
+namespace common
+{
+enum ConfigLevel
+{
+  INIT,      // Unchangeable, initialized during database init
+  RESTART,   // Can be changed, but the database must be restarted to take effect
+  USERSET    // Session level update
+};
+
+typedef struct ConfigValue
+{
+  uint32_t tsblock_mem_inc_step_size_;    // tsblock memory self-increment step size
+  uint32_t tsblock_max_memory_;           // the maximum memory of a single tsblock
+  const char *rest_service_ip_;
+  int32_t rest_service_port_;
+  WALFlushPolicy wal_flush_policy_;
+  uint32_t seqtvlist_primary_array_size_;
+  uint32_t seqtvlist_max_record_count_;
+  uint32_t page_writer_max_point_num_;
+  uint32_t page_writer_max_memory_bytes_;
+  uint32_t max_degree_of_index_node_;
+  double tsfile_index_bloom_filter_error_percent_;
+  const char *tsfile_prefix_path_;
+  TSEncoding time_encoding_type_;
+  uint32_t memtable_flusher_poll_interval_seconds_;
+} ConfigValue;
+
+extern void init_config_value();
+
+// In the future, configuration items need to be dynamically adjusted according to the level
+extern void set_config_value();
+extern void config_set_page_max_point_count(uint32_t page_max_ponint_count);
+extern void config_set_max_degree_of_index_node(uint32_t max_degree_of_index_node);
+
+// FORCE_INLINE bool wal_cfg_enabled() { return g_config_value_.wal_flush_policy_ != WAL_DISABLED; }
+// FORCE_INLINE bool wal_cfg_should_wait_persisted() { return g_config_value_.wal_flush_policy_ >= WAL_FLUSH; }
+
+}  // common
+}  // timecho
+
+#endif // COMMON_CONFIG_CONFIG_H
diff --git a/cpp/tsfile/src/common/container/CMakeLists.txt b/cpp/tsfile/src/common/container/CMakeLists.txt
new file mode 100644
index 00000000..c3d4b867
--- /dev/null
+++ b/cpp/tsfile/src/common/container/CMakeLists.txt
@@ -0,0 +1,12 @@
+message("Running in src/common/container directory")
+
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} common_container_SRC_LIST)
+set(common_container_INC_LIST)
+set(common_container_DEFINE_OPTIONS)
+set(common_container_COMPILE_OPTIONS)
+set(common_container_LINK_OPTIONS)
+
+add_statis_objtarget(common_container common_container_SRC_LIST common_container_INC_LIST
+                     "${common_container_DEFINE_OPTIONS}"
+                     "${common_container_COMPILE_OPTIONS}"
+                     "${common_container_LINK_OPTIONS}")
diff --git a/cpp/tsfile/src/common/container/array.h b/cpp/tsfile/src/common/container/array.h
new file mode 100644
index 00000000..70e7a891
--- /dev/null
+++ b/cpp/tsfile/src/common/container/array.h
@@ -0,0 +1,312 @@
+#ifndef COMMON_CONTAINER_ARRAY_H
+#define COMMON_CONTAINER_ARRAY_H
+
+#include <cstdlib>
+#include <cstdio>
+#include <stdint.h>
+#include <cstring>
+#include <iostream>
+#include "common/allocator/alloc_base.h"
+#include "common/logger/elog.h"
+#include "common/errno_define.h"
+#include "common/util_define.h" 
+
+#define ARRAY_INIT_CAPACITY 1000  // TODO: configurable mode
+#define ARRAY_GROWTH_THRESHOLD 50  // TODO: configurable mode
+#define ARRAY_SHRINK_THRESHOLD 50  // TODO: configurable mode
+
+namespace timecho 
+{
+namespace common
+{
+
+template <class ValueType>
+class Array 
+{
+public:
+
+#ifndef NDEBUG
+  friend std::ostream & operator << (std::ostream &out, Array<ValueType> &sa)
+  {
+    for (size_t idx = 0; idx < sa.size(); idx++) {
+      if (idx > 0) {
+        out << ' ';
+      }
+      out << sa[idx];
+    }
+    out << std::endl;
+    return out;
+  }
+#endif  // NDEBUG
+
+  Array()
+  {
+    capacity_ = ARRAY_INIT_CAPACITY;
+    size_ = 0;
+    is_inited_ = false;
+    array_ = nullptr;
+  }
+
+  Array(size_t capacity)
+  {
+    capacity_ = capacity;
+    size_ = 0;
+    is_inited_ = false;
+    array_ = nullptr;
+  }
+
+  ~Array()
+  {
+    if(is_inited_){
+      destroy();
+    }
+    capacity_ = 0;
+    size_ = 0;
+  }  
+
+  // int deep_copy(const Array &other)
+  // {
+  //   this->capacity_ = other.capacity_;
+  //   this->size_ = other.size_;
+  //   if (init() == E_OK) {
+  //     memcpy(this->array_, other.array_, this->capacity_ * sizeof(*(this->array_))); 
+  //     return E_OK;
+  //   }
+  //   return E_OOM;
+  // }
+
+  int init()
+  {
+    if(is_inited_) {
+      log_error("init repeated.");
+      ASSERT(!is_inited_);
+    }
+    array_ = (ValueType *)mem_alloc(capacity_ * sizeof(*(array_)), MOD_ARRAY);
+    if (UNLIKELY(nullptr == array_)) {
+      is_inited_ = false;
+      log_error("malloc failed.");
+      return E_OOM;  
+    }
+    is_inited_ = true;
+    return E_OK;  
+  }
+
+  void destroy()
+  {
+    capacity_ = 0;
+    size_ = 0;
+    if (is_inited_) {
+      mem_free(array_);
+      array_ = nullptr;
+    }
+    is_inited_ = false;
+  }
+
+private: 
+  static size_t linear_calc(size_t input)
+  {
+    if (input < ARRAY_GROWTH_THRESHOLD) {
+      return input;
+    }
+    size_t res = 1;
+    input /= 10;
+    while (input) {
+      input /= 10;
+      res *= 10;
+    }
+    return res;
+  }
+  
+public:
+  int extend()
+  {
+    // Check for a potential overflow
+    uint64_t tmp = (uint64_t) (linear_calc(capacity_) + capacity_);
+    if (tmp > SIZE_MAX) {
+      log_error("size overflow.");
+      return E_OVERFLOW;
+    }
+
+    size_t new_capacity = (size_t) tmp;
+    array_ = (ValueType *)mem_realloc(array_, new_capacity * sizeof(*(array_)));
+    if (UNLIKELY(nullptr == array_)) {
+      log_error("realloc failed.");
+      return E_OOM;  
+    }
+    capacity_ = new_capacity;
+    return E_OK;
+  }
+
+  int shrink()
+  {
+    size_t new_capacity = (size_t)(capacity_ / 2);
+    // if the size passed to realloc is smaller than before, OS will automatically release the rest memory
+    array_ = (ValueType *)mem_realloc(array_, new_capacity * sizeof(*(array_)));  
+    if (UNLIKELY(nullptr == array_)) {
+      log_error("malloc failed.");
+      return E_OOM;  
+    }    
+    capacity_ = new_capacity;
+    return E_OK;
+  }
+
+  int insert(size_t idx, const ValueType &value)
+  {
+    if (idx > size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      return E_OUT_OF_RANGE;
+    }
+    if (size_ >= capacity_) {
+      int ret = extend();
+      if(ret != E_OK) {
+        return ret;
+      }
+    }
+    ASSERT(idx <= size_);
+    ASSERT(size_ < capacity_);
+    if (idx == size_) {
+      array_[idx] = value;
+      size_++;
+      return E_OK;  
+    }
+
+    memmove(array_ + (idx + 1), array_ + idx, (size_ - idx) * sizeof(*(array_)));  
+    array_[idx] = value;
+    size_++;
+    return E_OK;
+  }
+
+  // int update(size_t idx, const ValueType &value)
+  // {
+  //   if (idx >= size_) {
+  //     log_error("index %lu is out of range, because size is %lu.", idx, size_);
+  //     return E_OUT_OF_RANGE;
+  //   }
+  //   array_[idx] = value;
+  //   return E_OK;
+  // }
+
+  int append(const ValueType &value)
+  {
+    if (size_ >= capacity_) {
+      int ret = extend();
+      if(ret != E_OK) {
+        return ret;
+      }
+    }
+    array_[size_] = value;
+    size_++;
+    return E_OK;    
+  }
+
+  FORCE_INLINE ValueType & at(size_t idx)
+  {
+    if (idx >= size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      ASSERT(idx < size_);
+      return dummy_;
+    }
+    return array_[idx];
+  }
+
+  FORCE_INLINE ValueType & operator [] (size_t idx)
+  {
+    if (idx >= size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      ASSERT(idx < size_);
+      return dummy_;
+    }  
+    return array_[idx];
+  }
+
+  bool contain(const ValueType& value)
+  {
+    for(int i = 0; i < size_; i++){
+        if(array_[i] == value) {
+          return true;
+        }
+    }
+    return false;    
+  }
+
+  /*
+   * if the value is not found, then set 'found' is false.
+   */
+  size_t find(const ValueType& target_val, bool &found)
+  {
+    for (size_t i = 0; i < size_; i++) {
+      if (array_[i] == target_val) {
+        found = true;
+        return i;
+      }
+    }
+    found = false;
+    return 0;    
+  }
+
+  ValueType remove(size_t idx)
+  {
+    if (idx >= size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      ASSERT(idx < size_);
+      return dummy_;
+    }
+    if (capacity_ > ARRAY_SHRINK_THRESHOLD && size_ <= capacity_ / 4) {
+      shrink(); 
+    }
+    ValueType ret = array_[idx];
+    memmove(array_ + idx, array_ + idx + 1, (size_ - idx - 1) * sizeof(*(array_)));  
+    size_--;
+
+    return ret;
+  }
+
+  int remove_value(const ValueType &value)
+  {
+    bool found = false;
+    size_t pos = find(value, found);
+    if (!found) {
+      log_warn("the value is not exist in the array.");
+      return E_NOT_EXIST;
+    }
+    while (found) {
+      remove(pos);
+      pos = find(value, found);
+    }
+
+    return E_OK;
+  }
+
+  FORCE_INLINE void clear()
+  {
+    size_ = 0;
+  }
+
+  FORCE_INLINE bool empty() const
+  {
+    return ATOMIC_LOAD(&size_) == 0;
+  }
+
+  FORCE_INLINE size_t size() const
+  {
+    return ATOMIC_LOAD(&size_);
+  }
+
+  FORCE_INLINE size_t capacity() const
+  {
+    return ATOMIC_LOAD(&capacity_);
+  }
+
+private:
+  size_t capacity_;
+  size_t size_;
+  ValueType *array_;
+  ValueType dummy_;  
+  bool is_inited_;
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+
+#endif  // COMMON_CONTAINER_ARRAY_H
diff --git a/cpp/tsfile/src/common/container/bit_map.cc b/cpp/tsfile/src/common/container/bit_map.cc
new file mode 100644
index 00000000..88d9515a
--- /dev/null
+++ b/cpp/tsfile/src/common/container/bit_map.cc
@@ -0,0 +1,32 @@
+
+#include "bit_map.h"
+#include "common/allocator/alloc_base.h"
+
+namespace timecho
+{
+namespace common
+{
+
+BitMap::~BitMap()
+{
+  if (bitmap_ && (size_ > 0)) {
+    mem_free(bitmap_);
+    bitmap_ = nullptr;
+    size_ = 0;
+  }
+}
+
+int BitMap::init(uint32_t item_size, bool init_as_zero)
+{
+  uint32_t size = (item_size + 7) / 8;
+  bitmap_ = static_cast<char*>(mem_alloc(size, MOD_TSBLOCK));
+  // need set to 0, otherwise there will be wrong data
+  const char initial_char = init_as_zero ? 0x00 : 0xFF;
+  memset(bitmap_, initial_char, size);
+  size_ = size;
+  init_as_zero_ = init_as_zero;
+  return common::E_OK;
+}
+
+}
+}
diff --git a/cpp/tsfile/src/common/container/bit_map.h b/cpp/tsfile/src/common/container/bit_map.h
new file mode 100644
index 00000000..5bde42f1
--- /dev/null
+++ b/cpp/tsfile/src/common/container/bit_map.h
@@ -0,0 +1,71 @@
+#ifndef COMMON_CONTAINER_BIT_MAP_H
+#define COMMON_CONTAINER_BIT_MAP_H
+
+#include <string.h>
+#include "common/errno_define.h"
+#include "common/util_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+class BitMap
+{
+public:
+  BitMap() : bitmap_(nullptr), size_(0), init_as_zero_(true) { }
+  ~BitMap();
+  int init(uint32_t item_size, bool init_as_zero = true);
+
+  FORCE_INLINE void reset()
+  {
+    const char initial_char = init_as_zero_ ? 0x00 : 0xFF;
+    memset(bitmap_, initial_char, size_);
+  }
+
+  FORCE_INLINE void set(uint32_t index)
+  {
+    uint32_t offset = index >> 3;
+    ASSERT(offset < size_);
+
+    char *start_addr = bitmap_ + offset;
+    uint8_t bit_mask = get_bit_mask(index);
+    *start_addr = (*start_addr) | (bit_mask);
+  }
+
+  FORCE_INLINE void clear(uint32_t index)
+  {
+    uint32_t offset = index >> 3;
+    ASSERT(offset < size_);
+
+    char *start_addr = bitmap_ + offset;
+    uint8_t bit_mask = get_bit_mask(index);
+    *start_addr = (*start_addr) ^ (~bit_mask);
+  }
+
+  FORCE_INLINE bool test(uint32_t index)
+  {
+    uint32_t offset = index >> 3;
+    ASSERT(offset < size_);
+
+    char *start_addr = bitmap_ + offset;
+    uint8_t bit_mask = get_bit_mask(index);
+    return (*start_addr & bit_mask);
+  }
+
+  FORCE_INLINE uint32_t get_size() { return size_; }
+
+  FORCE_INLINE char* get_bitmap() { return bitmap_; }  // for debug
+
+private:
+  FORCE_INLINE uint8_t get_bit_mask(uint32_t index) { return 1 << (index & 7); }
+
+private:
+  char      *bitmap_;
+  uint32_t  size_;
+  bool init_as_zero_;
+};
+}  // common
+}  // timecho
+
+#endif  // COMMON_CONTAINER_BIT_MAP_H
diff --git a/cpp/tsfile/src/common/container/blocking_queue.cc b/cpp/tsfile/src/common/container/blocking_queue.cc
new file mode 100644
index 00000000..9da55d23
--- /dev/null
+++ b/cpp/tsfile/src/common/container/blocking_queue.cc
@@ -0,0 +1,47 @@
+
+#include "blocking_queue.h"
+
+namespace timecho
+{
+namespace common
+{
+
+BlockingQueue::BlockingQueue() : queue_(), mutex_(), cond_()
+{
+  pthread_mutex_init(&mutex_, NULL);
+  pthread_cond_init(&cond_, NULL);
+}
+
+BlockingQueue::~BlockingQueue()
+{
+  pthread_mutex_destroy(&mutex_);
+  pthread_cond_destroy(&cond_);
+}
+
+void BlockingQueue::push(void *data)
+{
+  pthread_mutex_lock(&mutex_);
+  queue_.push(data);
+  pthread_mutex_unlock(&mutex_);
+  /*
+   * it is safe to signal after unlock.
+   * since pthread_cond_wait is guarantee to unlock and sleep atomically.
+   */
+  pthread_cond_signal(&cond_);
+}
+
+void* BlockingQueue::pop()
+{
+  void *ret_data = NULL;
+  pthread_mutex_lock(&mutex_);
+  while (queue_.empty()) {
+    pthread_cond_wait(&cond_, &mutex_);
+  }
+  ret_data = queue_.front();
+  queue_.pop();
+  pthread_mutex_unlock(&mutex_);
+  return ret_data;
+}
+
+} // end namespace common
+} // end namespace timecho
diff --git a/cpp/tsfile/src/common/container/blocking_queue.h b/cpp/tsfile/src/common/container/blocking_queue.h
new file mode 100644
index 00000000..84d2ee3c
--- /dev/null
+++ b/cpp/tsfile/src/common/container/blocking_queue.h
@@ -0,0 +1,32 @@
+#ifndef COMMON_CONTAINER_BLOCKING_QUEUE_H
+#define COMMON_CONTAINER_BLOCKING_QUEUE_H
+
+#include <queue>
+#include <pthread.h>
+
+namespace timecho
+{
+namespace common
+{
+
+class BlockingQueue
+{
+public:
+  BlockingQueue();
+  ~BlockingQueue();
+
+  void push(void *data);
+  // if empty, blocking
+  void* pop();
+
+private:
+  std::queue<void*> queue_;
+  pthread_mutex_t   mutex_;
+  pthread_cond_t    cond_;
+};
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_CONTAINER_BLOCKING_QUEUE_H
+
diff --git a/cpp/tsfile/src/common/container/byte_buffer.h b/cpp/tsfile/src/common/container/byte_buffer.h
new file mode 100644
index 00000000..9843770b
--- /dev/null
+++ b/cpp/tsfile/src/common/container/byte_buffer.h
@@ -0,0 +1,114 @@
+#ifndef COMMON_CONTAINER_BYTE_BUFFER_H
+#define COMMON_CONTAINER_BYTE_BUFFER_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common/allocator/alloc_base.h"
+#include "common/global.h"
+#include "common/util_define.h"
+
+namespace timecho
+{
+namespace common
+{
+class ByteBuffer
+{
+public:
+  ByteBuffer() : data_(nullptr), variable_type_len_(sizeof(uint32_t)), real_data_size_(0), reserved_size_(0) {}
+
+  ~ByteBuffer()
+  {
+    if (data_ && (reserved_size_ > 0)) {
+      mem_free(data_);
+      data_ = nullptr;
+      real_data_size_ = 0;
+      reserved_size_ = 0;
+    }
+  }
+
+  FORCE_INLINE void init(uint32_t size)
+  {
+    data_ = static_cast<char*>(mem_alloc(size, MOD_TSBLOCK));
+    reserved_size_ = size;
+  }
+
+  FORCE_INLINE void reset()
+  {
+    real_data_size_ = 0;
+  }
+
+  FORCE_INLINE void extend_memory(uint32_t new_size)
+  {
+    ASSERT(new_size > reserved_size_);
+    data_ = static_cast<char*>(mem_realloc(data_, new_size));
+    reserved_size_ = new_size;
+  }
+
+  FORCE_INLINE void append_variable_value(const char *value, uint32_t len)
+  {
+    // dynamic growth
+    if (UNLIKELY((real_data_size_ + len + variable_type_len_) > reserved_size_)) {
+      // extreme scenarios, when encountering very long string
+      uint32_t growth_size = g_config_value_.tsblock_mem_inc_step_size_ > len ?
+        g_config_value_.tsblock_mem_inc_step_size_ : (len + 1);
+      extend_memory(reserved_size_ + growth_size);
+    }
+
+    ASSERT(data_);
+    // append len
+    memcpy(&data_[real_data_size_], reinterpret_cast<char*>(&len), variable_type_len_);
+    real_data_size_ += variable_type_len_;
+    if (len > 0) {
+      // append data
+      memcpy(&data_[real_data_size_], value, len);
+      real_data_size_ += len;
+    }
+  }
+
+  FORCE_INLINE void append_fixed_value(const char *value, uint32_t len)
+  {
+    // dynamic growth
+    if (UNLIKELY(real_data_size_ + len > reserved_size_)) {
+      // extreme scenarios, when encountering very long string
+      uint32_t growth_size = g_config_value_.tsblock_mem_inc_step_size_ > len ?
+        g_config_value_.tsblock_mem_inc_step_size_ : (len + 1);
+      extend_memory(reserved_size_ + growth_size);
+    }
+
+    ASSERT(data_);
+    memcpy(&data_[real_data_size_], value, len);
+    real_data_size_ += len;
+  }
+
+  // for fixed len value
+  FORCE_INLINE char* read(uint32_t offset, uint32_t len)
+  {
+    ASSERT((offset + len) <= real_data_size_);
+    char *p = &data_[offset];
+    return p;
+  }
+
+  // for variable len value
+  FORCE_INLINE char* read(uint32_t offset, uint32_t *len)
+  {
+    // get len
+    *len = *reinterpret_cast<uint32_t*>(&data_[offset]);
+    // get value
+    char *p = &data_[offset + variable_type_len_];
+    return p;
+  }
+
+  FORCE_INLINE char* get_data() { return data_; }
+
+private:
+  char         *data_;
+  uint8_t      variable_type_len_;
+  uint32_t     real_data_size_;
+  uint32_t     reserved_size_;   // malloc memory size from system
+};
+
+}  // common
+}  // timecho
+#endif  // COMMON_CONTAINER_BYTE_BUFFER_H
\ No newline at end of file
diff --git a/cpp/tsfile/src/common/container/hash_func.h b/cpp/tsfile/src/common/container/hash_func.h
new file mode 100644
index 00000000..d8522eaa
--- /dev/null
+++ b/cpp/tsfile/src/common/container/hash_func.h
@@ -0,0 +1,102 @@
+#ifndef COMMON_CONTAINER_HASH_FUNC_H
+#define COMMON_CONTAINER_HASH_FUNC_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "common/db_utils.h"
+#include "common/container/slice.h"
+#include "common/container/hash_table.h"
+#include "common/container/murmur_hash3.h"
+
+#define TSID_MAX_LEN 20  
+
+namespace timecho
+{
+namespace common
+{
+
+/*
+ * using djb2 hash algorithm
+ */
+struct StringHashFunc
+{
+  uint32_t hash_fmix32(uint32_t h) 
+  {
+    h ^= h >> 16;
+    h *= 0x3243f6a9U;
+    h ^= h >> 16;
+    return h;
+  }
+
+  uint32_t operator()(const void *data) 
+  {
+    uint32_t hash_ = (const uint32_t)5381;
+    const char *str = (const char*)data;
+    char c;
+    while((c = *str++)) {
+      hash_ = ((hash_ << 5) + hash_) + c;
+    }
+    return hash_fmix32(hash_);
+  }
+};
+
+/*
+ * using djb2 hash algorithm
+ */
+struct SliceHashFunc
+{
+  uint32_t hash_fmix32(uint32_t h) 
+  {
+    h ^= h >> 16;
+    h *= 0x3243f6a9U;
+    h ^= h >> 16;
+    return h;
+  }
+
+  uint32_t operator()(const Slice &slice) 
+  {
+    uint32_t hash_ = (const uint32_t)5381;
+    const char *str = (const char*)slice.data();
+    char c;
+    while((c = *str++)) {
+      hash_ = ((hash_ << 5) + hash_) + c;
+    }
+    return hash_fmix32(hash_);
+  }
+};
+
+/*
+ * using murmur_hash hash algorithm
+ */
+struct TsIDHashFunc
+{
+  uint32_t hash_fmix32(uint32_t h) 
+  {
+    h ^= h >> 16;
+    h *= 0x3243f6a9U;
+    h ^= h >> 16;
+    return h;
+  }
+
+  uint32_t operator()(const TsID &data) 
+  {
+    int32_t tmp = data.db_nid_ * 10000 + data.device_nid_ * 100 + data.measurement_nid_;
+    return Murmur128Hash::hash(tmp, 0);
+  }
+};
+
+/*
+ * using murmur_hash hash algorithm
+ */
+struct NodeIDHashFunc
+{
+  uint32_t operator()(const NodeID &data) 
+  {
+    return Murmur128Hash::hash(static_cast<int32_t>(data), 0);
+  }
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif  // COMMON_CONTAINER_HASH_FUNC_H
diff --git a/cpp/tsfile/src/common/container/hash_node.h b/cpp/tsfile/src/common/container/hash_node.h
new file mode 100644
index 00000000..6a2ffe10
--- /dev/null
+++ b/cpp/tsfile/src/common/container/hash_node.h
@@ -0,0 +1,90 @@
+#ifndef COMMON_CONTAINER_HASH_NODE_H
+#define COMMON_CONTAINER_HASH_NODE_H
+
+#include "common/util_define.h" 
+
+namespace timecho
+{
+namespace common
+{
+
+template <class KeyType, class ValueType>
+class HashNode {
+public:
+  HashNode() 
+  {
+    is_valid_ = false;
+    rehash_ = 0;
+    next_ = nullptr;
+  }
+
+  HashNode(const KeyType &key, const ValueType &value) : key_(key), value_(value), 
+           is_valid_(true), rehash_(0), next_(nullptr) {}
+
+  ~HashNode()
+  {
+    is_valid_ = false;
+  }
+
+  FORCE_INLINE KeyType get_key() const 
+  {
+    return key_;
+  }
+
+  FORCE_INLINE ValueType get_value() const 
+  {
+    return value_;
+  }
+  
+  FORCE_INLINE void set_key(const KeyType &key) 
+  {
+    key_ = key;
+  }
+
+  FORCE_INLINE void set_value(const ValueType &value) 
+  {
+    value_ = value;
+  }
+
+  FORCE_INLINE HashNode* get_next() const 
+  {
+    return next_;
+  }
+
+  FORCE_INLINE void set_next(HashNode *next) 
+  {
+    next_ = next;
+  }  
+
+  FORCE_INLINE bool get_valid() const
+  {
+    return is_valid_;
+  }
+
+  FORCE_INLINE void set_valid(bool vd)
+  {
+    is_valid_ = vd;
+  }
+
+  FORCE_INLINE uint64_t get_rehashid() const
+  {
+    return rehash_;
+  }
+
+  FORCE_INLINE void set_rehashid(uint64_t id)
+  {
+    rehash_ = id;
+  }
+
+public:
+  bool is_valid_;
+  uint64_t rehash_;
+  KeyType key_;
+  ValueType value_;
+  HashNode *next_;  // pointer to the next node (same bucket)
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif  // COMMON_CONTAINER_HASH_NODE_H
\ No newline at end of file
diff --git a/cpp/tsfile/src/common/container/hash_segm.h b/cpp/tsfile/src/common/container/hash_segm.h
new file mode 100644
index 00000000..40746311
--- /dev/null
+++ b/cpp/tsfile/src/common/container/hash_segm.h
@@ -0,0 +1,41 @@
+#ifndef COMMON_CONTAINER_HASH_SEGM_H
+#define COMMON_CONTAINER_HASH_SEGM_H
+
+#include <stddef.h>
+#include "common/container/hash_node.h"
+#include "common/errno_define.h"
+#include "common/util_define.h" 
+#include "common/mutex/mutex.h"
+
+#define SEGMENT_CAPACITY 100
+
+namespace timecho
+{
+namespace common
+{
+
+template <class KeyType, class ValueType>
+class HashSegm {
+public:
+  HashSegm() {}
+  ~HashSegm() {}
+
+  FORCE_INLINE HashNode<KeyType, ValueType> & operator [] (size_t idx) 
+  {
+    if (idx >= SEGMENT_CAPACITY) {
+      log_error("index %lu is out of range.", idx);
+      ASSERT(idx < SEGMENT_CAPACITY);
+    }      
+    return segm_pointer_[idx];
+  }
+
+public:
+  Mutex mutexes_[SEGMENT_CAPACITY];
+  HashNode<KeyType, ValueType> segm_pointer_[SEGMENT_CAPACITY];
+};
+
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif  // COMMON_CONTAINER_HASH_SEGM_H
\ No newline at end of file
diff --git a/cpp/tsfile/src/common/container/hash_table.h b/cpp/tsfile/src/common/container/hash_table.h
new file mode 100644
index 00000000..d72e2167
--- /dev/null
+++ b/cpp/tsfile/src/common/container/hash_table.h
@@ -0,0 +1,685 @@
+#ifndef COMMON_CONTAINER_HASH_TABLE_H
+#define COMMON_CONTAINER_HASH_TABLE_H
+
+#include "common/allocator/alloc_base.h"
+#include "common/container/array.h"
+#include "common/container/hash_func.h"
+#include "common/container/hash_node.h"
+#include "common/container/hash_segm.h"
+
+#define TABLE_CAPACITY 100
+#define TABLE_GROWTH 2
+
+namespace timecho
+{
+namespace common
+{
+
+template < typename KeyType, typename ValueType, typename F >
+class HashTable {
+public:
+  HashTable() : table_(TABLE_CAPACITY)
+  {
+    new_table_capacity_ = TABLE_CAPACITY;
+    old_table_capacity_ = TABLE_CAPACITY;    
+    size_ = 0;    
+    is_inited_ = false;
+    hash_version_ = 0;
+    is_extending_ = 0;
+  }
+
+  HashTable(size_t total_capacity) : table_(total_capacity / SEGMENT_CAPACITY)
+  {
+    new_table_capacity_ = total_capacity / SEGMENT_CAPACITY;
+    old_table_capacity_ = new_table_capacity_;
+    size_ = 0;    
+    is_inited_ = false;
+    hash_version_ = 0;    
+    is_extending_ = 0;
+  }
+  ~HashTable()
+  {
+    new_table_capacity_ = 0;
+    size_ = 0;
+    is_inited_ = false;
+    hash_version_ = 0;    
+    is_extending_ = 0;
+  }
+
+  int init()
+  {
+    if (is_inited_) {
+      log_error("init repeated.");
+      ASSERT(!is_inited_);
+    }
+
+    int ret = E_OK;
+    ret = table_.init();
+    if (ret != E_OK) {
+      return E_OOM;
+    }
+    for (size_t i = 0; i < new_table_capacity_; i++) {
+      void *buf = mem_alloc(sizeof(HashSegm<KeyType, ValueType>), MOD_HASH_TABLE);
+      if (UNLIKELY(nullptr == buf)) {
+        log_error("malloc() failed.");
+        return E_OOM;  
+      }
+      HashSegm<KeyType, ValueType> *tmp_segm = new (buf) HashSegm<KeyType, ValueType>; 
+      table_.append(tmp_segm);
+    }
+    is_inited_ = true;
+    return E_OK;  
+  }
+
+  void destroy()
+  {
+    if (is_inited_) {
+      for (size_t i = 0; i < new_table_capacity_; i++) {
+        for (size_t j = 0; j < SEGMENT_CAPACITY; j++) {
+          if ((*table_[i])[j].get_valid()) {
+            HashNode<KeyType, ValueType>* prev = nullptr;
+            HashNode<KeyType, ValueType>* entry = (*table_[i])[j].get_next();
+            while (entry != nullptr) {
+              prev = entry;
+              entry = entry->get_next();
+              prev->~HashNode();
+              mem_free(prev);
+              prev = nullptr;
+            }
+            (*table_[i])[j].set_valid(false);
+          } 
+        }
+        table_[i]->~HashSegm();
+        mem_free(table_[i]); 
+        table_[i] = nullptr;
+      }    
+      table_.destroy();
+    }
+    is_inited_ = false;
+  }
+
+  int table_extend()
+  {
+    int ret = table_.extend();
+    if ( ret != E_OK) {
+      return ret;
+    }
+    for (size_t i = ATOMIC_LOAD(&new_table_capacity_); i < table_.capacity(); i++) {
+      void *buf = mem_alloc(sizeof(HashSegm<KeyType, ValueType>), MOD_HASH_TABLE);
+      if (UNLIKELY(nullptr == buf)) {
+        log_error("malloc() failed.");
+        return E_OOM;  
+      }
+      HashSegm<KeyType, ValueType> *tmp_segm = new (buf) HashSegm<KeyType, ValueType>; 
+      table_.append(tmp_segm);
+    }    
+    return E_OK;
+  }
+
+  int move_bucket_head(size_t from_segment_idx, size_t from_bucket_idx)
+  {
+    HashNode<KeyType, ValueType>* prev = &((*table_[from_segment_idx])[from_bucket_idx]);
+    HashNode<KeyType, ValueType>* entry = ((*table_[from_segment_idx])[from_bucket_idx]).get_next();  
+
+    while ((*table_[from_segment_idx])[from_bucket_idx].get_rehashid() != ATOMIC_LOAD(&hash_version_)) {  // if the hashnode hasn't rehashed
+      uint32_t hash_value = hashfunc_((*table_[from_segment_idx])[from_bucket_idx].get_key());
+      size_t to_segment_idx = hash_value % ATOMIC_LOAD(&new_table_capacity_);
+      size_t to_bucket_idx = hash_value % SEGMENT_CAPACITY;
+      if (from_segment_idx == to_segment_idx && from_bucket_idx == to_bucket_idx) {
+        ((*table_[to_segment_idx])[to_bucket_idx]).set_rehashid(ATOMIC_LOAD(&hash_version_));  // only update rehashid
+      } else {
+        // put
+        table_[to_segment_idx]->mutexes_[to_bucket_idx].lock();
+        int ret = put_nolock((*table_[from_segment_idx])[from_bucket_idx].get_key(), (*table_[from_segment_idx])[from_bucket_idx].get_value(), to_segment_idx, to_bucket_idx); 
+        table_[to_segment_idx]->mutexes_[to_bucket_idx].unlock(); 
+        if (ret != E_OK) {
+          return ret;
+        }
+        // remove
+        if (entry != nullptr) {
+          ((*table_[from_segment_idx])[from_bucket_idx]).set_key(entry->get_key());
+          ((*table_[from_segment_idx])[from_bucket_idx]).set_value(entry->get_value());
+          ((*table_[from_segment_idx])[from_bucket_idx]).set_next(entry->get_next());      
+          ((*table_[from_segment_idx])[from_bucket_idx]).set_valid(true);        
+          ((*table_[from_segment_idx])[from_bucket_idx]).set_rehashid(entry->get_rehashid());
+          ATOMIC_AAF(&size_, -1);
+          entry->~HashNode();  
+          mem_free(entry);
+          entry = prev->get_next();           
+        } else {
+          ((*table_[from_segment_idx])[from_bucket_idx]).set_valid(false);
+          ATOMIC_AAF(&size_, -1);
+          break;
+        }
+      }
+    }
+
+    return E_OK;
+  }
+
+  int move_bucket_chain(size_t from_segment_idx, size_t from_bucket_idx)
+  {
+    HashNode<KeyType, ValueType>* prev = &((*table_[from_segment_idx])[from_bucket_idx]);
+    HashNode<KeyType, ValueType>* entry = ((*table_[from_segment_idx])[from_bucket_idx]).get_next();      
+
+    while (entry != nullptr) {
+      if (entry->get_rehashid() != ATOMIC_LOAD(&hash_version_)) {
+        uint32_t hash_value = hashfunc_(entry->get_key());
+        size_t to_segment_idx = hash_value % ATOMIC_LOAD(&new_table_capacity_);
+        size_t to_bucket_idx = hash_value % SEGMENT_CAPACITY;
+        if (from_segment_idx == to_segment_idx && from_bucket_idx == to_bucket_idx) {
+          entry->set_rehashid(ATOMIC_LOAD(&hash_version_));
+          prev = entry;
+          entry = entry->get_next();
+        } else {
+          table_[to_segment_idx]->mutexes_[to_bucket_idx].lock();          
+          if ((*table_[to_segment_idx])[to_bucket_idx].get_valid() == false) {
+            ((*table_[to_segment_idx])[to_bucket_idx]).set_key(entry->get_key());
+            ((*table_[to_segment_idx])[to_bucket_idx]).set_value(entry->get_value());
+            ((*table_[to_segment_idx])[to_bucket_idx]).set_next(nullptr);      
+            ((*table_[to_segment_idx])[to_bucket_idx]).set_valid(true);
+            ((*table_[to_segment_idx])[to_bucket_idx]).set_rehashid(ATOMIC_LOAD(&hash_version_));   
+            prev->set_next(entry->get_next());
+            entry->~HashNode();  
+            mem_free(entry);
+            entry = prev->get_next();
+            // entry = entry->get_next();               
+          } else {
+            entry->set_rehashid(ATOMIC_LOAD(&hash_version_));
+            prev->set_next(entry->get_next());
+            entry->set_next((*table_[to_segment_idx])[to_bucket_idx].get_next());
+            (*table_[to_segment_idx])[to_bucket_idx].set_next(entry);
+            entry = prev->get_next();
+          }
+          table_[to_segment_idx]->mutexes_[to_bucket_idx].unlock();
+        }  
+      } else {
+        prev = prev->get_next();  
+        entry = entry->get_next();              
+      }
+    }    
+    return E_OK;
+  }
+
+  int extend()
+  {
+    int ret = table_extend();
+    if (ret != E_OK) {
+      return ret;
+    }    
+    ATOMIC_STORE(&old_table_capacity_, ATOMIC_LOAD(&new_table_capacity_));
+    ATOMIC_STORE(&new_table_capacity_, table_.capacity());
+    // ATOMIC_STORE(&hash_total_capacity_, table_.capacity() * SEGMENT_CAPACITY);
+
+    int64_t next_hash_version = ATOMIC_LOAD(&hash_version_) + 1;  // the highest position of next_hash_version is 0
+    ATOMIC_STORE(&hash_version_, next_hash_version | (1UL<<63));  // set the highest position to 1 which means 'extend' is beginning.    
+
+    // rehash
+    for (size_t from_segment_idx = 0; from_segment_idx < ATOMIC_LOAD(&old_table_capacity_); from_segment_idx++) {
+      for (size_t from_bucket_idx = 0; from_bucket_idx < SEGMENT_CAPACITY; from_bucket_idx++) {
+        table_[from_segment_idx]->mutexes_[from_bucket_idx].lock();
+        if ((*table_[from_segment_idx])[from_bucket_idx].get_valid()) {
+          ret = move_bucket_head(from_segment_idx,from_bucket_idx);
+          if (ret != E_OK) {
+            table_[from_segment_idx]->mutexes_[from_bucket_idx].unlock();
+            return ret;
+          }
+          ret = move_bucket_chain(from_segment_idx,from_bucket_idx);
+          if (ret != E_OK) {
+            table_[from_segment_idx]->mutexes_[from_bucket_idx].unlock();
+            return ret;
+          }          
+        }
+        table_[from_segment_idx]->mutexes_[from_bucket_idx].unlock();
+      }
+    }
+
+    ATOMIC_STORE(&hash_version_, next_hash_version & (~(1UL<<63)));  // set extending flag is false
+
+    return E_OK;
+  }
+
+  /*
+   * when the key already exists, just update old value to new value;
+   */
+  int put(const KeyType& key, const ValueType& value)
+  {
+    int ret;
+    uint32_t hash_value = hashfunc_(key);
+    
+    while (true) {
+      uint8_t cur_table_capacity = ATOMIC_LOAD(&new_table_capacity_);  
+      size_t segment_idx = hash_value % cur_table_capacity;
+      size_t bucket_idx = hash_value % SEGMENT_CAPACITY;
+
+      table_[segment_idx]->mutexes_[bucket_idx].lock();
+      ret = put_nolock(key, value, segment_idx, bucket_idx); 
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      if (ret != E_OK) {
+        return ret;
+      }           
+
+      if (UNLIKELY(cur_table_capacity != ATOMIC_LOAD(&new_table_capacity_))) {  // resolve the problem of insert into old position
+        ret = remove_from_wrong_bucket(key, segment_idx, bucket_idx);
+        // if (ret != E_OK) {
+        //   return ret;
+        // }
+        continue;
+      } else {
+        break;
+      }
+    }
+
+    if (ATOMIC_LOAD(&size_) > ATOMIC_LOAD(&new_table_capacity_) * SEGMENT_CAPACITY * TABLE_GROWTH) {
+      int tmp = 0;
+      if (ATOMIC_CAS(&is_extending_, &tmp, 1)) {
+        ret = extend();
+        if (ret != E_OK) {
+          ATOMIC_AAF(&is_extending_, -1);
+          return ret;
+        }        
+        ATOMIC_AAF(&is_extending_, -1);
+      }
+    }
+
+    return ret;
+  }
+
+  /*
+   * when the key already exists, just update old value to new value;
+   */
+  int put_nolock(const KeyType& key, const ValueType& value, size_t segment_idx, size_t bucket_idx) 
+  {  
+    if (((*table_[segment_idx])[bucket_idx]).get_valid() == false) {  // if current segment has no valid node
+      ((*table_[segment_idx])[bucket_idx]).set_key(key);
+      ((*table_[segment_idx])[bucket_idx]).set_value(value);
+      ((*table_[segment_idx])[bucket_idx]).set_next(nullptr);      
+      ((*table_[segment_idx])[bucket_idx]).set_valid(true);
+      ((*table_[segment_idx])[bucket_idx]).set_rehashid(ATOMIC_LOAD(&hash_version_));
+      ATOMIC_AAF(&size_, 1);
+    } else if (((*table_[segment_idx])[bucket_idx]).get_key() == key) {  // if current segment's first node's key is same as the target key
+      ((*table_[segment_idx])[bucket_idx]).set_value(value);  // update value of existing node
+      ((*table_[segment_idx])[bucket_idx]).set_rehashid(ATOMIC_LOAD(&hash_version_));
+    } else {  // follow the link list 
+      HashNode<KeyType, ValueType>* prev = &((*table_[segment_idx])[bucket_idx]);
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next();   
+      while (entry != nullptr && entry->get_key() != key) {
+        prev = entry;
+        entry = entry->get_next();
+      }
+      if (LIKELY(entry == nullptr)) {
+        void *buf = mem_alloc(sizeof(HashNode<KeyType, ValueType>), MOD_HASH_TABLE);
+        if (UNLIKELY(nullptr == buf)) {
+          log_error("malloc() failed.");
+          return E_OOM;  
+        }
+        entry = new (buf) HashNode<KeyType, ValueType>;
+        entry->set_key(key);
+        entry->set_value(value);
+        entry->set_valid(true);
+        entry->set_rehashid(ATOMIC_LOAD(&hash_version_));
+        prev->set_next(entry);
+        ATOMIC_AAF(&size_, 1);
+      } else {
+        entry->set_value(value); // update value of existing node
+        entry->set_rehashid(ATOMIC_LOAD(&hash_version_));
+      }
+    }
+    return E_OK;
+  }
+
+  /*
+   * when the key already exists, then remain the old value and return the old value and set 'exist' to true
+   */
+  int put_no_update(const KeyType& key, ValueType& value, bool &exist)
+  {
+    int ret;
+    uint32_t hash_value = hashfunc_(key);    
+    
+    while (true) {
+      uint8_t cur_table_capacity = ATOMIC_LOAD(&new_table_capacity_);  
+      size_t segment_idx = hash_value % cur_table_capacity;
+      size_t bucket_idx = hash_value % SEGMENT_CAPACITY;
+
+      table_[segment_idx]->mutexes_[bucket_idx].lock();
+      ret = put_nolock_no_update(key, value, segment_idx, bucket_idx, exist); 
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      if (ret != E_OK) {
+        return ret;
+      }           
+
+      if (UNLIKELY(cur_table_capacity != ATOMIC_LOAD(&new_table_capacity_))) {  // resolve the problem of insert into old position
+        ret = remove_from_wrong_bucket(key, segment_idx, bucket_idx);
+        // if (ret != E_OK) {
+        //   return ret;
+        // }
+        continue;
+      } else {
+        break;
+      }
+    }
+
+    if (ATOMIC_LOAD(&size_) > ATOMIC_LOAD(&new_table_capacity_) * SEGMENT_CAPACITY * TABLE_GROWTH) {
+      int tmp = 0;
+      if (ATOMIC_CAS(&is_extending_, &tmp, 1)) {
+        ret = extend();
+        if (ret != E_OK) {
+          return ret;
+        }        
+        ATOMIC_AAF(&is_extending_, -1);
+      }
+    }
+
+    return ret;
+  }
+
+
+  /*
+   * when the key already exists, then remain the old value and return the old value and set 'exist' to true
+   */
+  int put_nolock_no_update(const KeyType& key, ValueType& value, size_t segment_idx, size_t bucket_idx, bool &exist) 
+  {  
+    if (((*table_[segment_idx])[bucket_idx]).get_valid() == false) {  // if current segment has no valid node
+      ((*table_[segment_idx])[bucket_idx]).set_key(key);
+      ((*table_[segment_idx])[bucket_idx]).set_value(value);
+      ((*table_[segment_idx])[bucket_idx]).set_next(nullptr);      
+      ((*table_[segment_idx])[bucket_idx]).set_valid(true);
+      ((*table_[segment_idx])[bucket_idx]).set_rehashid(ATOMIC_LOAD(&hash_version_));
+      ATOMIC_AAF(&size_, 1);
+    } else if (((*table_[segment_idx])[bucket_idx]).get_key() == key) {  // if current segment's first node's key is same as the target key
+      exist = true;
+      value = ((*table_[segment_idx])[bucket_idx]).get_value();
+      ((*table_[segment_idx])[bucket_idx]).set_rehashid(ATOMIC_LOAD(&hash_version_));
+    } else {  // follow the link list 
+      HashNode<KeyType, ValueType>* prev = &((*table_[segment_idx])[bucket_idx]);
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next();   
+      while (entry != nullptr && entry->get_key() != key) {
+        prev = entry;
+        entry = entry->get_next();
+      }
+      if (LIKELY(entry == nullptr)) {
+        void *buf = mem_alloc(sizeof(HashNode<KeyType, ValueType>), MOD_HASH_TABLE);
+        if (UNLIKELY(nullptr == buf)) {
+          log_error("malloc() failed.");
+          return E_OOM;  
+        }
+        entry = new (buf) HashNode<KeyType, ValueType>;
+        entry->set_key(key);
+        entry->set_value(value);
+        entry->set_valid(true);
+        entry->set_rehashid(ATOMIC_LOAD(&hash_version_));
+        prev->set_next(entry);
+        ATOMIC_AAF(&size_, 1);
+      } else {
+        exist = true;
+        value = entry->get_value();
+        entry->set_rehashid(ATOMIC_LOAD(&hash_version_));
+      }
+    }
+    return E_OK;
+  }
+
+  int get(const KeyType &key, ValueType &result_value)
+  {
+    if (!ATOMIC_LOAD(&size_)){
+      return E_NOT_EXIST;
+    }    
+    int ret;
+    ValueType result1;
+    ValueType result2;
+    ValueType result3;
+    while (true) {
+      uint64_t hv1 = ATOMIC_LOAD(&hash_version_);
+
+      if ((hv1 & (1UL<<63))) {
+        ret = get_by_bucket(key, result1, ATOMIC_LOAD(&old_table_capacity_));
+        if (ret == E_OK) {
+          result_value = result1;
+          return ret;
+        }
+        ret = get_by_bucket(key, result2, ATOMIC_LOAD(&new_table_capacity_));
+        if (ret == E_OK) {
+          result_value = result2;
+          return ret;
+        }          
+      } else {  // 
+        ret = get_by_bucket(key, result3, ATOMIC_LOAD(&new_table_capacity_));
+        if (ret == E_OK) {
+          result_value = result3;
+          return ret;
+        }    
+      }
+
+      uint64_t hv2 = ATOMIC_LOAD(&hash_version_);
+      if ((hv1 & (~(1UL<<63))) != (hv2 & (~(1UL<<63)))) {
+        continue; 
+      } else if (ATOMIC_LOAD(&is_extending_)) {
+        continue;
+      } else {
+        return E_NOT_EXIST;
+      }      
+    }    
+  }
+
+  int get_by_bucket(const KeyType &key, ValueType &result_value, size_t table_capacity) 
+  {
+    uint32_t hash_value = hashfunc_(key);
+    size_t segment_idx = hash_value % table_capacity; 
+    size_t bucket_idx = hash_value % SEGMENT_CAPACITY;
+
+    table_[segment_idx]->mutexes_[bucket_idx].lock();
+    
+    if (!((*table_[segment_idx])[bucket_idx]).get_valid()) {  // if current segment has no node
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_NOT_EXIST;
+    } else if (((*table_[segment_idx])[bucket_idx]).get_key() == key) {
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      result_value = ((*table_[segment_idx])[bucket_idx]).get_value();
+      return E_OK;
+    } else {
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next();   
+      while (entry != nullptr) {
+        if (entry->get_key() == key) {
+          table_[segment_idx]->mutexes_[bucket_idx].unlock();
+          result_value = entry->get_value();
+          return E_OK;
+        }
+        entry = entry->get_next();
+      }
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_NOT_EXIST;
+    }
+  }  
+
+  int remove(const KeyType& key)
+  {
+    if (!ATOMIC_LOAD(&size_)){
+      return E_NOT_EXIST;
+    }     
+    int ret;
+    while (true) {
+      uint64_t hv1 = ATOMIC_LOAD(&hash_version_);
+
+      if ((hv1 & (1UL<<63))) {
+        ret = remove_by_bucket(key, ATOMIC_LOAD(&old_table_capacity_));
+        if (ret == E_OK) {
+          return ret;
+        }
+        ret = remove_by_bucket(key, ATOMIC_LOAD(&new_table_capacity_));
+        if (ret == E_OK) {
+          return ret;
+        }          
+      } else {
+        ret = remove_by_bucket(key, ATOMIC_LOAD(&new_table_capacity_));
+        if (ret == E_OK) {
+          return ret;
+        }    
+      }
+
+      uint64_t hv2 = ATOMIC_LOAD(&hash_version_);
+      if ((hv1 & (~(1UL<<63))) != (hv2 & (~(1UL<<63)))) {
+        continue; 
+      } else if (ATOMIC_LOAD(&is_extending_)) {
+        continue;
+      } else {
+        return E_NOT_EXIST;
+      }      
+    }      
+  }
+
+  int remove_by_bucket(const KeyType& key, size_t table_capacity) 
+  {
+    uint32_t hash_value = hashfunc_(key);
+    size_t segment_idx = hash_value % table_capacity;
+    size_t bucket_idx = hash_value % SEGMENT_CAPACITY;  
+
+    table_[segment_idx]->mutexes_[bucket_idx].lock();
+
+    if (!((*table_[segment_idx])[bucket_idx]).get_valid()) {  // if current segment has no node
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_NOT_EXIST;
+    } else if (((*table_[segment_idx])[bucket_idx]).get_key() == key) {
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next(); 
+      if (entry != nullptr) {
+        ((*table_[segment_idx])[bucket_idx]).set_key(entry->get_key());
+        ((*table_[segment_idx])[bucket_idx]).set_value(entry->get_value());
+        ((*table_[segment_idx])[bucket_idx]).set_next(entry->get_next());      
+        ((*table_[segment_idx])[bucket_idx]).set_valid(true);        
+        ((*table_[segment_idx])[bucket_idx]).set_rehashid(entry->get_rehashid());
+        entry->~HashNode(); 
+        mem_free(entry);
+        entry = nullptr;
+      } else {
+        ((*table_[segment_idx])[bucket_idx]).set_valid(false);
+      }
+      ATOMIC_AAF(&size_, -1);
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_OK;  
+    } else {
+      HashNode<KeyType, ValueType>* prev = &((*table_[segment_idx])[bucket_idx]);
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next();   
+      while (entry != nullptr) {
+        if (entry->get_key() == key) {
+          prev->set_next(entry->get_next()); // remove node and reconnect
+          entry->~HashNode(); 
+          mem_free(entry);
+          entry = nullptr;
+          ATOMIC_AAF(&size_, -1);
+          table_[segment_idx]->mutexes_[bucket_idx].unlock();
+          return E_OK;
+        }
+        prev = entry;
+        entry = entry->get_next();
+      }
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_NOT_EXIST;
+    }
+  }
+
+  int remove_from_wrong_bucket(const KeyType& key, size_t segment_idx, size_t bucket_idx) 
+  {
+    if (!ATOMIC_LOAD(&size_)){ 
+      return E_NO_MORE_DATA;
+    }
+
+    table_[segment_idx]->mutexes_[bucket_idx].lock();
+
+    if (!((*table_[segment_idx])[bucket_idx]).get_valid()) {  // if current segment has no node
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_NOT_EXIST;
+    } else if (((*table_[segment_idx])[bucket_idx]).get_key() == key) {
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next(); 
+      if (entry != nullptr) {
+        ((*table_[segment_idx])[bucket_idx]).set_key(entry->get_key());
+        ((*table_[segment_idx])[bucket_idx]).set_value(entry->get_value());
+        ((*table_[segment_idx])[bucket_idx]).set_next(entry->get_next());      
+        ((*table_[segment_idx])[bucket_idx]).set_valid(true);        
+        ((*table_[segment_idx])[bucket_idx]).set_rehashid(entry->get_rehashid());
+        entry->~HashNode(); 
+        mem_free(entry);
+        entry = nullptr;
+      } else {
+        ((*table_[segment_idx])[bucket_idx]).set_valid(false);
+      }
+      ATOMIC_AAF(&size_, -1);
+      table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_OK;  
+    } else {
+      HashNode<KeyType, ValueType>* prev = &((*table_[segment_idx])[bucket_idx]);
+      HashNode<KeyType, ValueType>* entry = ((*table_[segment_idx])[bucket_idx]).get_next();   
+      while (entry != nullptr) {
+        if (entry->get_key() == key) {
+          prev->set_next(entry->get_next()); // remove node and reconnect
+          entry->~HashNode(); 
+          mem_free(entry);
+          entry = nullptr;
+          ATOMIC_AAF(&size_, -1);
+          table_[segment_idx]->mutexes_[bucket_idx].unlock();
+          return E_OK;
+        }
+        prev = entry;
+        entry = entry->get_next();
+      }
+        table_[segment_idx]->mutexes_[bucket_idx].unlock();
+      return E_NOT_EXIST;
+    }
+  }
+
+#ifndef NDEBUG
+  void print() 
+  {
+    printf("<< The Hash Table >>\n");
+    if (!ATOMIC_AAF(&size_, 0)){
+      printf("  Empty now!\n");
+      return;
+    }
+    size_t bucket_num = 0;
+    for (size_t i = 0; i < ATOMIC_AAF(&new_table_capacity_, 0); i++) {
+      for (size_t j = 0; j < SEGMENT_CAPACITY; j++) {
+        // printf("----(%ld)segment id is %ld, bucket id is %ld----\n", bucket_num++, i, j);
+        if ((*table_[i])[j].get_valid()) {
+          printf("----(%ld)segment id is %ld, bucket id is %ld----\n", bucket_num++, i, j);
+          std::cout << "|      " << "key is " << (*table_[i])[j].get_key() << ", value is " << (*table_[i])[j].get_value() << ", rehashid is " << (int)(*table_[i])[j].get_rehashid() << std::endl;
+          HashNode<KeyType, ValueType>* entry = ((*table_[i])[j]).get_next();   
+          while (entry != nullptr) {
+            std::cout << "|      " << "key is " << entry->get_key() << ", value is " << entry->get_value() << ", rehashid is " << (int)entry->get_rehashid() << std::endl;
+            entry = entry->get_next();
+          }
+        } else {
+          bucket_num++;
+        }
+      }
+    }  
+  }  
+#endif // #ifndef NDEBUG
+
+  FORCE_INLINE bool empty() const
+  {
+    return ATOMIC_LOAD(&size_) == 0;
+  }
+
+  FORCE_INLINE size_t size()
+  {
+    return ATOMIC_LOAD(&size_);
+  }
+
+  FORCE_INLINE size_t total_capacity() 
+  {
+    return ATOMIC_LOAD(&new_table_capacity_) * SEGMENT_CAPACITY;
+  }
+
+private:
+  size_t new_table_capacity_;
+  size_t old_table_capacity_;
+  size_t size_;
+  uint64_t hash_version_;
+  Array< HashSegm<KeyType, ValueType>* > table_;  // the element in Array is pointer. 
+  bool is_inited_;
+  uint8_t is_extending_;    
+  F hashfunc_;  
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif  // COMMON_CONTAINER_HASH_TABLE_H
diff --git a/cpp/tsfile/src/common/container/list.h b/cpp/tsfile/src/common/container/list.h
new file mode 100644
index 00000000..151f5feb
--- /dev/null
+++ b/cpp/tsfile/src/common/container/list.h
@@ -0,0 +1,147 @@
+
+#ifndef COMMON_CONTAINER_LIST_H
+#define COMMON_CONTAINER_LIST_H
+
+#include "common/allocator/page_arena.h"
+#include "common/errno_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+#define INVALID_NODE_PTR ((SimpleListNode*)0xABCDEF)
+
+/*
+ * A very simple list.
+ * There are such scenarios:
+ *   We prepare all data in the list, and pass the list as immutable
+ *   parameters to other module or caller. We never do delete or complex
+ *   push operations.
+ *   for example:
+ *     SchemaMgr::get_timeseries_by_tsid(TsID, list<ColumnDesc>&)
+ *     SchemaMgr::create_aligned_timeseries(..., const list<char*> &measurement_list, ...)
+ * 
+ * Note: not thread safe!
+ */
+template<class T>
+class SimpleList
+{
+private:
+  struct SimpleListNode
+  {
+    T data_;
+    SimpleListNode *next_;
+
+    SimpleListNode() : next_(nullptr) {}
+    SimpleListNode(const T &data) : data_(data), next_(nullptr) {}
+  };
+
+public:
+  class Iterator
+  {
+  public:
+    Iterator(SimpleListNode *node) : cur_(node) {}
+    Iterator() : cur_(INVALID_NODE_PTR) {}
+    T &get() { return cur_->data_; }
+    FORCE_INLINE bool is_inited() const
+    {
+      return cur_ != INVALID_NODE_PTR;
+    }
+    FORCE_INLINE Iterator& operator++(int n)
+    {
+      if (LIKELY(cur_ != nullptr)) {
+        cur_ = cur_->next_;
+      }
+      return *this;
+    }
+    FORCE_INLINE bool operator!=(const Iterator &other) const
+    {
+      return this->cur_ != other.cur_;
+    }
+    FORCE_INLINE bool operator==(const Iterator &other) const
+    {
+      return this->cur_ == other.cur_;
+    }
+  private:
+    SimpleListNode *cur_;
+  };
+
+public:
+  SimpleList(const uint32_t page_size, AllocModID mid) : head_(nullptr), tail_(nullptr), size_(0)
+  {
+    own_page_arena_.init(page_size, mid);
+    page_arena_ = &own_page_arena_;
+  }
+
+  SimpleList(PageArena *page_arena) : page_arena_(page_arena), head_(nullptr), tail_(nullptr), size_(0)
+  {
+    // page_arena_ should be destroy outside by caller
+  }
+
+  int push_back(const T &data)
+  {
+    void *buf = page_arena_->alloc(sizeof(SimpleListNode));
+    if (UNLIKELY(buf == nullptr)) {
+      return common::E_OOM;
+    }
+    SimpleListNode *node = new(buf) SimpleListNode(data);
+    if (head_ == nullptr) {
+      head_ = node;
+      tail_ = node;
+    } else {
+      assert(tail_ != nullptr);
+      tail_->next_ = node;
+      tail_ = node;
+    }
+    size_++;
+    return common::E_OK;
+  }
+
+  FORCE_INLINE T& front()
+  {
+    ASSERT(size_ > 0 && head_ != nullptr);
+    return head_->data_;
+  }
+
+  int remove(T target)
+  {
+    if (head_ == nullptr) {
+      return common::E_NOT_EXIST;
+    }
+    SimpleListNode *prev = head_;
+    SimpleListNode *cur = head_->next_;
+    while (cur && cur->data_ != target) {
+      cur = cur->next_;
+    }
+    if (cur) {
+      return common::E_NOT_EXIST;
+    }
+    prev->next_ = cur->next_;
+    // cur is allocated from PageArena, it should not reclaim now
+    return common::E_OK;
+  }
+
+  FORCE_INLINE Iterator begin() const { return Iterator(head_); }
+  FORCE_INLINE Iterator end() const { return Iterator(nullptr); }
+  FORCE_INLINE uint32_t size() const { return size_; }
+  FORCE_INLINE void clear()
+  {
+    head_ = nullptr;
+    tail_ = nullptr;
+    size_ = 0;
+    own_page_arena_.destroy();
+  }
+private:
+  PageArena *page_arena_;
+  PageArena own_page_arena_;
+  SimpleListNode *head_;
+  SimpleListNode *tail_;
+  uint32_t size_;
+};
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_CONTAINER_LIST_H
+
diff --git a/cpp/tsfile/src/common/container/murmur_hash3.cc b/cpp/tsfile/src/common/container/murmur_hash3.cc
new file mode 100644
index 00000000..2604a00f
--- /dev/null
+++ b/cpp/tsfile/src/common/container/murmur_hash3.cc
@@ -0,0 +1,126 @@
+#include "murmur_hash3.h"
+
+namespace timecho 
+{
+namespace common
+{
+
+/* ================ Murmur128Hash ================ */
+// follow Java IoTDB exactly.
+int64_t Murmur128Hash::inner_hash(const char *buf, int32_t len, int64_t seed)
+{
+  const int block_count = len >> 4; // as 128-bit blocks
+  int64_t h1 = seed;
+  int64_t h2 = seed;
+  int64_t c1 = 0x87c37b91114253d5L;
+  int64_t c2 = 0x4cf5ad432745937fL;
+
+  for (int i = 0; i < block_count; i++) {
+    int64_t k1 = get_block(buf, i * 2);
+    int64_t k2 = get_block(buf, i * 2 + 1);
+    k1 *= c1;
+    k1 = rotl64(k1, 31);
+    k1 *= c2;
+    h1 ^= k1;
+    h1 = rotl64(h1, 27);
+    h1 += h2;
+    h1 = h1 * 5 + 0x52dce729;
+    k2 *= c2;
+    k2 = rotl64(k2, 33);
+    k2 *= c1;
+    h2 ^= k2;
+    h2 = rotl64(h2, 31);
+    h2 += h1;
+    h2 = h2 * 5 + 0x38495ab5;
+  }
+
+  int offset = block_count * 16;
+  int64_t k1 = 0;
+  int64_t k2 = 0;
+  switch (len & 15) {
+    case 15:
+      k2 ^= ((int64_t)(buf[offset + 14])) << 48;
+      // fallthrough
+    case 14:
+      k2 ^= ((int64_t)(buf[offset + 13])) << 40;
+      // fallthrough
+    case 13:
+      k2 ^= ((int64_t)(buf[offset + 12])) << 32;
+      // fallthrough
+    case 12:
+      k2 ^= ((int64_t)(buf[offset + 11])) << 24;
+      // fallthrough
+    case 11:
+      k2 ^= ((int64_t)(buf[offset + 10])) << 16;
+      // fallthrough
+    case 10:
+      k2 ^= ((int64_t)(buf[offset + 9])) << 8;
+      // fallthrough
+    case 9:
+      k2 ^= buf[offset + 8];
+      k2 *= c2;
+      k2 = rotl64(k2, 33);
+      k2 *= c1;
+      h2 ^= k2;
+      // fallthrough
+    case 8:
+      k1 ^= ((int64_t)buf[offset + 7]) << 56;
+      // fallthrough
+    case 7:
+      k1 ^= ((int64_t)buf[offset + 6]) << 48;
+      // fallthrough
+    case 6:
+      k1 ^= ((int64_t)buf[offset + 5]) << 40;
+      // fallthrough
+    case 5:
+      k1 ^= ((int64_t)buf[offset + 4]) << 32;
+      // fallthrough
+    case 4:
+      k1 ^= ((int64_t)buf[offset + 3]) << 24;
+      // fallthrough
+    case 3:
+      k1 ^= ((int64_t)buf[offset + 2]) << 16;
+      // fallthrough
+    case 2:
+      k1 ^= ((int64_t)buf[offset + 1]) << 8;
+      // fallthrough
+    case 1:
+      k1 ^= buf[offset];
+      k1 *= c1;
+      k1 = rotl64(k1, 31);
+      k1 *= c2;
+      h1 ^= k1;
+      break;
+    default: // 0
+      // do nothing
+      break;
+  }
+
+  h1 ^= len;
+  h2 ^= len;
+  h1 += h2;
+  h2 += h1;
+  h1 = fmix(h1);
+  h2 = fmix(h2);
+  h1 += h2;
+  h2 += h1;
+  return h1 + h2;
+}
+
+int64_t Murmur128Hash::get_block(const char *buf, int32_t index)
+{
+  int block_offset = index << 3;
+  int64_t res = 0;
+  res +=  ((int64_t)(buf[block_offset + 0] & 0xFF));
+  res += (((int64_t)(buf[block_offset + 1] & 0xFF)) <<  8);
+  res += (((int64_t)(buf[block_offset + 2] & 0xFF)) << 16);
+  res += (((int64_t)(buf[block_offset + 3] & 0xFF)) << 24);
+  res += (((int64_t)(buf[block_offset + 4] & 0xFF)) << 32);
+  res += (((int64_t)(buf[block_offset + 5] & 0xFF)) << 40);
+  res += (((int64_t)(buf[block_offset + 6] & 0xFF)) << 48);
+  res += (((int64_t)(buf[block_offset + 7] & 0xFF)) << 56);
+  return res;
+}
+
+}  // end namespace common
+}  // end namespace timecho
diff --git a/cpp/tsfile/src/common/container/murmur_hash3.h b/cpp/tsfile/src/common/container/murmur_hash3.h
new file mode 100644
index 00000000..e0d69600
--- /dev/null
+++ b/cpp/tsfile/src/common/container/murmur_hash3.h
@@ -0,0 +1,67 @@
+#ifndef COMMON_CONTAINER_MURMUR3_MURMUR_HASH3_H
+#define COMMON_CONTAINER_MURMUR3_MURMUR_HASH3_H
+
+#include <string>
+#include "common/db_utils.h"
+#include "common/allocator/my_string.h"
+
+namespace timecho 
+{
+namespace common
+{
+
+/*
+ * Murmur128Hash has to follow the logic in Java IoTDB,
+ * since the bitmap buffer will be serialized to tsfile.
+ */
+class Murmur128Hash
+{
+public:
+  FORCE_INLINE static int32_t hash(int32_t value, uint32_t seed) 
+  {
+    return inner_hash(reinterpret_cast<const char *>(&value), 4, seed);
+  }
+
+  FORCE_INLINE static int32_t hash(int64_t value, uint32_t seed)
+  {
+    return inner_hash(reinterpret_cast<const char *>(&value), 8, seed);
+  }
+
+  FORCE_INLINE static int32_t hash(double value, uint32_t seed) 
+  {
+    return inner_hash(reinterpret_cast<const char *>(&value), 8, seed);
+  }
+
+  FORCE_INLINE static int32_t hash(std::string &value, uint32_t seed) 
+  {
+    return inner_hash(value.data(), static_cast<uint32_t >(value.size()), seed);
+  }
+
+  FORCE_INLINE static int32_t hash(const common::String &buf, int32_t seed)
+  {
+    return inner_hash(buf.buf_, buf.len_ - 1, seed);
+  }
+private:
+  FORCE_INLINE static int64_t rotl64(int64_t v, int n)
+  {
+    uint64_t uv = (uint64_t)v;
+    return ((uv << n) | (uv >> (64 - n)));
+  }
+  FORCE_INLINE static int64_t fmix(int64_t k)
+  {
+    uint64_t uk = (uint64_t)k;
+    uk ^= uk >> 33;
+    uk *= 0xff51afd7ed558ccdL;
+    uk ^= uk >> 33;
+    uk *= 0xc4ceb9fe1a85ec53L;
+    uk ^= uk >> 33;
+    return (int64_t)uk;
+  }
+  static int64_t get_block(const char *buf, int32_t index);
+  static int64_t inner_hash(const char *buf, int32_t len, int64_t seed);
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif // COMMON_CONTAINER_MURMUR3_MURMUR_HASH3_H
diff --git a/cpp/tsfile/src/common/container/simple_vector.h b/cpp/tsfile/src/common/container/simple_vector.h
new file mode 100644
index 00000000..67c69749
--- /dev/null
+++ b/cpp/tsfile/src/common/container/simple_vector.h
@@ -0,0 +1,48 @@
+#ifndef COMMON_CONTAINER_VECTOR_H
+#define COMMON_CONTAINER_VECTOR_H
+
+#include "common/util_define.h" 
+
+namespace timecho 
+{
+namespace common
+{
+
+template<typename T>
+class SimpleVector
+{
+public:
+  SimpleVector() : std_vec_(), size_(0) {}
+  void push_back(T t)
+  {
+    if (LIKELY(size_ < STACKED_ITEM_COUNT)) {
+      stacked_items_[size_] = t;
+    } else {
+      std_vec_.push_back(t);
+    }
+    size_++;
+  }
+  size_t size() { return size_; }
+  T operator[](int index)
+  {
+    if (UNLIKELY((size_t)index > size_)) {
+      abort();
+    }
+    if (index < STACKED_ITEM_COUNT) {
+      return stacked_items_[index];
+    } else {
+      return std_vec_[index - STACKED_ITEM_COUNT];
+    }
+  }
+private:
+  static const int STACKED_ITEM_COUNT = 16;
+  T stacked_items_[STACKED_ITEM_COUNT];
+  std::vector<T> std_vec_;
+  size_t size_;
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+
+#endif
diff --git a/cpp/tsfile/src/common/container/slice.h b/cpp/tsfile/src/common/container/slice.h
new file mode 100644
index 00000000..b2e44247
--- /dev/null
+++ b/cpp/tsfile/src/common/container/slice.h
@@ -0,0 +1,142 @@
+#ifndef COMMON_CONTAINER_SLICE_H
+#define COMMON_CONTAINER_SLICE_H
+
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <string>
+#include "common/allocator/alloc_base.h"
+#include "common/logger/elog.h"
+#include "common/errno_define.h"
+#include "common/util_define.h" 
+
+namespace timecho 
+{
+namespace common
+{
+
+class Slice 
+{
+ public:
+  // Create an empty slice.
+  // Slice() : data_(""), size_(0) {}
+  Slice()
+  {
+    data_ = nullptr;
+    size_ = 0;
+  }
+
+  // Create a slice that refers to the contents of "s"
+  // Slice(const std::string& s) : data_(s.data()), size_(s.size()) {}
+  Slice(const std::string &s)
+  {
+    int len = s.size();
+    data_ = (char *)malloc(len + 1);  // TODO: user ourself's mem_alloc()
+    if (UNLIKELY(nullptr == data_)) {
+      log_error("malloc() failed.");
+    }  
+    strcpy(data_, s.c_str());
+    size_ = len;
+  }
+
+  // Create a slice that refers to s[0,strlen(s)-1]
+  // Slice(const char* s) : data_(s), size_(strlen(s)) {}
+  Slice(const char *s)
+  {
+    int len = strlen(s);
+    data_ = (char *)malloc(len + 1);  // TODO: user ourself's mem_alloc()
+    if (UNLIKELY(nullptr == data_)) {
+      log_error("malloc() failed.");
+    }  
+    strcpy(data_, s);
+    size_ = len;
+  }
+
+  ~Slice()
+  {
+    free(data_);  // TODO: user ourself's mem_free()
+    data_ = nullptr;
+    size_ = 0;
+  }
+
+  // Intentionally copyable.
+  // Slice(const Slice&) = default;
+  // Slice& operator=(const Slice&) = default;
+  Slice(const Slice &other) 
+  {
+    int len = other.size_;
+    data_ = (char *)malloc(len + 1);  // TODO: user ourself's mem_alloc()
+    if (UNLIKELY(nullptr == data_)) {
+      log_error("malloc() failed.");
+    }  
+    strcpy(data_, other.data_);
+    size_ = len;    
+  }
+  Slice& operator=(const Slice &other)
+  {
+    if (this->data_ != nullptr) {
+      free(data_);  // TODO: user ourself's mem_free()
+      data_ = nullptr;
+    }
+    int len = other.size_;
+    this->data_ = (char *)malloc(len + 1);  // TODO: user ourself's mem_alloc()
+    if (UNLIKELY(nullptr == data_)) {
+      log_error("malloc() failed.");
+    }  
+    strcpy(this->data_, other.data_);
+    this->size_ = len;
+    return *this;     
+  }
+
+  // Return a pointer to the beginning of the referenced data
+  char* data() const { return data_; }
+
+  // Return the length (in bytes) of the referenced data
+  size_t size() const { return size_; }
+
+  // Return true iff the length of the referenced data is zero
+  bool empty() const { return size_ == 0; }
+
+  // Return the ith byte in the referenced data.
+  char operator[](size_t n) const {
+    ASSERT(n < size());
+    return data_[n];
+  }
+
+  // Return a string that contains the copy of the referenced data.
+  std::string to_string() const { return std::string(data_, size_); }
+
+  friend bool operator==(const Slice &x, const Slice &y) {
+    return ((x.size() == y.size()) &&
+          (memcmp(x.data(), y.data(), x.size()) == 0));
+  }
+
+  friend bool operator!=(const Slice &x, const Slice &y) { return !(x == y); }
+
+  // Three-way comparison.  Returns value:
+  //   <  0 iff "*this" <  "b",
+  //   == 0 iff "*this" == "b",
+  //   >  0 iff "*this" >  "b"
+  int compare(const Slice &b) const 
+  {
+    const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
+    int r = memcmp(data_, b.data_, min_len);
+    if (r == 0) {
+      if (size_ < b.size_)
+        r = -1;
+      else if (size_ > b.size_)
+        r = +1;
+    }
+    return r;
+  }
+
+
+private:
+  char   *data_;
+  size_t size_;
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif  // COMMON_CONTAINER_SLICE_H
diff --git a/cpp/tsfile/src/common/container/sorted_array.h b/cpp/tsfile/src/common/container/sorted_array.h
new file mode 100644
index 00000000..dfcae3b2
--- /dev/null
+++ b/cpp/tsfile/src/common/container/sorted_array.h
@@ -0,0 +1,333 @@
+/*
+* no duplicated elements
+*/
+#ifndef COMMON_CONTAINER_SORTEDARRAY_H
+#define COMMON_CONTAINER_SORTEDARRAY_H
+
+#include <cstdlib>
+#include <cstdio>
+#include <stdint.h>
+#include <cstring>
+#include <iostream>
+#include "common/allocator/alloc_base.h"
+#include "common/logger/elog.h"
+#include "common/errno_define.h"
+#include "common/util_define.h" 
+
+#define SORTED_ARRAY_INIT_CAPACITY 1000  // TODO: configurable mode
+#define SORTED_ARRAY_GROWTH_THRESHOLD 50  // TODO: configurable mode
+#define SORTED_ARRAY_SHRINK_THRESHOLD 50  // TODO: configurable mode
+
+namespace timecho 
+{
+namespace common
+{
+
+template <class ValueType>
+class SortedArray
+{
+public:
+
+#ifndef NDEBUG
+  friend std::ostream& operator << (std::ostream &out, SortedArray<ValueType> &sa)
+  {
+    for (size_t idx = 0; idx < sa.size(); idx++) {
+      if (idx > 0) {
+        out << ' ';
+      }
+      out << sa.at(idx);
+    }
+    out << std::endl;
+    return out;
+  }
+#endif  // NDEBUG
+
+  SortedArray()
+  {
+    capacity_ = SORTED_ARRAY_INIT_CAPACITY;
+    size_ = 0;
+    is_inited_ = false;
+    array_ = nullptr;      
+  }
+
+  SortedArray(size_t capacity)
+  {
+    capacity_ = capacity;
+    size_ = 0;
+    is_inited_ = false;  
+    array_ = nullptr;      
+  }
+
+  ~SortedArray()
+  {
+    if (is_inited_) {
+      destroy();
+    }
+    capacity_ = 0;
+    size_ = 0;
+  }  
+
+  // int deep_copy(const SortedArray &other)
+  // {
+  //   this->capacity_ = other.capacity_;
+  //   this->size_ = other.size_;
+  //   if (init() == E_OK) {
+  //     memcpy(this->array_, other.array_, this->capacity_ * sizeof(*(this->array_))); 
+  //     return E_OK;
+  //   }
+  //   return E_OOM;
+  // }
+
+  int init()
+  {
+    if (is_inited_) {
+      log_error("init repeated.");
+      ASSERT(!is_inited_);
+    } 
+    array_ = (ValueType *)mem_alloc(capacity_ * sizeof(*(array_)), MOD_ARRAY);
+    if (UNLIKELY(nullptr == array_)) {
+      is_inited_ = false;
+      log_error("malloc failed.");
+      return E_OOM;  
+    }
+    is_inited_ = true;
+    return E_OK;  
+  }
+
+  void destroy()
+  {
+    capacity_ = 0;
+    size_ = 0;
+    if (is_inited_) {
+      mem_free(array_);
+      array_ = nullptr;
+    }
+    is_inited_ = false;
+  }
+
+private:
+  static size_t linear_calc(size_t input)
+  {
+    if (input < SORTED_ARRAY_GROWTH_THRESHOLD) {
+      return input;
+    }
+    size_t res = 1;
+    input /= 10;
+    while (input) {
+      input /= 10;
+      res *= 10;
+    }
+    return res;
+  }
+
+  int extend()
+  {
+    // Check for a potential overflow
+    uint64_t tmp = (uint64_t) (linear_calc(capacity_) + capacity_);
+    if (tmp > SIZE_MAX) {
+      log_error("size overflow.");
+      return E_OVERFLOW;
+    }
+
+    size_t new_capacity = (size_t) tmp;
+    array_ = (ValueType *)mem_realloc(array_, new_capacity * sizeof(*(array_)));
+    if (UNLIKELY(nullptr == array_)) {
+      log_error("realloc failed.");
+      return E_OOM;  
+    }
+    capacity_ = new_capacity;
+    return E_OK;
+  }
+
+  int shrink()
+  {
+    size_t new_capacity = (size_t)(capacity_ / 2);
+    // if the size passed to realloc is smaller than before, OS will automatically release the rest memory
+    array_ = (ValueType *)mem_realloc(array_, new_capacity * sizeof(*(array_)));  // TODO: user ourself's mem_alloc()
+    if (UNLIKELY(nullptr == array_)) {
+      log_error("malloc failed.");
+      return E_OOM;  
+    }    
+    capacity_ = new_capacity;
+    return E_OK;
+  }
+
+public:
+  int insert(const ValueType &value)
+  {
+    if (size_ >= capacity_) {
+      int ret = extend();
+      if(ret != E_OK) {
+        return ret;
+      }
+    }
+
+    bool found = false;
+    size_t pos = find(value, found);
+    if (found) {
+      log_warn("the new value has already in the sorted array.");
+      return E_ALREADY_EXIST;
+    }
+    
+    if (pos == size_) {
+      array_[pos] = value;
+      size_++;
+      return E_OK;  
+    }
+
+    memmove(array_ + (pos + 1), array_ + pos, (size_ - pos) * sizeof(*(array_)));  
+    array_[pos] = value;
+    size_++;
+    return E_OK;
+  }
+
+  FORCE_INLINE ValueType at(size_t idx)
+  {
+    if (idx >= size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      ASSERT(idx < size_);
+      return dummy_;
+    }
+    return array_[idx];
+  }
+
+  FORCE_INLINE ValueType operator [] (size_t idx)
+  {
+    if (idx >= size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      ASSERT(idx < size_);
+      return dummy_;
+    }  
+    return array_[idx];
+  }
+
+  bool contain(const ValueType &target_val)
+  {
+    if (size_ == 0) {
+      return false;
+    }
+    int64_t left = 0;
+    int64_t right = size_ - 1;
+    while (left <= right) {
+      size_t mid = (left + right) / 2;
+      ValueType mid_val = array_[mid];
+      if (mid_val == target_val) {
+        return true;
+      } else if (mid_val < target_val) {
+        left = mid + 1;
+      } else if (mid_val > target_val) {
+        right = mid - 1; 
+      } 
+    }
+    return false;    
+  }
+
+  /*
+   * if the value is not found, then set 'found' is false ant return the first bigger one's location
+   */
+  size_t find(const ValueType &target_val, bool &found)
+  {
+    if (size_ == 0) {
+      found = false;
+      return 0;
+    }
+    int64_t left = 0;
+    int64_t right = size_ - 1;
+    while (left <= right) {
+      size_t mid = (left + right) / 2;
+      ValueType mid_val = array_[mid];
+      if (mid_val == target_val) {
+        found = true;
+        return mid;
+      } else if (mid_val < target_val) {
+        left = mid + 1;
+      } else if (mid_val > target_val) {
+        right = mid - 1; 
+      } 
+    }
+    found = false;
+    return (size_t)left;
+  }
+
+  ValueType remove(size_t idx)
+  {
+    if (idx >= size_) {
+      log_error("index %lu is out of range, because size is %lu.", idx, size_);
+      ASSERT(idx < size_);
+    }
+    if (capacity_ > SORTED_ARRAY_SHRINK_THRESHOLD && size_ <= capacity_ / 4) {
+      shrink(); 
+    }
+    ValueType ret = array_[idx];
+    memmove(array_ + idx, array_ + idx + 1, (size_ - idx - 1) * sizeof(*(array_)));  
+    size_--;
+
+    return ret;
+  }
+
+  int remove_value(const ValueType &value)
+  {
+    bool found = false;
+    size_t pos = find(value, found);
+    if(found) {
+      remove(pos);
+    } else {
+      log_warn("the value is not exist in the array.");
+      return E_NOT_EXIST;
+    }
+    return E_OK;
+  }
+
+  FORCE_INLINE void clear()
+  {
+    size_ = 0;
+  }
+
+  ValueType get_min()
+  {
+    if (size_ == 0) {
+      log_warn("The array is empty now.");
+      ASSERT(size_ > 0);
+      return dummy_;
+    }
+    return array_[0];
+  }
+
+  ValueType& get_max()
+  {
+    if (size_ == 0) {
+      log_warn("The array is empty now.");
+      ASSERT(size_ > 0);
+      return dummy_;
+    }
+    return array_[size_ - 1];
+  }
+
+  FORCE_INLINE bool empty() const
+  {
+    return ATOMIC_LOAD(&size_) == 0;
+  }
+
+  FORCE_INLINE size_t size() const
+  {
+    return ATOMIC_LOAD(&size_);
+  }
+
+  FORCE_INLINE size_t capacity() const
+  {
+    return ATOMIC_LOAD(&capacity_);
+  }
+
+private:
+  size_t capacity_;
+  size_t size_;
+  ValueType *array_;
+  ValueType dummy_;
+  bool is_inited_;
+};
+
+}  // end namespace common
+}  // end namespace timecho
+
+
+#endif  // COMMON_CONTAINER_SORTEDARRAY_H
diff --git a/cpp/tsfile/src/common/datatype/CMakeLists.txt b/cpp/tsfile/src/common/datatype/CMakeLists.txt
new file mode 100644
index 00000000..9beefbae
--- /dev/null
+++ b/cpp/tsfile/src/common/datatype/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+# message("Running in src/common/datatype directory")
+# 
+# aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} common_datatype_SRC_LIST)
+# set(common_datatype_INC_LIST)
+# set(common_datatype_DEFINE_OPTIONS)
+# set(common_datatype_COMPILE_OPTIONS)
+# set(common_datatype_LINK_OPTIONS)
+# 
+# add_statis_objtarget(common_datatype common_datatype_SRC_LIST common_datatype_INC_LIST
+#                      "${common_datatype_DEFINE_OPTIONS}"
+#                      "${common_datatype_COMPILE_OPTIONS}"
+#                      "${common_datatype_LINK_OPTIONS}")
diff --git a/cpp/tsfile/src/common/datatype/value.h b/cpp/tsfile/src/common/datatype/value.h
new file mode 100644
index 00000000..bc73cb71
--- /dev/null
+++ b/cpp/tsfile/src/common/datatype/value.h
@@ -0,0 +1,216 @@
+#ifndef COMMON_DATATYPE_VALUE_H
+#define COMMON_DATATYPE_VALUE_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <float.h>
+#include <vector>
+#include <utility>
+
+#include "common/db_utils.h"
+#include "common/logger/elog.h"
+
+namespace timecho
+{
+namespace common
+{
+
+struct Value
+{
+  Value(TSDataType type) : type_(type) {}
+
+  ~Value()
+  {
+    if (value_.sval_) {
+      free(value_.sval_);
+    }
+  }
+
+  FORCE_INLINE void free_memory()
+  {
+    if (value_.sval_) {
+      free(value_.sval_);
+      value_.sval_ = nullptr;
+    }
+  }
+
+  FORCE_INLINE bool is_type(TSDataType type) const
+  {
+    return type == type_;
+  }
+
+  FORCE_INLINE bool is_literal() const
+  {
+    return is_type(BOOLEAN) || is_type(DOUBLE) ||
+           is_type(TEXT) || is_type(INT64) || is_type(NULL_TYPE);
+  }
+
+  template<class T>
+  FORCE_INLINE void set_value(TSDataType type, T val)
+  {
+    type_ = type;
+    switch (type) {
+      case common::BOOLEAN: {
+        value_.bval_ = *(bool*)val;
+        break;
+      }
+      case common::INT32: {
+        value_.ival_ = *(int32_t*)val;
+        break;
+      }
+      case common::INT64: {
+        value_.lval_ = *(int64_t*)val;
+        break;
+      }
+      case common::FLOAT: {
+        value_.fval_ = *(float*)val;
+        break;
+      }
+      case common::DOUBLE: {
+        value_.dval_ = *(double*)val;
+        break;
+      }
+      case common::TEXT: {
+        value_.sval_ = strdup(val);
+        break;
+      }
+      default: {
+        common::log_error("unknown data type");
+      }
+    }
+  }
+
+public:
+  TSDataType type_;
+
+  union {
+    bool    bval_;
+    int64_t lval_;
+    int32_t ival_;
+    float   fval_;
+    double  dval_;
+    char    *sval_;
+  } value_;
+};
+
+FORCE_INLINE Value* make(TSDataType type)
+{
+  Value *value = new Value(type);
+  return value;
+}
+
+FORCE_INLINE Value* make_literal(int64_t val)
+{
+  Value *value = new Value(INT64);
+  value->value_.lval_ = val;
+  return value;
+}
+
+FORCE_INLINE Value* make_literal(double val)
+{
+  Value *value = new Value(DOUBLE);
+  value->value_.dval_ = val;
+  return value;
+}
+
+FORCE_INLINE Value* make_literal(char *string)
+{
+  Value *value = new Value(TEXT);
+  value->value_.sval_ = string;
+  return value;
+}
+
+FORCE_INLINE Value* make_literal(bool val)
+{
+  Value *value = new Value(BOOLEAN);
+  value->value_.bval_ = val;
+  return value;
+}
+
+FORCE_INLINE Value* make_null_literal()
+{
+  Value *value = new Value(NULL_TYPE);
+  return value;
+}
+
+FORCE_INLINE std::string value_to_string(Value *value)
+{
+  if (value->type_ == timecho::common::TEXT) {
+    return std::string(value->value_.sval_);
+  } else {
+    std::stringstream ss;
+    switch (value->type_) {
+      case timecho::common::BOOLEAN:
+        ss << (value->value_.bval_ ? "true" : "false");
+        break;
+      case timecho::common::INT32:
+      case timecho::common::INT64:
+        ss << value->value_.lval_;
+        break;
+      case timecho::common::FLOAT:
+      case timecho::common::DOUBLE:
+        ss << value->value_.dval_;
+        break;
+      case timecho::common::NULL_TYPE:
+        ss << "NULL";
+      default:
+        ASSERT(false);
+        break;
+    }
+    return ss.str();
+  }
+}
+
+// return true if cast succ.
+template<typename T>
+FORCE_INLINE int get_typed_data_from_value(Value *value, T &ret_data) { return E_OK; }
+
+template<> FORCE_INLINE int get_typed_data_from_value<bool>(Value *value, bool &ret_data)
+{
+  ret_data = value->value_.bval_;
+  return (value->type_ == BOOLEAN) ? E_OK : E_TYPE_NOT_MATCH;
+}
+
+template<> FORCE_INLINE int get_typed_data_from_value<int32_t>(Value *value, int32_t &ret_data)
+{
+  if (value->value_.lval_ > INT32_MAX || value->value_.lval_ < INT32_MIN) {
+    return E_OVERFLOW;
+  }
+  ret_data = (int32_t)value->value_.lval_;
+  // number value will be parsed as INT64
+  return (value->type_ == INT64) ? E_OK : E_TYPE_NOT_MATCH;
+}
+
+template<> FORCE_INLINE int get_typed_data_from_value<int64_t>(Value *value, int64_t &ret_data)
+{
+  ret_data = value->value_.lval_;
+  return (value->type_ == INT64) ? E_OK : E_TYPE_NOT_MATCH;
+}
+
+template<> FORCE_INLINE int get_typed_data_from_value<float>(Value *value, float &ret_data)
+{
+  if (value->value_.dval_ > FLT_MAX || value->value_.dval_ < FLT_MIN) {
+    return E_OVERFLOW;
+  }
+  ret_data = (float)value->value_.dval_;
+  return (value->type_ == DOUBLE) ? E_OK : E_TYPE_NOT_MATCH;
+}
+
+template<> FORCE_INLINE int get_typed_data_from_value<double>(Value *value, double &ret_data)
+{
+  ret_data = value->value_.dval_;
+  return (value->type_ == DOUBLE) ? E_OK : E_TYPE_NOT_MATCH;
+}
+
+// template<> FORCE_INLINE int get_typed_data_from_value<Text>(Value *value, Text &ret_data)
+// {
+//   ret_data.buf_ = value->value_.sval_;
+//   ret_data.len_ = strlen(ret_data.buf_);
+//   return value->type_ == TEXT;
+// }
+ 
+}  // common
+}  // timecho
+
+#endif  // COMMON_DATATYPE_VALUE_H
diff --git a/cpp/tsfile/src/common/db_common.h b/cpp/tsfile/src/common/db_common.h
new file mode 100644
index 00000000..9ab5b2ad
--- /dev/null
+++ b/cpp/tsfile/src/common/db_common.h
@@ -0,0 +1,168 @@
+
+#ifndef COMMON_DB_COMMON_H
+#define COMMON_DB_COMMON_H
+
+#include <iostream>
+#include "common/util_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+enum TSDataType
+{
+  BOOLEAN = 0,
+  INT32 = 1,
+  INT64 = 2,
+  FLOAT = 3,
+  DOUBLE = 4,
+  TEXT = 5,
+  VECTOR = 6,
+  NULL_TYPE = 254,
+  INVALID_DATATYPE = 255
+};
+
+enum TSEncoding
+{
+  PLAIN = 0,
+  DICTIONARY = 1,
+  RLE = 2,
+  DIFF = 3,
+  TS_2DIFF = 4,
+  BITMAP = 5,
+  GORILLA_V1 = 6,
+  REGULAR = 7,
+  GORILLA = 8,
+  ZIGZAG = 9,
+  FREQ = 10,
+  INVALID_ENCODING = 255
+};
+
+enum CompressionType
+{
+  UNCOMPRESSED = 0,
+  SNAPPY = 1,
+  GZIP = 2,
+  LZO = 3,
+  SDT = 4,
+  PAA = 5,
+  PLA = 6,
+  LZ4 = 7,
+  INVALID_COMPRESSION = 255
+};
+
+extern const char* s_data_type_names[7];
+extern const char* s_encoding_names[12];
+extern const char* s_compression_names[8];
+
+FORCE_INLINE const char* get_data_type_name(TSDataType type)
+{
+  ASSERT(type >= BOOLEAN && type <= VECTOR);
+  return s_data_type_names[type];
+}
+
+FORCE_INLINE const char* get_encoding_name(TSEncoding encoding)
+{
+  ASSERT(encoding >= PLAIN && encoding <= FREQ);
+  return s_encoding_names[encoding];
+}
+
+FORCE_INLINE const char* get_compression_name(CompressionType type)
+{
+  return s_compression_names[type];
+}
+
+FORCE_INLINE TSEncoding get_default_encoding_for_type(TSDataType type)
+{
+  if (type == timecho::common::BOOLEAN) {
+    return PLAIN;
+  } else if (type == timecho::common::INT32) {
+    return PLAIN;
+  } else if (type == timecho::common::INT64) {
+    return PLAIN;
+  } else if (type == timecho::common::FLOAT) {
+    return PLAIN;
+  } else if (type == timecho::common::DOUBLE) {
+    return PLAIN;
+  } else if (type == timecho::common::TEXT) {
+    return PLAIN;
+  } else {
+    ASSERT(false);
+  }
+  return INVALID_ENCODING;
+}
+
+FORCE_INLINE CompressionType get_default_compression_for_type(TSDataType type)
+{
+  if (type == timecho::common::BOOLEAN) {
+    return UNCOMPRESSED;
+  } else if (type == timecho::common::INT32) {
+    return UNCOMPRESSED;
+  } else if (type == timecho::common::INT64) {
+    return UNCOMPRESSED;
+  } else if (type == timecho::common::FLOAT) {
+    return UNCOMPRESSED;
+  } else if (type == timecho::common::DOUBLE) {
+    return UNCOMPRESSED;
+  } else if (type == timecho::common::TEXT) {
+    return UNCOMPRESSED;
+  } else {
+    ASSERT(false);
+  }
+  return INVALID_COMPRESSION;
+}
+
+enum Ordering
+{
+  DESC,
+  ASC
+};
+
+template<typename T>
+FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType() { return common::INVALID_DATATYPE; }
+
+template<> FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<bool>() { return common::BOOLEAN; }
+template<> FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<int32_t>() { return common::INT32; }
+template<> FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<int64_t>() { return common::INT64; }
+template<> FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<float>() { return common::FLOAT; }
+template<> FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<double>() { return common::DOUBLE; }
+
+FORCE_INLINE size_t get_data_type_size(TSDataType data_type)
+{
+  switch (data_type) {
+    case timecho::common::BOOLEAN:
+      return 1;
+    case timecho::common::INT32:
+    case timecho::common::FLOAT:
+      return 4;
+    case timecho::common::INT64:
+    case timecho::common::DOUBLE:
+      return 8;
+    default:
+      ASSERT(false);
+      return 8;
+  }
+}
+
+} // end namespace common
+
+namespace storage
+{
+
+struct TimeRange
+{
+  TimeRange() : start_time_(INT64_MAX),
+                end_time_(INT64_MIN) {}
+  TimeRange(int64_t start_time, int64_t end_time) : start_time_(start_time), end_time_(end_time) {}
+
+  int64_t start_time_;
+  int64_t end_time_;
+};
+
+}
+
+} // end namespace timecho
+
+#endif
+
diff --git a/cpp/tsfile/src/common/db_utils.h b/cpp/tsfile/src/common/db_utils.h
new file mode 100644
index 00000000..96358b53
--- /dev/null
+++ b/cpp/tsfile/src/common/db_utils.h
@@ -0,0 +1,457 @@
+
+#ifndef COMMON_UTILS_H
+#define COMMON_UTILS_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <sstream>
+#include <string>
+#include <string.h> // memcpy
+#include <sys/time.h>
+#include <iostream>
+#include "common/util_define.h"
+#include "common/db_common.h"
+#include "common/allocator/my_string.h"
+
+namespace timecho
+{
+namespace common
+{
+
+typedef struct FileID
+{
+  int64_t seq_; // timestamp when create
+  int32_t version_;
+  int32_t merge_;
+
+  FileID() : seq_(0), version_(0), merge_(0) {}
+  void reset()
+  {
+    seq_ = 0;
+    version_ = 0;
+    merge_ = 0;
+  }
+  FORCE_INLINE bool is_valid() const { return seq_ != 0; }
+  FORCE_INLINE bool operator < (const FileID &that) const
+  {
+    return this->seq_ < that.seq_;
+  }
+  FORCE_INLINE bool operator == (const FileID &that) const
+  {
+    return this->seq_ == that.seq_;
+  }
+#ifndef NDEBUG
+  friend std::ostream& operator << (std::ostream& out, const FileID &file_id)
+  {
+    out << "{seq_=" << file_id.seq_ << ", version_=" << file_id.version_ << ", merge_=" << file_id.merge_ << "}";
+    return out;
+  }
+#endif
+} FileID;
+
+typedef uint16_t NodeID;
+struct TsID
+{
+  NodeID db_nid_;
+  NodeID device_nid_;
+  NodeID measurement_nid_;
+
+  TsID() : db_nid_(0),
+           device_nid_(0),
+           measurement_nid_(0) {};
+
+  TsID(NodeID db_nid,
+       NodeID device_nid,
+       NodeID measurement_nid)
+    : db_nid_(db_nid),
+      device_nid_(device_nid),
+      measurement_nid_(measurement_nid) {}
+
+  /*
+   * To make TsID to be a trival copyable struct.
+   */
+#if 0
+  TsID(const TsID &other) : db_nid_(other.db_nid_),
+                            device_nid_(other.device_nid_),
+                            measurement_nid_(other.measurement_nid_) {}
+
+  TsID & operator = (const TsID &other) 
+  {
+    db_nid_ = other.db_nid_;
+    device_nid_ = other.device_nid_;
+    measurement_nid_ = other.measurement_nid_;
+    return *this;
+  }
+#endif
+
+  void reset()
+  {
+    db_nid_ = 0;
+    device_nid_ = 0;
+    measurement_nid_ = 0;
+  }
+
+  bool is_valid() const
+  {
+    // TODO
+    return true;
+  }
+
+  FORCE_INLINE bool operator == (const TsID &other) const
+  {
+    return db_nid_ == other.db_nid_
+           && device_nid_ == other.device_nid_
+           && measurement_nid_ == other.measurement_nid_;
+  }
+  FORCE_INLINE bool operator != (const TsID &other) const
+  {
+    return db_nid_ != other.db_nid_
+           || device_nid_ != other.device_nid_
+           || measurement_nid_ != other.measurement_nid_;
+  }
+
+  FORCE_INLINE int64_t to_int64() const
+  {
+    int64_t res = db_nid_;
+    res = (res << 16) | device_nid_;
+    res = (res << 16) | measurement_nid_;
+    return res;
+  }
+
+  FORCE_INLINE bool operator < (const TsID &that) const
+  {
+    return to_int64() < that.to_int64();
+  }
+
+  FORCE_INLINE bool operator > (const TsID &other)
+  {
+    return to_int64() > other.to_int64();
+  }
+
+  friend std::ostream& operator << (std::ostream& out, TsID& ti)
+  {
+    out << "(" << ti.db_nid_ << ", " << ti.device_nid_ << ", " << ti.measurement_nid_ << ")  ";
+    return out;
+  }
+
+  FORCE_INLINE void to_string(char *print_buf, int len) const
+  {
+    snprintf(print_buf, len, "<%d,%d,%d>", db_nid_, device_nid_, measurement_nid_);
+  }
+  FORCE_INLINE std::string to_string() const 
+  {
+    const int buf_len = 32;
+    char buf[buf_len];
+    snprintf(buf, buf_len, "<%d,%d,%d>", db_nid_, device_nid_, measurement_nid_);
+    // construct std::string will invoke memory allocation and copy.
+    // try to use first to_string instead.
+    return std::string(buf);
+  }
+};
+
+struct DeviceID
+{
+  NodeID db_nid_;
+  NodeID device_nid_;
+
+  DeviceID() : db_nid_(0),
+               device_nid_(0) {}
+  DeviceID(const NodeID db_nid, const NodeID device_nid)
+    : db_nid_(db_nid),
+      device_nid_(device_nid) {}
+  explicit DeviceID(const TsID &ts_id)
+    : db_nid_(ts_id.db_nid_),
+      device_nid_(ts_id.device_nid_) {}
+
+  FORCE_INLINE bool operator == (const DeviceID &other) const
+  {
+    return db_nid_ == other.db_nid_
+           && device_nid_ == other.device_nid_;
+  }
+  FORCE_INLINE bool operator != (const DeviceID &other) const
+  {
+    return db_nid_ != other.db_nid_
+           || device_nid_ != other.device_nid_;
+  }
+  FORCE_INLINE void from(const TsID &ts_id)
+  {
+    db_nid_ = ts_id.db_nid_;
+    device_nid_ = ts_id.device_nid_;
+  }
+  FORCE_INLINE bool operator < (const DeviceID &that) const
+  {
+    int32_t this_i32 = (((int32_t)db_nid_) << 16) | (device_nid_);
+    int32_t that_i32 = (((int32_t)that.db_nid_) << 16) | (that.device_nid_);
+    return this_i32 < that_i32;
+  }
+};
+
+#define INVALID_TTL (-1)
+
+// describe single database
+struct DatabaseDesc
+{
+  int64_t      ttl_;
+  std::string  db_name_;
+  TsID         ts_id_;
+
+  DatabaseDesc() : ttl_(INVALID_TTL), db_name_(""), ts_id_() {}
+  DatabaseDesc(uint64_t ttl, const std::string &name, const TsID &ts_id) :
+    ttl_(ttl), db_name_(name), ts_id_(ts_id) {}
+};
+
+// Describe single timeseries
+struct ColumnDesc
+{
+  TSDataType       type_;
+  TSEncoding       encoding_;
+  CompressionType  compression_;
+  int64_t          ttl_;          // obtained from the metadata and passed to the storage
+  std::string      column_name_;  // measurement name or Time
+  TsID             ts_id_;        // id of timeseries
+
+  ColumnDesc() :
+    type_(INVALID_DATATYPE),
+    encoding_(PLAIN),
+    compression_(UNCOMPRESSED),
+    ttl_(INVALID_TTL),
+    column_name_(""),
+    ts_id_() {}
+
+  ColumnDesc(TSDataType type,
+             TSEncoding encoding,
+             CompressionType compression,
+             uint64_t ttl,
+             const std::string &name,
+             const TsID &ts_id)
+    : type_(type),
+      encoding_(encoding),
+      compression_(compression),
+      ttl_(ttl),
+      column_name_(name),
+      ts_id_(ts_id) {}
+
+  ~ColumnDesc() {}
+
+  bool operator == (const ColumnDesc &other) const
+  {
+    return (type_ == other.type_
+            && encoding_ == other.encoding_
+            && compression_ == other.compression_
+            && column_name_ == other.column_name_
+            && ts_id_ == other.ts_id_);
+  }
+
+  bool operator != (const ColumnDesc &other) const
+  {
+    return (type_ != other.type_
+            || encoding_ != other.encoding_
+            || compression_ != other.compression_
+            || column_name_ != other.column_name_
+            || ts_id_ != other.ts_id_);
+  }
+
+  bool is_valid() const
+  {
+    return type_ != INVALID_DATATYPE
+           && encoding_ != INVALID_ENCODING
+           && compression_ != INVALID_COMPRESSION
+           && ts_id_.is_valid();
+  }
+
+  void reset()
+  {
+    // TODO
+  }
+
+  void get_device_name(char *ret_device_name_buf,
+                       const int buf_len,
+                       uint32_t &ret_len) const
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0 && pos < buf_len);
+    memcpy(ret_device_name_buf, column_name_.c_str(), pos);
+    ret_device_name_buf[pos] = '\0';
+    ret_len = pos;
+  }
+  std::string get_device_name_str() const
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0);
+    return column_name_.substr(0, pos);
+  }
+  void get_device_name(String &device_name) const
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0);
+    const char *c_string = column_name_.c_str();
+    device_name.buf_ = (char*)c_string;
+    device_name.len_ = pos;
+  }
+  void get_measurement_name(char *ret_measurement_name_buf,
+                            const int buf_len,
+                            uint32_t &ret_len) const
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0 && pos < buf_len);
+    ret_len = column_name_.size() - pos - 1;
+    memcpy(ret_measurement_name_buf, column_name_.c_str() + pos + 1, ret_len);
+    ret_measurement_name_buf[ret_len] = '\0';
+  }
+  std::string get_measurement_name_str() const
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0);
+    return column_name_.substr(pos + 1, column_name_.size() - pos);
+  }
+  // TODO remove
+  void get_measurement_name(String &measurement_name) const
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0);
+    const char *c_string = column_name_.c_str();
+    measurement_name.buf_ = (char*)c_string + pos + 1;
+    measurement_name.len_ = column_name_.size() - pos - 1;
+  }
+  String get_measurement_name()
+  {
+    int pos = column_name_.find_last_of('.');
+    ASSERT(pos > 0);
+    const char *c_string = column_name_.c_str();
+    String res;
+    res.buf_ = (char*)c_string + pos + 1;
+    res.len_ = column_name_.size() - pos - 1;
+    return res;
+  }
+
+  std::string debug_string()  // for debug
+  {
+    std::stringstream out;
+    out << "print ColumnDesc: " << this << std::endl
+        << "name: " << column_name_.c_str() << std::endl
+        << "datatype: " << type_ << std::endl
+        << "encoding: " << encoding_ << std::endl
+        << "compression:" << compression_ << std::endl
+        << "ttl:" << ttl_ << std::endl
+        << "tsid:" << ts_id_.to_string().c_str() << std::endl;
+    return out.str();
+  }
+};
+
+enum WALFlushPolicy
+{
+  WAL_DISABLED = 0,
+  WAL_ASYNC = 1,
+  WAL_FLUSH = 2,
+  WAL_SYNC = 3,
+};
+
+template<typename T>
+std::string to_string(const T &val)
+{
+  // todo: There may be a better way to avoid the memory problem of ostringstream
+  std::ostringstream oss;
+  oss << val;
+  return oss.str();	
+}
+  
+// TODO rename to DatabaseIdTTL
+struct DatabaseIdTTL
+{
+  NodeID db_nid_;
+  int64_t  ttl_;
+  DatabaseIdTTL() {}
+  DatabaseIdTTL(NodeID db_nid, int64_t ttl) :  db_nid_(db_nid), ttl_(ttl) {}  
+  DatabaseIdTTL(const DatabaseIdTTL &other) :  db_nid_(other.db_nid_), ttl_(other.ttl_) {}
+  DatabaseIdTTL & operator = (const DatabaseIdTTL &other) 
+  {
+    this->db_nid_ = other.db_nid_;
+    this->ttl_ = other.ttl_;
+    return *this;
+  }
+  bool operator == (const DatabaseIdTTL &other)
+  {
+    if (db_nid_ != other.db_nid_ || ttl_ != other.ttl_) {
+      return false;
+    }
+    return true;
+  }
+  friend std::ostream& operator << (std::ostream& out, DatabaseIdTTL& di)
+  {
+    out << "(" << di.db_nid_ << ", " << di.ttl_ << ")  ";
+    return out;
+  }    
+};
+
+FORCE_INLINE int64_t get_cur_timestamp()
+{
+  int64_t timestamp = 0;
+  struct timeval tv;
+  if (gettimeofday(&tv, NULL) >= 0) {
+    timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+  }
+  return timestamp;
+}
+
+#if 0
+struct DatabaseIdTTL
+{
+  NodeID db_nid_;
+  int64_t  ttl_;
+  int16_t counter_;  // suppose we at most support 64k timeseries.
+  DatabaseIdTTL() {}
+  DatabaseIdTTL(NodeID db_nid, int64_t ttl, int16_t counter) :  db_nid_(db_nid), ttl_(ttl), counter_(counter) {}  
+  DatabaseIdTTL(const DatabaseIdTTL &other) :  db_nid_(other.db_nid_), ttl_(other.ttl_), counter_(other.counter_) {}
+  DatabaseIdTTL & operator = (const DatabaseIdTTL &other) 
+  {
+    this->db_nid_ = other.db_nid_;
+    this->ttl_ = other.ttl_;
+    this->counter_ = other.counter_;
+    return *this;
+  }
+  bool operator == (const DatabaseIdTTL &other)
+  {
+    if (db_nid_ != other.db_nid_ || ttl_ != other.ttl_ || counter_ != other.counter_) {
+      return false;
+    }
+    return true;
+  }
+  friend std::ostream& operator << (std::ostream& out, DatabaseIdTTL& di)
+  {
+
+    return out;
+  }    
+};
+
+struct DeviceIDWithCounter
+{
+  NodeID device_nid_;
+  int16_t counter_;  // suppose we at most support 64k timeseries.
+  DeviceIDWithCounter() {}
+  DeviceIDWithCounter(NodeID device_nid, int16_t counter) :  device_nid_(device_nid), counter_(counter) {}  
+  DeviceIDWithCounter(const DeviceIDWithCounter &other) :  device_nid_(other.device_nid_), counter_(other.counter_) {}
+  DeviceIDWithCounter& operator = (const DeviceIDWithCounter &other) 
+  {
+    this->device_nid_ = other.device_nid_;
+    this->counter_ = other.counter_;
+    return *this;
+  }
+  bool operator == (const DeviceID &other)
+  {
+    if (device_nid_ != other.device_nid_ || counter_ != other.counter_) {
+      return false;
+    }
+    return true;
+  }
+  friend std::ostream& operator << (std::ostream& out, DeviceID& di)
+  {
+    out << "(" << di.device_nid_ << ", " << di.counter_ << ")  ";
+    return out;
+  }    
+};
+#endif
+
+} // end namespace common
+} // end namespace timecho
+
+#endif 
diff --git a/cpp/tsfile/src/common/errno_define.h b/cpp/tsfile/src/common/errno_define.h
new file mode 100644
index 00000000..eef043cc
--- /dev/null
+++ b/cpp/tsfile/src/common/errno_define.h
@@ -0,0 +1,64 @@
+
+#ifndef COMMON_ERRNO_DEFINE_H
+#define COMMON_ERRNO_DEFINE_H
+
+namespace timecho
+{
+namespace common
+{
+
+const int E_OK = 0;
+const int E_OOM = 1;
+const int E_NOT_EXIST = 2;
+const int E_ALREADY_EXIST = 3;
+const int E_INVALID_ARG = 4;
+const int E_OUT_OF_RANGE = 5;
+const int E_PARTIAL_READ = 6;
+const int E_NET_BIND_ERR = 7;
+const int E_NET_SOCKET_ERR = 8;
+const int E_NET_EPOLL_ERR = 9;
+const int E_NET_EPOLL_WAIT_ERR = 10;
+const int E_NET_RECV_ERR = 11;
+const int E_NET_ACCEPT_ERR = 12;
+const int E_NET_FCNTL_ERR = 13;
+const int E_NET_LISTEN_ERR = 14;
+const int E_NET_SEND_ERR = 15;
+const int E_PIPE_ERR = 16;
+const int E_THREAD_CREATE_ERR = 17;
+const int E_MUTEX_ERR = 18;
+const int E_COND_ERR = 19;
+const int E_OVERFLOW = 20;
+const int E_NO_MORE_DATA = 21;
+const int E_OUT_OF_ORDER = 22;
+const int E_TSBLOCK_TYPE_NOT_SUPPORTED = 23;
+const int E_TSBLOCK_DATA_INCONSISTENCY = 24;
+const int E_DDL_UNKNOWN_TYPE = 25;
+const int E_TYPE_NOT_SUPPORTED = 26;
+const int E_TYPE_NOT_MATCH = 27;
+const int E_FILE_OPEN_ERR = 28;
+const int E_FILE_CLOSE_ERR = 29;
+const int E_FILE_WRITE_ERR = 30;
+const int E_FILE_READ_ERR = 31;
+const int E_FILE_SYNC_ERR = 32;
+const int E_TSFILE_WRITER_META_ERR = 33;
+const int E_FILE_STAT_ERR = 34;
+const int E_TSFILE_CORRUPTED = 35;
+const int E_BUF_NOT_ENOUGH = 36;
+const int E_INVALID_PATH = 37;
+const int E_NOT_MATCH = 38;
+const int E_JSON_INVALID = 39;
+const int E_NOT_SUPPORT = 40;
+const int E_PARSER_ERR = 41;
+const int E_ANALYZE_ERR = 42;
+const int E_INVALID_DATA_POINT = 43;
+const int E_DEVICE_NOT_EXIST = 44;
+const int E_MEASUREMENT_NOT_EXIST = 45;
+const int E_INVALID_QUERY = 46;
+const int E_SDK_QUERY_OPTIMIZE_ERR = 47;
+const int E_COMPRESS_ERR = 48;
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_ERRNO_DEFINE_H
+
diff --git a/cpp/tsfile/src/common/global.cc b/cpp/tsfile/src/common/global.cc
new file mode 100644
index 00000000..d8b96399
--- /dev/null
+++ b/cpp/tsfile/src/common/global.cc
@@ -0,0 +1,201 @@
+
+#include "global.h"
+#include <stdlib.h>
+#include <execinfo.h>
+#include "injection.h"
+
+namespace timecho
+{
+namespace common
+{
+
+ColumnDesc g_time_column_desc;
+ConfigValue g_config_value_;
+
+// TODO move to server.cc ?
+void init_config_value()
+{
+  g_config_value_.tsblock_mem_inc_step_size_ = 8000;     // 8k
+  g_config_value_.tsblock_max_memory_ = 64000;          // 64k
+  // g_config_value_.tsblock_max_memory_ = 32;
+  g_config_value_.rest_service_ip_ = "0.0.0.0";
+
+  char *timechodb_port = getenv("TIMECHODB_PORT");
+  if (nullptr == timechodb_port) {
+    g_config_value_.rest_service_port_ = 8899;
+  } else {
+    g_config_value_.rest_service_port_ = atoi(timechodb_port);
+  }
+
+  g_config_value_.wal_flush_policy_ = WAL_DISABLED;
+  g_config_value_.seqtvlist_primary_array_size_ = 32; // 32;
+  g_config_value_.seqtvlist_max_record_count_ = 1024; // 64;
+  g_config_value_.page_writer_max_point_num_ = 5;
+  g_config_value_.page_writer_max_memory_bytes_ = 128 * 1024; // 128 k
+  g_config_value_.max_degree_of_index_node_ = 256;
+  g_config_value_.tsfile_index_bloom_filter_error_percent_ = 0.05;
+  // g_config_value_.tsfile_prefix_path_ = "./data";
+  g_config_value_.tsfile_prefix_path_ = "";
+  //g_config_value_.time_encoding_type_ = TS_2DIFF;
+  g_config_value_.time_encoding_type_ = PLAIN;
+  g_config_value_.memtable_flusher_poll_interval_seconds_ = 1;
+}
+
+void config_set_page_max_point_count(uint32_t page_max_ponint_count)
+{
+  g_config_value_.page_writer_max_point_num_ = page_max_ponint_count;
+}
+
+void config_set_max_degree_of_index_node(uint32_t max_degree_of_index_node)
+{
+  g_config_value_.max_degree_of_index_node_ = max_degree_of_index_node;
+}
+
+void set_config_value() {}
+
+const char* s_data_type_names[7] = {
+  "BOOLEAN",
+  "INT32",
+  "INT64",
+  "FLOAT",
+  "DOUBLE",
+  "TEXT",
+  "VECTOR"
+};
+
+const char* s_encoding_names[12] = {
+  "PLAIN",
+  "DICTIONARY",
+  "RLE",
+  "DIFF",
+  "TS_2DIFF",
+  "BITMAP",
+  "GORILLA_V1",
+  "REGULAR",
+  "GORILLA",
+  "ZIGZAG",
+  "FREQ"
+};
+
+const char* s_compression_names[8] = {
+  "UNCOMPRESSED",
+  "SNAPPY",
+  "GZIP",
+  "LZO",
+  "SDT",
+  "PAA",
+  "PLA",
+  "LZ4",
+};
+
+int init_common()
+{
+  int ret = E_OK;
+  common::init_config_value();
+  g_time_column_desc.type_ = INT64;
+  g_time_column_desc.encoding_ = PLAIN;
+  g_time_column_desc.compression_ = UNCOMPRESSED;
+  g_time_column_desc.ttl_ = INT64_MAX; // TODO
+  g_time_column_desc.column_name_ = std::string("time");
+  g_time_column_desc.ts_id_ = TsID(0, 0, 0);
+  return ret;
+}
+
+bool is_timestamp_column_name(const char *time_col_name)
+{
+  // both "time" and "timestamp" refer to timestmap column.
+  int32_t len = strlen(time_col_name);
+  if (len == 4) {
+    return strncasecmp(time_col_name, "time", 4) == 0;
+  } else if (len == 9) {
+    return strncasecmp(time_col_name, "timestamp", 9) == 0;
+  } else {
+    return false;
+  }
+}
+
+void cols_to_json(ByteStream *byte_stream, std::vector<common::ColumnDesc> &ret_ts_list)
+{
+  // 1. append start tag
+  byte_stream->write_buf("{\n", 2);
+
+  size_t ts_count = ret_ts_list.size();
+  for (size_t i = 0; i < ts_count; ++i) {
+    // 2. append timeseries name
+    std::string name = ret_ts_list[i].column_name_;
+    byte_stream->write_buf("  \"", 3);
+    byte_stream->write_buf(name.c_str(), name.length());
+    byte_stream->write_buf("\" : {\n", 6);
+    
+    // 3. append DataType
+    const char* data_type = get_data_type_name(ret_ts_list[i].type_);
+    byte_stream->write_buf("    \"DataType\" : \"", 18);
+    byte_stream->write_buf(data_type, strlen(data_type));
+    byte_stream->write_buf("\",\n", 3);
+    
+    // 4. append Encoding
+    const char* encoding = get_encoding_name(ret_ts_list[i].encoding_);
+    byte_stream->write_buf("    \"Encoding\" : \"", 18);
+    byte_stream->write_buf(encoding, strlen(encoding));
+    byte_stream->write_buf("\",\n", 3);  
+
+    // 5. append CompressionType
+    const char* compression = get_compression_name(ret_ts_list[i].compression_);
+    byte_stream->write_buf("    \"Compression\" : \"", 21);
+    byte_stream->write_buf(compression, strlen(compression));
+    byte_stream->write_buf("\",\n", 3);    
+
+    // 6. append TTL
+    std::string ttl_str = to_string(ret_ts_list[i].ttl_);
+    if (ret_ts_list[i].ttl_ == INVALID_TTL) {
+      byte_stream->write_buf("    \"TTL\" : \"INVALID\",\n", 23);  // if it is the end, delete ','     
+    } else {
+      byte_stream->write_buf("    \"TTL\" : \"", 13);
+      byte_stream->write_buf(ttl_str.c_str(), ttl_str.length());
+      byte_stream->write_buf("\",\n", 3);  // if it is the end, delete ','         
+    }
+
+    // TODO : this is used for Debug
+    // 7. append TsId
+    std::string tsid_str = ret_ts_list[i].ts_id_.to_string();
+    byte_stream->write_buf("    \"TsID\" : \"", 14);
+    byte_stream->write_buf(tsid_str.c_str(), tsid_str.length());
+    byte_stream->write_buf("\"\n", 2);   
+
+    // 8. append footer
+    if (i == ts_count - 1) {
+      byte_stream->write_buf("  }\n", 4);
+    } else {
+      byte_stream->write_buf("  },\n", 5);
+    }
+  }
+
+  // 9. end
+  byte_stream->write_buf("}\n", 2);  
+
+  // DEBUG_print_byte_stream(*byte_stream);  // for debug
+}
+
+void print_backtrace()
+{
+  const int MAX_FRAMES = 32;
+  int layers = 0;
+  char **symbols = NULL;
+  void *frames[MAX_FRAMES];
+
+  memset(frames, 0, sizeof(frames));
+  layers = backtrace(frames, MAX_FRAMES);
+  symbols = backtrace_symbols(frames, layers);
+  if (symbols) {
+    for (int i = 0; i < layers; i++) {
+      printf("SYMBOL layer %d: %s\n", i, symbols[i]);
+    }
+    free(symbols);
+  }
+}
+
+Mutex g_all_inject_points_mutex;
+std::map<std::string, InjectPoint> g_all_inject_points;
+
+}  // common
+}  // timecho
diff --git a/cpp/tsfile/src/common/global.h b/cpp/tsfile/src/common/global.h
new file mode 100644
index 00000000..3fc3e64a
--- /dev/null
+++ b/cpp/tsfile/src/common/global.h
@@ -0,0 +1,28 @@
+#ifndef COMMON_GLOBAL_H
+#define COMMON_GLOBAL_H
+
+#include <string>
+#include <vector>
+#include "common/config/config.h"
+#include "common/allocator/byte_stream.h"
+
+namespace timecho
+{
+namespace common
+{
+
+extern ConfigValue g_config_value_;
+
+FORCE_INLINE bool wal_cfg_enabled() { return g_config_value_.wal_flush_policy_ != WAL_DISABLED; }
+FORCE_INLINE bool wal_cfg_should_wait_persisted() { return g_config_value_.wal_flush_policy_ >= WAL_FLUSH; }
+
+extern ColumnDesc g_time_column_desc;
+extern int init_common();
+extern bool is_timestamp_column_name(const char *time_col_name);
+extern void cols_to_json(ByteStream *byte_stream, std::vector<common::ColumnDesc> &ret_ts_list);
+extern void print_backtrace();
+
+}
+}
+
+#endif  // COMMON_GLOBAL_H
diff --git a/cpp/tsfile/src/common/injection.h b/cpp/tsfile/src/common/injection.h
new file mode 100644
index 00000000..16d02cb6
--- /dev/null
+++ b/cpp/tsfile/src/common/injection.h
@@ -0,0 +1,53 @@
+#ifndef COMMON_INJECTION_H
+#define COMMON_INJECTION_H
+
+#include <iostream>
+#include <string>
+#include <map>
+
+namespace timecho
+{
+namespace common
+{
+
+// define struct 
+struct InjectPoint
+{
+  int count_down_; // left count
+};
+
+// define DBUG_EXECUTE_IF
+#define DBUG_EXECUTE_IF(inject_point_name, code) \
+  do { \
+    common::MutexGuard mg(g_all_inject_points_mutex); \
+    if (g_all_inject_points.find(inject_point_name) != g_all_inject_points.end()) { \
+      InjectPoint& inject_point = g_all_inject_points[inject_point_name]; \
+      if (inject_point.count_down_ <= 0) { \
+        code; \
+      } \
+      inject_point.count_down_--; \
+    } \
+  } while(0)
+
+// open injection
+#define ENABLE_INJECTION(inject_point_name, count) \
+  do { \
+    common::MutexGuard mg(g_all_inject_points_mutex); \
+    g_all_inject_points[inject_point_name] = {count}; \
+  } while(0)
+
+// close injection 
+#define DISABLE_INJECTION(inject_point_name) \
+  do { \
+    common::MutexGuard mg(g_all_inject_points_mutex); \
+    g_all_inject_points.erase(inject_point_name); \
+  } while(0)
+
+// the map save all inject points
+extern Mutex g_all_inject_points_mutex;
+extern std::map<std::string, InjectPoint> g_all_inject_points;
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_INJECTION_H
diff --git a/cpp/tsfile/src/common/mutex/CMakeLists.txt b/cpp/tsfile/src/common/mutex/CMakeLists.txt
new file mode 100644
index 00000000..139597f9
--- /dev/null
+++ b/cpp/tsfile/src/common/mutex/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+
diff --git a/cpp/tsfile/src/common/mutex/mutex.h b/cpp/tsfile/src/common/mutex/mutex.h
new file mode 100644
index 00000000..e5d7da72
--- /dev/null
+++ b/cpp/tsfile/src/common/mutex/mutex.h
@@ -0,0 +1,64 @@
+
+#ifndef COMMON_MUTEX_MUTEX_H
+#define COMMON_MUTEX_MUTEX_H
+
+#include <errno.h>
+#include <pthread.h>
+#include "common/util_define.h"
+
+namespace timecho
+{
+namespace common
+{
+
+class Mutex
+{
+public:
+  Mutex() : mutex_() { pthread_mutex_init(&mutex_, NULL); }
+  ~Mutex() { pthread_mutex_destroy(&mutex_); }
+
+  void lock()
+  {
+    int ret = EBUSY;
+    do {
+      ret = pthread_mutex_lock(&mutex_);
+    } while (UNLIKELY(ret == EBUSY || ret == EAGAIN));
+    ASSERT(ret == 0);
+  }
+
+  void unlock()
+  {
+    int ret = pthread_mutex_unlock(&mutex_);
+    ASSERT(ret == 0);
+  }
+
+  bool try_lock()
+  {
+    int ret = pthread_mutex_trylock(&mutex_);
+    if (ret == 0) {
+      return true;
+    } else if (ret == EBUSY || ret == EAGAIN) {
+      return false;
+    } else {
+      ASSERT(false);
+      return false;
+    }
+  }
+
+private:
+  pthread_mutex_t mutex_;
+};
+
+class MutexGuard
+{
+public:
+  MutexGuard(Mutex &m) : m_(m) { m_.lock(); }
+  ~MutexGuard() { m_.unlock(); }
+private:
+  Mutex &m_;
+};
+
+} // end namespace common
+} // end namespace timecho
+
+#endif // COMMON_MUTEX_MUTEX_H
diff --git a/cpp/tsfile/src/common/tsblock/CMakeLists.txt b/cpp/tsfile/src/common/tsblock/CMakeLists.txt
new file mode 100644
index 00000000..e498c112
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/CMakeLists.txt
@@ -0,0 +1,11 @@
+message("Running in src/common/tsblock directory")
+
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} common_tsblock_SRC_LIST)
+set(common_tsblock_INC_LIST)
+set(common_tsblock_DEFINE_OPTIONS)
+set(common_tsblock_COMPILE_OPTIONS)
+set(common_tsblock_LINK_OPTIONS)
+add_statis_objtarget(common_tsblock common_tsblock_SRC_LIST common_tsblock_INC_LIST
+                     "${common_tsblock_DEFINE_OPTIONS}"
+                     "${common_tsblock_COMPILE_OPTIONS}"
+                     "${common_tsblock_LINK_OPTIONS}")
diff --git a/cpp/tsfile/src/common/tsblock/tsblock.cc b/cpp/tsfile/src/common/tsblock/tsblock.cc
new file mode 100644
index 00000000..e60b1077
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/tsblock.cc
@@ -0,0 +1,293 @@
+#include "tsblock.h"
+
+#include <string>
+
+namespace timecho
+{
+namespace common
+{
+
+int TsBlock::init()
+{
+  // todo: The current version select_list_ is useless, so it is not initialized
+  int ret = 0;
+  uint32_t row_size = tuple_desc_->get_single_row_len(&ret);
+  if (ret != 0) {
+    return ret;
+  }
+
+  // No maximum number of rows given, calculated with capacity_
+  if (LIKELY(max_row_count_ == 0)) {
+    max_row_count_ = capacity_ / row_size;
+  } else {
+    // max_row_count_ given, calculated with max_row_count_
+    capacity_ = row_size * max_row_count_;
+  }
+  int colnum = tuple_desc_->get_column_count();
+  for (int i = 0; i < colnum; ++i) {
+    ret = build_vector(tuple_desc_->get_column_type(i), max_row_count_);
+    if (ret != 0) {
+      return ret;
+    }
+  }
+  return ret;
+}
+
+int TsBlock::build_vector(common::TSDataType type, uint32_t row_count)
+{
+  Vector *vec;
+  int ret = 0;
+  if (LIKELY(type != common::TEXT)) {
+    vec = new FixedLengthVector(type, row_count, get_len(type), this);
+  } else if (type == common::TEXT) {
+    vec = new VariableLengthVector(type, row_count, DEFAULT_RESERVED_SIZE_OF_TEXT + TEXT_LEN, this);
+  } else {
+    log_error("TsBlock::BuildVector failed because of unknown type %d", static_cast<int>(type));
+    ret = E_TYPE_NOT_SUPPORTED;
+  }
+  vectors_.push_back(vec);
+  return ret;
+}
+
+void TsBlock::write_data(ByteStream* __restrict byte_stream, char* __restrict val, uint32_t len,
+    bool has_null, TSDataType type)
+{
+  std::string strval;
+  switch (type) {
+    case timecho::common::INT64: {
+      int64_t ival = *reinterpret_cast<int64_t*>(val);
+      strval = to_string(ival);
+      break;
+    }
+    case timecho::common::INT32: {
+      int32_t ival = *reinterpret_cast<int32_t*>(val);
+      strval = to_string(ival);
+      break;
+    }
+    case timecho::common::FLOAT: {
+      float ival = *reinterpret_cast<float*>(val); // cppcheck-suppress invalidPointerCast
+      strval = to_string(ival);
+      break;
+    }
+    case timecho::common::DOUBLE: {
+      double ival = *reinterpret_cast<double*>(val); // cppcheck-suppress invalidPointerCast
+      strval = to_string(ival);
+      break;
+    }
+    case timecho::common::BOOLEAN: {
+      bool ival = *reinterpret_cast<bool*>(val);
+      if (ival) {
+        strval = "true";
+      } else {
+        strval = "false";
+      }
+      break;
+    }
+    case timecho::common::TEXT:{
+      if (LIKELY(!has_null)) {
+        byte_stream->write_buf(val, len);
+      } else {
+        byte_stream->write_buf("null", 4);
+      }
+      byte_stream->write_buf(",\n", 2);
+      return;
+    }
+    default: {
+      log_error("write_data unknown type");
+    }
+  }
+  if (LIKELY(!has_null)) {
+    byte_stream->write_buf(const_cast<char*>(strval.c_str()), strval.length());
+  } else {
+    byte_stream->write_buf("null", 4);
+  }
+}
+
+void TsBlock::tsblock_to_json(ByteStream *byte_stream)
+{
+  // 1. append start tag
+  byte_stream->write_buf("{\n", 2);
+
+  // 2. append output columns to bytestream
+  int column_count = tuple_desc_->get_column_count();
+  // 2.1 append header
+  byte_stream->write_buf("  \"expressions\": [\n", 19);
+  // 2.2 append column names
+  for (int i = 1; i < column_count; ++i) {
+    std::string name = tuple_desc_->get_column_name(i);
+    byte_stream->write_buf("    ", 4);
+    byte_stream->write_buf("\"", 1);
+    byte_stream->write_buf(name.c_str(), name.length());
+    byte_stream->write_buf("\"", 1);
+    if (i == column_count - 1) {
+      byte_stream->write_buf("\n", 1);
+    } else {
+      byte_stream->write_buf(",\n", 2);
+    }
+  }
+  byte_stream->write_buf("  ],\n", 5);
+
+  // 3. append column_names
+  byte_stream->write_buf("  \"column_names\": null,\n", 24);
+
+  // 4. append time value
+  byte_stream->write_buf("  \"timestamps\": [\n", 18);
+  ColIterator time_iter(0, this);
+  bool is_first = true;
+  while (!time_iter.end()) {
+    uint32_t ilen;
+    byte_stream->write_buf("    ", 4);
+    char *val = time_iter.read(&ilen);
+    if (!is_first) {
+      byte_stream->write_buf(",\n", 2);
+    }
+    is_first = false;
+    write_data(byte_stream, val, ilen, false, INT64);
+    time_iter.next();
+  }
+  byte_stream->write_buf("  ],\n", 5);
+
+  // 5. append user values
+  byte_stream->write_buf("  \"values\": [\n", 14);
+  for (int i = 1; i < column_count; ++i) {
+    byte_stream->write_buf("    [\n", 6);
+
+    ColIterator value_iter(i, this);
+    bool has_null = value_iter.has_null();
+    if (LIKELY(!has_null)) {
+      bool is_first = true; // cppcheck-suppress shadowVariable
+      while (!value_iter.end()) {
+        uint32_t ilen = 0;
+        byte_stream->write_buf("      ", 6);
+        char *val = value_iter.read(&ilen);
+        if (!is_first) {
+          byte_stream->write_buf(",\n", 2);
+        }
+        is_first = false;
+        write_data(byte_stream, val, ilen, false, tuple_desc_->get_column_type(i));
+        value_iter.next();
+      }
+    } else {
+      while (!value_iter.end()) {
+        bool inull;
+        uint32_t ilen = 0;
+        byte_stream->write_buf("      ", 6);
+        char *val = value_iter.read(&ilen, &inull);
+        if (!is_first) {
+          byte_stream->write_buf(",\n", 2);
+        }
+        is_first = false;
+        write_data(byte_stream, val, ilen, inull, tuple_desc_->get_column_type(i));
+        value_iter.next();
+      }
+    }
+    if (i == column_count - 1) {
+      byte_stream->write_buf("    ]\n", 6);
+    } else {
+      byte_stream->write_buf("    ],\n", 7);
+    }
+  }
+  byte_stream->write_buf("  ]\n", 4);
+
+  // 6. end
+  byte_stream->write_buf("}\n", 2);
+}
+
+std::string TsBlock::debug_string()
+{
+  std::stringstream out;
+  out << "print TsBlock: " << this << std::endl
+      << "capacity_: " << capacity_ << std::endl
+      << "row_count_: " << row_count_ << std::endl
+      << "max_row_count_: " << max_row_count_ << std::endl;
+
+  out << "------ tuple desc ------" << std::endl << std::endl;
+  out << tuple_desc_->debug_string() << std::endl;
+
+  out << "------ real data area ------" << std::endl;
+
+  RowIterator iter(this);
+  while (!iter.end()) {
+    out << iter.debug_string() << std::endl;
+    iter.next();
+  }
+  return out.str();
+}
+
+std::string RowIterator::debug_string()
+{
+  std::stringstream out;
+  out.precision(20);  // Default precision is 6, set precision, otherwise double precision will be lost
+
+  for (uint32_t i = 0; i < column_count_; ++i) {
+    bool is_null = false;
+    uint32_t len = 0;
+    void *value = read(i, &len, &is_null);
+    if (is_null) {
+      out << "NULL";
+    } else {
+      ColumnDesc &col_desc = tsblock_->tuple_desc_->get_column_desc(i);
+      switch (col_desc.type_) {
+        case timecho::common::BOOLEAN: {
+          out << *static_cast<bool*>(value);
+          break;
+        }
+        case timecho::common::INT32: {
+          out << *static_cast<int32_t*>(value);
+          break;
+        }
+        case timecho::common::INT64: {
+          out << *static_cast<int64_t*>(value);
+          break;
+        }
+        case timecho::common::FLOAT: {
+          out << *static_cast<float*>(value);
+          break;
+        }
+        case timecho::common::DOUBLE: {
+          out << *static_cast<double*>(value);
+          break;
+        }
+        case timecho::common::TEXT: {
+          out << std::string(static_cast<char*>(value), len);
+          break;
+        }
+        default: {
+          out << "ERR";
+        }
+      }
+    }
+    if (i + 1 < tsblock_->tuple_desc_->get_column_count()) {
+      out << ", ";
+    }
+  }
+  return out.str();
+}
+
+// TODO use memcpy in vector instead of using iter/appender
+int merge_tsblock_by_row(TsBlock *sea, TsBlock *river)
+{
+  int ret = E_OK;
+  TupleDesc *sea_tuple_desc = sea->get_tuple_desc();
+  TupleDesc *river_tupe_desc = river->get_tuple_desc();
+  if (!sea_tuple_desc->equal_to(*river_tupe_desc)) {
+    ret = E_NOT_MATCH;
+  } else {
+    RowAppender sea_appender(sea);
+    RowIterator river_iter(river);
+    while (!river_iter.end()) {
+      sea_appender.add_row();
+      for (uint32_t c = 0; c < sea_tuple_desc->get_column_count(); c++) {
+        uint32_t len = 0;
+        bool null = false;
+        char *val = river_iter.read(c, &len, &null);
+        sea_appender.append(c, val, len);
+      }
+      river_iter.next();
+    }
+  }
+  return ret;
+}
+
+}  // common
+}  // timecho
diff --git a/cpp/tsfile/src/common/tsblock/tsblock.h b/cpp/tsfile/src/common/tsblock/tsblock.h
new file mode 100644
index 00000000..a38f6e8d
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/tsblock.h
@@ -0,0 +1,291 @@
+#ifndef COMMON_TSBLOCK_TSBLOCK_H
+#define COMMON_TSBLOCK_TSBLOCK_H
+
+#include <stdint.h>
+
+#include "common/allocator/byte_stream.h"
+#include "common/container/byte_buffer.h"
+#include "common/global.h"
+
+#include "tuple_desc.h"
+#include "vector/fixed_length_vector.h"
+#include "vector/variable_length_vector.h"
+#include "vector/vector.h"
+
+namespace timecho
+{
+namespace common
+{
+class TsBlock
+{
+public:
+  friend class RowIterator;
+  friend class ColIterator;
+
+  friend class RowAppender;
+  friend class ColAppender;
+  /*
+   * row_count: If we can clearly estimate the number of tsblock rows,
+   *            such as limit scenarios, such as based on statistical information,
+   *            such as insert scenarios, etc.
+   *            Then we will use the given number of rows
+   */
+  explicit TsBlock(TupleDesc *tupledesc, uint32_t max_row_count = 0) :
+    capacity_(g_config_value_.tsblock_max_memory_),
+    row_count_(0), max_row_count_(max_row_count), tuple_desc_(tupledesc) { }
+
+  virtual ~TsBlock()
+  {
+    int size = vectors_.size();
+    for (int i = 0; i < size; ++i) {
+      delete vectors_[i];
+    }
+  }
+
+  FORCE_INLINE uint32_t get_row_count() const { return row_count_; }
+
+  FORCE_INLINE TupleDesc* get_tuple_desc() const { return tuple_desc_; }
+  
+  FORCE_INLINE Vector* get_vector(uint32_t index) { return vectors_[index]; }
+
+  FORCE_INLINE uint32_t get_column_count() const { return tuple_desc_->get_column_count(); }
+
+  FORCE_INLINE uint32_t get_max_row_count() const { return max_row_count_; }
+
+  FORCE_INLINE uint32_t get_capacity() const { return capacity_; }
+
+  FORCE_INLINE void update_capacity(uint32_t extend_size) { capacity_ += extend_size; }
+
+  // need to call flush_row_count after using colappender
+  FORCE_INLINE int flush_row_count(uint32_t row_count)
+  {
+    int errnum = E_OK;
+    if (row_count_ == 0) {
+      row_count_ = row_count;
+    } else if (row_count_ != row_count) {
+        log_error("Inconsistent number of rows in two columns");
+        errnum = E_TSBLOCK_DATA_INCONSISTENCY;
+    }
+    return errnum;
+  }
+
+  FORCE_INLINE void reset()
+  {
+    int size = vectors_.size();
+    for (int i = 0; i < size; ++i) {
+      vectors_[i]->reset();
+    }
+    row_count_ = 0;
+  }
+
+  int init();
+  void tsblock_to_json(ByteStream *byte_stream);
+
+  std::string debug_string();
+
+private:
+  int build_vector(common::TSDataType type, uint32_t row_count);
+  void write_data(ByteStream* __restrict byte_stream,
+                  char* __restrict val,
+                  uint32_t len,
+                  bool has_null,
+                  TSDataType type);
+
+private:
+  uint32_t capacity_;       // maximum memory capacity
+  uint32_t row_count_;      // real row count
+  uint32_t max_row_count_;
+
+  common::BitMap       select_list_;
+  TupleDesc            *tuple_desc_;
+  std::vector<Vector*> vectors_;
+};
+
+class RowAppender
+{
+public:
+  explicit RowAppender(TsBlock *tsblock) :tsblock_(tsblock) {}
+  ~RowAppender() {}
+
+  // todo:(yanghao) maybe need to consider select-list
+  FORCE_INLINE bool add_row()
+  {
+    if (LIKELY(tsblock_->row_count_ < tsblock_->max_row_count_)) {
+      ++tsblock_->row_count_;
+      return true;
+    } else {
+      return false;
+    }
+  }
+  FORCE_INLINE void backoff_add_row()
+  {
+    ASSERT(tsblock_->row_count_ > 0);
+    tsblock_->row_count_--;
+  }
+
+  FORCE_INLINE void append(uint32_t slot_index, const char *value, uint32_t len)
+  {
+    ASSERT(slot_index < tsblock_->tuple_desc_->get_column_count());
+    Vector *vec = tsblock_->vectors_[slot_index];
+    vec->append(value, len);
+  }
+
+  FORCE_INLINE void append_null(uint32_t slot_index)
+  {
+    Vector *vec = tsblock_->vectors_[slot_index];
+    vec->set_null(tsblock_->row_count_ - 1);
+  }
+
+private:
+  TsBlock *tsblock_;
+};
+
+class ColAppender
+{
+public:
+  ColAppender(uint32_t column_index, TsBlock *tsblock) :
+    column_index_(column_index), column_row_count_(0), tsblock_(tsblock)
+  {
+    ASSERT(column_index < tsblock_->tuple_desc_->get_column_count());
+    vec_ = tsblock_->vectors_[column_index];
+  }
+
+  ~ColAppender() {}
+
+  // todo:(yanghao) maybe need to consider select-list
+  FORCE_INLINE bool add_row()
+  {
+    if (LIKELY(column_row_count_ < tsblock_->max_row_count_)) {
+      ++column_row_count_;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  FORCE_INLINE void append(const char *value, uint32_t len)
+  {
+    vec_->append(value, len);
+  }
+
+  FORCE_INLINE void append_null()
+  {
+    vec_->set_null(column_row_count_ - 1);
+  }
+
+  FORCE_INLINE uint32_t get_col_row_count() { return column_row_count_; }
+  FORCE_INLINE uint32_t get_column_index() { return column_index_; }
+
+private:
+  uint32_t  column_index_;
+  uint32_t  column_row_count_;
+  TsBlock   *tsblock_;
+  Vector    *vec_;
+};
+
+// todo:(yanghao) need to deal with select-list
+class RowIterator
+{
+public:
+  explicit RowIterator(TsBlock *tsblock) : tsblock_(tsblock), row_id_(0)
+  {
+    column_count_ = tsblock_->tuple_desc_->get_column_count();
+  }
+
+  ~RowIterator()
+  {
+    /*
+     * if use RowIterator and ColIterator at the same time,
+     * need to reset the offset after one is used,
+     * otherwise it will cause the offset to be wrong
+     */
+    for (uint32_t i = 0; i < column_count_; ++i) {
+      tsblock_->vectors_[i]->reset_offset();
+    }
+  }
+
+  FORCE_INLINE bool end()
+  {
+    return row_id_ >= tsblock_->row_count_;
+  }
+
+  FORCE_INLINE void next()
+  {
+    ASSERT(row_id_ < tsblock_->row_count_);
+    ++row_id_;
+    for (uint32_t i = 0; i < column_count_; ++i) {
+      tsblock_->vectors_[i]->update_offset();
+    }
+  }
+
+  FORCE_INLINE char* read(uint32_t slot_index, uint32_t* __restrict len, bool* __restrict null)
+  {
+    ASSERT(slot_index < column_count_);
+    Vector *vec = tsblock_->vectors_[slot_index];
+    return vec->read(len, null, row_id_);
+  }
+
+  std::string debug_string();  // for debug
+
+private:
+  TsBlock  *tsblock_;
+  uint32_t row_id_;    // The line number currently being read
+  uint32_t column_count_;
+};
+
+// todo:(yanghao) need to deal with select-list
+class ColIterator
+{
+public:
+  ColIterator(uint32_t column_index, const TsBlock *tsblock) :
+    column_index_(column_index), row_id_(0), tsblock_(tsblock)
+  {
+    ASSERT(column_index < tsblock_->tuple_desc_->get_column_count());
+    vec_ = tsblock_->vectors_[column_index];
+  }
+  
+  ~ColIterator()
+  {
+    vec_->reset_offset();
+  }
+
+  FORCE_INLINE bool end() const
+  {
+    return row_id_ >= tsblock_->row_count_;
+  }
+
+  FORCE_INLINE void next()
+  {
+    ++row_id_;
+    vec_->update_offset();
+  }
+
+  FORCE_INLINE bool has_null() { return vec_->has_null(); }
+
+  FORCE_INLINE TSDataType get_data_type() { return vec_->get_vector_type(); }
+
+  FORCE_INLINE char* read(uint32_t* __restrict len, bool* __restrict null)
+  {
+    return vec_->read(len, null, row_id_);
+  }
+
+  FORCE_INLINE char* read(uint32_t *len)
+  {
+    return vec_->read(len);
+  }
+
+  FORCE_INLINE uint32_t get_column_index() { return column_index_; }
+
+private:
+  uint32_t column_index_;
+  uint32_t row_id_;
+  const TsBlock  *tsblock_;
+  Vector   *vec_;
+};
+
+int merge_tsblock_by_row(TsBlock *sea, TsBlock *river);
+
+}  // end namespace common
+}  // end namespace timecho
+
+#endif // COMMON_TSBLOCK_TSBLOCK_H
diff --git a/cpp/tsfile/src/common/tsblock/tuple_desc.cc b/cpp/tsfile/src/common/tsblock/tuple_desc.cc
new file mode 100644
index 00000000..802b32d7
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/tuple_desc.cc
@@ -0,0 +1,76 @@
+#include "tuple_desc.h"
+
+namespace timecho
+{
+namespace common
+{
+  uint32_t TupleDesc::get_single_row_len(int *erro_code)
+  {
+    int size = get_column_count();
+    int totol_len = 0;
+    for (int i = 0; i < size; ++i) {
+      switch (column_list_[i].type_) {
+      case timecho::common::BOOLEAN: {
+        totol_len += sizeof(bool);
+        break;
+      }
+      case timecho::common::INT32: {
+        totol_len += sizeof(int32_t);
+        break;
+      }
+      case timecho::common::INT64: {
+        totol_len += sizeof(int64_t);
+        break;
+      }
+      case timecho::common::FLOAT: {
+        totol_len += sizeof(float);
+        break;
+      }
+      case timecho::common::DOUBLE: {
+        totol_len += sizeof(double);
+        break;
+      }
+      case timecho::common::TEXT: {
+        totol_len += DEFAULT_RESERVED_SIZE_OF_TEXT + TEXT_LEN;
+        break;
+      }
+      default: {
+        log_error("TsBlock::BuildVector unknown type %d", static_cast<int>(column_list_[i].type_));
+        *erro_code = E_TYPE_NOT_SUPPORTED;
+        break;
+      }
+      }
+    }
+    return totol_len;
+  }
+
+  uint32_t get_len(TSDataType type)
+  {
+    switch (type)
+    {
+    case timecho::common::BOOLEAN: {
+      return sizeof(bool);
+    }
+    case timecho::common::INT32: {
+      return sizeof(int32_t);
+    }
+    case timecho::common::INT64: {
+      return sizeof(int64_t);
+    }
+    case timecho::common::FLOAT: {
+      return sizeof(float);
+    }
+    case timecho::common::DOUBLE: {
+      return sizeof(double);
+    }
+    case timecho::common::TEXT: {
+      return DEFAULT_RESERVED_SIZE_OF_TEXT + TEXT_LEN;
+    }
+    default: {
+      // todo: log error
+    }
+    }
+    return 0;
+  }
+}  // common
+}  // timecho
diff --git a/cpp/tsfile/src/common/tsblock/tuple_desc.h b/cpp/tsfile/src/common/tsblock/tuple_desc.h
new file mode 100644
index 00000000..f9c04f93
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/tuple_desc.h
@@ -0,0 +1,116 @@
+#ifndef COMMON_TSBLOCK_TUPLE_DESC_H
+#define COMMON_TSBLOCK_TUPLE_DESC_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include "common/db_utils.h"
+#include "common/errno_define.h"
+#include "common/logger/elog.h"
+
+namespace timecho
+{
+namespace common
+{
+
+/*
+ * Anyway, a default length of text type is needed for easy calculation,
+ * and it will be changed to a configurable item later
+ */
+#define DEFAULT_RESERVED_SIZE_OF_TEXT 16
+#define TEXT_LEN 4
+
+extern uint32_t get_len(TSDataType type);
+
+// Describe merged information of multiple timeseries
+class TupleDesc
+{
+public:
+  TupleDesc() {}
+  virtual ~TupleDesc() {}
+
+  FORCE_INLINE void reset()
+  {
+    column_list_.clear();
+  }
+
+  FORCE_INLINE void push_back(ColumnDesc &desc)
+  {
+    column_list_.push_back(desc);
+  }
+
+  FORCE_INLINE uint32_t get_column_count() const
+  {
+    return column_list_.size();
+  }
+
+  FORCE_INLINE ColumnDesc& operator[](uint32_t index)
+  {
+    ASSERT(index < column_list_.size());
+    return column_list_[index];
+  }
+
+  FORCE_INLINE ColumnDesc& get_column_desc(uint32_t index)
+  {
+    ASSERT(index < column_list_.size());
+    return column_list_[index];
+  }
+
+  FORCE_INLINE common::TSDataType get_column_type(uint32_t index)
+  {
+    return column_list_[index].type_;
+  }
+
+  FORCE_INLINE std::string get_column_name(uint32_t index)
+  {
+    return column_list_[index].column_name_;
+  }
+
+  FORCE_INLINE void remove_column(uint32_t idx)
+  {
+    column_list_.erase(column_list_.begin() + idx);
+  }
+
+  // get the single row len, ignore nulls and select-list memory for the moment
+  uint32_t get_single_row_len(int *erro_code);
+
+  bool equal_to(const TupleDesc &that) const
+  {
+    if (column_list_.size() != that.column_list_.size()) {
+      return false;
+    }
+    for (uint32_t i = 0; i < column_list_.size(); i++) {
+      const ColumnDesc &this_col_desc = column_list_[i];
+      const ColumnDesc &that_col_desc = that.column_list_[i];
+      if (this_col_desc != that_col_desc) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void clone_from(TupleDesc *that)
+  {
+    ASSERT(column_list_.size() == 0);
+    column_list_ = that->column_list_; // deep copy
+  }
+
+  std::string debug_string()  // for debug
+  {
+    std::stringstream out;
+    for (size_t i = 0; i < column_list_.size(); ++i) {
+      out << column_list_[i].debug_string() << std::endl;
+    }
+    return out.str();
+  }
+
+private:
+  std::vector<ColumnDesc> column_list_;
+};
+
+}  // common
+}  // timecho
+
+#endif // COMMON_TSBLOCK_TUPLE_DESC_H
diff --git a/cpp/tsfile/src/common/tsblock/vector/fixed_length_vector.h b/cpp/tsfile/src/common/tsblock/vector/fixed_length_vector.h
new file mode 100644
index 00000000..8b0ec674
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/vector/fixed_length_vector.h
@@ -0,0 +1,76 @@
+#ifndef COMMON_TSBLOCK_VECTOR_FIX_LENGTH_VECTOR_H
+#define COMMON_TSBLOCK_VECTOR_FIX_LENGTH_VECTOR_H
+
+#include "vector.h"
+
+namespace timecho
+{
+namespace common
+{
+class FixedLengthVector : public Vector
+{
+public:
+  FixedLengthVector(common::TSDataType type, uint32_t max_row_num,
+      uint32_t type_size, common::TsBlock *tsblock) :
+    Vector(type, max_row_num, tsblock), type_len_(type_size)
+  {
+    values_.init(type_size * max_row_num);
+  }
+
+  ~FixedLengthVector() { }
+
+ // cppcheck-suppress missingOverride
+  FORCE_INLINE void reset() OVERRIDE
+  {
+    has_null_ = false;
+    row_num_ = 0;
+    offset_ = 0;
+    nulls_.reset();
+    values_.reset();
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE void update_offset() OVERRIDE
+  {
+    offset_ += type_len_;
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE void append(const char *value, uint32_t len) OVERRIDE
+  {
+    values_.append_fixed_value(value, len);
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE char* read(uint32_t* __restrict len, bool* __restrict null, uint32_t rowid) OVERRIDE
+  {
+    *len = type_len_;
+    if (UNLIKELY(has_null_)) {
+      *null = nulls_.test(rowid);
+    } else {
+      *null = false;
+    }
+    if (LIKELY(!(*null))) {
+      char *result = values_.read(offset_, type_len_);
+      return result;
+    } else {
+      return nullptr;
+    }
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE char* read(uint32_t *len) OVERRIDE
+  {
+    *len = type_len_;
+    char *result = values_.read(offset_, type_len_);
+    return result;
+  }
+
+private:
+  uint32_t type_len_;
+};
+
+}  // common
+}  // timecho
+
+#endif  // COMMON_TSBLOCK_VECTOR_FIX_LENGTH_VECTOR_H
diff --git a/cpp/tsfile/src/common/tsblock/vector/variable_length_vector.h b/cpp/tsfile/src/common/tsblock/vector/variable_length_vector.h
new file mode 100644
index 00000000..b1fe97e5
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/vector/variable_length_vector.h
@@ -0,0 +1,77 @@
+#ifndef COMMON_TSBLOCK_VECTOR_VARIABLE_LENGTH_VECTOR_H
+#define COMMON_TSBLOCK_VECTOR_VARIABLE_LENGTH_VECTOR_H
+
+#include "vector.h"
+
+namespace timecho
+{
+namespace common
+{
+class VariableLengthVector : public Vector
+{
+public:
+  VariableLengthVector(common::TSDataType type, uint32_t max_row_num,
+      uint32_t type_size, common::TsBlock *tsblock) : Vector(type, max_row_num, tsblock),
+      variable_type_len_(sizeof(uint32_t)), last_value_len_(0)
+  {
+    values_.init(type_size * max_row_num);
+  }
+
+  ~VariableLengthVector() {}
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE void reset() OVERRIDE
+  {
+    last_value_len_ = 0;
+    has_null_ = false;
+    row_num_ = 0;
+    offset_ = 0;
+    nulls_.reset();
+    values_.reset();
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE void update_offset() OVERRIDE
+  {
+    offset_ += variable_type_len_;
+    offset_ += last_value_len_;
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE void append(const char *value, uint32_t len) OVERRIDE
+  {
+    values_.append_variable_value(value, len);
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE char* read(uint32_t* __restrict len, bool* __restrict null, uint32_t rowid) OVERRIDE
+  {
+    if (UNLIKELY(has_null_)) {
+      *null = nulls_.test(rowid);
+    } else {
+      *null = false;
+    }
+    if (LIKELY(!(*null))) {
+      char *result = values_.read(offset_, len);
+      last_value_len_ = *len;
+      return result;
+    } else {
+      return nullptr;
+    }
+  }
+
+  // cppcheck-suppress missingOverride
+  FORCE_INLINE char* read(uint32_t *len) OVERRIDE
+  {
+    char *result = values_.read(offset_, len);
+    last_value_len_ = *len;
+    return result;
+  }
+
+private:
+  uint8_t  variable_type_len_;
+  uint32_t last_value_len_;
+};
+}
+}
+
+#endif  // COMMON_TSBLOCK_VECTOR_VARIABLE_LENGTH_VECTOR_H
diff --git a/cpp/tsfile/src/common/tsblock/vector/vector.h b/cpp/tsfile/src/common/tsblock/vector/vector.h
new file mode 100644
index 00000000..a300472e
--- /dev/null
+++ b/cpp/tsfile/src/common/tsblock/vector/vector.h
@@ -0,0 +1,75 @@
+#ifndef COMMON_TSBLOCK_VECTOR_VECTOR_H
+#define COMMON_TSBLOCK_VECTOR_VECTOR_H
+
+#include "common/container/bit_map.h"
+#include "common/container/byte_buffer.h"
+#include "common/db_utils.h"
+#include "common/util_define.h"
+#include "common/allocator/page_arena.h"
+
+namespace timecho
+{
+namespace common
+{
+
+class TsBlock;
+
+class Vector
+{
+public:
+  Vector(common::TSDataType type, uint32_t max_row_num, common::TsBlock *tsblock)
+    : has_null_(false), type_(type), max_row_num_(max_row_num), row_num_(0), offset_(0), tsblock_(tsblock)
+    {
+      nulls_.init(max_row_num, true);
+    }
+
+  virtual ~Vector() { }
+
+  // len == 0 is '' or ""
+  virtual void append(const char *value, uint32_t len) = 0;
+
+  virtual char* read(uint32_t* __restrict len, bool* __restrict null, uint32_t rowid) = 0;
+
+  // For ColIterator, it is known that no null value exists in this column
+  virtual char* read(uint32_t *len) = 0;
+
+  virtual void reset() = 0;
+
+  virtual void update_offset() = 0;
+
+  FORCE_INLINE void reset_offset() { offset_ = 0; } 
+
+  FORCE_INLINE bool is_null(uint32_t row_id) { return nulls_.test(row_id); }
+
+  FORCE_INLINE void set_null(uint32_t row_id)
+  {
+    nulls_.set(row_id);
+    has_null_ = true;
+  }
+
+  FORCE_INLINE void set_vector_type(common::TSDataType type) { type_ = type; }
+
+  FORCE_INLINE common::TSDataType get_vector_type() { return type_; }
+
+  FORCE_INLINE uint32_t get_row_num() { return row_num_; }
+
+  FORCE_INLINE common::TsBlock* get_tsblock() { return tsblock_; }
+
+  FORCE_INLINE bool has_null() { return has_null_; }
+
+// We want derived class to have access to base class members, so it is defined as protected
+protected:
+  bool               has_null_;     // mark whether there is a null value
+  common::TSDataType type_;
+  uint32_t           max_row_num_;  // max row num
+  uint32_t           row_num_;      // real row num
+  uint32_t           offset_;
+
+  common::TsBlock    *tsblock_;     // parent tsblock
+  common::BitMap     nulls_;        // null bit value
+  common::ByteBuffer values_;       // real user data
+};
+}  // common
+}  // timecho
+
+#endif // COMMON_TSBLOCK_VECTOR_VECTOR_H
diff --git a/cpp/tsfile/src/common/util_define.h b/cpp/tsfile/src/common/util_define.h
new file mode 100644
index 00000000..377590d3
--- /dev/null
+++ b/cpp/tsfile/src/common/util_define.h
@@ -0,0 +1,133 @@
+
+/*
+ * This file defines some basic macros
+ */
+
+#ifndef COMMON_UTIL_DEFINE_H
+#define COMMON_UTIL_DEFINE_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* ======== unsued ======== */
+#define UNUSED(v) ((void)(v))
+
+
+/* ======== inline ======== */
+#ifdef __GNUC__
+#define FORCE_INLINE inline __attribute__((always_inline))
+#else
+#define FORCE_INLINE inline
+#endif // __GNUC__
+
+#ifdef BUILD_FOR_SMALL_BINARY
+#define INLINE FORCE_INLINE
+#else
+#define INLINE
+#endif // BUILD_FOR_SMALL_BINARY
+
+
+/* ======== likely ======== */
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LIKELY(x)   (__builtin_expect((x), 1))
+#define UNLIKELY(x) (__builtin_expect((x), 0))
+#else
+#define LIKELY(x)   (x)
+#define UNLIKELY(x) (x)
+#endif // __GNUC__ >= 4
+
+
+/* ======== nullptr ======== */
+#if __cplusplus < 201103L
+#ifndef nullptr
+#define nullptr NULL
+#endif
+#define OVERRIDE 
+#else
+#define OVERRIDE override
+#endif // __cplusplus < 201103L
+
+
+/* ======== cache line ======== */
+#ifndef CACHE_LINE_SIZE
+#define CACHE_LINE_SIZE 64
+#endif // CACHE_LINE_SIZE
+
+
+/* ======== assert ======== */
+#ifdef NDEBUG
+#define ASSERT(condition) ((void)0)
+#else
+#define ASSERT(condition) assert((condition))
+#endif  // NDEBUG
+
+/* ======== statis assert ======== */
+/*
+ * To be compatible with C++ before C++11,
+ * @msg should be a single word (use -/_ to concat)
+ * such as This_should_be_TRUE
+ */
+#if __cplusplus < 201103L
+// TODO only define this when DEBUG
+#define STATIC_ASSERT(cond, msg) typedef char static_assertion_##msg[(cond) ? 1 : -1] __attribute__((unused))
+#else
+#define STATIC_ASSERT(cond, msg) static_assert((cond), #msg)
+#endif // __cplusplus < 201103L
+
+
+/* ======== atomic operation ======== */
+#define ATOMIC_FAA(val_addr, addv)  __atomic_fetch_add((val_addr), (addv), __ATOMIC_SEQ_CST)
+#define ATOMIC_AAF(val_addr, addv)  __atomic_add_fetch((val_addr), (addv), __ATOMIC_SEQ_CST)
+/*
+ * It implements an atomic compare and exchange operation.
+ * This compares the contents of *ptr with the contents of *expected.
+ * - If equal, the operation is a read-modify-write operation that writes desired into *ptr.
+ * - If they are not equal, the operation is a read and the current contents of *ptr are written into *expected
+ */
+#define ATOMIC_CAS(val_addr, expected, desired) \
+  __atomic_compare_exchange_n((val_addr), (expected),(desired), \
+                              /* weak = */ false, \
+                              /* success_memorder = */ __ATOMIC_SEQ_CST, \
+                              /* failure_memorder = */ __ATOMIC_SEQ_CST)
+#define ATOMIC_LOAD(val_addr)  __atomic_load_n((val_addr), __ATOMIC_SEQ_CST)
+#define ATOMIC_STORE(val_addr, val) __atomic_store_n((val_addr), (val), __ATOMIC_SEQ_CST)
+
+/* ======== align ======== */
+#define ALIGNED(a) __attribute__((aligned(a)))
+#define ALIGNED_4 ALIGNED(4)
+#define ALIGNED_8 ALIGNED(8)
+
+/* ======== disallow copy and assign ======== */
+#if __cplusplus < 201103L
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+#else
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete; \
+  TypeName& operator=(const TypeName&) = delete;
+#endif
+
+/* ======== return value check ======== */
+#define RET_FAIL(expr) UNLIKELY(common::E_OK != (ret = (expr)))
+#define RFAIL(expr) UNLIKELY(common::E_OK != (ret = (expr)))
+#define RET_SUCC(expr) LIKELY(common::E_OK != (ret = (exprt)))
+#define RSUCC(expr) LIKELY(common::E_OK != (ret = (exprt)))
+#define IS_SUCC(ret) LIKELY(common::E_OK == (ret))
+#define IS_FAIL(ret) UNLIKELY(common::E_OK != (ret))
+
+#define IS_NULL(ptr) UNLIKELY((ptr) == nullptr)
+
+/* ======== min/max ======== */
+#define UTIL_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define UTIL_MIN(a, b) ((a) > (b) ? (b) : (a))
+
+/*
+ * int64_max < 10^20
+ * consider +/- and the '\0' tail. 24 is enough
+ */
+#define INT64_TO_BASE10_MAX_LEN 24
+
+#endif // COMMON_UTIL_DEFINE_H
+
diff --git a/cpp/tsfile/src/tsfile.cpp b/cpp/tsfile/src/tsfile.cpp
deleted file mode 100644
index 7683a289..00000000
--- a/cpp/tsfile/src/tsfile.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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
- *
- *   https://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.
- */
-#include "common.hpp"
-#include "tsfile.hpp"
-
-TsFile::TsFile() {
-    // Not really doing anything here ...
-}
-
-int TsFile::doSomethingElse(int a, int b, int c) const {
-    Common* common = new Common();
-    return common->doSomething(a, b - c);
-}
\ No newline at end of file
diff --git a/cpp/tsfile/src/tsfile/CMakeLists.txt b/cpp/tsfile/src/tsfile/CMakeLists.txt
new file mode 100644
index 00000000..92beda98
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/CMakeLists.txt
@@ -0,0 +1,118 @@
+
+message("Running in src/storage/tsfile directory")
+
+aux_source_directory(. storage_tsfile_SRC_LIST)
+aux_source_directory(filter storage_tsfile_filter_SRC_LIST)
+set(storage_tsfile_INC_LIST )
+set(storage_tsfile_DEFINE_OPTIONS )
+set(storage_tsfile_COMPILE_OPTIONS )
+set(storage_tsfile_LINK_OPTIONS )
+set(storage_tsfile_for_server_SRC_LIST ${storage_tsfile_SRC_LIST}
+                                       ${storage_tsfile_filter_SRC_LIST})
+
+add_statis_objtarget(storage_tsfile storage_tsfile_for_server_SRC_LIST
+                                    storage_tsfile_INC_LIST
+                                 "${storage_tsfile_DEFINE_OPTIONS}"
+                                 "${storage_tsfile_COMPILE_OPTIONS}"
+                                 "${storage_tsfile_LINK_OPTIONS}")
+
+add_subdirectory(compress)
+add_subdirectory(encode)
+
+# for libtsfile SDK
+# FIXME remove elog
+aux_source_directory(. libtsfile_SRC_LIST)
+aux_source_directory(../common common_SRC_LIST)
+aux_source_directory(../common/allocator common_allocator_SRC_LIST)
+aux_source_directory(../common/container common_container_SRC_LIST)
+aux_source_directory(../common/tsblock common_tsblock_SRC_LIST)
+aux_source_directory(../common/logger common_logger_SRC_LIST)
+aux_source_directory(. storage_tsfile_SRC_LIST)
+aux_source_directory(compress storage_tsfile_compress_SRC_LIST)
+set(libtsfile_tsfile_SRC_LIST tsfile_writer.cc
+        qds_with_timegenerator.cc
+        qds_without_timegenerator.cc
+        tablet.cc
+        qds_with_timegenerator.cc
+        qds_without_timegenerator.cc
+        tablet.cc
+        tsfile_executor.cc
+        tsfile_reader.cc)
+set(libtsfile_DEP_SRC_LIST ${common_SRC_LIST}
+                           ${common_allocator_SRC_LIST}
+                           ${common_logger_SRC_LIST}
+                           ${common_container_SRC_LIST}
+                           ${common_tsblock_SRC_LIST}
+                           ${storage_tsfile_SRC_LIST}
+                           ${libtsfile_tsfile_SRC_LIST}
+                           ${storage_tsfile_filter_SRC_LIST}
+                           ${storage_tsfile_compress_SRC_LIST})
+                           
+add_library(tsfile SHARED ${libtsfile_SRC_LIST} ${libtsfile_DEP_SRC_LIST})
+
+# set(CMAKE_PREFIX_PATH ../../third-party/zlib-1.2.13/install/lib)
+# set(ZLIB_LIB_DIR ../../third-party/zlib-1.2.13/install/lib)
+# # find_library(my_z_lib NAMES z PATHS ${ZLIB_LIB_DIR} NO_DEFAULT_PATH REQUIRED)
+# # target_link_libraries(tsfile ${my_z_lib})
+
+# set(CMAKE_PREFIX_PATH ../../third-party/lz4-dev/lib)
+# set(LZ4_LIB_DIR ../../third-party/lz4-dev/lib)
+# find_library(my_lz4_lib NAMES lz4 PATHS ${LZ4_LIB_DIR} NO_DEFAULT_PATH REQUIRED)
+# link_directories(${LZ4_LIB_DIR})
+# target_link_libraries(tsfile ${my_lz4_lib})
+
+set(LIBTSFILE_PROJECT_VERSION 1.0)
+set(LIBTSFILE_SO_VERSION 1.0)
+set_target_properties(tsfile PROPERTIES VERSION ${LIBTSFILE_PROJECT_VERSION})
+set_target_properties(tsfile PROPERTIES SOVERSION ${LIBTSFILE_SO_VERSION})
+
+set(LIBTSFILE_SDK_DIR ${EXECUTABLE_OUTPUT_PATH}/libtsfile_sdk/)
+install(TARGETS tsfile LIBRARY DESTINATION ${LIBTSFILE_SDK_DIR}/lib)
+
+set(libtsfile_tsfile_HEADER_FILES tsfile_reader.h
+        schema.h
+        record.h
+        tsfile_writer.h
+        tablet.h
+        write_file.h
+        read_file.h
+        row_record.h
+        path.h
+        query_data_set.h
+        expression.h)
+install(FILES ${libtsfile_tsfile_HEADER_FILES} DESTINATION ${LIBTSFILE_SDK_DIR}/include/storage/tsfile)
+
+set(libtsfile_common_HEADER_FILES ../common/db_common.h
+        ../common/util_define.h
+        ../common/errno_define.h
+        ../../cmake/cmake_config.h)
+install(FILES ${libtsfile_common_HEADER_FILES} DESTINATION ${LIBTSFILE_SDK_DIR}/include/common)
+
+set(libtsfile_common_container_HEADER_FILES ../common/container/bit_map.h
+        ../common/container/simple_vector.h)
+install(FILES ${libtsfile_common_container_HEADER_FILES} DESTINATION ${LIBTSFILE_SDK_DIR}/include/common/container)
+
+set(libtsfile_tsfile_filter_HEADER_FILES filter/time_filter.h
+        filter/time_operator.h
+        filter/and_filter.h
+        filter/binary_filter.h
+        filter/between.h
+        filter/eq.h
+        filter/filter.h
+        filter/filter_type.h
+        filter/gt_eq.h
+        filter/gt.h
+        filter/in.h
+        filter/lt_eq.h
+        filter/lt.h
+        filter/not_eq.h
+        filter/or_filter.h
+        filter/time_filter.h
+        filter/time_operator.h)
+              
+install(FILES ${libtsfile_tsfile_filter_HEADER_FILES} DESTINATION ${LIBTSFILE_SDK_DIR}/include/storage/tsfile/filter)
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  add_custom_command(TARGET tsfile POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change `otool -L ${LIBRARY_OUTPUT_PATH}/libtsfile.dylib | grep liblz4 | sed 's/dylib.*/dylib/g'` ${my_lz4_lib} ${LIBRARY_OUTPUT_PATH}/libtsfile.dylib)
+  add_custom_command(TARGET tsfile POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change `otool -L ${LIBRARY_OUTPUT_PATH}/libtsfile.dylib | grep libz | sed 's/dylib.*/dylib/g'` ${my_z_lib} ${LIBRARY_OUTPUT_PATH}/libtsfile.dylib)
+endif()
diff --git a/cpp/tsfile/src/tsfile/Makefile b/cpp/tsfile/src/tsfile/Makefile
new file mode 100644
index 00000000..de7837ad
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/Makefile
@@ -0,0 +1,1281 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.24
+
+# Default target executed when no arguments are given to make.
+default_target: all
+.PHONY : default_target
+
+# Allow only one "make -f Makefile2" at a time, but pass parallelism.
+.NOTPARALLEL:
+
+#=============================================================================
+# Special targets provided by cmake.
+
+# Disable implicit rules so canonical targets will work.
+.SUFFIXES:
+
+# Disable VCS-based implicit rules.
+% : %,v
+
+# Disable VCS-based implicit rules.
+% : RCS/%
+
+# Disable VCS-based implicit rules.
+% : RCS/%,v
+
+# Disable VCS-based implicit rules.
+% : SCCS/s.%
+
+# Disable VCS-based implicit rules.
+% : s.%
+
+.SUFFIXES: .hpux_make_needs_suffix_list
+
+# Command-line flag to silence nested $(MAKE).
+$(VERBOSE)MAKESILENT = -s
+
+#Suppress display of executed commands.
+$(VERBOSE).SILENT:
+
+# A target that is always out of date.
+cmake_force:
+.PHONY : cmake_force
+
+#=============================================================================
+# Set environment variables for the build.
+
+# The shell in which to execute make rules.
+SHELL = /bin/sh
+
+# The CMake executable.
+CMAKE_COMMAND = /opt/cmake-3.24.2-linux-x86_64/bin/cmake
+
+# The command to remove a file.
+RM = /opt/cmake-3.24.2-linux-x86_64/bin/cmake -E rm -f
+
+# Escaping for special characters.
+EQUALS = =
+
+# The top-level source directory on which CMake was run.
+CMAKE_SOURCE_DIR = /home/oushu/dev/timechodb-edge
+
+# The top-level build directory on which CMake was run.
+CMAKE_BINARY_DIR = /home/oushu/dev/timechodb-edge/build/Debug
+
+#=============================================================================
+# Targets provided globally by CMake.
+
+# Special rule for the target edit_cache
+edit_cache:
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+.PHONY : edit_cache
+
+# Special rule for the target edit_cache
+edit_cache/fast: edit_cache
+.PHONY : edit_cache/fast
+
+# Special rule for the target rebuild_cache
+rebuild_cache:
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+.PHONY : rebuild_cache
+
+# Special rule for the target rebuild_cache
+rebuild_cache/fast: rebuild_cache
+.PHONY : rebuild_cache/fast
+
+# Special rule for the target list_install_components
+list_install_components:
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
+.PHONY : list_install_components
+
+# Special rule for the target list_install_components
+list_install_components/fast: list_install_components
+.PHONY : list_install_components/fast
+
+# Special rule for the target install
+install: preinstall
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake -P cmake_install.cmake
+.PHONY : install
+
+# Special rule for the target install
+install/fast: preinstall/fast
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake -P cmake_install.cmake
+.PHONY : install/fast
+
+# Special rule for the target install/local
+install/local: preinstall
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
+.PHONY : install/local
+
+# Special rule for the target install/local
+install/local/fast: preinstall/fast
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
+.PHONY : install/local/fast
+
+# Special rule for the target install/strip
+install/strip: preinstall
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
+.PHONY : install/strip
+
+# Special rule for the target install/strip
+install/strip/fast: preinstall/fast
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
+	/opt/cmake-3.24.2-linux-x86_64/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
+.PHONY : install/strip/fast
+
+# The main all target
+all: cmake_check_build_system
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(CMAKE_COMMAND) -E cmake_progress_start /home/oushu/dev/timechodb-edge/build/Debug/CMakeFiles /home/oushu/dev/timechodb-edge/build/Debug/src/storage/tsfile//CMakeFiles/progress.marks
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/storage/tsfile/all
+	$(CMAKE_COMMAND) -E cmake_progress_start /home/oushu/dev/timechodb-edge/build/Debug/CMakeFiles 0
+.PHONY : all
+
+# The main clean target
+clean:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/storage/tsfile/clean
+.PHONY : clean
+
+# The main clean target
+clean/fast: clean
+.PHONY : clean/fast
+
+# Prepare targets for installation.
+preinstall: all
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/storage/tsfile/preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/storage/tsfile/preinstall
+.PHONY : preinstall/fast
+
+# clear depends
+depend:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
+.PHONY : depend
+
+# Convenience name for target.
+src/storage/tsfile/CMakeFiles/storage_tsfile.dir/rule:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/storage/tsfile/CMakeFiles/storage_tsfile.dir/rule
+.PHONY : src/storage/tsfile/CMakeFiles/storage_tsfile.dir/rule
+
+# Convenience name for target.
+storage_tsfile: src/storage/tsfile/CMakeFiles/storage_tsfile.dir/rule
+.PHONY : storage_tsfile
+
+# fast build rule for target.
+storage_tsfile/fast:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build
+.PHONY : storage_tsfile/fast
+
+# Convenience name for target.
+src/storage/tsfile/CMakeFiles/tsfile.dir/rule:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/storage/tsfile/CMakeFiles/tsfile.dir/rule
+.PHONY : src/storage/tsfile/CMakeFiles/tsfile.dir/rule
+
+# Convenience name for target.
+tsfile: src/storage/tsfile/CMakeFiles/tsfile.dir/rule
+.PHONY : tsfile
+
+# fast build rule for target.
+tsfile/fast:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/build
+.PHONY : tsfile/fast
+
+__/__/common/allocator/mem_alloc.o: __/__/common/allocator/mem_alloc.cc.o
+.PHONY : __/__/common/allocator/mem_alloc.o
+
+# target to build an object file
+__/__/common/allocator/mem_alloc.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/allocator/mem_alloc.cc.o
+.PHONY : __/__/common/allocator/mem_alloc.cc.o
+
+__/__/common/allocator/mem_alloc.i: __/__/common/allocator/mem_alloc.cc.i
+.PHONY : __/__/common/allocator/mem_alloc.i
+
+# target to preprocess a source file
+__/__/common/allocator/mem_alloc.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/allocator/mem_alloc.cc.i
+.PHONY : __/__/common/allocator/mem_alloc.cc.i
+
+__/__/common/allocator/mem_alloc.s: __/__/common/allocator/mem_alloc.cc.s
+.PHONY : __/__/common/allocator/mem_alloc.s
+
+# target to generate assembly for a file
+__/__/common/allocator/mem_alloc.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/allocator/mem_alloc.cc.s
+.PHONY : __/__/common/allocator/mem_alloc.cc.s
+
+__/__/common/allocator/page_arena.o: __/__/common/allocator/page_arena.cc.o
+.PHONY : __/__/common/allocator/page_arena.o
+
+# target to build an object file
+__/__/common/allocator/page_arena.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/allocator/page_arena.cc.o
+.PHONY : __/__/common/allocator/page_arena.cc.o
+
+__/__/common/allocator/page_arena.i: __/__/common/allocator/page_arena.cc.i
+.PHONY : __/__/common/allocator/page_arena.i
+
+# target to preprocess a source file
+__/__/common/allocator/page_arena.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/allocator/page_arena.cc.i
+.PHONY : __/__/common/allocator/page_arena.cc.i
+
+__/__/common/allocator/page_arena.s: __/__/common/allocator/page_arena.cc.s
+.PHONY : __/__/common/allocator/page_arena.s
+
+# target to generate assembly for a file
+__/__/common/allocator/page_arena.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/allocator/page_arena.cc.s
+.PHONY : __/__/common/allocator/page_arena.cc.s
+
+__/__/common/container/bit_map.o: __/__/common/container/bit_map.cc.o
+.PHONY : __/__/common/container/bit_map.o
+
+# target to build an object file
+__/__/common/container/bit_map.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/bit_map.cc.o
+.PHONY : __/__/common/container/bit_map.cc.o
+
+__/__/common/container/bit_map.i: __/__/common/container/bit_map.cc.i
+.PHONY : __/__/common/container/bit_map.i
+
+# target to preprocess a source file
+__/__/common/container/bit_map.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/bit_map.cc.i
+.PHONY : __/__/common/container/bit_map.cc.i
+
+__/__/common/container/bit_map.s: __/__/common/container/bit_map.cc.s
+.PHONY : __/__/common/container/bit_map.s
+
+# target to generate assembly for a file
+__/__/common/container/bit_map.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/bit_map.cc.s
+.PHONY : __/__/common/container/bit_map.cc.s
+
+__/__/common/container/blocking_queue.o: __/__/common/container/blocking_queue.cc.o
+.PHONY : __/__/common/container/blocking_queue.o
+
+# target to build an object file
+__/__/common/container/blocking_queue.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/blocking_queue.cc.o
+.PHONY : __/__/common/container/blocking_queue.cc.o
+
+__/__/common/container/blocking_queue.i: __/__/common/container/blocking_queue.cc.i
+.PHONY : __/__/common/container/blocking_queue.i
+
+# target to preprocess a source file
+__/__/common/container/blocking_queue.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/blocking_queue.cc.i
+.PHONY : __/__/common/container/blocking_queue.cc.i
+
+__/__/common/container/blocking_queue.s: __/__/common/container/blocking_queue.cc.s
+.PHONY : __/__/common/container/blocking_queue.s
+
+# target to generate assembly for a file
+__/__/common/container/blocking_queue.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/blocking_queue.cc.s
+.PHONY : __/__/common/container/blocking_queue.cc.s
+
+__/__/common/container/murmur_hash3.o: __/__/common/container/murmur_hash3.cc.o
+.PHONY : __/__/common/container/murmur_hash3.o
+
+# target to build an object file
+__/__/common/container/murmur_hash3.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/murmur_hash3.cc.o
+.PHONY : __/__/common/container/murmur_hash3.cc.o
+
+__/__/common/container/murmur_hash3.i: __/__/common/container/murmur_hash3.cc.i
+.PHONY : __/__/common/container/murmur_hash3.i
+
+# target to preprocess a source file
+__/__/common/container/murmur_hash3.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/murmur_hash3.cc.i
+.PHONY : __/__/common/container/murmur_hash3.cc.i
+
+__/__/common/container/murmur_hash3.s: __/__/common/container/murmur_hash3.cc.s
+.PHONY : __/__/common/container/murmur_hash3.s
+
+# target to generate assembly for a file
+__/__/common/container/murmur_hash3.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/container/murmur_hash3.cc.s
+.PHONY : __/__/common/container/murmur_hash3.cc.s
+
+__/__/common/global.o: __/__/common/global.cc.o
+.PHONY : __/__/common/global.o
+
+# target to build an object file
+__/__/common/global.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/global.cc.o
+.PHONY : __/__/common/global.cc.o
+
+__/__/common/global.i: __/__/common/global.cc.i
+.PHONY : __/__/common/global.i
+
+# target to preprocess a source file
+__/__/common/global.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/global.cc.i
+.PHONY : __/__/common/global.cc.i
+
+__/__/common/global.s: __/__/common/global.cc.s
+.PHONY : __/__/common/global.s
+
+# target to generate assembly for a file
+__/__/common/global.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/global.cc.s
+.PHONY : __/__/common/global.cc.s
+
+__/__/common/logger/elog.o: __/__/common/logger/elog.cc.o
+.PHONY : __/__/common/logger/elog.o
+
+# target to build an object file
+__/__/common/logger/elog.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog.cc.o
+.PHONY : __/__/common/logger/elog.cc.o
+
+__/__/common/logger/elog.i: __/__/common/logger/elog.cc.i
+.PHONY : __/__/common/logger/elog.i
+
+# target to preprocess a source file
+__/__/common/logger/elog.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog.cc.i
+.PHONY : __/__/common/logger/elog.cc.i
+
+__/__/common/logger/elog.s: __/__/common/logger/elog.cc.s
+.PHONY : __/__/common/logger/elog.s
+
+# target to generate assembly for a file
+__/__/common/logger/elog.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog.cc.s
+.PHONY : __/__/common/logger/elog.cc.s
+
+__/__/common/logger/elog_async.o: __/__/common/logger/elog_async.cc.o
+.PHONY : __/__/common/logger/elog_async.o
+
+# target to build an object file
+__/__/common/logger/elog_async.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_async.cc.o
+.PHONY : __/__/common/logger/elog_async.cc.o
+
+__/__/common/logger/elog_async.i: __/__/common/logger/elog_async.cc.i
+.PHONY : __/__/common/logger/elog_async.i
+
+# target to preprocess a source file
+__/__/common/logger/elog_async.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_async.cc.i
+.PHONY : __/__/common/logger/elog_async.cc.i
+
+__/__/common/logger/elog_async.s: __/__/common/logger/elog_async.cc.s
+.PHONY : __/__/common/logger/elog_async.s
+
+# target to generate assembly for a file
+__/__/common/logger/elog_async.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_async.cc.s
+.PHONY : __/__/common/logger/elog_async.cc.s
+
+__/__/common/logger/elog_buf.o: __/__/common/logger/elog_buf.cc.o
+.PHONY : __/__/common/logger/elog_buf.o
+
+# target to build an object file
+__/__/common/logger/elog_buf.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_buf.cc.o
+.PHONY : __/__/common/logger/elog_buf.cc.o
+
+__/__/common/logger/elog_buf.i: __/__/common/logger/elog_buf.cc.i
+.PHONY : __/__/common/logger/elog_buf.i
+
+# target to preprocess a source file
+__/__/common/logger/elog_buf.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_buf.cc.i
+.PHONY : __/__/common/logger/elog_buf.cc.i
+
+__/__/common/logger/elog_buf.s: __/__/common/logger/elog_buf.cc.s
+.PHONY : __/__/common/logger/elog_buf.s
+
+# target to generate assembly for a file
+__/__/common/logger/elog_buf.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_buf.cc.s
+.PHONY : __/__/common/logger/elog_buf.cc.s
+
+__/__/common/logger/elog_file.o: __/__/common/logger/elog_file.cc.o
+.PHONY : __/__/common/logger/elog_file.o
+
+# target to build an object file
+__/__/common/logger/elog_file.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_file.cc.o
+.PHONY : __/__/common/logger/elog_file.cc.o
+
+__/__/common/logger/elog_file.i: __/__/common/logger/elog_file.cc.i
+.PHONY : __/__/common/logger/elog_file.i
+
+# target to preprocess a source file
+__/__/common/logger/elog_file.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_file.cc.i
+.PHONY : __/__/common/logger/elog_file.cc.i
+
+__/__/common/logger/elog_file.s: __/__/common/logger/elog_file.cc.s
+.PHONY : __/__/common/logger/elog_file.s
+
+# target to generate assembly for a file
+__/__/common/logger/elog_file.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_file.cc.s
+.PHONY : __/__/common/logger/elog_file.cc.s
+
+__/__/common/logger/elog_utils.o: __/__/common/logger/elog_utils.cc.o
+.PHONY : __/__/common/logger/elog_utils.o
+
+# target to build an object file
+__/__/common/logger/elog_utils.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_utils.cc.o
+.PHONY : __/__/common/logger/elog_utils.cc.o
+
+__/__/common/logger/elog_utils.i: __/__/common/logger/elog_utils.cc.i
+.PHONY : __/__/common/logger/elog_utils.i
+
+# target to preprocess a source file
+__/__/common/logger/elog_utils.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_utils.cc.i
+.PHONY : __/__/common/logger/elog_utils.cc.i
+
+__/__/common/logger/elog_utils.s: __/__/common/logger/elog_utils.cc.s
+.PHONY : __/__/common/logger/elog_utils.s
+
+# target to generate assembly for a file
+__/__/common/logger/elog_utils.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/logger/elog_utils.cc.s
+.PHONY : __/__/common/logger/elog_utils.cc.s
+
+__/__/common/tsblock/tsblock.o: __/__/common/tsblock/tsblock.cc.o
+.PHONY : __/__/common/tsblock/tsblock.o
+
+# target to build an object file
+__/__/common/tsblock/tsblock.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/tsblock/tsblock.cc.o
+.PHONY : __/__/common/tsblock/tsblock.cc.o
+
+__/__/common/tsblock/tsblock.i: __/__/common/tsblock/tsblock.cc.i
+.PHONY : __/__/common/tsblock/tsblock.i
+
+# target to preprocess a source file
+__/__/common/tsblock/tsblock.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/tsblock/tsblock.cc.i
+.PHONY : __/__/common/tsblock/tsblock.cc.i
+
+__/__/common/tsblock/tsblock.s: __/__/common/tsblock/tsblock.cc.s
+.PHONY : __/__/common/tsblock/tsblock.s
+
+# target to generate assembly for a file
+__/__/common/tsblock/tsblock.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/tsblock/tsblock.cc.s
+.PHONY : __/__/common/tsblock/tsblock.cc.s
+
+__/__/common/tsblock/tuple_desc.o: __/__/common/tsblock/tuple_desc.cc.o
+.PHONY : __/__/common/tsblock/tuple_desc.o
+
+# target to build an object file
+__/__/common/tsblock/tuple_desc.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/tsblock/tuple_desc.cc.o
+.PHONY : __/__/common/tsblock/tuple_desc.cc.o
+
+__/__/common/tsblock/tuple_desc.i: __/__/common/tsblock/tuple_desc.cc.i
+.PHONY : __/__/common/tsblock/tuple_desc.i
+
+# target to preprocess a source file
+__/__/common/tsblock/tuple_desc.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/tsblock/tuple_desc.cc.i
+.PHONY : __/__/common/tsblock/tuple_desc.cc.i
+
+__/__/common/tsblock/tuple_desc.s: __/__/common/tsblock/tuple_desc.cc.s
+.PHONY : __/__/common/tsblock/tuple_desc.s
+
+# target to generate assembly for a file
+__/__/common/tsblock/tuple_desc.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/__/__/common/tsblock/tuple_desc.cc.s
+.PHONY : __/__/common/tsblock/tuple_desc.cc.s
+
+bloom_filter.o: bloom_filter.cc.o
+.PHONY : bloom_filter.o
+
+# target to build an object file
+bloom_filter.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/bloom_filter.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/bloom_filter.cc.o
+.PHONY : bloom_filter.cc.o
+
+bloom_filter.i: bloom_filter.cc.i
+.PHONY : bloom_filter.i
+
+# target to preprocess a source file
+bloom_filter.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/bloom_filter.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/bloom_filter.cc.i
+.PHONY : bloom_filter.cc.i
+
+bloom_filter.s: bloom_filter.cc.s
+.PHONY : bloom_filter.s
+
+# target to generate assembly for a file
+bloom_filter.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/bloom_filter.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/bloom_filter.cc.s
+.PHONY : bloom_filter.cc.s
+
+chunk_reader.o: chunk_reader.cc.o
+.PHONY : chunk_reader.o
+
+# target to build an object file
+chunk_reader.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/chunk_reader.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/chunk_reader.cc.o
+.PHONY : chunk_reader.cc.o
+
+chunk_reader.i: chunk_reader.cc.i
+.PHONY : chunk_reader.i
+
+# target to preprocess a source file
+chunk_reader.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/chunk_reader.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/chunk_reader.cc.i
+.PHONY : chunk_reader.cc.i
+
+chunk_reader.s: chunk_reader.cc.s
+.PHONY : chunk_reader.s
+
+# target to generate assembly for a file
+chunk_reader.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/chunk_reader.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/chunk_reader.cc.s
+.PHONY : chunk_reader.cc.s
+
+chunk_writer.o: chunk_writer.cc.o
+.PHONY : chunk_writer.o
+
+# target to build an object file
+chunk_writer.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/chunk_writer.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/chunk_writer.cc.o
+.PHONY : chunk_writer.cc.o
+
+chunk_writer.i: chunk_writer.cc.i
+.PHONY : chunk_writer.i
+
+# target to preprocess a source file
+chunk_writer.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/chunk_writer.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/chunk_writer.cc.i
+.PHONY : chunk_writer.cc.i
+
+chunk_writer.s: chunk_writer.cc.s
+.PHONY : chunk_writer.s
+
+# target to generate assembly for a file
+chunk_writer.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/chunk_writer.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/chunk_writer.cc.s
+.PHONY : chunk_writer.cc.s
+
+compress/compressor.o: compress/compressor.c.o
+.PHONY : compress/compressor.o
+
+# target to build an object file
+compress/compressor.c.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/compressor.c.o
+.PHONY : compress/compressor.c.o
+
+compress/compressor.i: compress/compressor.c.i
+.PHONY : compress/compressor.i
+
+# target to preprocess a source file
+compress/compressor.c.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/compressor.c.i
+.PHONY : compress/compressor.c.i
+
+compress/compressor.s: compress/compressor.c.s
+.PHONY : compress/compressor.s
+
+# target to generate assembly for a file
+compress/compressor.c.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/compressor.c.s
+.PHONY : compress/compressor.c.s
+
+compress/gzip_compressor.o: compress/gzip_compressor.cc.o
+.PHONY : compress/gzip_compressor.o
+
+# target to build an object file
+compress/gzip_compressor.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/gzip_compressor.cc.o
+.PHONY : compress/gzip_compressor.cc.o
+
+compress/gzip_compressor.i: compress/gzip_compressor.cc.i
+.PHONY : compress/gzip_compressor.i
+
+# target to preprocess a source file
+compress/gzip_compressor.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/gzip_compressor.cc.i
+.PHONY : compress/gzip_compressor.cc.i
+
+compress/gzip_compressor.s: compress/gzip_compressor.cc.s
+.PHONY : compress/gzip_compressor.s
+
+# target to generate assembly for a file
+compress/gzip_compressor.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/gzip_compressor.cc.s
+.PHONY : compress/gzip_compressor.cc.s
+
+compress/lz4_compressor.o: compress/lz4_compressor.cc.o
+.PHONY : compress/lz4_compressor.o
+
+# target to build an object file
+compress/lz4_compressor.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/lz4_compressor.cc.o
+.PHONY : compress/lz4_compressor.cc.o
+
+compress/lz4_compressor.i: compress/lz4_compressor.cc.i
+.PHONY : compress/lz4_compressor.i
+
+# target to preprocess a source file
+compress/lz4_compressor.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/lz4_compressor.cc.i
+.PHONY : compress/lz4_compressor.cc.i
+
+compress/lz4_compressor.s: compress/lz4_compressor.cc.s
+.PHONY : compress/lz4_compressor.s
+
+# target to generate assembly for a file
+compress/lz4_compressor.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/compress/lz4_compressor.cc.s
+.PHONY : compress/lz4_compressor.cc.s
+
+expression.o: expression.cc.o
+.PHONY : expression.o
+
+# target to build an object file
+expression.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/expression.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/expression.cc.o
+.PHONY : expression.cc.o
+
+expression.i: expression.cc.i
+.PHONY : expression.i
+
+# target to preprocess a source file
+expression.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/expression.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/expression.cc.i
+.PHONY : expression.cc.i
+
+expression.s: expression.cc.s
+.PHONY : expression.s
+
+# target to generate assembly for a file
+expression.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/expression.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/expression.cc.s
+.PHONY : expression.cc.s
+
+filter/time_filter.o: filter/time_filter.cc.o
+.PHONY : filter/time_filter.o
+
+# target to build an object file
+filter/time_filter.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/filter/time_filter.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/filter/time_filter.cc.o
+.PHONY : filter/time_filter.cc.o
+
+filter/time_filter.i: filter/time_filter.cc.i
+.PHONY : filter/time_filter.i
+
+# target to preprocess a source file
+filter/time_filter.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/filter/time_filter.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/filter/time_filter.cc.i
+.PHONY : filter/time_filter.cc.i
+
+filter/time_filter.s: filter/time_filter.cc.s
+.PHONY : filter/time_filter.s
+
+# target to generate assembly for a file
+filter/time_filter.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/filter/time_filter.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/filter/time_filter.cc.s
+.PHONY : filter/time_filter.cc.s
+
+filter/time_operator.o: filter/time_operator.cc.o
+.PHONY : filter/time_operator.o
+
+# target to build an object file
+filter/time_operator.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/filter/time_operator.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/filter/time_operator.cc.o
+.PHONY : filter/time_operator.cc.o
+
+filter/time_operator.i: filter/time_operator.cc.i
+.PHONY : filter/time_operator.i
+
+# target to preprocess a source file
+filter/time_operator.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/filter/time_operator.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/filter/time_operator.cc.i
+.PHONY : filter/time_operator.cc.i
+
+filter/time_operator.s: filter/time_operator.cc.s
+.PHONY : filter/time_operator.s
+
+# target to generate assembly for a file
+filter/time_operator.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/filter/time_operator.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/filter/time_operator.cc.s
+.PHONY : filter/time_operator.cc.s
+
+open_file.o: open_file.cc.o
+.PHONY : open_file.o
+
+# target to build an object file
+open_file.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/open_file.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/open_file.cc.o
+.PHONY : open_file.cc.o
+
+open_file.i: open_file.cc.i
+.PHONY : open_file.i
+
+# target to preprocess a source file
+open_file.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/open_file.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/open_file.cc.i
+.PHONY : open_file.cc.i
+
+open_file.s: open_file.cc.s
+.PHONY : open_file.s
+
+# target to generate assembly for a file
+open_file.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/open_file.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/open_file.cc.s
+.PHONY : open_file.cc.s
+
+page_writer.o: page_writer.cc.o
+.PHONY : page_writer.o
+
+# target to build an object file
+page_writer.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/page_writer.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/page_writer.cc.o
+.PHONY : page_writer.cc.o
+
+page_writer.i: page_writer.cc.i
+.PHONY : page_writer.i
+
+# target to preprocess a source file
+page_writer.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/page_writer.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/page_writer.cc.i
+.PHONY : page_writer.cc.i
+
+page_writer.s: page_writer.cc.s
+.PHONY : page_writer.s
+
+# target to generate assembly for a file
+page_writer.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/page_writer.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/page_writer.cc.s
+.PHONY : page_writer.cc.s
+
+qds_with_timegenerator.o: qds_with_timegenerator.cc.o
+.PHONY : qds_with_timegenerator.o
+
+# target to build an object file
+qds_with_timegenerator.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/qds_with_timegenerator.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/qds_with_timegenerator.cc.o
+.PHONY : qds_with_timegenerator.cc.o
+
+qds_with_timegenerator.i: qds_with_timegenerator.cc.i
+.PHONY : qds_with_timegenerator.i
+
+# target to preprocess a source file
+qds_with_timegenerator.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/qds_with_timegenerator.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/qds_with_timegenerator.cc.i
+.PHONY : qds_with_timegenerator.cc.i
+
+qds_with_timegenerator.s: qds_with_timegenerator.cc.s
+.PHONY : qds_with_timegenerator.s
+
+# target to generate assembly for a file
+qds_with_timegenerator.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/qds_with_timegenerator.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/qds_with_timegenerator.cc.s
+.PHONY : qds_with_timegenerator.cc.s
+
+qds_without_timegenerator.o: qds_without_timegenerator.cc.o
+.PHONY : qds_without_timegenerator.o
+
+# target to build an object file
+qds_without_timegenerator.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/qds_without_timegenerator.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/qds_without_timegenerator.cc.o
+.PHONY : qds_without_timegenerator.cc.o
+
+qds_without_timegenerator.i: qds_without_timegenerator.cc.i
+.PHONY : qds_without_timegenerator.i
+
+# target to preprocess a source file
+qds_without_timegenerator.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/qds_without_timegenerator.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/qds_without_timegenerator.cc.i
+.PHONY : qds_without_timegenerator.cc.i
+
+qds_without_timegenerator.s: qds_without_timegenerator.cc.s
+.PHONY : qds_without_timegenerator.s
+
+# target to generate assembly for a file
+qds_without_timegenerator.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/qds_without_timegenerator.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/qds_without_timegenerator.cc.s
+.PHONY : qds_without_timegenerator.cc.s
+
+read_file.o: read_file.cc.o
+.PHONY : read_file.o
+
+# target to build an object file
+read_file.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/read_file.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/read_file.cc.o
+.PHONY : read_file.cc.o
+
+read_file.i: read_file.cc.i
+.PHONY : read_file.i
+
+# target to preprocess a source file
+read_file.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/read_file.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/read_file.cc.i
+.PHONY : read_file.cc.i
+
+read_file.s: read_file.cc.s
+.PHONY : read_file.s
+
+# target to generate assembly for a file
+read_file.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/read_file.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/read_file.cc.s
+.PHONY : read_file.cc.s
+
+tablet.o: tablet.cc.o
+.PHONY : tablet.o
+
+# target to build an object file
+tablet.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tablet.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tablet.cc.o
+.PHONY : tablet.cc.o
+
+tablet.i: tablet.cc.i
+.PHONY : tablet.i
+
+# target to preprocess a source file
+tablet.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tablet.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tablet.cc.i
+.PHONY : tablet.cc.i
+
+tablet.s: tablet.cc.s
+.PHONY : tablet.s
+
+# target to generate assembly for a file
+tablet.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tablet.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tablet.cc.s
+.PHONY : tablet.cc.s
+
+tsfile_common.o: tsfile_common.cc.o
+.PHONY : tsfile_common.o
+
+# target to build an object file
+tsfile_common.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_common.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_common.cc.o
+.PHONY : tsfile_common.cc.o
+
+tsfile_common.i: tsfile_common.cc.i
+.PHONY : tsfile_common.i
+
+# target to preprocess a source file
+tsfile_common.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_common.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_common.cc.i
+.PHONY : tsfile_common.cc.i
+
+tsfile_common.s: tsfile_common.cc.s
+.PHONY : tsfile_common.s
+
+# target to generate assembly for a file
+tsfile_common.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_common.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_common.cc.s
+.PHONY : tsfile_common.cc.s
+
+tsfile_executor.o: tsfile_executor.cc.o
+.PHONY : tsfile_executor.o
+
+# target to build an object file
+tsfile_executor.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_executor.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_executor.cc.o
+.PHONY : tsfile_executor.cc.o
+
+tsfile_executor.i: tsfile_executor.cc.i
+.PHONY : tsfile_executor.i
+
+# target to preprocess a source file
+tsfile_executor.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_executor.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_executor.cc.i
+.PHONY : tsfile_executor.cc.i
+
+tsfile_executor.s: tsfile_executor.cc.s
+.PHONY : tsfile_executor.s
+
+# target to generate assembly for a file
+tsfile_executor.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_executor.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_executor.cc.s
+.PHONY : tsfile_executor.cc.s
+
+tsfile_io_reader.o: tsfile_io_reader.cc.o
+.PHONY : tsfile_io_reader.o
+
+# target to build an object file
+tsfile_io_reader.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_io_reader.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_io_reader.cc.o
+.PHONY : tsfile_io_reader.cc.o
+
+tsfile_io_reader.i: tsfile_io_reader.cc.i
+.PHONY : tsfile_io_reader.i
+
+# target to preprocess a source file
+tsfile_io_reader.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_io_reader.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_io_reader.cc.i
+.PHONY : tsfile_io_reader.cc.i
+
+tsfile_io_reader.s: tsfile_io_reader.cc.s
+.PHONY : tsfile_io_reader.s
+
+# target to generate assembly for a file
+tsfile_io_reader.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_io_reader.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_io_reader.cc.s
+.PHONY : tsfile_io_reader.cc.s
+
+tsfile_io_writer.o: tsfile_io_writer.cc.o
+.PHONY : tsfile_io_writer.o
+
+# target to build an object file
+tsfile_io_writer.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_io_writer.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_io_writer.cc.o
+.PHONY : tsfile_io_writer.cc.o
+
+tsfile_io_writer.i: tsfile_io_writer.cc.i
+.PHONY : tsfile_io_writer.i
+
+# target to preprocess a source file
+tsfile_io_writer.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_io_writer.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_io_writer.cc.i
+.PHONY : tsfile_io_writer.cc.i
+
+tsfile_io_writer.s: tsfile_io_writer.cc.s
+.PHONY : tsfile_io_writer.s
+
+# target to generate assembly for a file
+tsfile_io_writer.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_io_writer.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_io_writer.cc.s
+.PHONY : tsfile_io_writer.cc.s
+
+tsfile_mgr.o: tsfile_mgr.cc.o
+.PHONY : tsfile_mgr.o
+
+# target to build an object file
+tsfile_mgr.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_mgr.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_mgr.cc.o
+.PHONY : tsfile_mgr.cc.o
+
+tsfile_mgr.i: tsfile_mgr.cc.i
+.PHONY : tsfile_mgr.i
+
+# target to preprocess a source file
+tsfile_mgr.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_mgr.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_mgr.cc.i
+.PHONY : tsfile_mgr.cc.i
+
+tsfile_mgr.s: tsfile_mgr.cc.s
+.PHONY : tsfile_mgr.s
+
+# target to generate assembly for a file
+tsfile_mgr.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_mgr.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_mgr.cc.s
+.PHONY : tsfile_mgr.cc.s
+
+tsfile_reader.o: tsfile_reader.cc.o
+.PHONY : tsfile_reader.o
+
+# target to build an object file
+tsfile_reader.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_reader.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_reader.cc.o
+.PHONY : tsfile_reader.cc.o
+
+tsfile_reader.i: tsfile_reader.cc.i
+.PHONY : tsfile_reader.i
+
+# target to preprocess a source file
+tsfile_reader.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_reader.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_reader.cc.i
+.PHONY : tsfile_reader.cc.i
+
+tsfile_reader.s: tsfile_reader.cc.s
+.PHONY : tsfile_reader.s
+
+# target to generate assembly for a file
+tsfile_reader.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_reader.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_reader.cc.s
+.PHONY : tsfile_reader.cc.s
+
+tsfile_series_scan_iterator.o: tsfile_series_scan_iterator.cc.o
+.PHONY : tsfile_series_scan_iterator.o
+
+# target to build an object file
+tsfile_series_scan_iterator.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_series_scan_iterator.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_series_scan_iterator.cc.o
+.PHONY : tsfile_series_scan_iterator.cc.o
+
+tsfile_series_scan_iterator.i: tsfile_series_scan_iterator.cc.i
+.PHONY : tsfile_series_scan_iterator.i
+
+# target to preprocess a source file
+tsfile_series_scan_iterator.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_series_scan_iterator.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_series_scan_iterator.cc.i
+.PHONY : tsfile_series_scan_iterator.cc.i
+
+tsfile_series_scan_iterator.s: tsfile_series_scan_iterator.cc.s
+.PHONY : tsfile_series_scan_iterator.s
+
+# target to generate assembly for a file
+tsfile_series_scan_iterator.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_series_scan_iterator.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_series_scan_iterator.cc.s
+.PHONY : tsfile_series_scan_iterator.cc.s
+
+tsfile_writer.o: tsfile_writer.cc.o
+.PHONY : tsfile_writer.o
+
+# target to build an object file
+tsfile_writer.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_writer.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_writer.cc.o
+.PHONY : tsfile_writer.cc.o
+
+tsfile_writer.i: tsfile_writer.cc.i
+.PHONY : tsfile_writer.i
+
+# target to preprocess a source file
+tsfile_writer.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_writer.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_writer.cc.i
+.PHONY : tsfile_writer.cc.i
+
+tsfile_writer.s: tsfile_writer.cc.s
+.PHONY : tsfile_writer.s
+
+# target to generate assembly for a file
+tsfile_writer.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/tsfile_writer.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/tsfile_writer.cc.s
+.PHONY : tsfile_writer.cc.s
+
+write_file.o: write_file.cc.o
+.PHONY : write_file.o
+
+# target to build an object file
+write_file.cc.o:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/write_file.cc.o
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/write_file.cc.o
+.PHONY : write_file.cc.o
+
+write_file.i: write_file.cc.i
+.PHONY : write_file.i
+
+# target to preprocess a source file
+write_file.cc.i:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/write_file.cc.i
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/write_file.cc.i
+.PHONY : write_file.cc.i
+
+write_file.s: write_file.cc.s
+.PHONY : write_file.s
+
+# target to generate assembly for a file
+write_file.cc.s:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/storage_tsfile.dir/build.make src/storage/tsfile/CMakeFiles/storage_tsfile.dir/write_file.cc.s
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(MAKE) $(MAKESILENT) -f src/storage/tsfile/CMakeFiles/tsfile.dir/build.make src/storage/tsfile/CMakeFiles/tsfile.dir/write_file.cc.s
+.PHONY : write_file.cc.s
+
+# Help Target
+help:
+	@echo "The following are some of the valid targets for this Makefile:"
+	@echo "... all (the default if no target is provided)"
+	@echo "... clean"
+	@echo "... depend"
+	@echo "... edit_cache"
+	@echo "... install"
+	@echo "... install/local"
+	@echo "... install/strip"
+	@echo "... list_install_components"
+	@echo "... rebuild_cache"
+	@echo "... storage_tsfile"
+	@echo "... tsfile"
+	@echo "... __/__/common/allocator/mem_alloc.o"
+	@echo "... __/__/common/allocator/mem_alloc.i"
+	@echo "... __/__/common/allocator/mem_alloc.s"
+	@echo "... __/__/common/allocator/page_arena.o"
+	@echo "... __/__/common/allocator/page_arena.i"
+	@echo "... __/__/common/allocator/page_arena.s"
+	@echo "... __/__/common/container/bit_map.o"
+	@echo "... __/__/common/container/bit_map.i"
+	@echo "... __/__/common/container/bit_map.s"
+	@echo "... __/__/common/container/blocking_queue.o"
+	@echo "... __/__/common/container/blocking_queue.i"
+	@echo "... __/__/common/container/blocking_queue.s"
+	@echo "... __/__/common/container/murmur_hash3.o"
+	@echo "... __/__/common/container/murmur_hash3.i"
+	@echo "... __/__/common/container/murmur_hash3.s"
+	@echo "... __/__/common/global.o"
+	@echo "... __/__/common/global.i"
+	@echo "... __/__/common/global.s"
+	@echo "... __/__/common/logger/elog.o"
+	@echo "... __/__/common/logger/elog.i"
+	@echo "... __/__/common/logger/elog.s"
+	@echo "... __/__/common/logger/elog_async.o"
+	@echo "... __/__/common/logger/elog_async.i"
+	@echo "... __/__/common/logger/elog_async.s"
+	@echo "... __/__/common/logger/elog_buf.o"
+	@echo "... __/__/common/logger/elog_buf.i"
+	@echo "... __/__/common/logger/elog_buf.s"
+	@echo "... __/__/common/logger/elog_file.o"
+	@echo "... __/__/common/logger/elog_file.i"
+	@echo "... __/__/common/logger/elog_file.s"
+	@echo "... __/__/common/logger/elog_utils.o"
+	@echo "... __/__/common/logger/elog_utils.i"
+	@echo "... __/__/common/logger/elog_utils.s"
+	@echo "... __/__/common/tsblock/tsblock.o"
+	@echo "... __/__/common/tsblock/tsblock.i"
+	@echo "... __/__/common/tsblock/tsblock.s"
+	@echo "... __/__/common/tsblock/tuple_desc.o"
+	@echo "... __/__/common/tsblock/tuple_desc.i"
+	@echo "... __/__/common/tsblock/tuple_desc.s"
+	@echo "... bloom_filter.o"
+	@echo "... bloom_filter.i"
+	@echo "... bloom_filter.s"
+	@echo "... chunk_reader.o"
+	@echo "... chunk_reader.i"
+	@echo "... chunk_reader.s"
+	@echo "... chunk_writer.o"
+	@echo "... chunk_writer.i"
+	@echo "... chunk_writer.s"
+	@echo "... compress/compressor.o"
+	@echo "... compress/compressor.i"
+	@echo "... compress/compressor.s"
+	@echo "... compress/gzip_compressor.o"
+	@echo "... compress/gzip_compressor.i"
+	@echo "... compress/gzip_compressor.s"
+	@echo "... compress/lz4_compressor.o"
+	@echo "... compress/lz4_compressor.i"
+	@echo "... compress/lz4_compressor.s"
+	@echo "... expression.o"
+	@echo "... expression.i"
+	@echo "... expression.s"
+	@echo "... filter/time_filter.o"
+	@echo "... filter/time_filter.i"
+	@echo "... filter/time_filter.s"
+	@echo "... filter/time_operator.o"
+	@echo "... filter/time_operator.i"
+	@echo "... filter/time_operator.s"
+	@echo "... open_file.o"
+	@echo "... open_file.i"
+	@echo "... open_file.s"
+	@echo "... page_writer.o"
+	@echo "... page_writer.i"
+	@echo "... page_writer.s"
+	@echo "... qds_with_timegenerator.o"
+	@echo "... qds_with_timegenerator.i"
+	@echo "... qds_with_timegenerator.s"
+	@echo "... qds_without_timegenerator.o"
+	@echo "... qds_without_timegenerator.i"
+	@echo "... qds_without_timegenerator.s"
+	@echo "... read_file.o"
+	@echo "... read_file.i"
+	@echo "... read_file.s"
+	@echo "... tablet.o"
+	@echo "... tablet.i"
+	@echo "... tablet.s"
+	@echo "... tsfile_common.o"
+	@echo "... tsfile_common.i"
+	@echo "... tsfile_common.s"
+	@echo "... tsfile_executor.o"
+	@echo "... tsfile_executor.i"
+	@echo "... tsfile_executor.s"
+	@echo "... tsfile_io_reader.o"
+	@echo "... tsfile_io_reader.i"
+	@echo "... tsfile_io_reader.s"
+	@echo "... tsfile_io_writer.o"
+	@echo "... tsfile_io_writer.i"
+	@echo "... tsfile_io_writer.s"
+	@echo "... tsfile_mgr.o"
+	@echo "... tsfile_mgr.i"
+	@echo "... tsfile_mgr.s"
+	@echo "... tsfile_reader.o"
+	@echo "... tsfile_reader.i"
+	@echo "... tsfile_reader.s"
+	@echo "... tsfile_series_scan_iterator.o"
+	@echo "... tsfile_series_scan_iterator.i"
+	@echo "... tsfile_series_scan_iterator.s"
+	@echo "... tsfile_writer.o"
+	@echo "... tsfile_writer.i"
+	@echo "... tsfile_writer.s"
+	@echo "... write_file.o"
+	@echo "... write_file.i"
+	@echo "... write_file.s"
+.PHONY : help
+
+
+
+#=============================================================================
+# Special targets to cleanup operation of make.
+
+# Special rule to run CMake to check the build system integrity.
+# No rule that depends on this can have commands that come from listfiles
+# because they might be regenerated.
+cmake_check_build_system:
+	cd /home/oushu/dev/timechodb-edge/build/Debug && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
+.PHONY : cmake_check_build_system
+
diff --git a/cpp/tsfile/src/tsfile/bloom_filter.cc b/cpp/tsfile/src/tsfile/bloom_filter.cc
new file mode 100644
index 00000000..374285a8
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/bloom_filter.cc
@@ -0,0 +1,254 @@
+
+#include "bloom_filter.h"
+#if USE_SYS_MATH
+#include <math.h>
+#endif
+
+using namespace timecho::common;
+
+namespace timecho
+{
+namespace storage
+{
+
+#if USE_SYS_MATH
+// Returns the natural logarithm (base e) of a double value
+double math_log(double in)
+{
+  return math.log(in);
+}
+#else
+// Returns the natural logarithm (base e) of a double value
+// To avoid use libm.so (however libstdc++ use libm.so sigh..)
+double math_log(double in)
+{
+  // result table: 0.90, 0.91, ... , 0.99
+  const double in_arr[10] = {
+    0.01,
+    0.02,
+    0.03,
+    0.04,
+    0.05,
+    0.06,
+    0.07,
+    0.08,
+    0.09,
+    0.10,
+  };
+  const double res_arr[10] = {
+    /* ln(0.01) = */ -4.60517018599,
+    /* ln(0.02) = */ -3.91202300543,
+    /* ln(0.03) = */ -3.50655789732,
+    /* ln(0.04) = */ -3.21887582487,
+    /* ln(0.05) = */ -2.99573227355,
+    /* ln(0.06) = */ -2.81341071676,
+    /* ln(0.07) = */ -2.65926003693,
+    /* ln(0.08) = */ -2.52572864431,
+    /* ln(0.09) = */ -2.40794560865,
+    /* ln(0.10) = */ -2.30258509299,
+  };
+
+  if (in <= 0.01) {
+    return res_arr[0];
+  } else if (in >= 0.10) {
+    return res_arr[9];
+  }
+  int i = 0;
+  for (; i < 10; i++) {
+    if (in < in_arr[i]) {
+      break;
+    }
+  }
+  if (i > 0) { // float number is not precise
+    return res_arr[i - 1];
+  } else {
+    return res_arr[0];
+  }
+}
+#endif
+
+/* ================ BitSet ================ */
+void BitSet::to_bytes(uint8_t *&ret_bytes, int32_t &ret_len) const
+{
+  int32_t words_in_use = get_words_in_use();
+  if (words_in_use == 0) {
+    return;
+  }
+
+  int len = 8 * (words_in_use - 1);
+  uint64_t x = words_[words_in_use - 1]; 
+  while (x != 0) {
+    len++;
+    x = x >> 8;
+  }
+
+  uint8_t *res = (uint8_t*)mem_alloc(sizeof(uint8_t) * len, MOD_BLOOM_FILTER);
+  int32_t res_pos = 0;
+  for (int32_t w = 0; w < words_in_use - 1; w++) {
+    uint64_t word = words_[w];
+    for (int b = 0; b < 8; b++) {
+      *(res + res_pos) = (uint8_t)(word & 0xFF);
+      word = word >> 8;
+      res_pos++;
+    }
+  }
+  uint64_t last_word = words_[words_in_use - 1];
+  for (; res_pos < len; res_pos++) {
+    *(res + res_pos) = (uint8_t)(last_word & 0xFF);
+    last_word = last_word >> 8;
+  }
+
+  ASSERT(res_pos == len);
+  ret_bytes = res;
+  ret_len = len;
+}
+
+// TODO byte-wise unittest
+int BitSet::from_bytes(uint8_t *filter_data, uint32_t filter_data_bytes_len)
+{
+  int ret = E_OK;
+
+  word_count_ = (filter_data_bytes_len / 8) + (filter_data_bytes_len % 8 == 0 ? 0 : 1);
+  words_ = (uint64_t*)mem_alloc(word_count_ * sizeof(uint64_t), MOD_BLOOM_FILTER);
+  if (IS_NULL(words_)) {
+    return E_OOM;
+  }
+
+  uint32_t word_idx = 0;
+  for (; word_idx < (filter_data_bytes_len / 8); word_idx += 1) {
+    uint64_t cur_word = 0;
+    uint8_t *cur_word_start_byte = filter_data + (word_idx * 8);
+    cur_word |= *(cur_word_start_byte + 0);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 1);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 2);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 3);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 4);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 5);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 6);  cur_word = cur_word << 8;
+    cur_word |= *(cur_word_start_byte + 7);  cur_word = cur_word << 8;
+    *(words_ + word_idx) = cur_word;
+  }
+
+  if (filter_data_bytes_len - word_idx * 8 > 0) {
+    uint64_t cur_word = 0;
+    uint8_t *cur_word_start_byte = filter_data + (word_idx * 8);
+    for (uint32_t r = 0; r < filter_data_bytes_len - word_idx * 8; r++) {
+      cur_word |= *(cur_word_start_byte + r);
+      cur_word = cur_word << 8;
+    }
+    *(words_ + word_idx) = cur_word;
+  }
+  return ret;
+}
+
+/* ================ Bloom Filter ================ */
+const double BloomFilter::MIN_BF_ERROR_RATE = 0.01;
+const double BloomFilter::MAX_BF_ERROR_RATE = 0.1;
+const int32_t BloomFilter::SEEDS[MAX_HASH_FUNC_COUNT] = {5, 7, 11, 19, 31, 37, 43, 59};
+
+int BloomFilter::init(double error_percent, int entry_count)
+{
+  if (error_percent < MIN_BF_ERROR_RATE) {
+    error_percent = MIN_BF_ERROR_RATE;
+  } else if (error_percent > MAX_BF_ERROR_RATE) {
+    error_percent = MAX_BF_ERROR_RATE;
+  }
+
+  double ln2 = 0.6931471805599453;
+  double math_log_error_percent = math_log(error_percent);
+  int32_t size = (-1) * ((int32_t)(entry_count * math_log_error_percent / ln2 / ln2)) + 1;
+  int32_t hash_func_count = (-1) * (math_log_error_percent / ln2) + 1;
+  size_ = UTIL_MAX(size, MIN_SIZE);
+  hash_func_count_ = UTIL_MIN(hash_func_count, MAX_HASH_FUNC_COUNT);
+
+  for (uint32_t i = 0; i < hash_func_count_; i++) {
+    hash_func_arr_[i].init(size_, SEEDS[i]);
+  }
+  int ret = bitset_.init(size_);
+  return ret;
+}
+
+String BloomFilter::get_entry_string(const String &device_name,
+                                     const String &measurement_name)
+{
+  String ret_str;
+  int len = device_name.len_ + measurement_name.len_ + 2; // '.' and '\0'
+  char *path_buf = (char*)mem_alloc(len, MOD_BLOOM_FILTER);
+  if (IS_NULL(path_buf)) {
+    return ret_str;
+  }
+  memcpy(path_buf, device_name.buf_, device_name.len_);
+  *(path_buf + device_name.len_) = '.';
+  memcpy(path_buf + device_name.len_ + 1, measurement_name.buf_, measurement_name.len_);
+  *(path_buf + device_name.len_ + measurement_name.len_ + 1) = '\0';
+  ret_str.buf_ = path_buf;
+  ret_str.len_ = len;
+  return ret_str;
+}
+
+int BloomFilter::add_path_entry(const String &device_name,
+                                const String &measurement_name)
+{
+  if (device_name.is_null() || measurement_name.is_null()) {
+    return E_INVALID_ARG;
+  }
+
+  String entry = get_entry_string(device_name, measurement_name);
+  if (IS_NULL(entry.buf_)) {
+    return E_OOM;
+  }
+
+  for (uint32_t i = 0; i < hash_func_count_; i++) {
+    HashFunction &hf = hash_func_arr_[i];
+    int32_t hv = hf.hash(entry);
+    bitset_.set(hv);
+  }
+  free_entry_buf(entry.buf_);
+  return E_OK;
+}
+
+int BloomFilter::serialize_to(ByteStream &out)
+{
+  int ret = E_OK;
+  uint8_t *filter_data_bytes = nullptr;
+  int32_t filter_data_bytes_len = 0;
+  bitset_.to_bytes(filter_data_bytes, filter_data_bytes_len);
+  ASSERT(filter_data_bytes_len > 0);
+
+  if (RET_FAIL(SerializationUtil::write_var_uint(filter_data_bytes_len, out))) {
+  } else if (RET_FAIL(out.write_buf(filter_data_bytes, filter_data_bytes_len))) {
+  } else if (RET_FAIL(SerializationUtil::write_var_uint(size_, out))) {
+  } else if (RET_FAIL(SerializationUtil::write_var_uint(hash_func_count_, out))) {
+  }
+  bitset_.revert_bytes(filter_data_bytes);
+  return ret;
+}
+
+int BloomFilter::deserialize_from(ByteStream &in)
+{
+  int ret = E_OK;
+  uint32_t filter_data_bytes_len = 0;
+  uint32_t ret_read_len = 0;
+  uint8_t *filter_data = nullptr;
+  if (RET_FAIL(SerializationUtil::read_var_uint(filter_data_bytes_len, in))) {
+  } else if (UNLIKELY(nullptr == (filter_data = (uint8_t*)mem_alloc(filter_data_bytes_len,
+                                                                    MOD_BLOOM_FILTER)))) {
+    ret = E_OOM;
+  } else if (RET_FAIL(in.read_buf(filter_data, filter_data_bytes_len, ret_read_len))) {
+  } else if (RET_FAIL(bitset_.from_bytes(filter_data, filter_data_bytes_len))) {
+  } else if (RET_FAIL(SerializationUtil::read_var_uint(size_, in))) {
+  } else if (RET_FAIL(SerializationUtil::read_var_uint(hash_func_count_, in))) {
+  } else {
+    for (uint32_t i = 0; i < hash_func_count_; i++) {
+      hash_func_arr_[i].init(size_, SEEDS[i]);
+    }
+  }
+  if (filter_data != nullptr) {
+    mem_free(filter_data);
+  }
+  return ret;
+}
+
+} // namespace storage
+} // namespace timecho
+
diff --git a/cpp/tsfile/src/tsfile/bloom_filter.h b/cpp/tsfile/src/tsfile/bloom_filter.h
new file mode 100644
index 00000000..b1bbf490
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/bloom_filter.h
@@ -0,0 +1,120 @@
+
+#ifndef STORAGE_TSFILE_BLOOM_FILTER_H
+#define STORAGE_TSFILE_BLOOM_FILTER_H
+
+#include "common/allocator/alloc_base.h"
+#include "common/allocator/my_string.h"
+#include "common/allocator/byte_stream.h"
+#include "common/container/murmur_hash3.h"
+
+namespace timecho
+{
+namespace storage
+{
+
+class HashFunction
+{
+public:
+  HashFunction() : cap_(0), seed_(0) {}
+  void init(int32_t cap, int32_t seed)
+  {
+    ASSERT(cap > 1);
+    cap_ = cap;
+    seed_ = seed;
+  }
+  FORCE_INLINE int32_t hash(common::String buf)
+  {
+    int res = common::Murmur128Hash::hash(buf, seed_);
+    if (res == INT32_MIN) {
+      res = 0;
+    }
+    res = (res > 0 ? res : (0 - res)) % cap_;
+    return res;
+  }
+private:
+  int32_t cap_;
+  int32_t seed_;
+};
+
+class BitSet
+{
+public:
+  BitSet() : words_(nullptr), word_count_(0) {}
+  int init(int32_t size)
+  {
+    ASSERT(size > 1);
+    word_count_ = (size - 1) / 64 + 1;
+    int32_t alloc_size = word_count_ * sizeof(uint64_t);
+    words_ = (uint64_t*)common::mem_alloc(alloc_size, common::MOD_BLOOM_FILTER);
+    if (IS_NULL(words_)) {
+      return common::E_OOM;
+    }
+    memset(words_, 0, alloc_size);
+    return common::E_OK;
+  }
+  void destroy()
+  {
+    if (!IS_NULL(words_)) {
+      common::mem_free(words_);
+      words_ = nullptr;
+    }
+  }
+  void set(int32_t pos)
+  {
+    int32_t word_idx = pos / 64;
+    int32_t word_offset = pos % 64;
+    words_[word_idx] |= (1ul << word_offset);
+  }
+  int32_t get_words_in_use() const
+  {
+    for (int32_t i = word_count_ - 1; i >= 0; i--) {
+      if (words_[i] != 0) {
+        return i + 1;
+      }
+    }
+    return 0;
+  }
+  void to_bytes(uint8_t *&ret_bytes, int32_t &ret_len) const;
+  void revert_bytes(uint8_t *bytes) { common::mem_free(bytes); }
+  int from_bytes(uint8_t *filter_data, uint32_t filter_data_bytes_len);
+private:
+  uint64_t *words_;
+  int32_t word_count_;
+};
+
+class BloomFilter
+{
+public:
+  static const int32_t MAX_HASH_FUNC_COUNT = 8;
+  static const int32_t MIN_SIZE = 256;
+  // static const non-integer variable can not be intialiazed in class
+  static const double MIN_BF_ERROR_RATE;
+  static const double MAX_BF_ERROR_RATE;
+  static const int32_t SEEDS[MAX_HASH_FUNC_COUNT];
+
+public:
+  BloomFilter() : size_(0), hash_func_count_(0), bitset_() {}
+  ~BloomFilter() { destroy(); }
+  int init(double error_percent, int entry_count);
+  void destroy() { bitset_.destroy(); }
+  int add_path_entry(const common::String &device_name,
+                     const common::String &measurement_name);
+  int serialize_to(common::ByteStream &out);
+  int deserialize_from(common::ByteStream &in);
+
+private:
+  common::String get_entry_string(const common::String &device_name,
+                                  const common::String &measurement_name);
+  FORCE_INLINE void free_entry_buf(char *entry_buf) { common::mem_free(entry_buf); }
+private:
+  uint32_t size_;
+  uint32_t hash_func_count_;
+  HashFunction hash_func_arr_[MAX_HASH_FUNC_COUNT];
+  BitSet bitset_;
+};
+
+} // end namespace storage
+} // end namespace timecho
+
+#endif
+
diff --git a/cpp/tsfile/src/tsfile/chunk_reader b/cpp/tsfile/src/tsfile/chunk_reader
new file mode 100644
index 00000000..e69de29b
diff --git a/cpp/tsfile/src/tsfile/chunk_reader.cc b/cpp/tsfile/src/tsfile/chunk_reader.cc
new file mode 100644
index 00000000..d4976831
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/chunk_reader.cc
@@ -0,0 +1,425 @@
+
+#include "chunk_reader.h"
+#include "tsfile/encode/decoder_factory.h"
+#include "tsfile/compress/compressor_factory.h"
+
+namespace timecho
+{
+using namespace common;
+namespace storage
+{
+
+int ChunkReader::init(ReadFile *read_file,
+                      String m_name,
+                      TSDataType data_type,
+                      Filter *time_filter)
+{
+  read_file_ = read_file;
+  measurement_name_.shallow_copy_from(m_name);
+  time_decoder_ = DecoderFactory::alloc_time_decoder();
+  value_decoder_ = nullptr;
+  compressor_ = nullptr;
+  time_filter_ = time_filter;
+  uncompressed_buf_ = nullptr;
+  if (IS_NULL(time_decoder_)) {
+    return E_OOM;
+  }
+  return E_OK;
+}
+
+void ChunkReader::reset()
+{
+  chunk_meta_ = nullptr;
+  chunk_header_.reset();
+  cur_page_header_.reset();
+
+  char *file_data_buf = in_stream_.get_wrapped_buf();
+  if (file_data_buf != nullptr) {
+    mem_free(file_data_buf);
+  }
+  in_stream_.reset();
+  file_data_buf_size_ = 0;
+  chunk_visit_offset_ = 0;
+}
+
+void ChunkReader::destroy()
+{
+  if (time_decoder_ != nullptr) {
+    time_decoder_->~Decoder();
+    DecoderFactory::free(time_decoder_);
+    time_decoder_ = nullptr;
+  }
+  if (value_decoder_ != nullptr) {
+    value_decoder_->~Decoder();
+    DecoderFactory::free(value_decoder_);
+    value_decoder_ = nullptr;
+  }
+  if (compressor_ != nullptr) {
+    compressor_->~Compressor();
+    CompressorFactory::free(compressor_);
+    compressor_ = nullptr;
+  }
+  char *buf = in_stream_.get_wrapped_buf();
+  if (buf != nullptr) {
+    mem_free(buf);
+    in_stream_.clear_wrapped_buf();
+  }
+  cur_page_header_.reset();
+}
+
+int ChunkReader::load_by_meta(ChunkMeta *meta)
+{
+  int ret = E_OK;
+  chunk_meta_ = meta;
+#if DEBUG_SE
+  std::cout << "ChunkReader::load_by_meta, meta=" << *meta << std::endl;
+#endif
+  /* ================ Step 1: read data from file ================*/
+  // at least, we can read the chunk header and the first page header.
+  // TODO configurable
+  file_data_buf_size_ = 1024;
+  int32_t ret_read_len = 0;
+  char *file_data_buf = (char*)mem_alloc(file_data_buf_size_, MOD_CHUNK_READER);
+  if (IS_NULL(file_data_buf)) {
+    return E_OOM;
+  }
+  ret = read_file_->read(chunk_meta_->offset_of_chunk_header_, file_data_buf,
+                         file_data_buf_size_, ret_read_len);
+  if (IS_SUCC(ret) && ret_read_len < ChunkHeader::MIN_SERIALIZED_SIZE) {
+    ret = E_TSFILE_CORRUPTED;
+    log_error("file corrupted, ret=%d, offset=%d, read_len=%d",
+              ret, chunk_meta_->offset_of_chunk_header_, ret_read_len);
+  }
+
+  /* ================ Step 2: deserialize chunk_header ================*/
+  if (IS_SUCC(ret)) {
+    in_stream_.wrap_from(file_data_buf, ret_read_len);
+    // std::cout << "in_stream_.wrap_from " << (void*)file_data_buf << std::endl;
+    if (RET_FAIL(chunk_header_.deserialize_from(in_stream_))) {
+    } else if (RET_FAIL(alloc_compressor_and_value_decoder(chunk_header_.encoding_type_,
+            chunk_header_.data_type_, chunk_header_.compression_type_))) {
+    } else {
+      chunk_visit_offset_ = in_stream_.read_pos(); // point to end of chunk_header_
+#if DEBUG_SE
+      std::cout << "ChunkReader::load_by_meta, chunk_header=" << chunk_header_ << std::endl;
+#endif
+    }
+  }
+  return ret;
+}
+
+int ChunkReader::alloc_compressor_and_value_decoder(TSEncoding encoding,
+                                                    TSDataType data_type,
+                                                    CompressionType compression)
+{
+  if (value_decoder_ != nullptr) {
+    delete value_decoder_;
+    value_decoder_ = nullptr;
+  }
+  value_decoder_ = DecoderFactory::alloc_value_decoder(encoding, data_type);
+  if (IS_NULL(value_decoder_)) {
+    return E_OOM;
+  }
+
+  if (compressor_ != nullptr) {
+    compressor_->reset(/*for_compress*/false);
+  } else {
+    compressor_ = CompressorFactory::alloc_compressor(compression);
+    if (compressor_ == nullptr) {
+      return E_OOM;
+    }
+  }
+  return E_OK;
+}
+
+int ChunkReader::get_next_page(TsBlock *ret_tsblock, Filter *oneshoot_filter)
+{
+  int ret = E_OK;
+  Filter *filter = (oneshoot_filter != nullptr ? oneshoot_filter : time_filter_);
+
+  if (prev_page_not_finish()) {
+    ret = decode_tv_buf_into_tsblock_by_datatype(time_in_, value_in_, ret_tsblock, filter);
+    if (ret == E_OVERFLOW) {
+      ret = E_OK;
+    } else {
+      if (uncompressed_buf_ != nullptr) {
+        compressor_->after_uncompress(uncompressed_buf_);
+        uncompressed_buf_ = nullptr;
+      }
+      time_in_.reset();
+      value_in_.reset();
+    }
+    return ret;
+  }
+
+  while (IS_SUCC(ret)) {
+    if (!has_more_data()) {
+      return E_NO_MORE_DATA;
+    }
+    if (RET_FAIL(get_cur_page_header())) {
+    } else if (cur_page_statisify_filter(filter)) {
+      break;
+    } else if (RET_FAIL(skip_cur_page())) {
+    }
+  }
+
+  if (IS_SUCC(ret)) {
+    ret = decode_cur_page_data(ret_tsblock, filter);
+  }
+  return ret;
+}
+
+int ChunkReader::get_cur_page_header()
+{
+  int ret = E_OK;
+  bool retry = true;
+  int cur_page_header_serialized_size = 0;
+  do {
+    in_stream_.mark_read_pos();
+    cur_page_header_.reset();
+    ret = cur_page_header_.deserialize_from(in_stream_,
+                                            !chunk_has_only_one_page(),
+                                            chunk_header_.data_type_);
+    cur_page_header_serialized_size = in_stream_.get_mark_len();
+    if (deserialize_buf_not_enough(ret) && retry) {
+      retry = false;
+      ret = read_from_file_and_rewrap();
+      if (E_OK == ret) {
+        continue;
+      }
+    }
+    break;
+  } while (true);
+  if (IS_SUCC(ret)) {
+    // visit a header
+    chunk_visit_offset_ += cur_page_header_serialized_size;
+  }
+#if DEBUG_SE
+  std::cout << "get_cur_page_header, ret=" << ret
+            << ", retry=" << retry
+            << ", cur_page_header_=" << cur_page_header_
+            << ", chunk_meta_->offset_of_chunk_header_=" << chunk_meta_->offset_of_chunk_header_
+            << ", cur_page_header_serialized_size=" << cur_page_header_serialized_size << std::endl;
+#endif
+  return ret;
+}
+
+// read at least @want_size bytes from file and wrap the buffer into @in_stream_
+int ChunkReader::read_from_file_and_rewrap(int want_size)
+{
+  int ret = E_OK;
+  const int DEFAULT_READ_SIZE = 4096; // may use page_size + page_header_size
+  char *file_data_buf = in_stream_.get_wrapped_buf();
+  int offset = chunk_meta_->offset_of_chunk_header_ + chunk_visit_offset_;
+  int read_size = (want_size < DEFAULT_READ_SIZE ? DEFAULT_READ_SIZE : want_size);
+  if (file_data_buf_size_ < read_size || read_size < file_data_buf_size_ / 10) {
+    file_data_buf = (char*)mem_realloc(file_data_buf, read_size);
+    if (IS_NULL(file_data_buf)) {
+      return E_OOM;
+    }
+    file_data_buf_size_ = read_size;
+  }
+  int ret_read_len = 0;
+  if (RET_FAIL(read_file_->read(offset,
+                                file_data_buf,
+                                DEFAULT_READ_SIZE,
+                                ret_read_len))) {
+  } else {
+    in_stream_.wrap_from(file_data_buf, ret_read_len);
+    // DEBUG_hex_dump_buf("wrapped buf = ", file_data_buf, 256);
+  }
+  return ret;
+}
+
+bool ChunkReader::cur_page_statisify_filter(Filter *filter)
+{
+  return filter == nullptr
+         || cur_page_header_.statistic_ == nullptr
+         || filter->satisfy(cur_page_header_.statistic_);
+}
+
+int ChunkReader::skip_cur_page()
+{
+  int ret = E_OK;
+  // visit a page tv data
+  chunk_visit_offset_ += cur_page_header_.compressed_size_;
+  in_stream_.wrapped_buf_advance_read_pos(cur_page_header_.compressed_size_);
+  return ret;
+}
+
+int ChunkReader::decode_cur_page_data(TsBlock *&ret_tsblock, Filter *filter)
+{
+  int ret = E_OK;
+
+  // Step 1: make sure we load the whole page data in @in_stream_
+  if (in_stream_.remaining_size() < cur_page_header_.compressed_size_) {
+    // std::cout << "decode_cur_page_data. in_stream_.remaining_size="<< in_stream_.remaining_size() << ", cur_page_header_.compressed_size_=" << cur_page_header_.compressed_size_ << std::endl;
+    if (RET_FAIL(read_from_file_and_rewrap(cur_page_header_.compressed_size_))) {
+    }
+  }
+
+  char *compressed_buf = nullptr;
+  char *uncompressed_buf = nullptr;
+  uint32_t compressed_buf_size = 0; // cppcheck-suppress unreadVariable
+  uint32_t uncompressed_buf_size = 0;
+  char *time_buf = nullptr;
+  char *value_buf = nullptr;
+  uint32_t time_buf_size = 0;
+  uint32_t value_buf_size = 0;
+
+  // Step 2: do uncompress
+  if (IS_SUCC(ret)) {
+    compressed_buf = in_stream_.get_wrapped_buf() + in_stream_.read_pos();
+    // std::cout << "ChunkReader::decode_cur_page_data, in_stream_.get_wrapped_buf=" <<(void*)(in_stream_.get_wrapped_buf())<< ", in_stream_.read_pos=" << in_stream_.read_pos() << std::endl;
+    compressed_buf_size = cur_page_header_.compressed_size_;
+    in_stream_.wrapped_buf_advance_read_pos(compressed_buf_size);
+    chunk_visit_offset_ += compressed_buf_size;
+    if (RET_FAIL(compressor_->reset(false))) {
+    } else if (RET_FAIL(compressor_->uncompress(compressed_buf, compressed_buf_size,
+                                  uncompressed_buf, uncompressed_buf_size))) {
+    } else {
+      uncompressed_buf_ = uncompressed_buf;
+    }
+    // DEBUG_hex_dump_buf("ChunkReader read, uncompressed buf = ", uncompressed_buf, uncompressed_buf_size);
+    if (ret != E_OK || uncompressed_buf_size != cur_page_header_.uncompressed_size_) {
+      ret = E_TSFILE_CORRUPTED;
+      ASSERT(false);
+    }
+  }
+
+  // Step 3: get time_buf & value_buf
+  if (IS_SUCC(ret)) {
+    int var_size = 0;
+    if (RET_FAIL(SerializationUtil::read_var_uint(time_buf_size, uncompressed_buf,
+                                                  uncompressed_buf_size, &var_size))) {
+    } else {
+      time_buf = uncompressed_buf + var_size;
+      value_buf = time_buf + time_buf_size;
+      value_buf_size = uncompressed_buf_size - var_size - time_buf_size;
+#if DEBUG_SE
+    std::cout << "ChunkReader uncompress: compressed_buf_size=" << compressed_buf_size
+             << ", uncompressed_buf_size=" << uncompressed_buf_size
+             << ", var_size=" << var_size
+             << ", time_buf_size=" << time_buf_size << std::endl;
+#endif
+      if (uncompressed_buf_size <= var_size + time_buf_size) {
+        ret = E_TSFILE_CORRUPTED;
+        ASSERT(false);
+      }
+    }
+  }
+
+  // Step 4: decode time-value buffer into @ret_tsblock
+  if (IS_SUCC(ret)) {
+    time_decoder_->reset();
+    value_decoder_->reset();
+    time_in_.wrap_from(time_buf, time_buf_size);
+    value_in_.wrap_from(value_buf, value_buf_size);
+    // ret = decode_tv_buf_into_tsblock(time_buf, value_buf, time_buf_size,
+    //                                  value_buf_size, ret_tsblock, filter);
+    ret = decode_tv_buf_into_tsblock_by_datatype(time_in_, value_in_, ret_tsblock, filter);
+    // if we return during @decode_tv_buf_into_tsblock, we should keep
+    // @uncompressed_buf_ valid until all TV pairs are decoded.
+    if (ret != E_OVERFLOW) {
+      if (uncompressed_buf_ != nullptr) {
+        compressor_->after_uncompress(uncompressed_buf_);
+        uncompressed_buf_ = nullptr;
+      }
+      time_in_.reset();
+      value_in_.reset();
+    } else {
+      ret = E_OK;
+    }
+  }
+  return ret;
+}
+
+#define DECODE_TYPED_TV_INTO_TSBLOCK(CppType, ReadType, time_in, value_in, row_appender)  \
+  do {                                                                                    \
+    int64_t time = 0;                                                                     \
+    CppType value;                                                                        \
+    while (time_decoder_->has_remaining() || time_in.has_remaining()) {                   \
+      ASSERT(value_decoder_->has_remaining() || value_in.has_remaining());                \
+      if (UNLIKELY(!row_appender.add_row())) {                                            \
+        ret = E_OVERFLOW;                                                                 \
+        break;                                                                            \
+      } else if (RET_FAIL(time_decoder_->read_int64(time, time_in))) {                    \
+      } else if (RET_FAIL(value_decoder_->read_##ReadType(value, value_in))) {            \
+      } else if (filter != nullptr && !filter->satisfy(time, value)) {                    \
+        row_appender.backoff_add_row();                                                   \
+        continue;                                                                         \
+      } else {                                                                            \
+        /*std::cout << "decoder: time=" << time << ", value=" << value << std::endl;*/    \
+        row_appender.append(0, (char*)&time, sizeof(time));                               \
+        row_appender.append(1, (char*)&value, sizeof(value));                             \
+      }                                                                                   \
+    }                                                                                     \
+  } while (false)
+
+int ChunkReader::i32_DECODE_TYPED_TV_INTO_TSBLOCK(ByteStream &time_in,
+                                                  ByteStream &value_in,
+                                                  RowAppender &row_appender,
+                                                  Filter *filter)
+{
+  int ret = E_OK;
+  do {
+    int64_t time = 0;
+    int32_t value;
+    while (time_decoder_->has_remaining() || time_in.has_remaining()) {
+      ASSERT(value_decoder_->has_remaining() || value_in.has_remaining());
+      if (UNLIKELY(!row_appender.add_row())) {
+        ret = E_OVERFLOW;
+        break;
+      } else if (RET_FAIL(time_decoder_->read_int64(time, time_in))) {
+      } else if (RET_FAIL(value_decoder_->read_int32(value, value_in))) {
+      } else if (filter != nullptr && !filter->satisfy(time, value)) {
+        row_appender.backoff_add_row();
+        continue;
+      } else {
+        /*std::cout << "decoder: time=" << time << ", value=" << value << std::endl;*/
+        row_appender.append(0, (char*)&time, sizeof(time));
+        row_appender.append(1, (char*)&value, sizeof(value));
+      }
+    }
+  } while (false);
+  return ret;
+}
+
+
+
+int ChunkReader::decode_tv_buf_into_tsblock_by_datatype(ByteStream &time_in,
+                                                        ByteStream &value_in,
+                                                        TsBlock *ret_tsblock,
+                                                        Filter *filter)
+{
+  int ret = E_OK;
+  RowAppender row_appender(ret_tsblock);
+  switch (chunk_header_.data_type_) {
+    case timecho::common::BOOLEAN:
+      DECODE_TYPED_TV_INTO_TSBLOCK(bool, boolean, time_in_, value_in_, row_appender);
+      break;
+    case timecho::common::INT32:
+      // DECODE_TYPED_TV_INTO_TSBLOCK(int32_t, int32, time_in_, value_in_, row_appender);
+      ret = i32_DECODE_TYPED_TV_INTO_TSBLOCK(time_in_, value_in_, row_appender, filter);
+      break;
+    case timecho::common::INT64:
+      DECODE_TYPED_TV_INTO_TSBLOCK(int64_t, int64, time_in_, value_in_, row_appender);
+      break;
+    case timecho::common::FLOAT:
+      DECODE_TYPED_TV_INTO_TSBLOCK(float, float, time_in_, value_in_, row_appender);
+      break;
+    case timecho::common::DOUBLE:
+      DECODE_TYPED_TV_INTO_TSBLOCK(double, double, time_in_, value_in_, row_appender);
+      break;
+    default:
+      ret = E_NOT_SUPPORT;
+      ASSERT(false);
+  }
+  if (ret_tsblock->get_row_count() == 0 && ret == E_OK) {
+    ret = E_NO_MORE_DATA;
+  }
+  return ret;
+}
+
+} // end namespace storage
+} // end namespace timecho
diff --git a/cpp/tsfile/src/tsfile/chunk_reader.h b/cpp/tsfile/src/tsfile/chunk_reader.h
new file mode 100644
index 00000000..ea901626
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/chunk_reader.h
@@ -0,0 +1,128 @@
+
+#ifndef STORAGE_TSFILE_CHUNK_READER_H
+#define STORAGE_TSFILE_CHUNK_READER_H
+
+#include "common/allocator/my_string.h"
+#include "tsfile/tsfile_common.h"
+#include "tsfile/read_file.h"
+#include "tsfile/encode/decoder.h"
+#include "tsfile/compress/compressor.h"
+#include "tsfile/filter/filter.h"
+
+namespace timecho
+{
+namespace storage
+{
+
+class ChunkReader
+{
+public:
+  ChunkReader() : read_file_(nullptr),
+                  chunk_meta_(nullptr),
+                  measurement_name_(),
+                  chunk_header_(),
+                  cur_page_header_(),
+                  in_stream_(),
+                  file_data_buf_size_(0),
+                  chunk_visit_offset_(0),
+                  compressor_(nullptr),
+                  time_filter_(nullptr),
+                  time_decoder_(nullptr),
+                  value_decoder_(nullptr),
+                  time_in_(),
+                  value_in_(),
+                  uncompressed_buf_(nullptr) {}
+  int init(ReadFile *read_file,
+           common::String m_name,
+           common::TSDataType data_type,
+           Filter *time_filter);
+  void reset();
+  void destroy();
+
+  bool has_more_data() const
+  {
+    return prev_page_not_finish()
+           || (chunk_visit_offset_ - chunk_header_.serialized_size_ < chunk_header_.data_size_);
+  }
+  ChunkHeader &get_chunk_header() { return chunk_header_; }
+
+  /*
+   * prepare data buffer, load the chunk_header
+   * and the first page_header.
+   */
+  int load_by_meta(ChunkMeta *meta);
+
+  int get_next_page(common::TsBlock *tsblock, Filter *oneshoot_filter);
+
+private:
+  FORCE_INLINE bool chunk_has_only_one_page() const
+  {
+    return chunk_header_.chunk_type_ == ONLY_ONE_PAGE_CHUNK_HEADER_MARKER;
+  }
+  int alloc_compressor_and_value_decoder(common::TSEncoding encoding,
+                                         common::TSDataType data_type,
+                                         common::CompressionType compression_type);
+  int get_cur_page_header();
+  int read_from_file_and_rewrap(int want_size = 0);
+  bool cur_page_statisify_filter(Filter *filter);
+  int skip_cur_page();
+  int decode_cur_page_data(common::TsBlock *&ret_tsblock,
+                           Filter *filter);
+  int decode_tv_buf_into_tsblock(char *time_buf, 
+                                 char *value_buf,
+                                 uint32_t time_buf_size,
+                                 uint32_t value_buf_size,
+                                 common::TsBlock *ret_tsblock,
+                                 Filter *filter);
+  bool prev_page_not_finish() const
+  {
+    return (time_decoder_ && time_decoder_->has_remaining()) || time_in_.has_remaining();
+  }
+
+  int decode_tv_buf_into_tsblock_by_datatype(common::ByteStream &time_in,
+                                             common::ByteStream &value_in,
+                                             common::TsBlock *ret_tsblock,
+                                             Filter *filter);
+  int i32_DECODE_TYPED_TV_INTO_TSBLOCK(common::ByteStream &time_in,
+                                       common::ByteStream &value_in,
+                                       common::RowAppender &row_appender,
+                                       Filter *filter);
+private:
+  ReadFile *read_file_;
+  ChunkMeta *chunk_meta_;
+  common::String measurement_name_;
+  ChunkHeader chunk_header_;
+  PageHeader cur_page_header_;
+
+  /*
+   * Data read from file is stored in @in_stream_, and the size
+   * is stored in @file_data_buf_size_. Note, in_stream_.total_size_
+   * is used to limit deserialization, that is why we still have 
+   * @file_data_buf_size_.
+   *
+   * Since we may want keep data of current page (and page header
+   * of next page) in memory, we need a byte-size cursor to tell
+   * us which byte we are processing, so we have @chunk_visit_offset_
+   * it refer to position from the start of chunk_header_,
+   * also refer to offset within the chunk (including chunk header).
+   * It advanced by step of a page header or a page tv data.
+   */
+  common::ByteStream in_stream_;
+  int32_t file_data_buf_size_;
+  uint32_t chunk_visit_offset_;
+
+  // Statistic *page_statistic_;
+  Compressor *compressor_;
+  Filter *time_filter_;
+
+  Decoder *time_decoder_;
+  Decoder *value_decoder_;
+  common::ByteStream time_in_;
+  common::ByteStream value_in_;
+  char *uncompressed_buf_;
+};
+
+} // end namespace storage
+} // end namespace timecho
+
+#endif // STORAGE_TSFILE_CHUNK_READER_H
diff --git a/cpp/tsfile/src/tsfile/chunk_writer.cc b/cpp/tsfile/src/tsfile/chunk_writer.cc
new file mode 100644
index 00000000..527c88a0
--- /dev/null
+++ b/cpp/tsfile/src/tsfile/chunk_writer.cc
@@ -0,0 +1,140 @@
+
+#include "chunk_writer.h"
+#include "common/logger/elog.h"
+
+using namespace timecho::common;
+
+namespace timecho
+{
+namespace storage
+{
+
+int ChunkWriter::init(const ColumnDesc &col_desc)
+{
+  return init(col_desc.column_name_, col_desc.type_, col_desc.encoding_, col_desc.compression_);
+}
+
+int ChunkWriter::init(const std::string &measurement_name,
+                      TSDataType data_type,
+                      TSEncoding encoding,
+                      CompressionType compression_type)
+{
+  int ret = E_OK;
+  chunk_statistic_ = StatisticFactory::alloc_statistic(data_type);
+  if (chunk_statistic_ == nullptr) {
+    return E_OOM;
+  } else if (RET_FAIL(page_writer_.init(data_type, encoding, compression_type))) {
+  } else if (IS_NULL((first_page_statistic_ = StatisticFactory::alloc_statistic(data_type)))) {
+    ret = E_OOM;
+  } else {
+    data_type_ = data_type;
+    chunk_header_.measurement_name_ = measurement_name;
+    chunk_header_.data_type_ = data_type;
+    chunk_header_.compression_type_ = compression_type;
+    chunk_header_.encoding_type_ = encoding;
+  }
+  return ret;
+}
+
+void ChunkWriter::destroy()
+{
+  page_writer_.destroy();
+  if (chunk_statistic_ != nullptr) {
+    StatisticFactory::free(chunk_statistic_);
+    chunk_statistic_ = nullptr;
+  }
+  if (first_page_statistic_ != nullptr) {
+    StatisticFactory::free(first_page_statistic_);
+    first_page_statistic_ = nullptr;
... 18011 lines suppressed ...