| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * License); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #ifndef COMMON_SEQ_TVLIST_H |
| #define COMMON_SEQ_TVLIST_H |
| |
| #include "common/allocator/alloc_base.h" |
| #include "common/allocator/page_arena.h" |
| #include "common/mutex/mutex.h" |
| #include "utils/db_utils.h" |
| #include "utils/errno_define.h" |
| #include "utils/storage_utils.h" |
| #include "utils/util_define.h" |
| |
| namespace storage { |
| |
| class SeqTVListBase { |
| public: |
| SeqTVListBase() |
| : data_type_(common::VECTOR), |
| mutex_(), |
| ref_count_(0), |
| primary_array_size_(0), |
| list_size_(0), |
| write_count_(0), |
| page_arena_(common::g_base_allocator), |
| use_page_arena_(false), |
| is_immutable_(false) {} |
| virtual ~SeqTVListBase() {} |
| virtual void destroy() {} |
| |
| FORCE_INLINE void ref() { ATOMIC_AAF(&ref_count_, 1); } |
| FORCE_INLINE bool unref() { return 0 == ATOMIC_AAF(&ref_count_, -1); } |
| |
| FORCE_INLINE void lock() { mutex_.lock(); } |
| FORCE_INLINE void unlock() { mutex_.unlock(); } |
| |
| int32_t get_total_count() const { return write_count_; } |
| common::TSDataType get_data_type() const { return data_type_; } |
| virtual TimeRange get_time_range() const = 0; |
| void mark_immutable() { is_immutable_ = true; } |
| bool is_immutable() const { return is_immutable_; } |
| |
| protected: |
| common::TSDataType data_type_; |
| mutable common::Mutex mutex_; |
| int32_t ref_count_; |
| int32_t primary_array_size_; |
| int32_t list_size_; |
| int32_t write_count_; |
| common::PageArena page_arena_; |
| bool use_page_arena_; |
| bool is_immutable_; |
| }; |
| |
| template <typename Type> |
| class SeqTVList : public SeqTVListBase { |
| public: |
| typedef struct TV { |
| int64_t time_; |
| Type value_; |
| } TV; |
| |
| struct Iterator { |
| SeqTVList *host_list_; |
| int32_t read_idx_; |
| int32_t end_idx_; |
| |
| Iterator() : host_list_(nullptr), read_idx_(UINT32_MAX), end_idx_(0) {} |
| |
| INLINE void init(SeqTVList *host, int32_t start_idx, int32_t end_idx) { |
| host_list_ = host; |
| read_idx_ = start_idx; |
| end_idx_ = end_idx; |
| } |
| |
| int next(TV &tv) { |
| if (read_idx_ >= end_idx_) { |
| return common::E_NO_MORE_DATA; |
| } |
| tv = host_list_->at(read_idx_); |
| read_idx_++; |
| return common::E_OK; |
| } |
| }; |
| |
| public: |
| SeqTVList() : tv_array_list_(nullptr), last_time_(-1) { |
| data_type_ = common::GetDataTypeFromTemplateType<Type>(); |
| } |
| virtual ~SeqTVList() {} |
| |
| int init(int32_t primary_array_size, int32_t max_count, |
| bool use_page_arena); |
| void destroy() OVERRIDE; |
| |
| int push(int64_t time, Type value); |
| int push_without_lock(int64_t time, Type value); |
| Iterator scan_without_lock(int64_t start_time, int64_t end_time); |
| Iterator scan_without_lock(); |
| |
| TimeRange get_time_range() const OVERRIDE { |
| TimeRange time_range; |
| common::MutexGuard mg(mutex_); |
| if (write_count_ > 0) { |
| time_range.start_time_ = time_at(0); |
| time_range.end_time_ = time_at(write_count_ - 1); |
| ASSERT(time_range.start_time_ <= time_range.end_time_); |
| } |
| return time_range; |
| } |
| |
| FORCE_INLINE TV at(int32_t tv_idx) const { |
| ASSERT(tv_idx < write_count_); |
| int32_t list_idx = tv_idx / primary_array_size_; |
| int32_t list_offset = tv_idx % primary_array_size_; |
| return tv_array_list_[list_idx][list_offset]; |
| } |
| |
| FORCE_INLINE int64_t time_at(int32_t tv_idx) const { |
| return at(tv_idx).time_; |
| } |
| |
| #ifdef ENABLE_TEST |
| int32_t TEST_binary_search_upper(int64_t time) { |
| return binary_search_upper(time); |
| } |
| int32_t TEST_binary_search_lower(int64_t time) { |
| return binary_search_lower(time); |
| } |
| #endif |
| |
| private: |
| FORCE_INLINE void *alloc(uint32_t size) { |
| if (use_page_arena_) { |
| return page_arena_.alloc(size); |
| } else { |
| return common::mem_alloc(size, common::MOD_TVLIST_DATA); |
| } |
| } |
| |
| // return the first tv which is larger or equal to @time |
| int32_t binary_search_upper(int64_t time); |
| // return the last tv which is less or equal to @time |
| int32_t binary_search_lower(int64_t time); |
| |
| private: |
| TV **tv_array_list_; |
| int64_t last_time_; |
| }; |
| |
| } // namespace storage |
| |
| #include "seq_tvlist.inc" |
| |
| #endif // COMMON_SEQ_TVLIST_H |