blob: 9595acf55a876a259961a35b171eded0e985e70c [file]
/*
* 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 READER_TSFILE_SERIES_SCAN_ITERATOR_H
#define READER_TSFILE_SERIES_SCAN_ITERATOR_H
#include <limits>
#include <string>
#include "aligned_chunk_reader.h"
#include "common/tsblock/tsblock.h"
#include "file/read_file.h"
#include "file/tsfile_io_reader.h"
#include "reader/chunk_reader.h"
#include "reader/filter/filter.h"
#include "utils/util_define.h"
#ifdef ENABLE_THREADS
namespace common {
class ThreadPool;
}
#endif
namespace storage {
class TsFileIOReader;
class TsFileSeriesScanIterator {
public:
TsFileSeriesScanIterator()
: read_file_(nullptr),
device_id_(),
measurement_name_(),
itimeseries_index_(),
timeseries_index_pa_(),
data_pa_(nullptr),
chunk_meta_cursor_(),
chunk_reader_(nullptr),
tuple_desc_(),
tsblock_(nullptr),
time_filter_(nullptr),
is_aligned_(false),
is_multi_value_(false),
row_offset_(0),
row_limit_(-1) {}
~TsFileSeriesScanIterator() { destroy(); }
int init(std::shared_ptr<IDeviceID> device_id,
const std::string& measurement_name, ReadFile* read_file,
Filter* time_filter, common::PageArena& data_pa) {
ASSERT(read_file != nullptr);
device_id_ = device_id;
measurement_name_ = measurement_name;
read_file_ = read_file;
time_filter_ = time_filter;
data_pa_ = &data_pa;
return common::E_OK;
}
void destroy();
void set_row_range(int offset, int limit) {
row_offset_ = offset;
row_limit_ = limit;
}
int get_row_offset() const { return row_offset_; }
int get_row_limit() const { return row_limit_; }
int get_next(common::TsBlock*& ret_tsblock, bool alloc_tsblock,
Filter* oneshoot_filter = nullptr,
int64_t min_time_hint = std::numeric_limits<int64_t>::min());
void revert_tsblock();
uint32_t get_value_column_count() const {
if (is_multi_value_ && chunk_reader_) {
auto* acr = static_cast<AlignedChunkReader*>(chunk_reader_);
return acr->get_value_column_count();
}
return 1;
}
bool is_multi_value() const { return is_multi_value_; }
friend class TsFileIOReader;
private:
int init_chunk_reader();
int init_chunk_reader_multi();
FORCE_INLINE bool has_next_chunk() const {
if (is_multi_value_) {
return !value_chunk_meta_cursors_.empty() &&
value_chunk_meta_cursors_[0] !=
itimeseries_index_->get_value_chunk_meta_list(0)->end();
}
if (is_aligned_) {
return value_chunk_meta_cursor_ !=
itimeseries_index_->get_value_chunk_meta_list()->end();
} else {
return chunk_meta_cursor_ !=
itimeseries_index_->get_chunk_meta_list()->end();
}
}
FORCE_INLINE void advance_to_next_chunk() {
if (is_multi_value_) {
time_chunk_meta_cursor_++;
for (auto& cur : value_chunk_meta_cursors_) cur++;
} else if (is_aligned_) {
time_chunk_meta_cursor_++;
value_chunk_meta_cursor_++;
} else {
chunk_meta_cursor_++;
}
}
FORCE_INLINE ChunkMeta* get_current_chunk_meta() {
return chunk_meta_cursor_.get();
}
bool should_skip_chunk_by_time(ChunkMeta* cm, int64_t min_time_hint);
bool should_skip_chunk_by_offset(ChunkMeta* cm);
/**
* Aligned (VECTOR): whole-chunk skip by row count is only safe when the
* time ChunkMeta and value ChunkMeta agree on statistic count (>0). If
* either side lacks count or counts differ, skip is disabled for this
* chunk; pages are loaded and page/row-level offset handling applies.
*/
bool should_skip_aligned_chunk_by_offset(ChunkMeta* time_cm,
ChunkMeta* value_cm);
common::TsBlock* alloc_tsblock();
common::TsBlock* alloc_tsblock_multi();
private:
ReadFile* read_file_;
std::shared_ptr<IDeviceID> device_id_;
std::string measurement_name_;
ITimeseriesIndex* itimeseries_index_;
common::PageArena timeseries_index_pa_;
common::PageArena* data_pa_;
common::SimpleList<ChunkMeta*>::Iterator chunk_meta_cursor_;
common::SimpleList<ChunkMeta*>::Iterator time_chunk_meta_cursor_;
common::SimpleList<ChunkMeta*>::Iterator value_chunk_meta_cursor_;
// Multi-value: one cursor per value column
std::vector<common::SimpleList<ChunkMeta*>::Iterator>
value_chunk_meta_cursors_;
IChunkReader* chunk_reader_;
common::TupleDesc tuple_desc_;
common::TsBlock* tsblock_;
Filter* time_filter_;
bool is_aligned_ = false;
bool is_multi_value_ = false;
int row_offset_;
int row_limit_;
#ifdef ENABLE_THREADS
common::ThreadPool* decode_pool_ =
nullptr; // owned, for multi-value decode
#endif
};
} // end namespace storage
#endif // READER_TSFILE_SERIES_SCAN_ITERATOR_H