259 lines
7.1 KiB
C++
259 lines
7.1 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.
|
|
*/
|
|
|
|
#ifndef OCEANBASE_STORAGE_OB_MULTIPLE_ROW_MERGER_
|
|
#define OCEANBASE_STORAGE_OB_MULTIPLE_ROW_MERGER_
|
|
#include "ob_scan_merge_loser_tree.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace storage
|
|
{
|
|
|
|
template <typename T, typename Comparator>
|
|
class ObSimpleRowsMerger : public common::ObRowsMerger<T, Comparator>
|
|
{
|
|
public:
|
|
static const int64_t USE_SIMPLE_MERGER_MAX_TABLE_CNT = 3;
|
|
virtual ObRowMergerType type() override { return ObRowMergerType::SIMPLE_MERGER; }
|
|
ObSimpleRowsMerger(Comparator& cmp);
|
|
virtual ~ObSimpleRowsMerger();
|
|
virtual int init(const int64_t table_cnt, common::ObIAllocator &allocator) override;
|
|
virtual bool is_inited() const override { return is_inited_; }
|
|
virtual int open(const int64_t table_cnt) override;
|
|
virtual void reset() override;
|
|
virtual void reuse() override;
|
|
virtual int top(const T *&item) override;
|
|
virtual int pop() override;
|
|
virtual int push(const T &item) override;
|
|
virtual int push_top(const T &item) override;
|
|
virtual int rebuild() override;
|
|
virtual int count() const override;
|
|
virtual bool empty() const override;
|
|
virtual bool is_unique_champion() const override;
|
|
TO_STRING_KV(K_(is_inited), K_(table_cnt), K_(item_cnt))
|
|
|
|
private:
|
|
bool is_inited_;
|
|
int64_t table_cnt_;
|
|
int64_t item_cnt_;
|
|
Comparator& cmp_;
|
|
T *items_;
|
|
common::ObIAllocator *allocator_;
|
|
};
|
|
typedef ObSimpleRowsMerger<ObScanMergeLoserTreeItem, ObScanMergeLoserTreeCmp> ObScanSimpleMerger;
|
|
|
|
template <typename T, typename Comparator>
|
|
ObSimpleRowsMerger<T, Comparator>::ObSimpleRowsMerger(Comparator& cmp)
|
|
: is_inited_(false),
|
|
table_cnt_(0),
|
|
item_cnt_(0),
|
|
cmp_(cmp),
|
|
items_(nullptr),
|
|
allocator_(nullptr)
|
|
{}
|
|
|
|
template <typename T, typename Comparator>
|
|
ObSimpleRowsMerger<T, Comparator>::~ObSimpleRowsMerger()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
void ObSimpleRowsMerger<T, Comparator>::reset()
|
|
{
|
|
is_inited_ = false;
|
|
table_cnt_ = 0;
|
|
item_cnt_ = 0;
|
|
if (nullptr != allocator_ && nullptr != items_) {
|
|
allocator_->free(items_);
|
|
}
|
|
items_ = nullptr;
|
|
allocator_ = nullptr;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
void ObSimpleRowsMerger<T, Comparator>::reuse()
|
|
{
|
|
table_cnt_ = 0;
|
|
item_cnt_ = 0;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::init(const int64_t table_cnt, common::ObIAllocator &allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_INIT) {
|
|
ret = OB_INIT_TWICE;
|
|
SERVER_LOG(WARN, "The merge has been inited", K(ret));
|
|
} else if (table_cnt <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
STORAGE_LOG(WARN, "Invalid table cnt", K(ret), K(table_cnt));
|
|
} else {
|
|
table_cnt_ = table_cnt;
|
|
allocator_ = &allocator;
|
|
if (nullptr == (items_ = static_cast<T*>(allocator_->alloc(sizeof(T) * USE_SIMPLE_MERGER_MAX_TABLE_CNT)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
STORAGE_LOG(WARN, "Failed to allocate items", K(ret), K(table_cnt_));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
is_inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::open(const int64_t table_cnt)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
SERVER_LOG(WARN, "not inited", K(ret));
|
|
} else if (table_cnt <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
STORAGE_LOG(WARN, "Invalid table cnt", K(ret), K(table_cnt));
|
|
} else {
|
|
table_cnt_ = table_cnt;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
bool ObSimpleRowsMerger<T, Comparator>::empty() const
|
|
{
|
|
return item_cnt_ <= 0;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::count() const
|
|
{
|
|
return item_cnt_;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
bool ObSimpleRowsMerger<T, Comparator>::is_unique_champion() const
|
|
{
|
|
bool bret = true;
|
|
if (!empty()) {
|
|
bret = !items_[0].equal_with_next_;
|
|
} else {
|
|
bret = true;
|
|
}
|
|
return bret;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::push(const T &item)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LIB_LOG(WARN, "The merger is not init", K(ret));
|
|
} else if (item_cnt_ + 1 > table_cnt_) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
STORAGE_LOG(WARN, "Unexpected state", K(ret), K(item_cnt_), K(table_cnt_));
|
|
} else {
|
|
if (0 == item_cnt_) {
|
|
items_[0] = item;
|
|
} else {
|
|
int64_t cmp_ret = 0;
|
|
bool equal_with_next = false;
|
|
int64_t i = item_cnt_ - 1;
|
|
for ( ; OB_SUCC(ret) && i >= 0; --i) {
|
|
if (OB_FAIL(cmp_.cmp(item, items_[i], cmp_ret))) {
|
|
STORAGE_LOG(WARN, "Fail to compare item", K(ret), K(i), K(items_[i]), K(item));
|
|
break;
|
|
} else if (cmp_ret < 0) {
|
|
items_[i+1] = items_[i];
|
|
} else if (0 == cmp_ret) {
|
|
// item's rowkey to be pushed is equal with current item
|
|
if (item.iter_idx_ < items_[i].iter_idx_) {
|
|
items_[i+1] = items_[i];
|
|
// the iter_idx_ is smaller, so put the item before current item
|
|
equal_with_next = true;
|
|
} else {
|
|
// the iter_idx_ is bigger, so put the item behind current item
|
|
items_[i].equal_with_next_ = true;
|
|
break;
|
|
}
|
|
} else {
|
|
// the item to be pushed will be inserted behind current item
|
|
break;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
items_[i+1] = item;
|
|
if (equal_with_next) {
|
|
// item to be pushed is equal with next item
|
|
items_[i+1].equal_with_next_ = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
++item_cnt_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::push_top(const T &item)
|
|
{
|
|
return push(item);
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::rebuild()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::top(const T *&item)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (empty()) {
|
|
ret = OB_EMPTY_RESULT;
|
|
STORAGE_LOG(WARN, "The merger is empty", K(ret), K(*this));
|
|
} else {
|
|
item = &items_[0];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename Comparator>
|
|
int ObSimpleRowsMerger<T, Comparator>::pop()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LIB_LOG(WARN, "The merger is not init", K(ret));
|
|
} else if (empty()) {
|
|
ret = OB_EMPTY_RESULT;
|
|
STORAGE_LOG(WARN, "The merger is empty", K(ret), K(*this));
|
|
} else {
|
|
for (int64_t i = 0; i < item_cnt_ - 1; ++i) {
|
|
items_[i] = items_[i+1];
|
|
}
|
|
--item_cnt_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace storage
|
|
} // namespace oceanbase
|
|
|
|
#endif // OCEANBASE_STORAGE_OB_MULTIPLE_ROW_MERGER_
|