[MDS] mds table flush by order

This commit is contained in:
obdev
2024-02-07 09:53:02 +00:00
committed by ob-robot
parent 94d4718fe6
commit 10706ab7d4
21 changed files with 878 additions and 175 deletions

View File

@ -53,6 +53,7 @@ storage_unittest(test_mds_node multi_data_source/test_mds_node.cpp)
# storage_unittest(test_mds_unit multi_data_source/test_mds_unit.cpp)
storage_unittest(test_mds_table multi_data_source/test_mds_table.cpp)
storage_unittest(test_mds_table_flush multi_data_source/test_mds_table_flush.cpp)
storage_unittest(test_mds_table_flusher multi_data_source/test_mds_table_flusher.cpp)
storage_unittest(test_mds_dump_kv multi_data_source/test_mds_dump_kv.cpp)
#storage_unittest(test_multiple_merge)
#storage_unittest(test_memtable_multi_version_row_iterator memtable/test_memtable_multi_version_row_iterator.cpp)

View File

@ -376,7 +376,7 @@ void TestMdsTable::test_flush() {
ctx2.on_redo(mock_scn(200));
int idx = 0;
ASSERT_EQ(OB_SUCCESS, mds_table_.flush(mock_scn(300)));// 1. 以300为版本号进行flush动作
ASSERT_EQ(OB_SUCCESS, mds_table_.flush(mock_scn(300), mock_scn(500)));// 1. 以300为版本号进行flush动作
ASSERT_EQ(mock_scn(199), mds_table_.p_mds_table_base_->flushing_scn_);// 2. 实际上以199为版本号进行flush动作
ASSERT_EQ(OB_SUCCESS, mds_table_.for_each_unit_from_small_key_to_big_from_old_node_to_new_to_dump(
[&idx](const MdsDumpKV &kv) -> int {// 2. 转储时扫描mds table
@ -432,7 +432,7 @@ void TestMdsTable::test_multi_key_remove() {
return OB_SUCCESS;
}, is_committed);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(OB_SUCCESS, mds_table_.flush(mock_scn(200)));
ASSERT_EQ(OB_SUCCESS, mds_table_.flush(mock_scn(200), mock_scn(500)));
ASSERT_EQ(OB_SUCCESS, mds_table_.try_recycle(mock_scn(200)));
ret = mds_table_.get_latest<ExampleUserKey, ExampleUserData1>(ExampleUserKey(2), [](const ExampleUserData1 &data){
return OB_SUCCESS;
@ -512,16 +512,16 @@ TEST_F(TestMdsTable, test_recycle) {
int64_t valid_cnt = 0;
ASSERT_EQ(OB_SUCCESS, mds_table_.get_node_cnt(valid_cnt));
ASSERT_EQ(1, valid_cnt);// 此时还有一个19001版本的已提交数据,因为rec_scn没有推上去
ASSERT_EQ(OB_SUCCESS, mds_table_.flush(mock_scn(20000)));
ASSERT_EQ(OB_SUCCESS, mds_table_.flush(mock_scn(20000), mock_scn(40000)));
mds_table_.for_each_unit_from_small_key_to_big_from_old_node_to_new_to_dump([](const MdsDumpKV &){
return OB_SUCCESS;
}, 0, true);
mds_table_.on_flush(mock_scn(20000), OB_SUCCESS);
mds_table_.on_flush(mock_scn(40000), OB_SUCCESS);
share::SCN rec_scn;
ASSERT_EQ(OB_SUCCESS, mds_table_.get_rec_scn(rec_scn));
MDS_LOG(INFO, "print rec scn", K(rec_scn));
ASSERT_EQ(share::SCN::max_scn(), rec_scn);
ASSERT_EQ(OB_SUCCESS, mds_table_.try_recycle(mock_scn(20000)));
ASSERT_EQ(OB_SUCCESS, mds_table_.try_recycle(mock_scn(40000)));
ASSERT_EQ(OB_SUCCESS, mds_table_.get_node_cnt(valid_cnt));
ASSERT_EQ(0, valid_cnt);// 此时还有一个19001版本的已提交数据,因为rec_scn没有推上去
}
@ -541,17 +541,17 @@ TEST_F(TestMdsTable, test_recalculate_flush_scn_op) {
ASSERT_EQ(OB_SUCCESS, mds_table.set(ExampleUserData1(3), ctx3));
ctx3.on_redo(mock_scn(9));
ctx3.on_commit(mock_scn(11), mock_scn(11));
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(4)));
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(4), mock_scn(4)));
ASSERT_EQ(mock_scn(4), mds_table.p_mds_table_base_->flushing_scn_);
mds_table.on_flush(mock_scn(4), OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(5)));// no need do flush, directly advance rec_scn
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(5), mock_scn(5)));// no need do flush, directly advance rec_scn
ASSERT_EQ(false, mds_table.p_mds_table_base_->flushing_scn_.is_valid());
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(6)));// no need do flush, directly advance rec_scn
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(6), mock_scn(6)));// no need do flush, directly advance rec_scn
ASSERT_EQ(false, mds_table.p_mds_table_base_->flushing_scn_.is_valid());
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(7)));
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(7), mock_scn(7)));
ASSERT_EQ(mock_scn(7), mds_table.p_mds_table_base_->flushing_scn_);
mds_table.on_flush(mock_scn(7), OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(8)));
ASSERT_EQ(OB_SUCCESS, mds_table.flush(mock_scn(8), mock_scn(8)));
ASSERT_EQ(false, mds_table.p_mds_table_base_->flushing_scn_.is_valid());
ASSERT_EQ(mock_scn(9), mds_table.p_mds_table_base_->rec_scn_);
}

View File

@ -9,12 +9,13 @@
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "lib/utility/utility.h"
#include "storage/multi_data_source/compile_utility/mds_dummy_key.h"
#define UNITTEST_DEBUG
static bool MDS_FLUSHER_ALLOW_ALLOC = true;
#include <gtest/gtest.h>
#define private public
#define protected public
#include "lib/utility/utility.h"
#include "storage/multi_data_source/compile_utility/mds_dummy_key.h"
#include "share/ob_ls_id.h"
#include "storage/multi_data_source/mds_writer.h"
#include <thread>
@ -37,12 +38,15 @@
#include <numeric>
#include "storage/multi_data_source/runtime_utility/mds_lock.h"
#include "storage/tablet/ob_tablet_meta.h"
#include "storage/multi_data_source/mds_table_mgr.h"
#include "storage/ls/ob_ls.h"
#include "storage/multi_data_source/mds_table_handle.h"
#include "storage/multi_data_source/mds_table_order_flusher.h"
namespace oceanbase {
namespace storage
{
share::SCN MOCK_MAX_CONSEQUENT_CALLBACKED_SCN;
share::SCN MOCK_FLUSHING_SCN;
namespace mds
{
@ -67,7 +71,6 @@ int MdsTableBase::get_ls_max_consequent_callbacked_scn_(share::SCN &max_conseque
int MdsTableBase::merge(const int64_t construct_sequence, const share::SCN &flushing_scn)
{
MOCK_FLUSHING_SCN = flushing_scn;
return OB_SUCCESS;
}
@ -144,7 +147,6 @@ int construct_tested_mds_table(MdsTableHandle &handle) {
}
TEST_F(TestMdsTableFlush, normal_flush) {
MOCK_MAX_CONSEQUENT_CALLBACKED_SCN = mock_scn(125);// 只转储一个node
MdsTableHandle handle;
ASSERT_EQ(OB_SUCCESS, construct_tested_mds_table(handle));
share::SCN rec_scn;
@ -152,7 +154,7 @@ TEST_F(TestMdsTableFlush, normal_flush) {
ASSERT_EQ(mock_scn(50), rec_scn);// 没转储的时候是最小的node的redo scn值
// 第一次转储
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000)));// 因为max_decided_scn较小,所以会用125做flush
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000), mock_scn(125)));// 因为max_decided_scn较小,所以会用125做flush
bool is_flusing = false;
ASSERT_EQ(OB_SUCCESS, handle.is_flushing(is_flusing));// 在flush流程中
ASSERT_EQ(true, is_flusing);
@ -163,14 +165,13 @@ TEST_F(TestMdsTableFlush, normal_flush) {
return OB_SUCCESS;
}, 0, true));
ASSERT_EQ(1, scan_cnt);
handle.on_flush(MOCK_FLUSHING_SCN, OB_SUCCESS);
handle.on_flush(mock_scn(125), OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, handle.get_rec_scn(rec_scn));
OCCAM_LOG(INFO, "print rec scn", K(rec_scn));
ASSERT_EQ(mock_scn(200), rec_scn);
// 第二次转储
MOCK_MAX_CONSEQUENT_CALLBACKED_SCN = mock_scn(140);// 对这个MdsTable没有影响
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000)));
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000), mock_scn(140)));
ASSERT_EQ(OB_SUCCESS, handle.is_flushing(is_flusing));
ASSERT_EQ(false, is_flusing);// 没转储
ASSERT_EQ(OB_SUCCESS, handle.get_rec_scn(rec_scn));
@ -178,8 +179,7 @@ TEST_F(TestMdsTableFlush, normal_flush) {
ASSERT_EQ(mock_scn(200), rec_scn);// 没变化
// 第三次转储
MOCK_MAX_CONSEQUENT_CALLBACKED_SCN = mock_scn(275);// 多转一个node
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000)));
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000), mock_scn(275)));
ASSERT_EQ(OB_SUCCESS, handle.is_flushing(is_flusing));// 在flush流程中
ASSERT_EQ(true, is_flusing);
ASSERT_EQ(mock_scn(249), handle.p_mds_table_base_->flushing_scn_);
@ -189,14 +189,13 @@ TEST_F(TestMdsTableFlush, normal_flush) {
return OB_SUCCESS;
}, 0, true));
ASSERT_EQ(1, scan_cnt);
handle.on_flush(MOCK_FLUSHING_SCN, OB_SUCCESS);
handle.on_flush(mock_scn(249), OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, handle.get_rec_scn(rec_scn));
OCCAM_LOG(INFO, "print rec scn", K(rec_scn));
ASSERT_EQ(mock_scn(250), rec_scn);
// 第四次转储
MOCK_MAX_CONSEQUENT_CALLBACKED_SCN = mock_scn(550);// 都转下去
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000)));
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000), mock_scn(550)));
ASSERT_EQ(OB_SUCCESS, handle.is_flushing(is_flusing));// 在flush流程中
ASSERT_EQ(true, is_flusing);
ASSERT_EQ(mock_scn(499), handle.p_mds_table_base_->flushing_scn_);
@ -206,14 +205,13 @@ TEST_F(TestMdsTableFlush, normal_flush) {
return OB_SUCCESS;
}, 0, true));
ASSERT_EQ(2, scan_cnt);
handle.on_flush(MOCK_FLUSHING_SCN, OB_SUCCESS);
handle.on_flush(mock_scn(499), OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, handle.get_rec_scn(rec_scn));
OCCAM_LOG(INFO, "print rec scn", K(rec_scn));
ASSERT_EQ(mock_scn(500), rec_scn);
// 第五次转储
MOCK_MAX_CONSEQUENT_CALLBACKED_SCN = mock_scn(600);// 对这个MdsTable没有影响
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000)));
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000), mock_scn(600)));
ASSERT_EQ(OB_SUCCESS, handle.is_flushing(is_flusing));
ASSERT_EQ(false, is_flusing);// 没转储
ASSERT_EQ(OB_SUCCESS, handle.get_rec_scn(rec_scn));
@ -221,8 +219,7 @@ TEST_F(TestMdsTableFlush, normal_flush) {
ASSERT_EQ(mock_scn(500), rec_scn);// 没变化
// 第六次转储
MOCK_MAX_CONSEQUENT_CALLBACKED_SCN = mock_scn(590);// 直接被过滤掉了
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000)));
ASSERT_EQ(OB_SUCCESS, handle.flush(mock_scn(1000), mock_scn(590)));
ASSERT_EQ(OB_SUCCESS, handle.is_flushing(is_flusing));
ASSERT_EQ(false, is_flusing);// 没转储
ASSERT_EQ(OB_SUCCESS, handle.get_rec_scn(rec_scn));

View File

@ -0,0 +1,302 @@
/**
* 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 "lib/future/ob_future.h"
#include <algorithm>
#include <chrono>
#include <condition_variable>
#include <thread>
#include <vector>
#include <gtest/gtest.h>
#define UNITTEST_DEBUG
#define private public
#define protected public
#include "storage/multi_data_source/runtime_utility/common_define.h"
#include "storage/multi_data_source/mds_table_base.h"
#include "storage/multi_data_source/mds_table_mgr.h"
#include "storage/ls/ob_ls.h"
#include "storage/multi_data_source/mds_table_handle.h"
#include "storage/multi_data_source/mds_table_order_flusher.h"
using namespace std;
oceanbase::common::ObPromise<void> PROMISE1, PROMISE2;
vector<oceanbase::storage::mds::FlushKey> V_ActualDoFlushKey;
static std::atomic<bool> NEED_ALLOC_FAIL(false);
static std::atomic<bool> NEED_ALLOC_FAIL_AFTER_RESERVE(false);
namespace oceanbase {
namespace logservice
{
int ObLogHandler::get_max_decided_scn(share::SCN &scn)
{
scn = unittest::mock_scn(500);
return OB_SUCCESS;
}
}
namespace storage
{
namespace mds
{
template <>
int MdsTableImpl<UnitTestMdsTable>::flush(share::SCN need_advanced_rec_scn_lower_limit, share::SCN max_decided_scn) {
V_ActualDoFlushKey.push_back({tablet_id_, rec_scn_});
return OB_SUCCESS;
}
void *MdsAllocator::alloc(const int64_t size)
{
void *ptr = ob_malloc(size, "MDS");
ATOMIC_INC(&alloc_times_);
MDS_LOG(DEBUG, "alloc obj", KP(ptr), K(size), K(lbt()));
return ptr;
}
void MdsAllocator::free(void *ptr) {
ATOMIC_INC(&free_times_);
MDS_LOG(DEBUG, "free obj", KP(ptr), K(lbt()));
ob_free(ptr);
}
void *MdsFlusherModulePageAllocator::alloc(const int64_t size, const ObMemAttr &attr) {
void *ret = nullptr;
if (!NEED_ALLOC_FAIL) {
ret = (NULL == allocator_) ? share::mtl_malloc(size, attr) : allocator_->alloc(size, attr);
} else {
MDS_LOG(DEBUG, "mock no memory", K(lbt()));
}
return ret;
}
// template <>
// void MdsTableOrderFlusher<FLUSH_FOR_ALL_SIZE, true>::reserve_memory(int64_t mds_table_total_size_likely) {// it'ok if failed
// int ret = OB_SUCCESS;
// abort();
// constexpr int64_t max_tablet_number = 100 * 10000;//sizeof(100w FlushKey) = 16MB
// int64_t reserve_size = std::min(mds_table_total_size_likely * 2, max_tablet_number);
// if (OB_FAIL(extra_mds_tables_.reserve(reserve_size))) {
// MDS_LOG(WARN, "fail to reserve memory", KR(ret));
// array_err_ = ret;
// }
// if (NEED_ALLOC_FAIL_AFTER_RESERVE) {
// NEED_ALLOC_FAIL = true;
// OCCAM_LOG(INFO, "set PEOMISE1 and wait PROMISE2");
// PROMISE1.set();
// ObFuture<void> future = PROMISE2.get_future();
// future.wait();
// }
// }
}
}
namespace unittest {
using namespace common;
using namespace std;
using namespace storage;
using namespace mds;
using namespace transaction;
static constexpr int64_t TEST_ALL_SIZE = FLUSH_FOR_ALL_SIZE * 10;
class TestMdsTableFlush: public ::testing::Test
{
public:
TestMdsTableFlush() {}
virtual ~TestMdsTableFlush() {}
virtual void SetUp() { V_ActualDoFlushKey.clear(); NEED_ALLOC_FAIL = false; NEED_ALLOC_FAIL_AFTER_RESERVE = false; }
virtual void TearDown() { }
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(TestMdsTableFlush);
};
TEST_F(TestMdsTableFlush, flusher_for_some_order) {
FlusherForSome some;
for (int i = FLUSH_FOR_SOME_SIZE; i > 0; --i) {
some.record_mds_table({ObTabletID(i), mock_scn(i)});
}
for (int i = 0; i < FLUSH_FOR_SOME_SIZE; ++i) {
ASSERT_EQ(some.high_priority_flusher_.high_priority_mds_tables_[i].rec_scn_, mock_scn(i + 1));
}
some.record_mds_table({ObTabletID(999), mock_scn(999)});// 没影响,被扔了
for (int i = 0; i < FLUSH_FOR_SOME_SIZE; ++i) {
ASSERT_EQ(some.high_priority_flusher_.high_priority_mds_tables_[i].rec_scn_, mock_scn(i + 1));
}
some.record_mds_table({ObTabletID(0), mock_scn(0)});// 变成第一个,其余的往后挤
for (int i = 0; i < FLUSH_FOR_SOME_SIZE; ++i) {
ASSERT_EQ(some.high_priority_flusher_.high_priority_mds_tables_[i].rec_scn_, mock_scn(i));
}
some.record_mds_table({ObTabletID(999), mock_scn(FLUSH_FOR_SOME_SIZE - 2)});// 最后一个有两份
for (int i = 0; i < FLUSH_FOR_SOME_SIZE - 1; ++i) {
ASSERT_EQ(some.high_priority_flusher_.high_priority_mds_tables_[i].rec_scn_, mock_scn(i));
}
ASSERT_EQ(some.high_priority_flusher_.high_priority_mds_tables_[FLUSH_FOR_SOME_SIZE - 1].rec_scn_, mock_scn(FLUSH_FOR_SOME_SIZE - 2));
}
TEST_F(TestMdsTableFlush, flusher_for_all_order_with_enough_memory) {
std::vector<FlushKey> v_key;
for (int i = 0; i < TEST_ALL_SIZE; ++i) {
v_key.push_back({ObTabletID(100 + i), mock_scn(100 + i)});
}
std::random_shuffle(v_key.begin(), v_key.end());
ObLS ls;
ObMdsTableMgr mgr;
vector<MdsTableHandle> v;
ASSERT_EQ(mgr.init(&ls), OB_SUCCESS);
// 加入mgr的顺序是乱序的
for (int i = 0; i < v_key.size(); ++i) {
MdsTableHandle mds_table;
ASSERT_EQ(OB_SUCCESS, mds_table.init<UnitTestMdsTable>(MdsAllocator::get_instance(),
v_key[i].tablet_id_,
share::ObLSID(1),
(ObTabletPointer*)0x111,
&mgr));
MdsTableBase *p_mds_table = mds_table.p_mds_table_base_.data_;
p_mds_table->rec_scn_ = v_key[i].rec_scn_;
v.push_back(mds_table);
}
ASSERT_EQ(OB_SUCCESS, mgr.flush(share::SCN::max_scn()));
ASSERT_EQ(TEST_ALL_SIZE, V_ActualDoFlushKey.size());
for (int i = 0; i < V_ActualDoFlushKey.size(); ++i) {
if (V_ActualDoFlushKey[i].rec_scn_ != mock_scn(100 + i)) {
MDS_LOG(INFO, "DEBUG", K(V_ActualDoFlushKey[i].rec_scn_), K(i));
}
ASSERT_EQ(V_ActualDoFlushKey[i].rec_scn_, mock_scn(100 + i));
ASSERT_EQ(V_ActualDoFlushKey[i].tablet_id_, ObTabletID(100 + i));
}
}
TEST_F(TestMdsTableFlush, flusher_for_all_order_with_limitted_memory_reserve_fail) {
NEED_ALLOC_FAIL = true;
std::vector<FlushKey> v_key;
for (int i = 0; i < TEST_ALL_SIZE; ++i) {
v_key.push_back({ObTabletID(100 + i), mock_scn(100 + i)});
}
std::random_shuffle(v_key.begin(), v_key.end());
ObLS ls;
ObMdsTableMgr mgr;
vector<MdsTableHandle> v;
ASSERT_EQ(mgr.init(&ls), OB_SUCCESS);
// 加入mgr的顺序是乱序的
for (int i = 0; i < v_key.size(); ++i) {
MdsTableHandle mds_table;
ASSERT_EQ(OB_SUCCESS, mds_table.init<UnitTestMdsTable>(MdsAllocator::get_instance(),
v_key[i].tablet_id_,
share::ObLSID(1),
(ObTabletPointer*)0x111,
&mgr));
MdsTableBase *p_mds_table = mds_table.p_mds_table_base_.data_;
p_mds_table->rec_scn_ = v_key[i].rec_scn_;
v.push_back(mds_table);
}
ASSERT_EQ(OB_SUCCESS, mgr.flush(share::SCN::max_scn()));
ASSERT_EQ(TEST_ALL_SIZE + FLUSH_FOR_ALL_SIZE, V_ActualDoFlushKey.size());// 只保证最前面的TEST_ALL_SIZE的tablet是有序的,并且rec scn最小
for (int i = 0; i < FLUSH_FOR_ALL_SIZE; ++i) {
if (V_ActualDoFlushKey[i].rec_scn_ != mock_scn(100 + i)) {
MDS_LOG(INFO, "DEBUG", K(V_ActualDoFlushKey[i].rec_scn_), K(i));
}
ASSERT_EQ(V_ActualDoFlushKey[i].rec_scn_, mock_scn(100 + i));
ASSERT_EQ(V_ActualDoFlushKey[i].tablet_id_, ObTabletID(100 + i));
}
}
TEST_F(TestMdsTableFlush, flusher_for_one) {
FlusherForOne one;
for (int i = FLUSH_FOR_SOME_SIZE; i > 0; --i) {
one.record_mds_table({ObTabletID(i), mock_scn(i)});
}
ASSERT_EQ(one.min_key().rec_scn_, mock_scn(1));
}
// // release版本的逻辑重写不生效
// TEST_F(TestMdsTableFlush, flusher_for_all_order_with_limitted_memory_reserve_success_but_push_back_fail) {
// NEED_ALLOC_FAIL_AFTER_RESERVE = true;// 只支持reserve的时候分配一次内存
// const int64_t BIG_TEST_SIZE = 5 * TEST_ALL_SIZE;
// std::vector<FlushKey> v_key;
// for (int i = 0; i < BIG_TEST_SIZE; ++i) {
// v_key.push_back({ObTabletID(100 + i), mock_scn(100 + i)});
// }
// std::random_shuffle(v_key.begin(), v_key.end());
// ObLS ls;
// ObMdsTableMgr mgr;
// vector<MdsTableHandle> v;
// ASSERT_EQ(mgr.init(&ls), OB_SUCCESS);
// // 首先加入第一部分
// for (int i = 0; i < TEST_ALL_SIZE; ++i) {
// MdsTableHandle mds_table;
// ASSERT_EQ(OB_SUCCESS, mds_table.init<UnitTestMdsTable>(MdsAllocator::get_instance(),
// v_key[i].tablet_id_,
// share::ObLSID(1),
// (ObTabletPointer*)0x111,
// &mgr));
// MdsTableBase *p_mds_table = mds_table.p_mds_table_base_.data_;
// p_mds_table->rec_scn_ = v_key[i].rec_scn_;
// v.push_back(mds_table);
// }
// ASSERT_EQ(OB_SUCCESS, PROMISE1.init());
// ASSERT_EQ(OB_SUCCESS, PROMISE2.init());
// // 开启一个新的线程做flush,模拟并发增加mds table的情况(以至于reverse的内存不够用了,过程中发生额外的内存分配,但失败的情况)
// std::thread t1([&](){
// ASSERT_EQ(OB_SUCCESS, mgr.flush(share::SCN::max_scn()));
// });
// {
// OCCAM_LOG(INFO, "wait PEOMISE1");
// ObFuture<void> future = PROMISE1.get_future();
// future.wait();
// }
// {
// for (int i = TEST_ALL_SIZE; i < v_key.size(); ++i) {// 继续再注册99 * TEST_ALL_SIZE的新mds table
// MdsTableHandle mds_table;
// ASSERT_EQ(OB_SUCCESS, mds_table.init<UnitTestMdsTable>(MdsAllocator::get_instance(),
// v_key[i].tablet_id_,
// share::ObLSID(1),
// (ObTabletPointer*)0x111,
// &mgr));
// MdsTableBase *p_mds_table = mds_table.p_mds_table_base_.data_;
// p_mds_table->rec_scn_ = v_key[i].rec_scn_;
// v.push_back(mds_table);
// }
// PROMISE2.set();
// }
// t1.join();
// ASSERT_EQ(BIG_TEST_SIZE + FLUSH_FOR_ALL_SIZE, V_ActualDoFlushKey.size());// 所有的mds table都经历了转储
// for (int i = 0; i < FLUSH_FOR_ALL_SIZE; ++i) {// 但只保证栈上记录的tablet是有序的,并且rec scn最小
// ASSERT_EQ(V_ActualDoFlushKey[i].rec_scn_, mock_scn(100 + i));
// ASSERT_EQ(V_ActualDoFlushKey[i].tablet_id_, ObTabletID(100 + i));
// }
// }
}
}
int main(int argc, char **argv)
{
system("rm -rf test_mds_table_flusher.log");
oceanbase::common::ObLogger &logger = oceanbase::common::ObLogger::get_logger();
logger.set_file_name("test_mds_table_flusher.log", false);
logger.set_log_level(OB_LOG_LEVEL_DEBUG);
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
int64_t alloc_times = oceanbase::storage::mds::MdsAllocator::get_alloc_times();
int64_t free_times = oceanbase::storage::mds::MdsAllocator::get_free_times();
if (alloc_times != free_times) {
MDS_LOG(ERROR, "memory may leak", K(free_times), K(alloc_times));
ret = -1;
} else {
MDS_LOG(INFO, "all memory released", K(free_times), K(alloc_times));
}
return ret;
}