// owner: cxf262476 // owner group: transaction /** * 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 #define protected public #define private public #include "storage/ls/ob_freezer.h" #include "storage/meta_mem/ob_tenant_meta_mem_mgr.h" #include "storage/tablelock/ob_lock_memtable.h" #include "table_lock_common_env.h" #include "storage/memtable/ob_memtable_context.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_(fake_memtable_ctx_) { 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, fake_memtable_ctx_.init(common::OB_SERVER_TENANT_ID)); ASSERT_EQ(OB_SUCCESS, mem_ctx_.init(handle_)); } private: ObLSID ls_id_; ObLockMemtable memtable_; ObTableHandleV2 handle_; ObTenantMetaMemMgr fake_t3m_; memtable::ObMemtableCtx fake_memtable_ctx_; 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; uint64_t lock_mode_cnt_in_same_trans[TABLE_LOCK_MODE_COUNT] = {0, 0, 0, 0, 0}; 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_cnt_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_cnt_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_cnt_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_cnt_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_cnt_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_cnt_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; uint64_t lock_mode_cnt_in_same_trans[TABLE_LOCK_MODE_COUNT] = {0, 0, 0, 0, 0}; 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_cnt_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_cnt_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_cnt_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_cnt_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; uint64_t lock_mode_cnt_in_same_trans[TABLE_LOCK_MODE_COUNT] = {0, 0, 0, 0, 0}; // 1. check rollback IN_TRANS lock // 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_ = ObTxSEQ(2, 0); ret = mem_ctx_.add_lock_record(lock_op1, 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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 1.3 rollback and check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 1.3"); auto rollback_to_seq_no = ObTxSEQ(1, 0); auto rollback_from_seq_no = ObTxSEQ(100, 0); ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no, rollback_from_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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, false); // 2. check rollback OUT_TRANS lock // 2.1 add lock record LOG_INFO("TestMemCtxTableLock::rollback_table_lock 2.1"); ObTableLockOp lock_op2 = DEFAULT_OUT_TRANS_LOCK_OP; lock_op2.lock_seq_no_ = ObTxSEQ(3, 0); ret = mem_ctx_.add_lock_record(lock_op2, lock_op_node); ASSERT_EQ(OB_SUCCESS, ret); // 2.2 check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 2.3 rollback and check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 2.3"); ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no, rollback_from_seq_no); ASSERT_EQ(OB_TRANS_NEED_ROLLBACK, 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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 3. check rollback OUT_TRANS and IN_TRANS lock // 3.1 add lock record LOG_INFO("TestMemCtxTableLock::rollback_table_lock 3.1"); ret = mem_ctx_.add_lock_record(lock_op1, lock_op_node); ASSERT_EQ(OB_SUCCESS, ret); // 3.2 check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 3.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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 3.3 rollback OUT_TRANS and check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 3.3"); rollback_from_seq_no = ObTxSEQ(3, 0); rollback_to_seq_no = ObTxSEQ(2, 0); ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no, rollback_from_seq_no); ASSERT_EQ(OB_TRANS_NEED_ROLLBACK, 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_cnt_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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 3.4 rollback IN_TRANS and check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 3.4"); rollback_from_seq_no = ObTxSEQ(2, 0); rollback_to_seq_no = ObTxSEQ(1, 0); ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no, rollback_from_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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, false); 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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 3.5 rollback all and check exist LOG_INFO("TestMemCtxTableLock::rollback_table_lock 3.4"); ret = mem_ctx_.add_lock_record(lock_op1, lock_op_node); ASSERT_EQ(OB_SUCCESS, ret); rollback_from_seq_no = ObTxSEQ(100, 0); rollback_to_seq_no = ObTxSEQ(1, 0); ret = mem_ctx_.rollback_table_lock(rollback_to_seq_no, rollback_from_seq_no); ASSERT_EQ(OB_TRANS_NEED_ROLLBACK, 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_cnt_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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, true); // 3.4 clean lock record LOG_INFO("TestMemCtxTableLock::rollback_table_lock 3.4"); mem_ctx_.remove_lock_record(lock_op1); mem_ctx_.remove_lock_record(lock_op2); 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_cnt_in_same_trans); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(lock_exist, false); 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_cnt_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"); uint64_t lock_mode_cnt_in_same_trans[TABLE_LOCK_MODE_COUNT] = {0, 0, 0, 0, 0}; 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_cnt_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(1, op_count); // 2 CHECK LOGGED LOCK LOG_INFO("TestMemCtxTableLock::check_lock_need_replay 2.1"); scn.set_base(); table_lock_info.reset(); mem_ctx_.sync_log_succ(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(2, 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_.sync_log_succ(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(); }