421 lines
13 KiB
C++
421 lines
13 KiB
C++
/**
|
|
* Copyright (c) 2023 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>
|
|
#include <gmock/gmock.h>
|
|
#include <thread>
|
|
|
|
#define USING_LOG_PREFIX STORAGE
|
|
#define protected public
|
|
#define private public
|
|
|
|
#include "mtlenv/mock_tenant_module_env.h"
|
|
#include "storage/ob_tenant_tablet_stat_mgr.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace share;
|
|
using namespace common;
|
|
using namespace storage;
|
|
using namespace compaction;
|
|
|
|
class TestTenantTabletStatMgr : public ::testing::Test
|
|
{
|
|
public:
|
|
TestTenantTabletStatMgr();
|
|
virtual ~TestTenantTabletStatMgr() = default;
|
|
virtual void SetUp() override;
|
|
virtual void TearDown() override;
|
|
static void SetUpTestCase();
|
|
static void TearDownTestCase();
|
|
static void report(ObTenantTabletStatMgr *mgr, const ObTabletStat &stat);
|
|
void batch_report_stat(int64_t report_num);
|
|
|
|
private:
|
|
const uint64_t tenant_id_;
|
|
ObTenantBase tenant_base_;
|
|
ObTenantTabletStatMgr *stat_mgr_;
|
|
};
|
|
|
|
TestTenantTabletStatMgr::TestTenantTabletStatMgr()
|
|
: tenant_id_(1),
|
|
tenant_base_(tenant_id_),
|
|
stat_mgr_(nullptr)
|
|
{
|
|
}
|
|
|
|
void TestTenantTabletStatMgr::SetUpTestCase()
|
|
{
|
|
EXPECT_EQ(OB_SUCCESS, MockTenantModuleEnv::get_instance().init());
|
|
}
|
|
|
|
void TestTenantTabletStatMgr::TearDownTestCase()
|
|
{
|
|
MockTenantModuleEnv::get_instance().destroy();
|
|
}
|
|
|
|
void TestTenantTabletStatMgr::SetUp()
|
|
{
|
|
ASSERT_TRUE(MockTenantModuleEnv::get_instance().is_inited());
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObTenantEnv::set_tenant(&tenant_base_);
|
|
stat_mgr_ = OB_NEW(ObTenantTabletStatMgr, ObModIds::TEST);
|
|
ret = stat_mgr_->init(tenant_id_);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
tenant_base_.set(stat_mgr_);
|
|
|
|
ObTenantEnv::set_tenant(&tenant_base_);
|
|
ASSERT_EQ(OB_SUCCESS, tenant_base_.init());
|
|
ASSERT_EQ(tenant_id_, MTL_ID());
|
|
ASSERT_EQ(stat_mgr_, MTL(ObTenantTabletStatMgr *));
|
|
}
|
|
|
|
void TestTenantTabletStatMgr::TearDown()
|
|
{
|
|
stat_mgr_->destroy();
|
|
ObTenantEnv::set_tenant(nullptr);
|
|
}
|
|
|
|
void TestTenantTabletStatMgr::report(ObTenantTabletStatMgr *mgr, const ObTabletStat &stat)
|
|
{
|
|
ASSERT_TRUE(NULL != mgr);
|
|
ASSERT_TRUE(stat.is_valid());
|
|
bool report_succ = false;
|
|
ASSERT_EQ(OB_SUCCESS, mgr->report_stat(stat, report_succ));
|
|
}
|
|
|
|
void TestTenantTabletStatMgr::batch_report_stat(int64_t report_num)
|
|
{
|
|
ASSERT_TRUE(NULL != stat_mgr_);
|
|
ASSERT_EQ(true, stat_mgr_->is_inited_);
|
|
|
|
for (int64_t i = 0; i < report_num; ++i) {
|
|
ObTabletStat curr_stat;
|
|
curr_stat.ls_id_ = 1;
|
|
curr_stat.tablet_id_ = 300001 + i;
|
|
curr_stat.query_cnt_ = 100 * (i + 1);
|
|
curr_stat.scan_physical_row_cnt_ = 10000 + i;
|
|
|
|
std::thread sub_report_thread(report, stat_mgr_, curr_stat);
|
|
if (sub_report_thread.joinable()) {
|
|
sub_report_thread.join();
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace unittest
|
|
{
|
|
TEST_F(TestTenantTabletStatMgr, basic)
|
|
{
|
|
EXPECT_EQ(OB_SYS_TENANT_ID, MTL_ID());
|
|
ObTenantTabletStatMgr *stat_mgr = MTL(ObTenantTabletStatMgr *);
|
|
ASSERT_TRUE(NULL != stat_mgr);
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, basic_tablet_stat_bucket)
|
|
{
|
|
ObTabletStat tablet_stat;
|
|
tablet_stat.ls_id_ = 1;
|
|
tablet_stat.tablet_id_ = 1;
|
|
tablet_stat.query_cnt_ = 100;
|
|
tablet_stat.scan_logical_row_cnt_ = 100;
|
|
tablet_stat.scan_physical_row_cnt_ = 100;
|
|
|
|
{
|
|
uint32_t step = 1;
|
|
ObTabletStatBucket<8> bucket(step);
|
|
ObTabletStat retired_stat;
|
|
bool has_retired = false;
|
|
for (int64_t i = 0; i < 8; ++i) {
|
|
ASSERT_EQ(i, bucket.head_idx_);
|
|
ASSERT_EQ(7 + i, bucket.curr_idx_);
|
|
bucket.add(tablet_stat);
|
|
ASSERT_EQ(100, bucket.units_[bucket.get_idx(7 + i)].query_cnt_);
|
|
bucket.refresh(retired_stat, has_retired);
|
|
ASSERT_EQ(true, has_retired);
|
|
}
|
|
bucket.refresh(retired_stat, has_retired);
|
|
ASSERT_EQ(100, retired_stat.scan_logical_row_cnt_);
|
|
}
|
|
|
|
{
|
|
uint32_t step = 16;
|
|
ObTabletStatBucket<4> bucket(step);
|
|
ObTabletStat retired_stat;
|
|
bool has_retired = false;
|
|
for (int64_t i = 0; i < 64; ++i) {
|
|
ASSERT_EQ(i / step, bucket.head_idx_);
|
|
ASSERT_EQ(3 + i / step, bucket.curr_idx_);
|
|
bucket.add(tablet_stat);
|
|
bucket.refresh(retired_stat, has_retired);
|
|
if (has_retired) {
|
|
ASSERT_EQ(0, bucket.units_[bucket.get_idx(bucket.curr_idx_)].query_cnt_);
|
|
}
|
|
}
|
|
|
|
ASSERT_TRUE(has_retired);
|
|
ASSERT_EQ(1600, retired_stat.scan_logical_row_cnt_);
|
|
}
|
|
|
|
{
|
|
uint32_t step = 32;
|
|
ObTabletStatBucket<4> bucket(step);
|
|
ObTabletStat retired_stat;
|
|
bool has_retired = false;
|
|
for (int64_t i = 0; i < 128; ++i) {
|
|
ASSERT_EQ(i / step, bucket.head_idx_);
|
|
ASSERT_EQ(3 + i / step, bucket.curr_idx_);
|
|
bucket.add(tablet_stat);
|
|
bucket.refresh(retired_stat, has_retired);
|
|
if (has_retired) {
|
|
ASSERT_EQ(0, bucket.units_[bucket.get_idx(bucket.curr_idx_)].query_cnt_);
|
|
}
|
|
}
|
|
ASSERT_TRUE(has_retired);
|
|
ASSERT_EQ(3200, retired_stat.scan_logical_row_cnt_);
|
|
}
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, basic_tablet_stream)
|
|
{
|
|
ObTabletStat tablet_stat;
|
|
tablet_stat.ls_id_ = 1;
|
|
tablet_stat.tablet_id_ = 200123;
|
|
tablet_stat.query_cnt_ = 100;
|
|
tablet_stat.scan_logical_row_cnt_ = 1000000;
|
|
tablet_stat.scan_physical_row_cnt_ = 1000000;
|
|
|
|
ObTabletStream stream;
|
|
auto &curr_buckets = stream.curr_buckets_;
|
|
auto &latest_buckets = stream.latest_buckets_;
|
|
auto &past_buckets = stream.past_buckets_;
|
|
|
|
for (int64_t i = 0; i < ObTabletStream::CURR_BUCKET_CNT * ObTabletStream::CURR_BUCKET_STEP; ++i) {
|
|
stream.add_stat(tablet_stat);
|
|
stream.refresh();
|
|
}
|
|
ASSERT_EQ(8, latest_buckets.refresh_cnt_);
|
|
// retired from curr_buckets
|
|
ASSERT_EQ(100, latest_buckets.units_[latest_buckets.get_idx(latest_buckets.curr_idx_)].query_cnt_);
|
|
|
|
for (int64_t i = 0; i < ObTabletStream::LATEST_BUCKET_CNT * ObTabletStream::LATEST_BUCKET_STEP; ++i) {
|
|
stream.add_stat(tablet_stat);
|
|
stream.refresh();
|
|
}
|
|
ASSERT_EQ(72, latest_buckets.refresh_cnt_);
|
|
ASSERT_EQ(800, latest_buckets.units_[latest_buckets.get_idx(latest_buckets.curr_idx_)].query_cnt_);
|
|
ASSERT_EQ(72, past_buckets.refresh_cnt_);
|
|
ASSERT_EQ(0, past_buckets.units_[past_buckets.get_idx(past_buckets.curr_idx_)].query_cnt_);
|
|
|
|
for (int64_t i = 0; i < ObTabletStream::CURR_BUCKET_CNT * ObTabletStream::CURR_BUCKET_STEP; ++i) {
|
|
stream.add_stat(tablet_stat);
|
|
stream.refresh();
|
|
}
|
|
ASSERT_EQ(80, latest_buckets.refresh_cnt_);
|
|
ASSERT_EQ(80, past_buckets.refresh_cnt_);
|
|
ASSERT_EQ(1600, past_buckets.units_[past_buckets.get_idx(past_buckets.curr_idx_)].query_cnt_);
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, get_all_tablet_stat)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObTabletStat tablet_stat;
|
|
tablet_stat.ls_id_ = 1;
|
|
tablet_stat.tablet_id_ = 1;
|
|
tablet_stat.query_cnt_ = 100;
|
|
tablet_stat.scan_logical_row_cnt_ = 100;
|
|
tablet_stat.scan_physical_row_cnt_ = 100;
|
|
|
|
ObTabletStream stream;
|
|
auto &curr_buckets = stream.curr_buckets_;
|
|
auto &latest_buckets = stream.latest_buckets_;
|
|
auto &past_buckets = stream.past_buckets_;
|
|
ObArray<ObTabletStat> tablet_stats;
|
|
|
|
int64_t curr_bucket_size = curr_buckets.count();
|
|
for (int64_t i = 0; i < curr_bucket_size; ++i) {
|
|
curr_buckets.units_[i] += tablet_stat;
|
|
}
|
|
ret = stream.get_bucket_tablet_stat<ObTabletStream::CURR_BUCKET_CNT>(curr_buckets, tablet_stats);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE(curr_bucket_size == tablet_stats.count());
|
|
|
|
int64_t latest_bucket_size = latest_buckets.count();
|
|
for (int64_t i = 0; i < latest_bucket_size; ++i) {
|
|
latest_buckets.units_[i] += tablet_stat;
|
|
}
|
|
ret = stream.get_bucket_tablet_stat(stream.latest_buckets_, tablet_stats);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE((curr_bucket_size + latest_bucket_size) == tablet_stats.count());
|
|
|
|
int64_t past_bucket_size = past_buckets.count();
|
|
for (int64_t i = 0; i < past_bucket_size; ++i) {
|
|
past_buckets.units_[i] += tablet_stat;
|
|
}
|
|
ret = stream.get_bucket_tablet_stat(stream.past_buckets_, tablet_stats);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE((curr_bucket_size + latest_bucket_size + past_bucket_size) == tablet_stats.count());
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, basic_stream_pool)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t max_free_list_num = 500;
|
|
const int64_t up_limit_node_num = 1000;
|
|
ObTabletStreamPool pool;
|
|
|
|
ret = pool.init(max_free_list_num, up_limit_node_num);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
|
|
int64_t free_num = pool.get_free_num();
|
|
ASSERT_EQ(max_free_list_num, free_num);
|
|
|
|
ObTabletStreamNode *fixed_node = nullptr;
|
|
bool is_retired = false;
|
|
ret = pool.alloc(fixed_node, is_retired);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE(NULL != fixed_node);
|
|
ASSERT_EQ(storage::ObTabletStreamPool::NodeAllocType::FIXED_ALLOC, fixed_node->flag_);
|
|
ASSERT_EQ(max_free_list_num - 1, pool.get_free_num());
|
|
pool.free(fixed_node);
|
|
fixed_node = nullptr;
|
|
ASSERT_EQ(max_free_list_num, pool.get_free_num());
|
|
|
|
common::ObSEArray<ObTabletStreamNode *, 500> free_nodes;
|
|
for (int64_t i = 0; i < max_free_list_num; ++i) {
|
|
ObTabletStreamNode *free_node = nullptr;
|
|
ret = pool.alloc(free_node, is_retired);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE(NULL != free_node);
|
|
ASSERT_EQ(storage::ObTabletStreamPool::NodeAllocType::FIXED_ALLOC, free_node->flag_);
|
|
ret = free_nodes.push_back(free_node);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
}
|
|
ASSERT_EQ(0, pool.get_free_num());
|
|
|
|
ObTabletStreamNode *dynamic_node = nullptr;
|
|
ret = pool.alloc(dynamic_node, is_retired);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE(NULL != dynamic_node);
|
|
ASSERT_EQ(storage::ObTabletStreamPool::NodeAllocType::DYNAMIC_ALLOC, dynamic_node->flag_);
|
|
pool.free(dynamic_node);
|
|
dynamic_node = nullptr;
|
|
ASSERT_EQ(0, pool.get_free_num());
|
|
|
|
for (int64_t i = 0; i < free_nodes.count(); ++i) {
|
|
ObTabletStreamNode *node = free_nodes.at(i);
|
|
ASSERT_TRUE(NULL != node);
|
|
pool.free(node);
|
|
ASSERT_EQ(i + 1, pool.get_free_num());
|
|
}
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, check_fetch_node)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t max_free_list_num = 500;
|
|
const int64_t up_limit_node_num = 500;
|
|
ObTabletStreamPool pool;
|
|
common::ObDList<ObTabletStreamNode> lru_list_;
|
|
|
|
ret = pool.init(max_free_list_num, up_limit_node_num);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
|
|
int64_t free_num = pool.get_free_num();
|
|
ASSERT_EQ(max_free_list_num, free_num);
|
|
|
|
ObTabletStreamNode *first_node = nullptr;
|
|
for (int64_t i = 0; i < max_free_list_num; ++i) {
|
|
ObTabletStreamNode *curr_node = nullptr;
|
|
ret = pool.free_list_.pop(curr_node);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_TRUE(NULL == curr_node->prev_);
|
|
ASSERT_TRUE(NULL == curr_node->next_);
|
|
|
|
ASSERT_EQ(true, lru_list_.add_first(curr_node));
|
|
first_node = (NULL == first_node) ? curr_node : first_node;
|
|
}
|
|
|
|
ObTabletStreamNode *last_node = nullptr;
|
|
for (int64_t i = 0; i < max_free_list_num; ++i) {
|
|
last_node = lru_list_.get_last();
|
|
ASSERT_EQ(true, lru_list_.move_to_first(last_node));
|
|
ret = pool.free_list_.push(last_node);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
}
|
|
|
|
last_node = lru_list_.get_last();
|
|
ASSERT_TRUE(last_node == first_node);
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, basic_tablet_stat_mgr)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
EXPECT_EQ(OB_SYS_TENANT_ID, MTL_ID());
|
|
ObTenantTabletStatMgr *stat_mgr = MTL(ObTenantTabletStatMgr *);
|
|
ASSERT_TRUE(NULL != stat_mgr);
|
|
|
|
ObTabletStat tablet_stat;
|
|
tablet_stat.ls_id_ = 1;
|
|
tablet_stat.tablet_id_ = 200123;
|
|
tablet_stat.query_cnt_ = 100;
|
|
tablet_stat.scan_logical_row_cnt_ = 100000;
|
|
tablet_stat.scan_physical_row_cnt_ = 1000000;
|
|
|
|
bool report_succ = false;
|
|
ret = stat_mgr_->report_stat(tablet_stat, report_succ);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
stat_mgr_->process_stats();
|
|
|
|
ObTabletStat res;
|
|
share::ObLSID ls_id(1);
|
|
common::ObTabletID tablet_id(200123);
|
|
ret = stat_mgr_->get_latest_tablet_stat(ls_id, tablet_id, res);
|
|
ASSERT_EQ(OB_SUCCESS, ret);
|
|
ASSERT_EQ(100, res.query_cnt_);
|
|
}
|
|
|
|
TEST_F(TestTenantTabletStatMgr, multi_report_tablet_stat)
|
|
{
|
|
EXPECT_EQ(OB_SYS_TENANT_ID, MTL_ID());
|
|
ObTenantTabletStatMgr *stat_mgr = MTL(ObTenantTabletStatMgr *);
|
|
ASSERT_TRUE(NULL != stat_mgr);
|
|
ASSERT_TRUE(stat_mgr->is_inited_);
|
|
|
|
int64_t report_num = 10;
|
|
batch_report_stat(report_num);
|
|
stat_mgr_->process_stats();
|
|
|
|
int64_t report_cnt = 0;
|
|
ObTenantTabletStatMgr::TabletStreamMap::iterator iter = stat_mgr_->stream_map_.begin();
|
|
for ( ; iter != stat_mgr_->stream_map_.end(); ++iter) {
|
|
++report_cnt;
|
|
}
|
|
ASSERT_TRUE(report_cnt > 5);
|
|
}
|
|
|
|
} // end unittest
|
|
} // end oceanbase
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
system("rm -f test_tenant_tablet_stat_mgr.log*");
|
|
OB_LOGGER.set_file_name("test_tenant_tablet_stat_mgr.log", true);
|
|
OB_LOGGER.set_log_level("INFO");
|
|
OB_LOGGER.set_max_file_size(256*1024*1024);
|
|
return RUN_ALL_TESTS();
|
|
}
|