diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 185b39057..997e1d2a5 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 f2a4de754..486d0b14f 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 TYPE_LIST = {0, 0, 1, 0, 1}; } // namespace bench - diff --git a/cpp/build.sh b/cpp/build.sh index 8d907cdeb..e7d4d01f2 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 a04051385..3f63803f0 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 2fdf13cc2..b2e52aad2 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 d77b645c7..2fafb4655 100644 --- a/cpp/examples/cpp_examples/demo_write.cpp +++ b/cpp/examples/cpp_examples/demo_write.cpp @@ -20,39 +20,97 @@ #include #include +#include #include #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 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 161f4ca7d..bf46d9d7d 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 d7d8890b9..72bbce3f9 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 d97bc807b..9eea1086c 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 04d3ab906..29fd5706b 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 8aa729f6f..973c6cbba 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 bf973fc98..8106b5fd8 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 3a4573989..087439dd0 100644 --- a/cpp/src/common/schema.h +++ b/cpp/src/common/schema.h @@ -71,7 +71,7 @@ typedef std::pair 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 b7df814c7..37679ba17 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 3eabeec9a..a1643439a 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 +#include #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> groups; + std::map> groups; std::vector 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& 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 &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> 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 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 9ac501c4e..0a3d37028 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 *get_chunk_meta_list() const { + virtual inline common::SimpleList *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 &chunk_group_meta_list_; common::SimpleList::Iterator chunk_group_meta_iter_; common::SimpleList::Iterator chunk_meta_iter_; + + // timeseries measurenemnt chunk meta info + // map >> + std::map>> + tsm_chunk_meta_info_; + + // device iterator + std::map>>::iterator + tsm_device_iter_; + + // measurement iterator + std::map>::iterator + tsm_measurement_iter_; }; /* =============== TsFile Index ================ */ diff --git a/cpp/src/cwrapper/TsFile-cwrapper.cc b/cpp/src/cwrapper/TsFile-cwrapper.cc index d70c51999..d19c47694 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 2468d515e..099afc790 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 176c0ccd1..4a540ee28 100644 --- a/cpp/src/encoding/zigzag_decoder.h +++ b/cpp/src/encoding/zigzag_decoder.h @@ -33,7 +33,7 @@ template 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 40a7fb906..2543f1bf7 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 d1404ef57..abd08b821 100644 --- a/cpp/src/file/tsfile_io_writer.cc +++ b/cpp/src/file/tsfile_io_writer.cc @@ -21,6 +21,7 @@ #include +#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 07c4b87b6..bb7638cd9 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 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 ts_time_index_vector_; diff --git a/cpp/src/file/write_file.cc b/cpp/src/file/write_file.cc index 1f4c30a5a..71cb553e6 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 0b76353b8..4360f9877 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 c2d2d395d..4f11ce4ff 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 701c87954..a586ff8b9 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 abea04af8..858427660 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 c08e725d1..7b2f31819 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 54d51f54c..9b95a9dec 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 983818e44..bf290353f 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 e348cfad9..24b10805e 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 f8298f93c..9ae0d30d8 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 780398c49..bc5b82124 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 53a5464a5..f48ddfd75 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 7585a610f..b32b2dabf 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 5ce65a5da..649c00c38 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 df6d3015e..f5c42572d 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 ef0648bcb..08673458f 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(&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 b6174bfea..f19066522 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 000000000..18335fdf2 --- /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 +#include + +#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 f6ec68b77..cd6197cf1 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 53125cd88..665e1234b 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 55e7d6301..1d69915cd 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 0e2b20546..18349e7a0 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 d0337beef..4d066def4 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 299575c62..d69a9ff19 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 bc6075fe8..91c6ac8c6 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 e88712b94..07666e189 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(); }