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 0325d58a651675ddd22828d4bbcd4131ed7abf1a
Author: Colin Lee <[email protected]>
AuthorDate: Fri Sep 6 19:47:42 2024 +0800

    Enable address sanitizer in tsfile cpp. (#214)
    
    * Enable asan in tsfile cpp.
    
    * Cpp.Fix memory leak.
    
    * cpp.fix MeasurementSchemaGroup test error.
    
    * rename table_size to tablet_size at example.
---
 cpp/CMakeLists.txt                         |   1 +
 cpp/bench_mark/bench_mark_src/bench_conf.h |   1 -
 cpp/build.sh                               |   2 -
 cpp/examples/c_examples/c_examples.h       |   1 -
 cpp/examples/cpp_examples/cpp_examples.h   |   1 +
 cpp/examples/cpp_examples/demo_write.cpp   | 112 ++++++++++++++++++++++-------
 cpp/src/common/allocator/byte_stream.h     |   2 +-
 cpp/src/common/allocator/my_string.h       |   9 +--
 cpp/src/common/config/config.h             |   7 --
 cpp/src/common/datatype/value.h            |  33 +++++++--
 cpp/src/common/global.cc                   |  16 -----
 cpp/src/common/global.h                    |   8 ---
 cpp/src/common/schema.h                    |   2 +-
 cpp/src/common/statistic.h                 |   2 +-
 cpp/src/common/tsfile_common.cc            | 100 ++++++++++++--------------
 cpp/src/common/tsfile_common.h             |  17 ++++-
 cpp/src/cwrapper/TsFile-cwrapper.cc        |  14 ++--
 cpp/src/encoding/bitpack_decoder.h         |   3 +
 cpp/src/encoding/zigzag_decoder.h          |   3 +-
 cpp/src/file/open_file.cc                  |   1 +
 cpp/src/file/tsfile_io_writer.cc           |   2 +-
 cpp/src/file/tsfile_io_writer.h            |   2 +-
 cpp/src/file/write_file.cc                 |   8 +--
 cpp/src/reader/aligned_chunk_reader.cc     |   2 +
 cpp/src/reader/aligned_chunk_reader.h      |   8 ++-
 cpp/src/reader/chunk_reader.cc             |   3 +-
 cpp/src/reader/query_data_set.h            |   1 -
 cpp/src/writer/chunk_writer.cc             |   3 +
 cpp/src/writer/chunk_writer.h              |   4 ++
 cpp/src/writer/page_writer.cc              |   8 +++
 cpp/src/writer/page_writer.h               |   1 +
 cpp/src/writer/time_chunk_writer.cc        |   3 +
 cpp/src/writer/time_page_writer.h          |   1 +
 cpp/src/writer/tsfile_writer.cc            |   3 +-
 cpp/src/writer/value_chunk_writer.cc       |   3 +
 cpp/src/writer/value_page_writer.h         |   1 +
 cpp/test/CMakeLists.txt                    |   6 ++
 cpp/test/common/tsfile_common_test.cc      |  12 ++--
 cpp/test/compress/lz4_compressor_test.cc   |   2 +-
 cpp/test/cwrapper/cwrapper_test.cc         |  47 ++++++++++++
 cpp/test/encoding/ts2diff_codec_test.cc    |  15 +++-
 cpp/test/file/open_file_test.cc            |   7 +-
 cpp/test/writer/chunk_writer_test.cc       |   4 --
 cpp/test/writer/time_chunk_writer_test.cc  |   4 --
 cpp/test/writer/time_page_writer_test.cc   |   1 +
 cpp/test/writer/tsfile_writer_test.cc      |   5 ++
 cpp/test/writer/value_chunk_writer_test.cc |   4 --
 cpp/test/writer/value_page_writer_test.cc  |   1 +
 48 files changed, 320 insertions(+), 176 deletions(-)

diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 185b3905..997e1d2a 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -83,3 +83,4 @@ add_subdirectory(test)
 if(TESTS_ENABLED)
     add_dependencies(TsFile_Test tsfile)
 endif()
+
diff --git a/cpp/bench_mark/bench_mark_src/bench_conf.h 
b/cpp/bench_mark/bench_mark_src/bench_conf.h
index f2a4de75..486d0b14 100644
--- a/cpp/bench_mark/bench_mark_src/bench_conf.h
+++ b/cpp/bench_mark/bench_mark_src/bench_conf.h
@@ -25,4 +25,3 @@ int THREAD_NUM = 1;
 int TIMESERIES_NUM = 50;
 std::vector<int> TYPE_LIST = {0, 0, 1, 0, 1};
 }  // namespace bench
-
diff --git a/cpp/build.sh b/cpp/build.sh
index 8d907cde..e7d4d01f 100644
--- a/cpp/build.sh
+++ b/cpp/build.sh
@@ -25,7 +25,6 @@ use_cpp11=1
 enable_cov=0
 debug_se=0
 run_cov_only=0
-env_for_cyber=0
 
 shell_dir=$(cd "$(dirname "$0")";pwd)
 
@@ -127,7 +126,6 @@ cmake ../../                           \
   -DCMAKE_BUILD_TYPE=$build_type       \
   -DUSE_CPP11=$use_cpp11               \
   -DENABLE_COV=$enable_cov             \
-  -DENABLE_ASAN=$enable_asan           \
   -DDEBUG_SE=$debug_se                 \
   -DBUILD_TSFILE_ONLY=$build_tsfile_only
 
diff --git a/cpp/examples/c_examples/c_examples.h 
b/cpp/examples/c_examples/c_examples.h
index a0405138..3f63803f 100644
--- a/cpp/examples/c_examples/c_examples.h
+++ b/cpp/examples/c_examples/c_examples.h
@@ -29,4 +29,3 @@ ErrorCode read_tsfile();
 #ifdef __cplusplus
 }
 #endif
-
diff --git a/cpp/examples/cpp_examples/cpp_examples.h 
b/cpp/examples/cpp_examples/cpp_examples.h
index 2fdf13cc..b2e52aad 100644
--- a/cpp/examples/cpp_examples/cpp_examples.h
+++ b/cpp/examples/cpp_examples/cpp_examples.h
@@ -21,6 +21,7 @@
 #include "common/path.h"
 #include "common/record.h"
 #include "common/row_record.h"
+#include "common/schema.h"
 #include "reader/expression.h"
 #include "reader/filter/filter.h"
 #include "reader/qds_with_timegenerator.h"
diff --git a/cpp/examples/cpp_examples/demo_write.cpp 
b/cpp/examples/cpp_examples/demo_write.cpp
index d77b645c..2fafb465 100644
--- a/cpp/examples/cpp_examples/demo_write.cpp
+++ b/cpp/examples/cpp_examples/demo_write.cpp
@@ -20,39 +20,97 @@
 #include <time.h>
 
 #include <iostream>
+#include <random>
 #include <string>
 
 #include "cpp_examples.h"
 
+using namespace storage;
+
+long getNowTime() { return time(nullptr); }
+
+static std::string generate_random_string(int length) {
+    std::random_device rd;
+    std::mt19937 gen(rd());
+    std::uniform_int_distribution<> dis(0, 61);
+
+    const std::string chars =
+        "0123456789"
+        "abcdefghijklmnopqrstuvwxyz"
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    std::string random_string;
+
+    for (int i = 0; i < length; ++i) {
+        random_string += chars[dis(gen)];
+    }
+
+    return random_string;
+}
+
 int demo_write() {
-    storage::TsFileWriter tsfile_writer;
-    std::string device_name = "root.db001.dev001";
-    std::string measurement_name = "m001";
-    storage::libtsfile_init();
-    int ret = tsfile_writer.open("cpp_rw.tsfile", O_CREAT | O_RDWR, 0644);
-    ASSERT(ret == 0);
-    ret = tsfile_writer.register_timeseries(device_name, measurement_name,
-                                            common::INT32, common::PLAIN,
-                                            common::UNCOMPRESSED);
-    ASSERT(ret == 0);
-    std::cout << "get open ret: " << ret << std::endl;
-
-    int row_count = 100;
-    for (int i = 1; i < row_count; ++i) {
-        storage::DataPoint point(measurement_name, 10000 + i);
-        storage::TsRecord record(i, device_name, 1);
-        record.points_.push_back(point);
-        ret = tsfile_writer.write_record(record);
-        ASSERT(ret == 0);
+    TsFileWriter* tsfile_writer_ = new TsFileWriter();
+    libtsfile_init();
+    std::string file_name_ = std::string("tsfile_writer_test_") +
+                             generate_random_string(10) +
+                             std::string(".tsfile");
+    int flags = O_WRONLY | O_CREAT | O_TRUNC;
+#ifdef _WIN32
+    flags |= O_BINARY;
+#endif
+    mode_t mode = 0666;
+    tsfile_writer_->open(file_name_, flags, mode);
+    remove(file_name_.c_str());
+    const int device_num = 50;
+    const int measurement_num = 50;
+    std::vector<MeasurementSchema> schema_vec[50];
+    for (int i = 0; i < device_num; i++) {
+        std::string device_name = "test_device" + std::to_string(i);
+        for (int j = 0; j < measurement_num; j++) {
+            std::string measure_name = "measurement" + std::to_string(j);
+            schema_vec[i].push_back(
+                MeasurementSchema(measure_name, common::TSDataType::INT32,
+                                  common::TSEncoding::PLAIN,
+                                  common::CompressionType::UNCOMPRESSED));
+            tsfile_writer_->register_timeseries(
+                device_name, measure_name, common::TSDataType::INT32,
+                common::TSEncoding::PLAIN,
+                common::CompressionType::UNCOMPRESSED);
+        }
+    }
+
+    std::cout << "input tablet size" << std::endl;
+    int tablet_size;
+    std::cin >> tablet_size;
+
+    int max_rows = 100000;
+    int cur_row = 0;
+    long start = getNowTime();
+    for (; cur_row < max_rows;) {
+        if (cur_row + tablet_size > max_rows) {
+            tablet_size = max_rows - cur_row;
+        }
+        for (int i = 0; i < device_num; i++) {
+            std::string device_name = "test_device" + std::to_string(i);
+            Tablet tablet(device_name, &schema_vec[i], tablet_size);
+            tablet.init();
+            for (int row = 0; row < tablet_size; row++) {
+                tablet.set_timestamp(row, 16225600 + cur_row + row);
+            }
+            for (int j = 0; j < measurement_num; j++) {
+                for (int row = 0; row < tablet_size; row++) {
+                    tablet.set_value(row, j, row + cur_row);
+                }
+            }
+            tsfile_writer_->write_tablet(tablet);
+            tsfile_writer_->flush();
+        }
+        cur_row += tablet_size;
+        std::cout << "finish writing " << cur_row << " rows" << std::endl;
     }
 
-    tsfile_writer.flush();
-    std::cout << "finish flush" << std::endl;
-    tsfile_writer.close();
-    std::cout << "tsfile closed." << std::endl;
-    storage::libtsfile_destroy();
-    std::cout << "tsfile to destory." << std::endl;
-    std::cout << "finish writing" << std::endl;
-    std::cout << "will close our files" << std::endl;
+    tsfile_writer_->close();
+    long end = getNowTime();
+    printf("interval waitForResults is %ld \n", end - start);
     return 0;
 }
diff --git a/cpp/src/common/allocator/byte_stream.h 
b/cpp/src/common/allocator/byte_stream.h
index 161f4ca7..bf46d9d7 100644
--- a/cpp/src/common/allocator/byte_stream.h
+++ b/cpp/src/common/allocator/byte_stream.h
@@ -671,7 +671,7 @@ FORCE_INLINE int merge_byte_stream(ByteStream &sea, 
ByteStream &river,
 }
 
 FORCE_INLINE int copy_bs_to_buf(ByteStream &bs, char *src_buf,
-                                          uint32_t src_buf_len) {
+                                uint32_t src_buf_len) {
     ByteStream::BufferIterator buf_iter = bs.init_buffer_iterator();
     uint32_t copyed_len = 0;
     while (true) {
diff --git a/cpp/src/common/allocator/my_string.h 
b/cpp/src/common/allocator/my_string.h
index d7d8890b..72bbce3f 100644
--- a/cpp/src/common/allocator/my_string.h
+++ b/cpp/src/common/allocator/my_string.h
@@ -52,6 +52,11 @@ struct String {
         memcpy(buf_, str.c_str(), len_);
         return common::E_OK;
     }
+
+    FORCE_INLINE bool operator==(const String &other) const {
+        return equal_to(other);
+    }
+
     FORCE_INLINE int dup_from(const String &str, common::PageArena &pa) {
         len_ = str.len_;
         if (UNLIKELY(len_ == 0)) {
@@ -143,10 +148,6 @@ struct String {
         return this->len_ < other.len_;
     }
 
-    bool operator==(const String &that) const {
-        return equal_to(that);
-    }
-
 #ifndef NDEBUG
     friend std::ostream &operator<<(std::ostream &os, const String &s) {
         os << s.len_ << "@";
diff --git a/cpp/src/common/config/config.h b/cpp/src/common/config/config.h
index d97bc807..9eea1086 100644
--- a/cpp/src/common/config/config.h
+++ b/cpp/src/common/config/config.h
@@ -37,20 +37,13 @@ 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_;
     TSDataType time_data_type_;
     CompressionType time_compress_type_;
-    uint32_t memtable_flusher_poll_interval_seconds_;
     int32_t chunk_group_size_threshold_;
     int32_t record_count_for_next_mem_check_;
 } ConfigValue;
diff --git a/cpp/src/common/datatype/value.h b/cpp/src/common/datatype/value.h
index 04d3ab90..29fd5706 100644
--- a/cpp/src/common/datatype/value.h
+++ b/cpp/src/common/datatype/value.h
@@ -33,16 +33,41 @@
 namespace common {
 
 struct Value {
-    Value(TSDataType type) : type_(type), value_{0} {}
+    Value(TSDataType type) : type_(type) {
+        switch (type) {
+            case BOOLEAN:
+                value_.bval_ = false;
+                break;
+            case INT32:
+                value_.ival_ = 0;
+                break;
+            case INT64:
+                value_.lval_ = 0;
+                break;
+            case FLOAT:
+                value_.fval_ = 0.0f;
+                break;
+            case DOUBLE:
+                value_.dval_ = 0.0;
+                break;
+            case TEXT:
+                value_.sval_ = nullptr;
+                break;
+            case NULL_TYPE:
+                break;
+            default:
+                LOGE("unknown data type");
+        }
+    }
 
     ~Value() {
-        if (is_type(NULL_TYPE) && value_.sval_) {
+        if (is_type(TEXT) && value_.sval_) {
             free(value_.sval_);
         }
     }
 
     FORCE_INLINE void free_memory() {
-        if (is_type(NULL_TYPE) && value_.sval_) {
+        if (is_type(TEXT) && value_.sval_) {
             free(value_.sval_);
             value_.sval_ = nullptr;
         }
@@ -121,7 +146,7 @@ FORCE_INLINE Value *make_literal(double val) {
 
 FORCE_INLINE Value *make_literal(char *string) {
     Value *value = new Value(TEXT);
-    value->value_.sval_ = string;
+    value->value_.sval_ = strdup(string);
     return value;
 }
 
diff --git a/cpp/src/common/global.cc b/cpp/src/common/global.cc
index 8aa729f6..973c6cbb 100644
--- a/cpp/src/common/global.cc
+++ b/cpp/src/common/global.cc
@@ -31,35 +31,19 @@ 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_.record_count_for_next_mem_check_ = 100;
     g_config_value_.chunk_group_size_threshold_ = 128 * 1024 * 1024;
-    // 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_data_type_ = INT64;
     g_config_value_.time_compress_type_ = LZ4;
-    g_config_value_.memtable_flusher_poll_interval_seconds_ = 1;
 }
 
 void config_set_page_max_point_count(uint32_t page_max_ponint_count) {
diff --git a/cpp/src/common/global.h b/cpp/src/common/global.h
index bf973fc9..8106b5fd 100644
--- a/cpp/src/common/global.h
+++ b/cpp/src/common/global.h
@@ -28,14 +28,6 @@
 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);
diff --git a/cpp/src/common/schema.h b/cpp/src/common/schema.h
index 3a457398..087439dd 100644
--- a/cpp/src/common/schema.h
+++ b/cpp/src/common/schema.h
@@ -71,7 +71,7 @@ typedef std::pair<MeasurementSchemaMapIter, bool>
 struct MeasurementSchemaGroup {
     // measurement_name -> MeasurementSchema
     MeasurementSchemaMap measurement_schema_map_;
-    bool is_aligned_;
+    bool is_aligned_ = false;
     TimeChunkWriter *time_chunk_writer_ = nullptr;
 };
 
diff --git a/cpp/src/common/statistic.h b/cpp/src/common/statistic.h
index b7df814c..37679ba1 100644
--- a/cpp/src/common/statistic.h
+++ b/cpp/src/common/statistic.h
@@ -916,7 +916,7 @@ class StatisticFactory {
                 ASSERT(false);
                 break;
             case common::VECTOR:
-                ALLOC_STATISTIC(TimeStatistic);
+                ALLOC_STATISTIC_WITH_PA(TimeStatistic);
                 break;
             default:
                 ASSERT(false);
diff --git a/cpp/src/common/tsfile_common.cc b/cpp/src/common/tsfile_common.cc
index 3eabeec9..a1643439 100644
--- a/cpp/src/common/tsfile_common.cc
+++ b/cpp/src/common/tsfile_common.cc
@@ -20,6 +20,7 @@
 #include "common/tsfile_common.h"
 
 #include <algorithm>
+#include <map>
 
 #include "common/logger/elog.h"
 
@@ -59,10 +60,11 @@ int TSMIterator::init() {
          chunk_group_meta_iter++) {
         auto chunk_meta_list = chunk_group_meta_iter.get()->chunk_meta_list_;
         // Use a map to group chunks by measurement_name_
-        std::map<common::String, std::vector<ChunkMeta*>> groups;
+        std::map<common::String, std::vector<ChunkMeta *>> groups;
         std::vector<common::String> order;
-        for (auto it = chunk_meta_list.begin(); it != chunk_meta_list.end(); 
it++) {
-            auto* chunk_meta = it.get();
+        for (auto it = chunk_meta_list.begin(); it != chunk_meta_list.end();
+             it++) {
+            auto *chunk_meta = it.get();
             if (groups.find(chunk_meta->measurement_name_) == groups.end()) {
                 order.push_back(chunk_meta->measurement_name_);
             }
@@ -71,17 +73,19 @@ int TSMIterator::init() {
 
         // Sort each group of chunk metas by offset
         for (auto it = groups.begin(); it != groups.end(); ++it) {
-            std::vector<ChunkMeta*>& group = it->second;
-            std::sort(group.begin(), group.end(), [](ChunkMeta* a, ChunkMeta* 
b) {
-                return a->offset_of_chunk_header_ < b->offset_of_chunk_header_;
-            });
+            std::vector<ChunkMeta *> &group = it->second;
+            std::sort(group.begin(), group.end(),
+                      [](ChunkMeta *a, ChunkMeta *b) {
+                          return a->offset_of_chunk_header_ <
+                                 b->offset_of_chunk_header_;
+                      });
         }
-
         // Clear and refill chunk_group_meta_list
         chunk_group_meta_iter.get()->chunk_meta_list_.clear();
-        for (const auto& measurement_name : order) {
+        for (const auto &measurement_name : order) {
             for (auto chunk_meta : groups[measurement_name]) {
-                
chunk_group_meta_iter.get()->chunk_meta_list_.push_back(chunk_meta);
+                chunk_group_meta_iter.get()->chunk_meta_list_.push_back(
+                    chunk_meta);
             }
         }
     }
@@ -91,19 +95,30 @@ int TSMIterator::init() {
     if (chunk_group_meta_iter_ == chunk_group_meta_list_.end()) {
         return E_NOT_EXIST;
     }
-    chunk_meta_iter_ = chunk_group_meta_iter_.get()->chunk_meta_list_.begin();
-    /*
-     * if the chunk_group_meta_list_ is not sorted,
-     * do sort now.
-     * Currently, MemTableFlusher guarantee that chunk_group_meta_list_ is
-     * sorted
-     */
-    // do nothing.
+    while (chunk_group_meta_iter_ != chunk_group_meta_list_.end()) {
+        chunk_meta_iter_ =
+            chunk_group_meta_iter_.get()->chunk_meta_list_.begin();
+        std::map<common::String, std::vector<ChunkMeta *>> tmp;
+        while (chunk_meta_iter_ !=
+               chunk_group_meta_iter_.get()->chunk_meta_list_.end()) {
+            tmp[chunk_meta_iter_.get()->measurement_name_].emplace_back(
+                chunk_meta_iter_.get());
+            chunk_meta_iter_++;
+        }
+        if (!tmp.empty()) {
+            tsm_chunk_meta_info_[chunk_group_meta_iter_.get()->device_name_] =
+                tmp;
+        }
+
+        chunk_group_meta_iter_++;
+    }
+    tsm_measurement_iter_ = tsm_chunk_meta_info_.begin()->second.begin();
+    tsm_device_iter_ = tsm_chunk_meta_info_.begin();
     return E_OK;
 }
 
 bool TSMIterator::has_next() const {
-    return chunk_group_meta_iter_ != chunk_group_meta_list_.end();
+    return tsm_device_iter_ != tsm_chunk_meta_info_.end();
 }
 
 int TSMIterator::get_next(String &ret_device_name, String 
&ret_measurement_name,
@@ -111,57 +126,31 @@ int TSMIterator::get_next(String &ret_device_name, String 
&ret_measurement_name,
     int ret = E_OK;
     SimpleList<ChunkMeta *> chunk_meta_list_of_this_ts(
         1024, MOD_TIMESERIES_INDEX_OBJ);  // FIXME
-    String cur_measurement_name;
-
-    if (chunk_meta_iter_ !=
-        chunk_group_meta_iter_.get()->chunk_meta_list_.end()) {
-        cur_measurement_name.shallow_copy_from(
-            chunk_meta_iter_.get()->measurement_name_);
-    } else {
-        chunk_group_meta_iter_++;
-        if (chunk_group_meta_iter_ == chunk_group_meta_list_.end()) {
+    if (tsm_measurement_iter_ == tsm_device_iter_->second.end()) {
+        tsm_device_iter_++;
+        if (!has_next()) {
             return E_NO_MORE_DATA;
         } else {
-            chunk_meta_iter_ =
-                chunk_group_meta_iter_.get()->chunk_meta_list_.begin();
-            cur_measurement_name.shallow_copy_from(
-                chunk_meta_iter_.get()->measurement_name_);
+            tsm_measurement_iter_ = tsm_device_iter_->second.begin();
         }
     }
-
-    while (chunk_meta_iter_ !=
-           chunk_group_meta_iter_.get()->chunk_meta_list_.end()) {
-        if (cur_measurement_name.equal_to(
-                chunk_meta_iter_.get()->measurement_name_)) {
-            if (RET_FAIL(chunk_meta_list_of_this_ts.push_back(
-                    chunk_meta_iter_.get()))) {
-            } else {
-                chunk_meta_iter_++;
-            }
-        } else {
-            break;
-        }
+    ret_device_name.shallow_copy_from(tsm_device_iter_->first);
+    ret_measurement_name.shallow_copy_from(tsm_measurement_iter_->first);
+    for (auto meta : tsm_measurement_iter_->second) {
+        chunk_meta_list_of_this_ts.push_back(meta);
     }
-
     if (chunk_meta_list_of_this_ts.size() == 0) {
-        // log_err("fatal error, empty chunk meta list for %s",
-        // cur_measurement_name.buf_);
         return E_TSFILE_WRITER_META_ERR;
     }
 
-    String device_name;
-    device_name.shallow_copy_from(chunk_group_meta_iter_.get()->device_name_);
     const bool multi_chunks = chunk_meta_list_of_this_ts.size() > 1;
     ChunkMeta *first_chunk_meta = chunk_meta_list_of_this_ts.front();
     const char meta_type = (multi_chunks ? 1 : 0) | (first_chunk_meta->mask_);
     const TSDataType data_type = first_chunk_meta->data_type_;
-    String measurement_name;
-    measurement_name.shallow_copy_from(first_chunk_meta->measurement_name_);
     const TsID ts_id = first_chunk_meta->ts_id_;
 
     ret_ts_index.set_ts_meta_type(meta_type);
-    // ret_ts_index.set_measurement_name(measurement_name, index_page_arena);
-    ret_ts_index.set_measurement_name(measurement_name);
+    ret_ts_index.set_measurement_name(ret_measurement_name);
     ret_ts_index.set_data_type(data_type);
     ret_ts_index.init_statistic(data_type);
     ret_ts_index.set_ts_id(ts_id);
@@ -177,14 +166,13 @@ int TSMIterator::get_next(String &ret_device_name, String 
&ret_measurement_name,
     }
     if (IS_SUCC(ret)) {
         ret_ts_index.finish();
-        ret_device_name.shallow_copy_from(device_name);
-        ret_measurement_name.shallow_copy_from(measurement_name);
     }
     if (UNLIKELY(ret_device_name.is_null())) {
         ret = E_TSFILE_WRITER_META_ERR;
         // log_err("null device name from chunk_group_meta_iter, ret=%d", ret);
         ASSERT(false);
     }
+    tsm_measurement_iter_++;
     return ret;
 }
 
diff --git a/cpp/src/common/tsfile_common.h b/cpp/src/common/tsfile_common.h
index 9ac501c4..0a3d3702 100644
--- a/cpp/src/common/tsfile_common.h
+++ b/cpp/src/common/tsfile_common.h
@@ -378,7 +378,8 @@ class TimeseriesIndex : public ITimeseriesIndex {
     FORCE_INLINE virtual common::String get_measurement_name() {
         return measurement_name_;
     }
-    virtual inline common::SimpleList<ChunkMeta *> *get_chunk_meta_list() 
const {
+    virtual inline common::SimpleList<ChunkMeta *> *get_chunk_meta_list()
+        const {
         return chunk_meta_list_;
     }
     FORCE_INLINE void set_ts_meta_type(char ts_meta_type) {
@@ -638,6 +639,20 @@ class TSMIterator {
     common::SimpleList<ChunkGroupMeta *> &chunk_group_meta_list_;
     common::SimpleList<ChunkGroupMeta *>::Iterator chunk_group_meta_iter_;
     common::SimpleList<ChunkMeta *>::Iterator chunk_meta_iter_;
+
+    // timeseries measurenemnt chunk meta info
+    // map <device_name, <measurement_name, vector<chunk_meta>>>
+    std::map<common::String, std::map<common::String, std::vector<ChunkMeta 
*>>>
+        tsm_chunk_meta_info_;
+
+    // device iterator
+    std::map<common::String,
+             std::map<common::String, std::vector<ChunkMeta *>>>::iterator
+        tsm_device_iter_;
+
+    // measurement iterator
+    std::map<common::String, std::vector<ChunkMeta *>>::iterator
+        tsm_measurement_iter_;
 };
 
 /* =============== TsFile Index ================ */
diff --git a/cpp/src/cwrapper/TsFile-cwrapper.cc 
b/cpp/src/cwrapper/TsFile-cwrapper.cc
index d70c5199..d19c4769 100644
--- a/cpp/src/cwrapper/TsFile-cwrapper.cc
+++ b/cpp/src/cwrapper/TsFile-cwrapper.cc
@@ -34,13 +34,13 @@
 
 static bool is_init = false;
 
-#define INSERT_DATA_INTO_RECORD(record, column, value)                        \
-    do {                                                                      \
-        DataPoint point(column, value);                                       \
-        if (record->points_.size() + 1 > record->points_.capacity())          \
-            return E_BUF_NOT_ENOUGH;                                          \
-        record->points_.push_back(point);                                     \
-        return E_OK;                                                          \
+#define INSERT_DATA_INTO_RECORD(record, column, value)               \
+    do {                                                             \
+        DataPoint point(column, value);                              \
+        if (record->points_.size() + 1 > record->points_.capacity()) \
+            return E_BUF_NOT_ENOUGH;                                 \
+        record->points_.push_back(point);                            \
+        return E_OK;                                                 \
     } while (0)
 
 #define CONSTRUCT_EXP_INTERNAL(exp, column_name) \
diff --git a/cpp/src/encoding/bitpack_decoder.h 
b/cpp/src/encoding/bitpack_decoder.h
index 2468d515..099afc79 100644
--- a/cpp/src/encoding/bitpack_decoder.h
+++ b/cpp/src/encoding/bitpack_decoder.h
@@ -120,6 +120,9 @@ class BitPackDecoder {
 
     void read_bit_packing_buffer(int bit_packed_group_count,
                                  int last_bit_packed_num) {
+        if (current_buffer_ != nullptr) {
+            delete[] current_buffer_;
+        }
         current_buffer_ = new int64_t[bit_packed_group_count * 8];
         unsigned char bytes[bit_packed_group_count * bit_width_];
         int bytes_to_read = bit_packed_group_count * bit_width_;
diff --git a/cpp/src/encoding/zigzag_decoder.h 
b/cpp/src/encoding/zigzag_decoder.h
index 176c0ccd..4a540ee2 100644
--- a/cpp/src/encoding/zigzag_decoder.h
+++ b/cpp/src/encoding/zigzag_decoder.h
@@ -33,7 +33,7 @@ template <typename T>
 class ZigzagDecoder {
    public:
     ZigzagDecoder() { init(); }
-    ~ZigzagDecoder() {}
+    ~ZigzagDecoder() { destroy(); }
 
     void init() {
         type_ = common::ZIGZAG;
@@ -43,6 +43,7 @@ class ZigzagDecoder {
         first_bit_of_byte_ = 0;
         num_of_sorts_of_zigzag_ = 0;
         first_read_ = true;
+        zigzag_decode_arr_ = nullptr;
     }
 
     void reset() {
diff --git a/cpp/src/file/open_file.cc b/cpp/src/file/open_file.cc
index 40a7fb90..2543f1bf 100644
--- a/cpp/src/file/open_file.cc
+++ b/cpp/src/file/open_file.cc
@@ -35,6 +35,7 @@ int OpenFile::init() {
 void OpenFile::reset() {
     MutexGuard mg(mutex_);
     if (ts_time_range_map_ != nullptr) {
+        ts_time_range_map_->clear();
         mem_free(ts_time_range_map_);
         ts_time_range_map_ = nullptr;
     }
diff --git a/cpp/src/file/tsfile_io_writer.cc b/cpp/src/file/tsfile_io_writer.cc
index d1404ef5..abd08b82 100644
--- a/cpp/src/file/tsfile_io_writer.cc
+++ b/cpp/src/file/tsfile_io_writer.cc
@@ -21,6 +21,7 @@
 
 #include <fcntl.h>
 
+#include "common/global.h"
 #include "common/logger/elog.h"
 #include "writer/chunk_writer.h"
 
@@ -139,7 +140,6 @@ int TsFileIOWriter::start_flush_chunk(common::ByteStream 
&chunk_data,
     // Step 1. record chunk meta
     const int mask = 0;  // for common chunk
     ASSERT(cur_chunk_meta_ == nullptr);
-
     void *buf1 = meta_allocator_.alloc(sizeof(*cur_chunk_meta_));
     void *buf2 = meta_allocator_.alloc(get_typed_statistic_sizeof(data_type));
     if (IS_NULL(buf1) || IS_NULL(buf2)) {
diff --git a/cpp/src/file/tsfile_io_writer.h b/cpp/src/file/tsfile_io_writer.h
index 07c4b87b..bb7638cd 100644
--- a/cpp/src/file/tsfile_io_writer.h
+++ b/cpp/src/file/tsfile_io_writer.h
@@ -183,7 +183,7 @@ class TsFileIOWriter {
     ChunkGroupMeta *cur_chunk_group_meta_;
     int32_t chunk_meta_count_;  // for debug
     common::SimpleList<ChunkGroupMeta *> chunk_group_meta_list_;
-    bool use_prev_alloc_cgm_; // chunk group meta
+    bool use_prev_alloc_cgm_;  // chunk group meta
     std::string cur_device_name_;
     WriteFile *file_;
     std::vector<TimeseriesTimeIndexEntry> ts_time_index_vector_;
diff --git a/cpp/src/file/write_file.cc b/cpp/src/file/write_file.cc
index 1f4c30a5..71cb553e 100644
--- a/cpp/src/file/write_file.cc
+++ b/cpp/src/file/write_file.cc
@@ -120,16 +120,16 @@ int WriteFile::sync() {
 int WriteFile::close() {
     ASSERT(fd_ > 0);
     if (::close(fd_) < 0) {
-        #ifdef DEBUG_SE
+#ifdef DEBUG_SE
         std::cout << "failed to close " << path_ << " errorno " << errno
                   << std::endl;
-        #endif
+#endif
         // log_err("file close error, path=%s, errno=%d", path_.c_str(), 
errno);
         return E_FILE_CLOSE_ERR;
     }
-    #ifdef DEBUG_SE
+#ifdef DEBUG_SE
     std::cout << "close finish" << std::endl;
-    #endif
+#endif
     return E_OK;
 }
 
diff --git a/cpp/src/reader/aligned_chunk_reader.cc 
b/cpp/src/reader/aligned_chunk_reader.cc
index 0b76353b..4360f987 100644
--- a/cpp/src/reader/aligned_chunk_reader.cc
+++ b/cpp/src/reader/aligned_chunk_reader.cc
@@ -513,6 +513,8 @@ int AlignedChunkReader::decode_time_value_buf_into_tsblock(
         if (!prev_time_page_not_finish()) {
             time_in_.reset();
         }
+        value_page_col_notnull_bitmap_.clear();
+        value_page_col_notnull_bitmap_.shrink_to_fit();
     } else {
         ret = E_OK;
     }
diff --git a/cpp/src/reader/aligned_chunk_reader.h 
b/cpp/src/reader/aligned_chunk_reader.h
index c2d2d395..4f11ce4f 100644
--- a/cpp/src/reader/aligned_chunk_reader.h
+++ b/cpp/src/reader/aligned_chunk_reader.h
@@ -80,9 +80,11 @@ class AlignedChunkReader : public IChunkReader {
         const ChunkHeader &chunk_header) const {
         return chunk_header.chunk_type_ == ONLY_ONE_PAGE_CHUNK_HEADER_MARKER;
     }
-    int alloc_compressor_and_decoder(storage::Decoder* &decoder, 
storage::Compressor* &compressor,
-        common::TSEncoding encoding, common::TSDataType data_type,
-        common::CompressionType compression_type);
+    int alloc_compressor_and_decoder(storage::Decoder *&decoder,
+                                     storage::Compressor *&compressor,
+                                     common::TSEncoding encoding,
+                                     common::TSDataType data_type,
+                                     common::CompressionType compression_type);
     int get_cur_page_header(ChunkMeta *&chunk_meta,
                             common::ByteStream &in_stream_,
                             PageHeader &cur_page_header_,
diff --git a/cpp/src/reader/chunk_reader.cc b/cpp/src/reader/chunk_reader.cc
index 701c8795..a586ff8b 100644
--- a/cpp/src/reader/chunk_reader.cc
+++ b/cpp/src/reader/chunk_reader.cc
@@ -130,7 +130,8 @@ int ChunkReader::alloc_compressor_and_value_decoder(
     if (value_decoder_ != nullptr) {
         value_decoder_->reset();
     } else {
-        value_decoder_ = DecoderFactory::alloc_value_decoder(encoding, 
data_type);
+        value_decoder_ =
+            DecoderFactory::alloc_value_decoder(encoding, data_type);
         if (IS_NULL(value_decoder_)) {
             return E_OOM;
         }
diff --git a/cpp/src/reader/query_data_set.h b/cpp/src/reader/query_data_set.h
index abea04af..85842766 100644
--- a/cpp/src/reader/query_data_set.h
+++ b/cpp/src/reader/query_data_set.h
@@ -34,4 +34,3 @@ class QueryDataSet {
 }  // namespace storage
 
 #endif  // READER_QUERY_DATA_SET_H
-
diff --git a/cpp/src/writer/chunk_writer.cc b/cpp/src/writer/chunk_writer.cc
index c08e725d..7b2f3181 100644
--- a/cpp/src/writer/chunk_writer.cc
+++ b/cpp/src/writer/chunk_writer.cc
@@ -52,6 +52,9 @@ int ChunkWriter::init(const std::string &measurement_name, 
TSDataType data_type,
 }
 
 void ChunkWriter::destroy() {
+    if (num_of_pages_ == 1) {
+        free_first_writer_data();
+    }
     page_writer_.destroy();
     if (chunk_statistic_ != nullptr) {
         StatisticFactory::free(chunk_statistic_);
diff --git a/cpp/src/writer/chunk_writer.h b/cpp/src/writer/chunk_writer.h
index 54d51f54..9b95a9de 100644
--- a/cpp/src/writer/chunk_writer.h
+++ b/cpp/src/writer/chunk_writer.h
@@ -83,6 +83,10 @@ class ChunkWriter {
     int end_encode_chunk();
     common::ByteStream &get_chunk_data() { return chunk_data_; }
     Statistic *get_chunk_statistic() { return chunk_statistic_; }
+    bool hasData() {
+        return num_of_pages_ > 0 || (page_writer_.get_statistic() != nullptr &&
+                                     page_writer_.get_statistic()->count_ > 0);
+    }
     FORCE_INLINE int32_t num_of_pages() const { return num_of_pages_; }
 
     FORCE_INLINE bool is_full() const {
diff --git a/cpp/src/writer/page_writer.cc b/cpp/src/writer/page_writer.cc
index 983818e4..bf290353 100644
--- a/cpp/src/writer/page_writer.cc
+++ b/cpp/src/writer/page_writer.cc
@@ -93,12 +93,15 @@ int PageWriter::init(TSDataType data_type, TSEncoding 
encoding,
     if (ret != E_OK) {
         if (time_encoder_ != nullptr) {
             EncoderFactory::free(time_encoder_);
+            time_encoder_ = nullptr;
         }
         if (value_encoder_ != nullptr) {
             EncoderFactory::free(value_encoder_);
+            value_encoder_ = nullptr;
         }
         if (statistic_ != nullptr) {
             StatisticFactory::free(statistic_);
+            statistic_ = nullptr;
         }
     }
     if (ret == E_OK) {
@@ -126,9 +129,14 @@ void PageWriter::destroy() {
         statistic_->destroy();
 
         EncoderFactory::free(time_encoder_);
+        time_encoder_ = nullptr;
         EncoderFactory::free(value_encoder_);
+        value_encoder_ = nullptr;
         StatisticFactory::free(statistic_);
+        statistic_ = nullptr;
+        compressor_->destroy();
         CompressorFactory::free(compressor_);
+        compressor_ = nullptr;
     }
 }
 
diff --git a/cpp/src/writer/page_writer.h b/cpp/src/writer/page_writer.h
index e348cfad..24b10805 100644
--- a/cpp/src/writer/page_writer.h
+++ b/cpp/src/writer/page_writer.h
@@ -106,6 +106,7 @@ class PageWriter {
           is_inited_(false) {}
     int init(common::TSDataType data_type, common::TSEncoding encoding,
              common::CompressionType compression);
+    ~PageWriter() { destroy(); }
     // reset statistic_, time_out_stream_, value_out_stream_
     void reset();
     void destroy();
diff --git a/cpp/src/writer/time_chunk_writer.cc 
b/cpp/src/writer/time_chunk_writer.cc
index f8298f93..9ae0d30d 100644
--- a/cpp/src/writer/time_chunk_writer.cc
+++ b/cpp/src/writer/time_chunk_writer.cc
@@ -52,6 +52,9 @@ int TimeChunkWriter::init(const std::string &measurement_name,
 }
 
 void TimeChunkWriter::destroy() {
+    if (num_of_pages_ == 1) {
+        free_first_writer_data();
+    }
     time_page_writer_.destroy();
     if (chunk_statistic_ != nullptr) {
         StatisticFactory::free(chunk_statistic_);
diff --git a/cpp/src/writer/time_page_writer.h 
b/cpp/src/writer/time_page_writer.h
index 780398c4..bc5b8212 100644
--- a/cpp/src/writer/time_page_writer.h
+++ b/cpp/src/writer/time_page_writer.h
@@ -66,6 +66,7 @@ class TimePageWriter {
           cur_page_data_(),
           compressor_(nullptr),
           is_inited_(false) {}
+    ~TimePageWriter() { destroy(); }
     int init(common::TSEncoding encoding, common::CompressionType compression);
     void reset();
     void destroy();
diff --git a/cpp/src/writer/tsfile_writer.cc b/cpp/src/writer/tsfile_writer.cc
index 53a5464a..f48ddfd7 100644
--- a/cpp/src/writer/tsfile_writer.cc
+++ b/cpp/src/writer/tsfile_writer.cc
@@ -766,7 +766,7 @@ bool TsFileWriter::check_chunk_group_empty(
          ms_iter++) {
         MeasurementSchema *m_schema = ms_iter->second;
         if (m_schema->chunk_writer_ != NULL &&
-            m_schema->chunk_writer_->num_of_pages() > 0) {
+            m_schema->chunk_writer_->hasData()) {
             // first condition is to avoid first flush empty chunk group
             // second condition is to avoid repeated flush
             return false;
@@ -786,6 +786,7 @@ bool TsFileWriter::check_chunk_group_empty(
                    writer->get_chunk_statistic()))) {                          
\
     } else {                                                                   
\
         writer->destroy();                                                     
\
+        delete writer;                                                         
\
         writer = nullptr;                                                      
\
     }
 
diff --git a/cpp/src/writer/value_chunk_writer.cc 
b/cpp/src/writer/value_chunk_writer.cc
index 7585a610..b32b2dab 100644
--- a/cpp/src/writer/value_chunk_writer.cc
+++ b/cpp/src/writer/value_chunk_writer.cc
@@ -53,6 +53,9 @@ int ValueChunkWriter::init(const std::string 
&measurement_name,
 }
 
 void ValueChunkWriter::destroy() {
+    if (num_of_pages_ == 1) {
+        free_first_writer_data();
+    }
     value_page_writer_.destroy();
     if (chunk_statistic_ != nullptr) {
         StatisticFactory::free(chunk_statistic_);
diff --git a/cpp/src/writer/value_page_writer.h 
b/cpp/src/writer/value_page_writer.h
index 5ce65a5d..649c00c3 100644
--- a/cpp/src/writer/value_page_writer.h
+++ b/cpp/src/writer/value_page_writer.h
@@ -102,6 +102,7 @@ class ValuePageWriter {
           is_inited_(false),
           col_notnull_bitmap_(),
           size_(0) {}
+    ~ValuePageWriter() { destroy(); }
     int init(common::TSDataType data_type, common::TSEncoding encoding,
              common::CompressionType compression);
     void reset();
diff --git a/cpp/test/CMakeLists.txt b/cpp/test/CMakeLists.txt
index df6d3015..f5c42572 100644
--- a/cpp/test/CMakeLists.txt
+++ b/cpp/test/CMakeLists.txt
@@ -79,6 +79,11 @@ if (${COV_ENABLED})
     add_compile_options(-fprofile-arcs -ftest-coverage)
 endif ()
 
+if(NOT WIN32)
+# enable address sanitizer default
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
+endif()
+
 add_executable(TsFile_Test ${TEST_SRCS})
 target_link_libraries(
   TsFile_Test
@@ -88,5 +93,6 @@ target_link_libraries(
 )
 set_target_properties(TsFile_Test PROPERTIES RUNTIME_OUTPUT_DIRECTORY 
${LIBTSFILE_SDK_DIR})
 
+
 include(GoogleTest)
 gtest_discover_tests(TsFile_Test)
diff --git a/cpp/test/common/tsfile_common_test.cc 
b/cpp/test/common/tsfile_common_test.cc
index ef0648bc..08673458 100644
--- a/cpp/test/common/tsfile_common_test.cc
+++ b/cpp/test/common/tsfile_common_test.cc
@@ -167,17 +167,18 @@ class TSMIteratorTest : public ::testing::Test {
         arena.init(1024, common::MOD_DEFAULT);
         chunk_group_meta_list_ =
             new common::SimpleList<ChunkGroupMeta*>(&arena);
-        auto chunk_group_meta = new ChunkGroupMeta(&arena);
+        void* buf = arena.alloc(sizeof(ChunkGroupMeta));
+        auto chunk_group_meta = new (buf) ChunkGroupMeta(&arena);
         chunk_group_meta->device_name_.dup_from("device_1", arena);
 
-        auto chunk_meta = new ChunkMeta();
+        buf = arena.alloc(sizeof(ChunkMeta));
+        auto chunk_meta = new (buf) ChunkMeta();
         char measure_name[] = "measurement_1";
         common::String measurement_name(measure_name, sizeof(measure_name));
         stat_ = StatisticFactory::alloc_statistic(common::TSDataType::INT32);
         common::TsID ts_id;
-        common::PageArena pa;
         chunk_meta->init(measurement_name, common::TSDataType::INT32, 100,
-                         stat_, ts_id, 1, pa);
+                         stat_, ts_id, 1, arena);
 
         chunk_group_meta->chunk_meta_list_.push_back(chunk_meta);
         chunk_group_meta_list_->push_back(chunk_group_meta);
@@ -399,7 +400,8 @@ TEST_F(TsFileMetaTest, SerializeDeserialize) {
         new (pa_.alloc(sizeof(MetaIndexNode))) MetaIndexNode(&pa_);
     meta_.index_node_->push_entry(entry);
     meta_.meta_offset_ = 456;
-    meta_.bloom_filter_ = new BloomFilter();
+    void* buf = pa_.alloc(sizeof(BloomFilter));
+    meta_.bloom_filter_ = new (buf) BloomFilter();
     meta_.bloom_filter_->init(0.1, 100);
 
     ASSERT_EQ(meta_.serialize_to(*out_), common::E_OK);
diff --git a/cpp/test/compress/lz4_compressor_test.cc 
b/cpp/test/compress/lz4_compressor_test.cc
index b6174bfe..f1906652 100644
--- a/cpp/test/compress/lz4_compressor_test.cc
+++ b/cpp/test/compress/lz4_compressor_test.cc
@@ -109,6 +109,7 @@ TEST_F(LZ4Test, TestBytes2) {
     compressor.reset(true);
     compressor.compress(uncompressed.data(), uncompressed.size(),
                         compressed_buf, compressed_buf_len);
+    compressor.after_compress(compressed_buf);
 
     compressor.compress(uncompressed.data(), uncompressed.size(),
                         compressed_buf, compressed_buf_len_new);
@@ -127,5 +128,4 @@ TEST_F(LZ4Test, TestBytes2) {
     compressor.after_compress(compressed_buf);
     compressor.after_uncompress(decompressed_buf);
 }
-
 }  // namespace
diff --git a/cpp/test/cwrapper/cwrapper_test.cc 
b/cpp/test/cwrapper/cwrapper_test.cc
new file mode 100644
index 00000000..18335fdf
--- /dev/null
+++ b/cpp/test/cwrapper/cwrapper_test.cc
@@ -0,0 +1,47 @@
+/*
+ * 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 a
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+#include "cwrapper/TsFile-cwrapper.h"
+#include "utils/errno_define.h"
+
+using namespace common;
+
+namespace cwrapper {
+#define TSFILE_NAME "cwrapper.tsfile"
+class CWrapperTest : public testing::Test {};
+
+TEST_F(CWrapperTest, write_tsfile) {
+    ErrorCode code = 0;
+    CTsFileWriter writer = ts_writer_open(TSFILE_NAME, &code);
+    ASSERT_EQ(code, 0);
+    ASSERT_NE(writer, nullptr);
+    // open again
+    writer = ts_writer_open(TSFILE_NAME, &code);
+    ASSERT_EQ(code, E_ALREADY_EXIST);
+    ts_writer_close(writer);
+    ASSERT_EQ(writer, nullptr);
+    ASSERT_EQ(access(TSFILE_NAME, F_OK), 0);
+
+    writer = ts_writer_open(TSFILE_NAME, &code);
+    ASSERT_EQ(code, E_ALREADY_EXIST);
+    ASSERT_EQ(writer, nullptr);
+}
+}  // namespace cwrapper
\ No newline at end of file
diff --git a/cpp/test/encoding/ts2diff_codec_test.cc 
b/cpp/test/encoding/ts2diff_codec_test.cc
index f6ec68b7..cd6197cf 100644
--- a/cpp/test/encoding/ts2diff_codec_test.cc
+++ b/cpp/test/encoding/ts2diff_codec_test.cc
@@ -35,10 +35,21 @@ class TS2DIFFCodecTest : public ::testing::Test {
     }
 
     void TearDown() override {
-        delete encoder_int_;
-        delete encoder_long_;
+        if (encoder_int_ != nullptr) {
+            encoder_int_->destroy();
+            delete encoder_int_;
+            encoder_int_ = nullptr;
+        }
+        if (encoder_long_ != nullptr) {
+            encoder_long_->destroy();
+            delete encoder_long_;
+            encoder_long_ = nullptr;
+        }
+
         delete decoder_int_;
+        decoder_int_ = nullptr;
         delete decoder_long_;
+        decoder_long_ = nullptr;
     }
 
     IntTS2DIFFEncoder* encoder_int_;
diff --git a/cpp/test/file/open_file_test.cc b/cpp/test/file/open_file_test.cc
index 53125cd8..665e1234 100644
--- a/cpp/test/file/open_file_test.cc
+++ b/cpp/test/file/open_file_test.cc
@@ -29,7 +29,7 @@ class OpenFileTest : public ::testing::Test {
    protected:
     void SetUp() override {
         open_file_ = OpenFileFactory::alloc();
-        open_file_->init();
+        EXPECT_EQ(open_file_->init(), common::E_OK);
     }
 
     void TearDown() override {
@@ -40,11 +40,6 @@ class OpenFileTest : public ::testing::Test {
     OpenFile* open_file_;
 };
 
-TEST_F(OpenFileTest, Initialization) {
-    ASSERT_NE(open_file_, nullptr);
-    EXPECT_EQ(open_file_->init(), common::E_OK);
-}
-
 TEST_F(OpenFileTest, SetFileIdAndPath) {
     common::FileID file_id;
     file_id.seq_ = 1;
diff --git a/cpp/test/writer/chunk_writer_test.cc 
b/cpp/test/writer/chunk_writer_test.cc
index 55e7d630..1d69915c 100644
--- a/cpp/test/writer/chunk_writer_test.cc
+++ b/cpp/test/writer/chunk_writer_test.cc
@@ -46,10 +46,6 @@ class ChunkWriterTest : public ::testing::Test {
     void TearDown() override { chunk_writer.destroy(); }
 };
 
-TEST_F(ChunkWriterTest, InitWithColumnDesc) {
-    EXPECT_EQ(chunk_writer.init(col_desc), E_OK);
-}
-
 TEST_F(ChunkWriterTest, InitWithParameters) {
     ChunkWriter writer;
     EXPECT_EQ(writer.init("test_measurement", TSDataType::DOUBLE,
diff --git a/cpp/test/writer/time_chunk_writer_test.cc 
b/cpp/test/writer/time_chunk_writer_test.cc
index 0e2b2054..18349e7a 100644
--- a/cpp/test/writer/time_chunk_writer_test.cc
+++ b/cpp/test/writer/time_chunk_writer_test.cc
@@ -44,10 +44,6 @@ class TimeChunkWriterTest : public ::testing::Test {
     void TearDown() override { time_chunk_writer.destroy(); }
 };
 
-TEST_F(TimeChunkWriterTest, InitWithColumnDesc) {
-    EXPECT_EQ(time_chunk_writer.init(col_desc), E_OK);
-}
-
 TEST_F(TimeChunkWriterTest, InitWithParameters) {
     TimeChunkWriter writer;
     EXPECT_EQ(
diff --git a/cpp/test/writer/time_page_writer_test.cc 
b/cpp/test/writer/time_page_writer_test.cc
index d0337bee..4d066def 100644
--- a/cpp/test/writer/time_page_writer_test.cc
+++ b/cpp/test/writer/time_page_writer_test.cc
@@ -81,4 +81,5 @@ TEST_F(TimePageWriterTest, WritePageHeaderAndData) {
     common::ByteStream byte_stream(1024, common::MOD_DEFAULT);
     EXPECT_EQ(page_writer_->write_to_chunk(byte_stream, true, true, true),
               common::E_OK);
+    page_writer_->destroy_page_data();
 }
\ No newline at end of file
diff --git a/cpp/test/writer/tsfile_writer_test.cc 
b/cpp/test/writer/tsfile_writer_test.cc
index 299575c6..d69a9ff1 100644
--- a/cpp/test/writer/tsfile_writer_test.cc
+++ b/cpp/test/writer/tsfile_writer_test.cc
@@ -190,6 +190,7 @@ TEST_F(TsFileWriterTest, WriteDiffDataType) {
         cur_record_num++;
     } while (true);
     EXPECT_EQ(cur_record_num, row_num);
+    storage::QueryExpression::destory(query_expr);
     reader.destroy_query_data_set(qds);
 }
 
@@ -296,6 +297,7 @@ TEST_F(TsFileWriterTest, WriteMultipleTabletsMultiFlush) {
                       field_to_string(record->get_field(i)));
         }
     }
+    storage::QueryExpression::destory(query_expr);
     reader.destroy_query_data_set(qds);
 }
 
@@ -457,6 +459,7 @@ TEST_F(TsFileWriterTest, WriteAlignedTimeseries) {
                       field_to_string(record->get_field(i)));
         }
     }
+    storage::QueryExpression::destory(query_expr);
     reader.destroy_query_data_set(qds);
 }
 
@@ -522,6 +525,7 @@ TEST_F(TsFileWriterTest, WriteAlignedMultiFlush) {
                       field_to_string(record->get_field(i)));
         }
     }
+    storage::QueryExpression::destory(query_expr);
     reader.destroy_query_data_set(qds);
 }
 
@@ -591,5 +595,6 @@ TEST_F(TsFileWriterTest, WriteAlignedPartialData) {
         }
         cur_row += 2;
     } while (true);
+    storage::QueryExpression::destory(query_expr);
     reader.destroy_query_data_set(qds);
 }
\ No newline at end of file
diff --git a/cpp/test/writer/value_chunk_writer_test.cc 
b/cpp/test/writer/value_chunk_writer_test.cc
index bc6075fe..91c6ac8c 100644
--- a/cpp/test/writer/value_chunk_writer_test.cc
+++ b/cpp/test/writer/value_chunk_writer_test.cc
@@ -44,10 +44,6 @@ class ValueChunkWriterTest : public ::testing::Test {
     void TearDown() override { value_chunk_writer.destroy(); }
 };
 
-TEST_F(ValueChunkWriterTest, InitWithColumnDesc) {
-    EXPECT_EQ(value_chunk_writer.init(col_desc), E_OK);
-}
-
 TEST_F(ValueChunkWriterTest, InitWithParameters) {
     ValueChunkWriter writer;
     EXPECT_EQ(writer.init("test_measurement", TSDataType::DOUBLE,
diff --git a/cpp/test/writer/value_page_writer_test.cc 
b/cpp/test/writer/value_page_writer_test.cc
index e88712b9..07666e18 100644
--- a/cpp/test/writer/value_page_writer_test.cc
+++ b/cpp/test/writer/value_page_writer_test.cc
@@ -104,4 +104,5 @@ TEST_F(ValuePageWriterTest, WritePageHeaderAndData) {
     common::ByteStream byte_stream(1024, common::MOD_DEFAULT);
     EXPECT_EQ(value_page_writer.write_to_chunk(byte_stream, true, true, true),
               common::E_OK);
+    value_page_writer.destroy_page_data();
 }

Reply via email to