blob: be74085286ab7b60ea3097081d995cd59ae7d527 [file] [log] [blame]
/*
* 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.
*/
#include "device_meta_iterator.h"
#include "filter/tag_filter.h"
namespace storage {
bool DeviceMetaIterator::has_next() {
if (!result_cache_.empty()) {
return true;
}
if (load_results() != common::E_OK) {
return false;
}
return !result_cache_.empty();
}
int DeviceMetaIterator::next(
std::pair<std::shared_ptr<IDeviceID>, MetaIndexNode*>& ret_meta) {
if (!has_next()) {
return common::E_NO_MORE_DATA;
}
ret_meta = result_cache_.front();
result_cache_.pop();
return common::E_OK;
}
int DeviceMetaIterator::load_results() {
int root_num = meta_index_nodes_.size();
while (!meta_index_nodes_.empty()) {
// To avoid ASan overflow.
// using `const auto&` creates a reference
// to a queue element that may become invalid.
auto meta_data_index_node = meta_index_nodes_.front();
meta_index_nodes_.pop();
const auto& node_type = meta_data_index_node->node_type_;
if (node_type == MetaIndexNodeType::LEAF_DEVICE) {
load_leaf_device(meta_data_index_node);
} else if (node_type == MetaIndexNodeType::INTERNAL_DEVICE) {
load_internal_node(meta_data_index_node);
} else {
return common::E_INVALID_NODE_TYPE;
}
if (root_num-- <= 0) {
meta_data_index_node->~MetaIndexNode();
}
}
return common::E_OK;
}
int DeviceMetaIterator::load_leaf_device(MetaIndexNode* meta_index_node) {
int ret = common::E_OK;
const auto& leaf_children = meta_index_node->children_;
for (size_t i = 0; i < leaf_children.size(); i++) {
std::shared_ptr<IMetaIndexEntry> child = leaf_children[i];
if (id_filter_ != nullptr) {
if (!id_filter_->satisfyRow(
0, child->get_device_id()->get_segments())) {
continue;
}
}
int32_t start_offset = child->get_offset();
int32_t end_offset = i + 1 < leaf_children.size()
? leaf_children[i + 1]->get_offset()
: meta_index_node->end_offset_;
MetaIndexNode* child_node = nullptr;
if (RET_FAIL(io_reader_->read_device_meta_index(
start_offset, end_offset, pa_, child_node, true))) {
return ret;
} else {
auto device_id = child->get_device_id();
if (should_split_device_name) {
device_id->split_table_name();
}
result_cache_.push(std::make_pair(device_id, child_node));
}
}
return ret;
}
int DeviceMetaIterator::load_internal_node(MetaIndexNode* meta_index_node) {
int ret = common::E_OK;
const auto& internal_children = meta_index_node->children_;
for (size_t i = 0; i < internal_children.size(); i++) {
std::shared_ptr<IMetaIndexEntry> child = internal_children[i];
int32_t start_offset = child->get_offset();
int32_t end_offset = (i + 1 < internal_children.size())
? internal_children[i + 1]->get_offset()
: meta_index_node->end_offset_;
MetaIndexNode* child_node = nullptr;
if (RET_FAIL(io_reader_->read_device_meta_index(
start_offset, end_offset, pa_, child_node, false))) {
return ret;
} else {
meta_index_nodes_.push(child_node);
}
}
return ret;
}
} // namespace storage