356 lines
12 KiB
C++
356 lines
12 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.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#define private public
|
|
#define protected public
|
|
|
|
#include "lib/random/ob_random.h"
|
|
#include "storage/access/ob_index_tree_prefetcher.h"
|
|
#include "storage/access/ob_sstable_row_scanner.h"
|
|
#include "ob_index_block_data_prepare.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace storage;
|
|
using namespace common;
|
|
namespace blocksstable
|
|
{
|
|
class TestSSTableRowScanner : public TestIndexBlockDataPrepare
|
|
{
|
|
public:
|
|
TestSSTableRowScanner();
|
|
virtual ~TestSSTableRowScanner();
|
|
static void SetUpTestCase();
|
|
static void TearDownTestCase();
|
|
|
|
virtual void SetUp();
|
|
virtual void TearDown();
|
|
|
|
void generate_range(const int64_t start, const int64_t end, ObDatumRange &range);
|
|
void test_one_case(
|
|
const ObDatumRange &range,
|
|
const int64_t start,
|
|
const int64_t end,
|
|
const bool is_reverse_scan,
|
|
const int64_t hit_mode);
|
|
void test_border(const bool is_reverse_scan);
|
|
protected:
|
|
enum CacheHitMode
|
|
{
|
|
HIT_ALL = 0,
|
|
HIT_NONE,
|
|
HIT_PART,
|
|
HIT_MAX,
|
|
};
|
|
private:
|
|
ObArenaAllocator allocator_;
|
|
ObDatumRow start_row_;
|
|
ObDatumRow end_row_;
|
|
};
|
|
|
|
TestSSTableRowScanner::TestSSTableRowScanner()
|
|
: TestIndexBlockDataPrepare("Test sstable row scanner")
|
|
{
|
|
}
|
|
|
|
TestSSTableRowScanner::~TestSSTableRowScanner()
|
|
{
|
|
}
|
|
|
|
void TestSSTableRowScanner::SetUpTestCase()
|
|
{
|
|
TestIndexBlockDataPrepare::SetUpTestCase();
|
|
}
|
|
|
|
void TestSSTableRowScanner::TearDownTestCase()
|
|
{
|
|
TestIndexBlockDataPrepare::TearDownTestCase();
|
|
}
|
|
|
|
void TestSSTableRowScanner::SetUp()
|
|
{
|
|
TestIndexBlockDataPrepare::SetUp();
|
|
ASSERT_EQ(OB_SUCCESS, start_row_.init(allocator_, TEST_COLUMN_CNT));
|
|
ASSERT_EQ(OB_SUCCESS, end_row_.init(allocator_, TEST_COLUMN_CNT));
|
|
ObLSID ls_id(ls_id_);
|
|
ObTabletID tablet_id(tablet_id_);
|
|
ObLSHandle ls_handle;
|
|
ObLSService *ls_svr = MTL(ObLSService*);
|
|
ASSERT_EQ(OB_SUCCESS, ls_svr->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD));
|
|
|
|
ASSERT_EQ(OB_SUCCESS, ls_handle.get_ls()->get_tablet(tablet_id, tablet_handle_));
|
|
}
|
|
|
|
void TestSSTableRowScanner::TearDown()
|
|
{
|
|
tablet_handle_.reset();
|
|
TestIndexBlockDataPrepare::TearDown();
|
|
}
|
|
|
|
void TestSSTableRowScanner::generate_range(
|
|
const int64_t start,
|
|
const int64_t end,
|
|
ObDatumRange &range)
|
|
{
|
|
ObDatumRowkey tmp_rowkey;
|
|
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(start, start_row_));
|
|
tmp_rowkey.assign(start_row_.storage_datums_, TEST_ROWKEY_COLUMN_CNT);
|
|
ASSERT_EQ(OB_SUCCESS, tmp_rowkey.deep_copy(range.start_key_, allocator_));
|
|
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(end, end_row_));
|
|
tmp_rowkey.assign(end_row_.storage_datums_, TEST_ROWKEY_COLUMN_CNT);
|
|
ASSERT_EQ(OB_SUCCESS, tmp_rowkey.deep_copy(range.end_key_, allocator_));
|
|
range.border_flag_.set_inclusive_start();
|
|
range.border_flag_.set_inclusive_end();
|
|
}
|
|
|
|
void TestSSTableRowScanner::test_one_case(
|
|
const ObDatumRange &range,
|
|
const int64_t start,
|
|
const int64_t end,
|
|
const bool is_reverse_scan,
|
|
const int64_t hit_mode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObDatumRow row;
|
|
ASSERT_EQ(OB_SUCCESS, row.init(allocator_, TEST_COLUMN_CNT));
|
|
const ObDatumRow *prow = nullptr;
|
|
const ObDatumRow *kv_prow = nullptr;
|
|
ObSSTableRowScanner<> scanner;
|
|
ObSSTableRowScanner<> kv_scanner;
|
|
|
|
if (HIT_PART == hit_mode) {
|
|
const int64_t part_start = start + (end - start) / 3;
|
|
const int64_t part_end = end - (end - start) / 3;
|
|
ObDatumRange part_range;
|
|
ObDatumRow start_row;
|
|
ObDatumRow end_row;
|
|
ObDatumRowkey tmp_rowkey;
|
|
ASSERT_EQ(OB_SUCCESS, start_row.init(allocator_, TEST_COLUMN_CNT));
|
|
ASSERT_EQ(OB_SUCCESS, end_row.init(allocator_, TEST_COLUMN_CNT));
|
|
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(part_start, start_row));
|
|
tmp_rowkey.assign(start_row.storage_datums_, TEST_ROWKEY_COLUMN_CNT);
|
|
ASSERT_EQ(OB_SUCCESS, tmp_rowkey.deep_copy(part_range.start_key_, allocator_));
|
|
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(part_end, end_row));
|
|
tmp_rowkey.assign(end_row.storage_datums_, TEST_ROWKEY_COLUMN_CNT);
|
|
ASSERT_EQ(OB_SUCCESS, tmp_rowkey.deep_copy(part_range.end_key_, allocator_));
|
|
part_range.border_flag_.set_inclusive_start();
|
|
part_range.border_flag_.set_inclusive_end();
|
|
ASSERT_EQ(OB_SUCCESS, scanner.inner_open(
|
|
iter_param_,
|
|
context_,
|
|
&sstable_,
|
|
&part_range));
|
|
ASSERT_EQ(OB_SUCCESS, kv_scanner.inner_open(
|
|
iter_param_,
|
|
context_,
|
|
&ddl_kv_,
|
|
&part_range));
|
|
for (int64_t i = part_start; i <= part_end; ++i) {
|
|
if (i < row_cnt_) {
|
|
ret = scanner.inner_get_next_row(prow);
|
|
ASSERT_EQ(OB_SUCCESS, ret) << "i: " << i << " part_start: " << part_start
|
|
<< " part_end: " << part_end << " prow: " << prow;
|
|
ret = kv_scanner.inner_get_next_row(kv_prow);
|
|
ASSERT_EQ(OB_SUCCESS, ret) << "i: " << i << " part_start: " << part_start
|
|
<< " part_end: " << part_end << " kv_prow: " << kv_prow;
|
|
}
|
|
}
|
|
ASSERT_EQ(OB_ITER_END, scanner.inner_get_next_row(prow));
|
|
ASSERT_EQ(OB_ITER_END, kv_scanner.inner_get_next_row(kv_prow));
|
|
scanner.reuse();
|
|
kv_scanner.reuse();
|
|
}
|
|
|
|
ASSERT_EQ(OB_SUCCESS, scanner.inner_open(
|
|
iter_param_,
|
|
context_,
|
|
&sstable_,
|
|
&range));
|
|
ASSERT_EQ(OB_SUCCESS, kv_scanner.inner_open(
|
|
iter_param_,
|
|
context_,
|
|
&ddl_kv_,
|
|
&range));
|
|
for (int64_t i = start; i <= end; ++i) {
|
|
int64_t index = 0;
|
|
if (is_reverse_scan) {
|
|
ret = row_generate_.get_next_row(end - i + start, row);
|
|
index = end - i + start;
|
|
} else {
|
|
ret = row_generate_.get_next_row(i, row);
|
|
index = i;
|
|
}
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
if (index < row_cnt_) {
|
|
ret = scanner.inner_get_next_row(prow);
|
|
ASSERT_EQ(OB_SUCCESS, ret) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " prow: " << prow;
|
|
ASSERT_TRUE(row == *prow) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " prow: " << prow;
|
|
ret = kv_scanner.inner_get_next_row(kv_prow);
|
|
ASSERT_EQ(OB_SUCCESS, ret) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " kv_prow: " << kv_prow;
|
|
ASSERT_TRUE(row == *kv_prow) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " kv_prow: " << kv_prow;
|
|
}
|
|
}
|
|
ASSERT_EQ(OB_ITER_END, scanner.inner_get_next_row(prow));
|
|
ASSERT_EQ(OB_ITER_END, scanner.inner_get_next_row(prow));
|
|
ASSERT_EQ(OB_ITER_END, kv_scanner.inner_get_next_row(kv_prow));
|
|
ASSERT_EQ(OB_ITER_END, kv_scanner.inner_get_next_row(kv_prow));
|
|
scanner.reuse();
|
|
kv_scanner.reuse();
|
|
|
|
if (HIT_ALL == hit_mode) {
|
|
int64_t index = 0;
|
|
ASSERT_EQ(OB_SUCCESS, scanner.inner_open(
|
|
iter_param_,
|
|
context_,
|
|
&sstable_,
|
|
&range));
|
|
ASSERT_EQ(OB_SUCCESS, kv_scanner.inner_open(
|
|
iter_param_,
|
|
context_,
|
|
&ddl_kv_,
|
|
&range));
|
|
for (int64_t i = start; i <= end; ++i) {
|
|
if (is_reverse_scan) {
|
|
ret = row_generate_.get_next_row(end - i + start, row);
|
|
index = end - i + start;
|
|
} else {
|
|
ret = row_generate_.get_next_row(i, row);
|
|
index = i;
|
|
}
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
if (index < row_cnt_) {
|
|
ret = scanner.inner_get_next_row(prow);
|
|
ASSERT_EQ(OB_SUCCESS, ret) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " prow: " << prow;
|
|
ASSERT_TRUE(row == *prow) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " prow: " << prow;
|
|
ret = kv_scanner.inner_get_next_row(kv_prow);
|
|
ASSERT_EQ(OB_SUCCESS, ret) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " kv_prow: " << kv_prow;
|
|
ASSERT_TRUE(row == *kv_prow) << i << "index: " << index << " start: " << start
|
|
<< " end: " << end << " kv_prow: " << kv_prow;
|
|
}
|
|
}
|
|
ASSERT_EQ(OB_ITER_END, scanner.inner_get_next_row(prow));
|
|
ASSERT_EQ(OB_ITER_END, scanner.inner_get_next_row(prow));
|
|
ASSERT_EQ(OB_ITER_END, kv_scanner.inner_get_next_row(kv_prow));
|
|
ASSERT_EQ(OB_ITER_END, kv_scanner.inner_get_next_row(kv_prow));
|
|
scanner.reuse();
|
|
kv_scanner.reuse();
|
|
}
|
|
}
|
|
|
|
void TestSSTableRowScanner::test_border(const bool is_reverse_scan)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObDatumRange range;
|
|
|
|
// prepare query param
|
|
prepare_query_param(is_reverse_scan, tablet_handle_.get_obj()->get_full_read_info());
|
|
|
|
// full table scan
|
|
range.set_whole_range();
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, 0, row_cnt_ - 1, is_reverse_scan, i);
|
|
}
|
|
|
|
// the first row of sstable
|
|
generate_range(0, 0, range);
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, 0, 0, is_reverse_scan, i);
|
|
}
|
|
|
|
// the first 100 row of sstable
|
|
generate_range(0, 100, range);
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, 0, 100, is_reverse_scan, i);
|
|
}
|
|
|
|
// the last row of sstable
|
|
generate_range(row_cnt_ - 1, row_cnt_ - 1, range);
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, row_cnt_ - 1, row_cnt_ - 1, is_reverse_scan, i);
|
|
}
|
|
|
|
// the last 100 row of sstable
|
|
generate_range(row_cnt_ - 100, row_cnt_ - 1, range);
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, row_cnt_ - 100, row_cnt_ - 1, is_reverse_scan, i);
|
|
}
|
|
|
|
// not exist
|
|
generate_range(row_cnt_, row_cnt_, range);
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, row_cnt_, row_cnt_, is_reverse_scan, i);
|
|
}
|
|
|
|
destroy_query_param();
|
|
}
|
|
|
|
TEST_F(TestSSTableRowScanner, test_border)
|
|
{
|
|
bool is_reverse_scan = false;
|
|
test_border(is_reverse_scan);
|
|
is_reverse_scan = true;
|
|
test_border(is_reverse_scan);
|
|
STORAGE_LOG(INFO, "memory usage", K(lib::get_memory_hold()), K(lib::get_memory_limit()));
|
|
ObMallocAllocator::get_instance()->print_tenant_ctx_memory_usage(500);
|
|
ObMallocAllocator::get_instance()->print_tenant_memory_usage(500);
|
|
ObMallocAllocator::get_instance()->print_tenant_memory_usage(1);
|
|
}
|
|
|
|
TEST_F(TestSSTableRowScanner, test_random)
|
|
{
|
|
ObDatumRange range;
|
|
int64_t start = ObRandom::rand(0, row_cnt_ - 1);
|
|
int64_t end = ObRandom::rand(0, row_cnt_ - 1);
|
|
if (start > end) {
|
|
int64_t temp = start;
|
|
start = end;
|
|
end = temp;
|
|
}
|
|
generate_range(start, end, range);
|
|
|
|
bool is_reverse_scan = false;
|
|
// prepare query param
|
|
prepare_query_param(is_reverse_scan, tablet_handle_.get_obj()->get_full_read_info());
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, start, end, is_reverse_scan, i);
|
|
}
|
|
destroy_query_param();
|
|
|
|
is_reverse_scan = true;
|
|
// prepare query param
|
|
prepare_query_param(is_reverse_scan, tablet_handle_.get_obj()->get_full_read_info());
|
|
for (int64_t i = HIT_ALL; i < HIT_MAX; ++i) {
|
|
test_one_case(range, start, end, is_reverse_scan, i);
|
|
}
|
|
destroy_query_param();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
system("rm -f test_sstable_row_scanner.log*");
|
|
OB_LOGGER.set_file_name("test_sstable_row_scanner.log", true, true);
|
|
oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
|
|
testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|