Files
oceanbase/mittest/mtlenv/tablelock/test_mem_ctx_table_lock.cpp
obdev b2607a0ccf [FEAT MERGE] ddl parallel truncate table
Co-authored-by: obdev <obdev@oceanbase.com>
Co-authored-by: obdev <obdev@oceanbase.com>
Co-authored-by: obdev <obdev@oceanbase.com>
Co-authored-by: obdev <obdev@oceanbase.com>
Co-authored-by: obdev <obdev@oceanbase.com>
2023-01-28 13:37:56 +08:00

489 lines
19 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.
*/
#define USING_LOG_PREFIX TABLELOCK
#include <gtest/gtest.h>
#define protected public
#define private public
#include "lib/allocator/page_arena.h"
#include "storage/ls/ob_freezer.h"
#include "storage/meta_mem/ob_tenant_meta_mem_mgr.h"
#include "storage/tablelock/ob_lock_memtable.h"
#include "storage/tablelock/ob_mem_ctx_table_lock.h"
#include "table_lock_common_env.h"
namespace oceanbase
{
using namespace common;
using namespace share;
using namespace storage;
namespace transaction
{
namespace tablelock
{
int ObLockMemtable::update_lock_status(const ObTableLockOp &op_info,
const share::SCN &commit_version,
const share::SCN &commit_scn,
const ObTableLockOpStatus status)
{
UNUSEDx(op_info, commit_version, commit_scn, status);
return OB_SUCCESS;
}
class TestMemCtxTableLock : public ::testing::Test
{
public:
TestMemCtxTableLock()
: ls_id_(1),
fake_t3m_(common::OB_SERVER_TENANT_ID),
mem_ctx_(allocator_)
{
LOG_INFO("construct TestMemCtxTableLock");
}
~TestMemCtxTableLock() {}
static void SetUpTestCase();
static void TearDownTestCase();
virtual void SetUp() override
{
create_memtable();
init_mem_ctx();
LOG_INFO("set up success");
}
virtual void TearDown() override
{
LOG_INFO("tear down success");
}
public:
void create_memtable()
{
ObITable::TableKey table_key;
table_key.table_type_ = ObITable::LOCK_MEMTABLE;
table_key.tablet_id_ = LS_LOCK_TABLET;
table_key.scn_range_.start_scn_.convert_for_gts(1); // fake
table_key.scn_range_.end_scn_.convert_for_gts(2); // fake
ASSERT_EQ(OB_SUCCESS, memtable_.init(table_key, ls_id_, &freezer_));
ASSERT_EQ(OB_SUCCESS, handle_.set_table(&memtable_, &fake_t3m_, ObITable::LOCK_MEMTABLE));
}
void init_mem_ctx()
{
ASSERT_EQ(OB_SUCCESS, mem_ctx_.init(handle_));
}
private:
ObLSID ls_id_;
ObLockMemtable memtable_;
ObTableHandleV2 handle_;
ObTenantMetaMemMgr fake_t3m_;
ObFreezer freezer_;
ObLockMemCtx mem_ctx_;
ObArenaAllocator allocator_;
};
void TestMemCtxTableLock::SetUpTestCase()
{
LOG_INFO("SetUpTestCase");
init_default_lock_test_value();
}
void TestMemCtxTableLock::TearDownTestCase()
{
LOG_INFO("TearDownTestCase");
}
TEST_F(TestMemCtxTableLock, add_lock_record)
{
LOG_INFO("TestMemCtxTableLock::add_lock_record");
int ret = OB_SUCCESS;
bool lock_exist = false;
unsigned char lock_mode_in_same_trans = 0x0;
ObMemCtxLockOpLinkNode *lock_op_node = nullptr;
// 1. IN TRANS LOCK
// 1.1 add lock record
LOG_INFO("TestMemCtxTableLock::add_lock_record 1.1");
ret = mem_ctx_.add_lock_record(DEFAULT_IN_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
// 1.2 check lock exist
LOG_INFO("TestMemCtxTableLock::add_lock_record 1.2");
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, true);
// 2. OUT TRANS LOCK
// 2.1 add lock redord
LOG_INFO("TestMemCtxTableLock::add_lock_record 2.1");
ret = mem_ctx_.add_lock_record(DEFAULT_OUT_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
// 2.2 check lock exist
LOG_INFO("TestMemCtxTableLock::add_lock_record 2.2");
ret = mem_ctx_.check_lock_exist(DEFAULT_OUT_TRANS_LOCK_OP.lock_id_,
DEFAULT_OUT_TRANS_LOCK_OP.owner_id_,
DEFAULT_OUT_TRANS_LOCK_OP.lock_mode_,
DEFAULT_OUT_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, true);
// 3. REMOVE CHECK
// 3.1 in trans lock remove test
LOG_INFO("TestMemCtxTableLock::add_lock_record 3.1");
mem_ctx_.remove_lock_record(DEFAULT_IN_TRANS_LOCK_OP);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
// 3.2 out trans lock remove test
LOG_INFO("TestMemCtxTableLock::add_lock_record 3.2");
mem_ctx_.remove_lock_record(DEFAULT_OUT_TRANS_LOCK_OP);
ret = mem_ctx_.check_lock_exist(DEFAULT_OUT_TRANS_LOCK_OP.lock_id_,
DEFAULT_OUT_TRANS_LOCK_OP.owner_id_,
DEFAULT_OUT_TRANS_LOCK_OP.lock_mode_,
DEFAULT_OUT_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
// 4 REMOVE WITH PTR
// 4.1 add lock record
LOG_INFO("TestMemCtxTableLock::add_lock_record 4.1");
ret = mem_ctx_.add_lock_record(DEFAULT_IN_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, true);
// 4.2 remove lock record
LOG_INFO("TestMemCtxTableLock::add_lock_record 4.2");
mem_ctx_.remove_lock_record(lock_op_node);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
}
TEST_F(TestMemCtxTableLock, clear_table_lock)
{
LOG_INFO("TestMemCtxTableLock::clear_table_lock");
int ret = OB_SUCCESS;
bool lock_exist = false;
unsigned char lock_mode_in_same_trans = 0x0;
ObMemCtxLockOpLinkNode *lock_op_node = nullptr;
bool is_committed = false;
share::SCN commit_version;
share::SCN commit_scn;
commit_version.set_min();
commit_scn.set_min();
// 1 EMPTY CLEAR
LOG_INFO("TestMemCtxTableLock::clear_table_lock 1");
ret = mem_ctx_.clear_table_lock(is_committed, commit_version, commit_scn);
ASSERT_EQ(OB_SUCCESS, ret);
// 2 COMMIT CLEAR
is_committed = true;
commit_version = share::SCN::plus(share::SCN::min_scn(), 1);
// 2.1 in trans lock record
LOG_INFO("TestMemCtxTableLock::clear_table_lock 2.1");
ret = mem_ctx_.add_lock_record(DEFAULT_IN_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.clear_table_lock(is_committed, commit_version, commit_scn);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
// 2.2 out trans lock record
LOG_INFO("TestMemCtxTableLock::clear_table_lock 2.2");
ret = mem_ctx_.add_lock_record(DEFAULT_OUT_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.clear_table_lock(is_committed, commit_version, commit_scn);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.check_lock_exist(DEFAULT_OUT_TRANS_LOCK_OP.lock_id_,
DEFAULT_OUT_TRANS_LOCK_OP.owner_id_,
DEFAULT_OUT_TRANS_LOCK_OP.lock_mode_,
DEFAULT_OUT_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
// 2.3 out trans unlock record
LOG_INFO("TestMemCtxTableLock::clear_table_lock 2.3");
ret = mem_ctx_.add_lock_record(DEFAULT_OUT_TRANS_UNLOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.clear_table_lock(is_committed, commit_version, commit_scn);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.check_lock_exist(DEFAULT_OUT_TRANS_UNLOCK_OP.lock_id_,
DEFAULT_OUT_TRANS_UNLOCK_OP.owner_id_,
DEFAULT_OUT_TRANS_UNLOCK_OP.lock_mode_,
DEFAULT_OUT_TRANS_UNLOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
// 3 ABORT CLEAR
is_committed = false;
LOG_INFO("TestMemCtxTableLock::clear_table_lock 3.1");
ret = mem_ctx_.add_lock_record(DEFAULT_IN_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.clear_table_lock(is_committed, commit_version, commit_scn);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
}
TEST_F(TestMemCtxTableLock, rollback_table_lock)
{
LOG_INFO("TestMemCtxTableLock::rollback_table_lock");
int ret = OB_SUCCESS;
bool lock_exist = false;
ObMemCtxLockOpLinkNode *lock_op_node = nullptr;
unsigned char lock_mode_in_same_trans = 0x0;
// 1.1 add lock record
LOG_INFO("TestMemCtxTableLock::rollback_table_lock 1.1");
ObTableLockOp lock_op1 = DEFAULT_IN_TRANS_LOCK_OP;
lock_op1.lock_seq_no_ = 1;
ret = mem_ctx_.add_lock_record(lock_op1,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ObTableLockOp lock_op2 = DEFAULT_OUT_TRANS_LOCK_OP;
lock_op2.lock_seq_no_ = 2;
ret = mem_ctx_.add_lock_record(lock_op2,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
// 1.2 check exist
LOG_INFO("TestMemCtxTableLock::rollback_table_lock 1.2");
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, true);
ret = mem_ctx_.check_lock_exist(DEFAULT_OUT_TRANS_LOCK_OP.lock_id_,
DEFAULT_OUT_TRANS_LOCK_OP.owner_id_,
DEFAULT_OUT_TRANS_LOCK_OP.lock_mode_,
DEFAULT_OUT_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, true);
// 1.3 rollback
LOG_INFO("TestMemCtxTableLock::rollback_table_lock 1.3");
int64_t rollback_to_seq_no = 1;
ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, true);
ret = mem_ctx_.check_lock_exist(DEFAULT_OUT_TRANS_LOCK_OP.lock_id_,
DEFAULT_OUT_TRANS_LOCK_OP.owner_id_,
DEFAULT_OUT_TRANS_LOCK_OP.lock_mode_,
DEFAULT_OUT_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
// 1.4 rollback again
LOG_INFO("TestMemCtxTableLock::rollback_table_lock 1.4");
rollback_to_seq_no = 0;
ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
}
TEST_F(TestMemCtxTableLock, check_lock_need_replay)
{
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay");
unsigned char lock_mode_in_same_trans = 0x0;
int ret = OB_SUCCESS;
bool lock_exist = false;
share::SCN scn;
scn.set_min();
bool need_replay = false;
ObMemCtxLockOpLinkNode *lock_op_node = nullptr;
// 1.1 empty check.
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.1");
ret = mem_ctx_.check_lock_need_replay(scn,
DEFAULT_IN_TRANS_LOCK_OP,
need_replay);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(need_replay, true);
// 1.2 add a lock record
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.2");
ret = mem_ctx_.add_lock_record(DEFAULT_IN_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
// 1.3 not need replay because the lock op exist.
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.3");
ret = mem_ctx_.check_lock_need_replay(scn,
DEFAULT_IN_TRANS_LOCK_OP,
need_replay);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(need_replay, false);
// 1.4 need replay because of lock op no exist.
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.4");
ret = mem_ctx_.check_lock_need_replay(scn,
DEFAULT_OUT_TRANS_LOCK_OP,
need_replay);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(need_replay, true);
// 1.5 can not replay because of log ts too small
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.5");
scn = share::SCN::plus(share::SCN::min_scn(), 2);
mem_ctx_.max_durable_scn_ = scn;
scn = share::SCN::plus(share::SCN::min_scn(), 1);
ret = mem_ctx_.check_lock_need_replay(scn,
DEFAULT_OUT_TRANS_LOCK_OP,
need_replay);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(need_replay, false);
// 1.6 clear the lock op
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.6");
mem_ctx_.remove_lock_record(lock_op_node);
ret = mem_ctx_.check_lock_exist(DEFAULT_IN_TRANS_LOCK_OP.lock_id_,
DEFAULT_IN_TRANS_LOCK_OP.owner_id_,
DEFAULT_IN_TRANS_LOCK_OP.lock_mode_,
DEFAULT_IN_TRANS_LOCK_OP.op_type_,
lock_exist,
lock_mode_in_same_trans);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(lock_exist, false);
}
TEST_F(TestMemCtxTableLock, get_table_lock_store_info)
{
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay");
int ret = OB_SUCCESS;
bool lock_exist = false;
ObMemCtxLockOpLinkNode *lock_op_node = nullptr;
ObTableLockInfo table_lock_info;
int64_t op_count = 0;
share::SCN scn;
scn.set_min();
// 1 CHECK NOT LOGGED LOCK
// 1.1 add in trans lock
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 1.1");
ret = mem_ctx_.add_lock_record(DEFAULT_IN_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.get_table_lock_store_info(table_lock_info);
ASSERT_EQ(OB_SUCCESS, ret);
op_count = table_lock_info.table_lock_ops_.count();
ASSERT_EQ(0, op_count);
// 2 CHECK LOGGED LOCK
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 2.1");
scn.set_base();
mem_ctx_.set_log_synced(lock_op_node, scn);
ret = mem_ctx_.get_table_lock_store_info(table_lock_info);
ASSERT_EQ(OB_SUCCESS, ret);
op_count = table_lock_info.table_lock_ops_.count();
ASSERT_EQ(1, op_count);
ASSERT_EQ(scn, table_lock_info.max_durable_scn_);
// 3 CHECK LOGGED WITH NOT LOGGED
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 3.1");
table_lock_info.reset();
ret = mem_ctx_.add_lock_record(DEFAULT_OUT_TRANS_LOCK_OP,
lock_op_node);
ASSERT_EQ(OB_SUCCESS, ret);
ret = mem_ctx_.get_table_lock_store_info(table_lock_info);
ASSERT_EQ(OB_SUCCESS, ret);
op_count = table_lock_info.table_lock_ops_.count();
ASSERT_EQ(1, op_count);
ASSERT_EQ(scn, table_lock_info.max_durable_scn_);
// 4 CHECK TWO LOGGED
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 4.1");
table_lock_info.reset();
scn = share::SCN::plus(share::SCN::min_scn(), 2);
mem_ctx_.set_log_synced(lock_op_node, scn);
ret = mem_ctx_.get_table_lock_store_info(table_lock_info);
ASSERT_EQ(OB_SUCCESS, ret);
op_count = table_lock_info.table_lock_ops_.count();
ASSERT_EQ(2, op_count);
ASSERT_EQ(scn, table_lock_info.max_durable_scn_);
// 5 CLEAN TEST
LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 5.1");
mem_ctx_.remove_lock_record(DEFAULT_IN_TRANS_LOCK_OP);
mem_ctx_.remove_lock_record(DEFAULT_OUT_TRANS_LOCK_OP);
table_lock_info.reset();
ret = mem_ctx_.get_table_lock_store_info(table_lock_info);
ASSERT_EQ(OB_SUCCESS, ret);
op_count = table_lock_info.table_lock_ops_.count();
ASSERT_EQ(0, op_count);
}
} // tablelock
} // transaction
} // oceanbase
int main(int argc, char **argv)
{
system("rm -f test_mem_ctx_table_lock.log*");
oceanbase::common::ObLogger::get_logger().set_file_name("test_mem_ctx_table_lock.log", true);
oceanbase::common::ObLogger::get_logger().set_log_level("DEBUG");
oceanbase::common::ObLogger::get_logger().set_enable_async_log(false);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}