Files
oceanbase/src/storage/ob_macro_block_iterator.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

451 lines
16 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX STORAGE
#include "ob_macro_block_iterator.h"
#include "lib/container/ob_fixed_array_iterator.h"
#include "ob_sstable.h"
using namespace oceanbase::common;
using namespace oceanbase::blocksstable;
namespace oceanbase {
namespace storage {
ObMacroBlockDesc::ObMacroBlockDesc()
: data_version_(0),
block_idx_(0),
block_cnt_(0),
macro_block_ctx_(),
full_meta_(),
range_(),
row_store_type_(FLAT_ROW_STORE),
schema_version_(0),
data_seq_(0),
row_count_(0),
occupy_size_(0),
micro_block_count_(0),
data_checksum_(0),
snapshot_version_(0),
row_count_delta_(0),
progressive_merge_round_(0),
contain_uncommitted_row_(true)
{}
/**
* -----------------------------------------------------------ObMacroBlockRowComparor-------------------------------------------------------
*/
ObMacroBlockRowComparor::ObMacroBlockRowComparor()
: ret_(OB_SUCCESS),
use_collation_free_(false),
is_prefix_check_(false),
full_meta_(),
macro_block_rowkey_(),
sstable_(nullptr)
{}
ObMacroBlockRowComparor::~ObMacroBlockRowComparor()
{}
int ObMacroBlockRowComparor::compare_(
const blocksstable::MacroBlockId& block_id, const common::ObStoreRowkey& rowkey, int& cmp_ret)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(sstable_)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, sstable must not be null", K(ret));
} else if (OB_FAIL(sstable_->get_meta(block_id, full_meta_))) {
LOG_WARN("fail to get meta", K(ret), K(block_id));
} else if (OB_UNLIKELY(!full_meta_.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(ERROR, "Invalid macro meta, ", K(ret), K(full_meta_));
} else {
const ObMacroBlockMetaV2* macro_meta = full_meta_.meta_;
if (use_collation_free_) {
if (OB_ISNULL(macro_meta->collation_free_endkey_)) {
macro_block_rowkey_.assign(macro_meta->endkey_, macro_meta->rowkey_column_number_);
} else {
macro_block_rowkey_.assign(macro_meta->collation_free_endkey_, macro_meta->rowkey_column_number_);
}
} else {
macro_block_rowkey_.assign(macro_meta->endkey_, macro_meta->rowkey_column_number_);
}
if (is_prefix_check_) {
ret = macro_block_rowkey_.compare_prefix(rowkey, cmp_ret);
} else {
ret = macro_block_rowkey_.compare(rowkey, cmp_ret);
}
}
return ret;
}
bool ObMacroBlockRowComparor::operator()(
const blocksstable::MacroBlockId& block_id, const common::ObStoreRowkey& rowkey)
{
bool bret = false;
int32_t cmp_ret = 0;
if (OB_UNLIKELY(OB_SUCCESS != (ret_ = compare_(block_id, rowkey, cmp_ret)))) {
STORAGE_LOG(WARN, "Failed to compare block and rowkey", K(rowkey), K_(ret));
} else {
bret = cmp_ret < 0;
}
return bret;
}
bool ObMacroBlockRowComparor::operator()(
const common::ObStoreRowkey& rowkey, const blocksstable::MacroBlockId& block_id)
{
bool bret = false;
int32_t cmp_ret = 0;
if (OB_UNLIKELY(OB_SUCCESS != (ret_ = compare_(block_id, rowkey, cmp_ret)))) {
STORAGE_LOG(WARN, "Failed to compare block and rowkey", K(block_id), K(rowkey), K_(ret));
} else {
bret = cmp_ret > 0;
}
return bret;
}
void ObMacroBlockRowComparor::reset()
{
ret_ = OB_SUCCESS;
use_collation_free_ = false;
full_meta_.reset();
is_prefix_check_ = false;
sstable_ = nullptr;
}
/**
* -----------------------------------------------------------ObMacroBlockIterator-----------------------------------------------------------
*/
ObMacroBlockIterator::ObMacroBlockIterator()
: sstable_(NULL), is_reverse_scan_(false), step_(1), cur_idx_(-1), begin_(-1), end_(-1), check_lob_(false)
{}
ObMacroBlockIterator::~ObMacroBlockIterator()
{}
void ObMacroBlockIterator::reset()
{
sstable_ = NULL;
is_reverse_scan_ = false;
step_ = 1;
cur_idx_ = -1;
begin_ = -1;
end_ = -1;
check_lob_ = false;
}
int ObMacroBlockIterator::open(ObSSTable& sstable, const ObExtStoreRowkey& ext_rowkey)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!sstable.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument, ", K(ret), K(sstable));
} else {
sstable_ = &sstable;
if (OB_FAIL(locate_macro_block(ext_rowkey, cur_idx_))) {
STORAGE_LOG(WARN, "Fail to locate macro block, ", K(ret), K(ext_rowkey));
} else {
begin_ = end_ = cur_idx_;
}
}
return ret;
}
int ObMacroBlockIterator::open(ObSSTable& sstable, const bool is_reverse, const bool check_lob)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!sstable.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument, ", K(ret), K(sstable));
} else if (OB_UNLIKELY(check_lob && is_reverse)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Macro block scan with lob conflict with reverse scan", K(ret));
} else {
sstable_ = &sstable;
check_lob_ = check_lob;
is_reverse_scan_ = is_reverse;
begin_ = 0;
if (check_lob) {
end_ = sstable.get_total_macro_blocks().count() - 1;
} else {
end_ = sstable.get_macro_block_ids().count() - 1;
}
if (is_reverse) {
cur_idx_ = end_;
step_ = -1;
} else {
cur_idx_ = begin_;
step_ = 1;
}
}
return ret;
}
int ObMacroBlockIterator::open(ObSSTable& sstable, const common::ObExtStoreRange& ext_range, const bool is_reverse)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!sstable.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument, ", K(ret), K(sstable));
} else {
sstable_ = &sstable;
is_reverse_scan_ = is_reverse;
step_ = is_reverse ? -1 : 1;
if (OB_FAIL(locate_macro_block(ext_range.get_ext_start_key(), begin_))) {
STORAGE_LOG(WARN, "Fail to locate start macro block, ", K(ret));
} else if (-1 == begin_) {
// not exist range
end_ = cur_idx_ = -1;
} else if (OB_FAIL(locate_macro_block(ext_range.get_ext_end_key(), end_))) {
STORAGE_LOG(WARN, "Fail to locate end macro block, ", K(ret));
} else {
if (-1 == end_) {
end_ = sstable.get_macro_block_ids().count() - 1;
}
if (!ext_range.get_range().get_border_flag().inclusive_start()) {
const MacroBlockId& block_id = sstable_->get_macro_block_ids().at(begin_);
ObFullMacroBlockMeta full_meta;
if (OB_FAIL(sstable_->get_meta(block_id, full_meta))) {
STORAGE_LOG(WARN, "fail to get meta", K(ret));
} else {
const ObMacroBlockMetaV2* meta = full_meta.meta_;
ObStoreRowkey rowkey(meta->endkey_, meta->rowkey_column_number_);
if (ext_range.get_range().get_start_key() == rowkey) {
++begin_;
}
}
}
cur_idx_ = is_reverse ? end_ : begin_;
}
}
return ret;
}
int ObMacroBlockIterator::get_next_macro_block(blocksstable::ObMacroBlockCtx& macro_block_ctx)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(check_lob_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected check lob mode in ObMacroBlockIterator", K(ret));
} else if (cur_idx_ < begin_ || cur_idx_ > end_ || cur_idx_ < 0) {
ret = OB_ITER_END;
} else if (OB_FAIL(sstable_->get_macro_block_ctx(cur_idx_, macro_block_ctx))) {
STORAGE_LOG(WARN, "Fail to get_macro_ctx", K(ret), K(cur_idx_));
} else {
STORAGE_LOG(DEBUG, "Success to get macro block id, ", K_(cur_idx), K(macro_block_ctx));
cur_idx_ += step_;
}
return ret;
}
int ObMacroBlockIterator::get_next_macro_block(
blocksstable::ObMacroBlockCtx& macro_block_ctx, ObFullMacroBlockMeta& macro_meta)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(check_lob_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected check lob mode in ObMacroBlockIterator", K(ret));
} else if (cur_idx_ < begin_ || cur_idx_ > end_ || cur_idx_ < 0) {
ret = OB_ITER_END;
} else if (OB_FAIL(sstable_->get_macro_block_ctx(cur_idx_, macro_block_ctx))) {
STORAGE_LOG(WARN, "Fail to get_macro_ctx", K(ret), K(cur_idx_));
} else if (OB_FAIL(sstable_->get_meta(macro_block_ctx.sstable_block_id_.macro_block_id_, macro_meta))) {
STORAGE_LOG(WARN, "fail to get meta", K(ret));
} else if (OB_UNLIKELY(!macro_meta.is_valid())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected error, ", K(ret), K(macro_meta));
} else {
STORAGE_LOG(DEBUG, "Success to get macro block id, ", K_(cur_idx), K(macro_block_ctx));
cur_idx_ += step_;
}
return ret;
}
int ObMacroBlockIterator::get_next_macro_block(ObMacroBlockDesc& block_desc)
{
int ret = OB_SUCCESS;
ObFullMacroBlockMeta full_meta;
if (cur_idx_ < begin_ || cur_idx_ > end_ || cur_idx_ < 0) {
ret = OB_ITER_END;
} else if (cur_idx_ >= sstable_->get_macro_block_count()) {
const int64_t lob_idx = cur_idx_ - sstable_->get_macro_block_count();
if (OB_UNLIKELY(!check_lob_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN,
"Unexpected macro block iter index without check lob",
K_(cur_idx),
"macro_block_count",
sstable_->get_macro_block_count(),
K(ret));
} else if (OB_FAIL(sstable_->get_lob_macro_block_ctx(lob_idx, block_desc.macro_block_ctx_))) {
LOG_WARN("Failed to get lob macro block ctx", K(ret), K(lob_idx));
} else if (OB_FAIL(sstable_->get_meta(block_desc.macro_block_ctx_.sstable_block_id_.macro_block_id_, full_meta))) {
LOG_WARN("fail to get meta", K(ret));
} else {
block_desc.range_.get_start_key().assign(full_meta.meta_->endkey_, full_meta.meta_->rowkey_column_number_);
block_desc.range_.get_end_key().assign(full_meta.meta_->endkey_, full_meta.meta_->rowkey_column_number_);
}
} else {
if (0 == cur_idx_) {
block_desc.range_.get_start_key().set_min();
} else {
if (OB_FAIL(sstable_->get_meta(sstable_->get_macro_block_ids().at(cur_idx_ - 1), full_meta))) {
STORAGE_LOG(WARN, "fail to get meta", K(ret));
} else if (!full_meta.is_valid()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Invalid macro meta, ", K(ret), K(full_meta));
} else {
block_desc.range_.get_start_key().assign(full_meta.meta_->endkey_, full_meta.meta_->rowkey_column_number_);
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(sstable_->get_meta(sstable_->get_macro_block_ids().at(cur_idx_), full_meta))) {
STORAGE_LOG(WARN, "fail to get meta", K(ret));
} else if (!full_meta.is_valid()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Invalid macro meta, ", K(ret), K(full_meta));
} else if (OB_FAIL(sstable_->get_macro_block_ctx(cur_idx_, block_desc.macro_block_ctx_))) {
STORAGE_LOG(WARN, "failed to get macro block ctx", K(ret), K(cur_idx_));
} else {
if (cur_idx_ == sstable_->get_macro_block_ids().count() - 1) {
block_desc.range_.get_end_key().set_max();
} else {
block_desc.range_.get_end_key().assign(full_meta.meta_->endkey_, full_meta.meta_->rowkey_column_number_);
}
}
}
}
if (OB_SUCC(ret)) {
STORAGE_LOG(DEBUG,
"Success to get macro block id, ",
K_(cur_idx),
"macro_block_id",
sstable_->get_macro_block_ids().at(cur_idx_));
block_desc.block_idx_ = cur_idx_;
block_desc.data_version_ = full_meta.meta_->data_version_;
block_desc.row_store_type_ = full_meta.meta_->row_store_type_;
if (check_lob_) {
block_desc.block_cnt_ = sstable_->get_total_macro_blocks().count();
} else {
block_desc.block_cnt_ = sstable_->get_macro_block_ids().count();
}
block_desc.full_meta_ = full_meta;
block_desc.range_.get_border_flag().unset_inclusive_start();
block_desc.range_.get_border_flag().set_inclusive_end();
block_desc.schema_version_ = full_meta.meta_->schema_version_;
block_desc.data_seq_ = full_meta.meta_->data_seq_;
block_desc.row_count_ = full_meta.meta_->row_count_;
block_desc.occupy_size_ = full_meta.meta_->occupy_size_;
block_desc.micro_block_count_ = full_meta.meta_->micro_block_count_;
block_desc.data_checksum_ = full_meta.meta_->data_checksum_;
block_desc.snapshot_version_ = full_meta.meta_->snapshot_version_;
block_desc.row_count_delta_ = full_meta.meta_->row_count_delta_;
block_desc.progressive_merge_round_ = full_meta.meta_->progressive_merge_round_;
block_desc.contain_uncommitted_row_ = full_meta.meta_->contain_uncommitted_row_;
cur_idx_ += step_;
}
return ret;
}
int ObMacroBlockIterator::get_macro_block_count(int64_t& macro_block_count)
{
int ret = OB_SUCCESS;
if (begin_ < 0 || end_ < 0) {
macro_block_count = 0;
} else {
macro_block_count = end_ - begin_ + 1;
}
return ret;
}
int ObMacroBlockIterator::locate_macro_block(const ObExtStoreRowkey& ext_rowkey, int64_t& block_idx)
{
int ret = OB_SUCCESS;
block_idx = -1;
if (sstable_->get_macro_block_count() == 0) {
// pass empty sstable
} else if (sstable_->is_rowkey_helper_valid() &&
sstable_->get_rowkey_helper().is_oracle_mode() == share::is_oracle_mode()) {
if (OB_FAIL(sstable_->get_rowkey_helper().locate_block_idx(ext_rowkey, cur_idx_, block_idx))) {
STORAGE_LOG(WARN, "Failed to locate macro block with rowkey helper", K(ret));
}
} else {
ret = locate_macro_block_without_helper(ext_rowkey, block_idx);
}
return ret;
}
int ObMacroBlockIterator::locate_macro_block_without_helper(const ObExtStoreRowkey& ext_rowkey, int64_t& block_idx)
{
int ret = OB_SUCCESS;
const ObStoreRowkey* cmp_rowkey = NULL;
bool use_collation_free = false;
block_idx = -1;
if (OB_FAIL(ext_rowkey.check_use_collation_free(sstable_->exist_invalid_collation_free_meta_, use_collation_free))) {
STORAGE_LOG(WARN, "Fail to check use collation free, ", K(ret), K(ext_rowkey));
} else {
ObSSTable::MacroBlockArray::iterator begin = sstable_->meta_.macro_block_array_.begin();
ObSSTable::MacroBlockArray::iterator end = sstable_->meta_.macro_block_array_.end();
comparor_.reset();
comparor_.set_use_collation_free(use_collation_free);
comparor_.set_sstable(*sstable_);
if (use_collation_free) {
cmp_rowkey = &(ext_rowkey.get_collation_free_store_rowkey());
} else {
cmp_rowkey = &(ext_rowkey.get_store_rowkey());
}
comparor_.set_prefix_check(cmp_rowkey->get_obj_cnt() < sstable_->meta_.rowkey_column_count_);
if (!comparor_.is_prefix_check() && cur_idx_ >= 0 && cur_idx_ < sstable_->get_macro_block_ids().count()) {
// the rowkey may be in the same macro block, so check last macro block first
if (!comparor_(sstable_->get_macro_block_ids().at(cur_idx_), *cmp_rowkey)) {
if (0 == cur_idx_ || comparor_(sstable_->get_macro_block_ids().at(cur_idx_ - 1), *cmp_rowkey)) {
block_idx = cur_idx_;
}
}
}
if (-1 == block_idx) {
// binary search
ObSSTable::MacroBlockArray::iterator iter = std::lower_bound(begin, end, *cmp_rowkey, comparor_);
if (OB_FAIL(comparor_.get_ret())) {
STORAGE_LOG(ERROR, "Fail to find macro, ", K(ret));
} else {
if (iter < sstable_->meta_.macro_block_array_.end()) {
block_idx = iter - sstable_->meta_.macro_block_array_.begin();
}
}
}
}
return ret;
}
} // namespace storage
} // namespace oceanbase