[MDS] mds table flush by order
This commit is contained in:
@ -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)
|
||||
|
||||
@ -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_);
|
||||
}
|
||||
|
||||
@ -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));
|
||||
|
||||
302
unittest/storage/multi_data_source/test_mds_table_flusher.cpp
Normal file
302
unittest/storage/multi_data_source/test_mds_table_flusher.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user