/** * 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 "common/rowkey/ob_store_rowkey.h" #include "storage/ls/ob_freezer.h" #include "storage/memtable/ob_memtable_util.h" #include "mtlenv/mock_tenant_module_env.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; using namespace memtable; namespace memtable { void ObMemtableCtx::update_max_submitted_seq_no(const int64_t seq_no) { UNUSEDx(seq_no); } } 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 TestLockTableCallback : public ::testing::Test { public: TestLockTableCallback() : ls_id_(1), fake_t3m_(common::OB_SERVER_TENANT_ID) { LOG_INFO("construct TestLockTableCallback"); } ~TestLockTableCallback() {} static void SetUpTestCase(); static void TearDownTestCase(); virtual void SetUp() override { create_memtable(); init_mem_ctx(handle_); LOG_INFO("set up success"); } virtual void TearDown() override { LOG_INFO("tear down success"); } private: 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(ObTableHandleV2 &lock_memtable_handle) { mt_ctx_.is_inited_ = true; mt_ctx_.ctx_cb_allocator_.init(common::OB_SERVER_TENANT_ID); ASSERT_EQ(OB_SUCCESS, mt_ctx_.enable_lock_table(lock_memtable_handle)); } void create_callback(const ObTableLockOp &lock_op, ObOBJLockCallback *&cb) { int ret = OB_SUCCESS; bool is_replay = false; ObMemCtxLockOpLinkNode *lock_op_node = nullptr; static ObFakeStoreRowKey tablelock_fake_rowkey("tbl", 3); const ObStoreRowkey &rowkey = tablelock_fake_rowkey.get_rowkey(); ObMemtableKey mt_key; ret = mt_ctx_.lock_mem_ctx_.add_lock_record(lock_op, lock_op_node, is_replay); ASSERT_EQ(OB_SUCCESS, ret); cb = mt_ctx_.alloc_table_lock_callback(mt_ctx_, &memtable_); ASSERT_NE(nullptr, cb); ret = mt_key.encode(&rowkey); ASSERT_EQ(OB_SUCCESS, ret); cb->set(mt_key, lock_op_node); } private: ObLSID ls_id_; ObLockMemtable memtable_; ObTableHandleV2 handle_; ObTenantMetaMemMgr fake_t3m_; ObFreezer freezer_; ObMemtableCtx mt_ctx_; }; void TestLockTableCallback::SetUpTestCase() { LOG_INFO("SetUpTestCase"); init_default_lock_test_value(); } void TestLockTableCallback::TearDownTestCase() { LOG_INFO("TearDownTestCase"); } TEST_F(TestLockTableCallback, callback) { int ret = OB_SUCCESS; bool lock_exist = false; unsigned char lock_mode_in_same_trans = 0x0; const bool for_replay = false; ObIMemtable *memtable = nullptr; ObOBJLockCallback *cb = nullptr; // 1. UNNSED CALLBACK TYPE LOG_INFO("TestLockTableCallback::callback 1."); static const int UNUSED_TYPE_NUM = 4; create_callback(DEFAULT_IN_TRANS_LOCK_OP, cb); ret = cb->elr_trans_preparing(); ASSERT_EQ(OB_SUCCESS, ret); // 2. TCB_PRINT_CALLBACK LOG_INFO("TestLockTableCallback::callback 2."); ret = cb->print_callback(); ASSERT_EQ(OB_SUCCESS, ret); // 3. IN_TRANS_LOCK // 3.1 intrans commit LOG_INFO("TestLockTableCallback::callback 3.1"); ret = mt_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(lock_exist, true); ret = cb->trans_commit(); ASSERT_EQ(OB_SUCCESS, ret); ret = mt_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(lock_exist, false); // 3.2 intrans abort LOG_INFO("TestLockTableCallback::callback 3.2"); create_callback(DEFAULT_IN_TRANS_LOCK_OP, cb); ret = mt_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(lock_exist, true); ret = cb->trans_abort(); ASSERT_EQ(OB_SUCCESS, ret); ret = mt_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(lock_exist, false); // 3.3 intrans stmt abort LOG_INFO("TestLockTableCallback::callback 3.3"); create_callback(DEFAULT_IN_TRANS_LOCK_OP, cb); ret = mt_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(lock_exist, true); ret = cb->rollback_callback(); ASSERT_EQ(OB_SUCCESS, ret); ret = mt_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(lock_exist, false); } TEST_F(TestLockTableCallback, basic) { LOG_INFO("TestLockTableCallback::basic"); int ret = OB_SUCCESS; ObOBJLockCallback *cb = nullptr; ObTableLockOp lock_op = DEFAULT_IN_TRANS_LOCK_OP; create_callback(lock_op, cb); ASSERT_EQ(lock_op.lock_seq_no_, cb->get_seq_no()); ASSERT_EQ(false, cb->must_log()); ASSERT_EQ(false, cb->log_synced()); share::SCN scn_10; scn_10.convert_for_logservice(10); ret = cb->log_sync(scn_10); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(true, cb->log_synced()); ASSERT_EQ(LS_LOCK_TABLET, cb->get_tablet_id()); TableLockRedoDataNode redo_node; ret = cb->get_redo(redo_node); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(redo_node.lock_id_, DEFAULT_IN_TRANS_LOCK_OP.lock_id_); } } // tablelock } // transaction } // oceanbase int main(int argc, char **argv) { system("rm -f test_lock_table_callback.log*"); oceanbase::common::ObLogger::get_logger().set_file_name("test_lock_table_callback.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(); }