// 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 STORAGETEST #define protected public #define private public #include "src/storage/slog/ob_storage_log_item.h" #include "mtlenv/mock_tenant_module_env.h" #include "storage/test_tablet_helper.h" namespace oceanbase { using namespace common; using namespace rpc; using namespace rpc::frame; using namespace share; namespace storage { class TestLSService : public ::testing::Test { public: TestLSService() = default; virtual ~TestLSService() = default; static void SetUpTestCase(); static void TearDownTestCase(); void SetUp() { ASSERT_TRUE(MockTenantModuleEnv::get_instance().is_inited()); } private: common::ObArenaAllocator allocator_; }; using namespace oceanbase; using namespace oceanbase::lib; using namespace oceanbase::rpc; using namespace oceanbase::rpc::frame; using namespace oceanbase::obrpc; using namespace oceanbase::common; using namespace std; using namespace oceanbase::obsys; void TestLSService::SetUpTestCase() { EXPECT_EQ(OB_SUCCESS, MockTenantModuleEnv::get_instance().init()); SERVER_STORAGE_META_SERVICE.is_started_ = true; } void TestLSService::TearDownTestCase() { MockTenantModuleEnv::get_instance().destroy(); } TEST_F(TestLSService, basic) { int ret = OB_SUCCESS; uint64_t tenant_id = MTL_ID(); ObCreateLSArg arg; ObLSService* ls_svr = MTL(ObLSService*); bool exist = false; ObLSID id_100(100); ObLSID id_101(101); ObLSID id_102(102); ObLSID exist_id = id_100; ObLSID not_exist_id = id_101; ObLSHandle handle; ObLS *ls = NULL; common::ObSharedGuard iter; // TEST_F(ObLSServiceTest, create_ls) LOG_INFO("create_ls begin"); // 1. create 100 ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, id_100, arg)); LOG_INFO("create_ls", K(arg), K(id_100)); EXPECT_EQ(OB_SUCCESS, ls_svr->create_ls(arg)); // 2. left 101 ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, id_101, arg)); LOG_INFO("create_ls", K(arg), K(id_101)); // 3. create 102 ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, id_102, arg)); LOG_INFO("create_ls", K(arg), K(id_102)); EXPECT_EQ(OB_SUCCESS, ls_svr->create_ls(arg)); // TEST_F(ObLSServiceTest, get_ls) LOG_INFO("get_ls begin"); // 1. exist get EXPECT_EQ(OB_SUCCESS, ls_svr->get_ls(exist_id, handle, ObLSGetMod::STORAGE_MOD)); EXPECT_EQ(exist_id, handle.get_ls()->get_ls_id()); // 2. not exist get EXPECT_EQ(OB_LS_NOT_EXIST, ls_svr->get_ls(not_exist_id, handle, ObLSGetMod::STORAGE_MOD)); // TEST_F(ObLSServiceTest, check_ls_exist) LOG_INFO("check_ls_exist begin"); // 1. exist check EXPECT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(exist_id, exist)); EXPECT_TRUE(exist); // 2. not exist check EXPECT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(not_exist_id, exist)); EXPECT_FALSE(exist); // TEST_F(ObLSServiceTest, get_ls_iter) LOG_INFO("get_ls_iter begin"); // 1. create iter EXPECT_EQ(OB_SUCCESS, ls_svr->get_ls_iter(iter, ObLSGetMod::STORAGE_MOD)); // 2. iter LS EXPECT_EQ(OB_SUCCESS, iter->get_next(ls)); ObLSID first_id = ls->get_ls_id(); EXPECT_EQ(OB_SUCCESS, iter->get_next(ls)); ObLSID second_id = ls->get_ls_id(); // 3. iter end EXPECT_EQ(OB_ITER_END, iter->get_next(ls)); // 4. test the result. EXPECT_TRUE(((first_id == id_100) || (first_id == id_102))); EXPECT_TRUE(((second_id == id_100) || (second_id == id_102))); EXPECT_NE(first_id, second_id); // TEST_F(ObLSServiceTest, remove_ls) LOG_INFO("remove_ls begin"); // 1. remove not exist. EXPECT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(not_exist_id, exist)); EXPECT_FALSE(exist); EXPECT_EQ(OB_SUCCESS, ls_svr->remove_ls(not_exist_id)); // 2. remove exist. EXPECT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_100, exist)); EXPECT_TRUE(exist); EXPECT_EQ(OB_SUCCESS, ls_svr->remove_ls(id_100)); EXPECT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_100, exist)); EXPECT_FALSE(exist); EXPECT_EQ(OB_SUCCESS, ls_svr->remove_ls(id_102)); // 3. check empty iter. iter.reset(); EXPECT_EQ(OB_SUCCESS, ls_svr->get_ls_iter(iter, ObLSGetMod::STORAGE_MOD)); EXPECT_EQ(OB_ITER_END, iter->get_next(ls)); } TEST_F(TestLSService, tablet_test) { int ret = OB_SUCCESS; uint64_t tenant_id = MTL_ID(); ObCreateLSArg arg; ObLSService *ls_svr = MTL(ObLSService*); ObLSHandle handle; ObLS *ls = NULL; ObLSID ls_id(103); ObTabletID tablet_id(1001); obrpc::ObBatchCreateTabletArg create_tablet_arg; ObMemberList member_list; int64_t paxos_replica_num = 1; int64_t leader_epoch = 0; ObTabletHandle tablet_handle; ObTablet *tablet =NULL; (void) member_list.add_server(MockTenantModuleEnv::get_instance().self_addr_); // TEST_F(TestLSService, create_tablet) // create ls ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, ls_id, arg)); ASSERT_EQ(OB_SUCCESS, ls_svr->create_ls(arg)); EXPECT_EQ(OB_SUCCESS, ls_svr->get_ls(ls_id, handle, ObLSGetMod::STORAGE_MOD)); ls = handle.get_ls(); ASSERT_NE(nullptr, ls); GlobalLearnerList learner_list; ASSERT_EQ(OB_SUCCESS, ls->set_initial_member_list(member_list, paxos_replica_num, learner_list)); for (int i=0;i<15;i++) { ObRole role; int64_t proposal_id = 0; ASSERT_EQ(OB_SUCCESS, ls->get_log_handler()->get_role(role, proposal_id)); if (role == ObRole::LEADER) { break; } ::sleep(1); } // 1. create a tablet share::schema::ObTableSchema table_schema; uint64_t table_id = 12345; ASSERT_EQ(OB_SUCCESS, build_test_schema(table_schema, table_id)); ASSERT_EQ(OB_SUCCESS, TestTabletHelper::create_tablet(handle, tablet_id, table_schema, allocator_)); // 2. test tablet LOG_INFO("TestLSService::tablet_test 2."); ASSERT_EQ(OB_SUCCESS, ls->get_tablet(tablet_id, tablet_handle)); tablet = tablet_handle.get_obj(); ASSERT_NE(nullptr, tablet); ASSERT_EQ(tablet_id, tablet->get_tablet_meta().tablet_id_); // 3. remove tablet LOG_INFO("TestLSService::tablet_test 3."); obrpc::ObBatchRemoveTabletArg remove_tablet_arg; remove_tablet_arg.id_ = ls_id; remove_tablet_arg.tablet_ids_.push_back(tablet_id); ASSERT_EQ(OB_SUCCESS, TestTabletHelper::remove_tablet(handle, tablet_id)); EXPECT_EQ(OB_SUCCESS, ls_svr->remove_ls(ls_id)); } TEST_F(TestLSService, ls_safe_destroy) { int ret = OB_SUCCESS; uint64_t tenant_id = MTL_ID(); ObCreateLSArg arg; ObLSService* ls_svr = MTL(ObLSService*); bool exist = false; bool waiting = false; ObLSID id_104(104); ObLSHandle handle; ObLS *ls = NULL; // 1. TEST CREATE WHILE WAITING DESTROY // 1.1. CREATE LS // 1.2. REMOVE LS BUT KEEP LS HANDLE // 1.3. CREATE LS AGAIN // 1. create ls LOG_INFO("TestLSService::ls_safe_destroy 1.1"); ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, id_104, arg)); LOG_INFO("create_ls", K(arg), K(id_104)); ASSERT_EQ(OB_SUCCESS, ls_svr->create_ls(arg)); // 2. hold the ls with ls handle LOG_INFO("TestLSService::ls_safe_destroy 1.2"); LOG_INFO("get_ls begin"); ASSERT_EQ(OB_SUCCESS, ls_svr->get_ls(id_104, handle, ObLSGetMod::STORAGE_MOD)); ASSERT_EQ(id_104, handle.get_ls()->get_ls_id()); // 3. remove ls LOG_INFO("TestLSService::ls_safe_destroy 1.3"); ASSERT_EQ(OB_SUCCESS, ls_svr->remove_ls(id_104)); ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_104, exist)); ASSERT_FALSE(exist); // 4. create again and check waiting = true LOG_INFO("TestLSService::ls_safe_destroy 1.4"); LOG_INFO("create_ls", K(arg), K(id_104)); ASSERT_EQ(OB_LS_WAITING_SAFE_DESTROY, ls_svr->create_ls(arg)); ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_waiting_safe_destroy(id_104, waiting)); ASSERT_TRUE(waiting); // 5. release ls and check waiting = false LOG_INFO("TestLSService::ls_safe_destroy 1.5"); handle.reset(); int cnt = 0; while (cnt++ < 20) { ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_waiting_safe_destroy(id_104, waiting)); if (waiting) { ::sleep(1); } else { break; } } ASSERT_FALSE(waiting); // 6. recreate success LOG_INFO("TestLSService::ls_safe_destroy 1.6"); ASSERT_EQ(OB_SUCCESS, ls_svr->create_ls(arg)); // 7. remove ls LOG_INFO("TestLSService::ls_safe_destroy 1.7"); ASSERT_EQ(OB_SUCCESS, ls_svr->remove_ls(id_104)); ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_104, exist)); ASSERT_FALSE(exist); } TEST_F(TestLSService, create_and_clean) { int ret = OB_SUCCESS; uint64_t tenant_id = MTL_ID(); ObCreateLSArg arg; ObLSService* ls_svr = MTL(ObLSService*); bool exist = false; bool waiting = false; ObLSID id_105(105); int64_t MAX_CREATE_STEP = 100; int cnt = 0; LOG_INFO("TestLSService::create_and_clean"); ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, id_105, arg)); for (int64_t i = 1; i < MAX_CREATE_STEP; i++) { LOG_INFO("create ls break point", K(i)); ls_svr->break_point = i; if (OB_FAIL(ls_svr->create_ls(arg)) && OB_BREAK_BY_TEST == ret) { // check exist ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_105, exist)); ASSERT_FALSE(exist); // wait safe destroy cnt = 0; while (cnt++ < 20) { ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_waiting_safe_destroy(id_105, waiting)); if (waiting) { ::sleep(1); } else { break; } } ASSERT_FALSE(waiting); } else if (OB_FAIL(ret)) { LOG_WARN("create failed but not break by test", K(ret), K(id_105)); } else { // create success and finish the break test ls_svr->break_point = 0; ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_105, exist)); ASSERT_TRUE(exist); ASSERT_EQ(OB_SUCCESS, ls_svr->remove_ls(id_105)); ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_105, exist)); ASSERT_FALSE(exist); break; } } cnt = 0; while (cnt++ < 20) { ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_waiting_safe_destroy(id_105, waiting)); if (waiting) { ::sleep(1); } else { break; } } ASSERT_FALSE(waiting); } TEST_F(TestLSService, test_remove_ls) { int ret = OB_SUCCESS; uint64_t tenant_id = MTL_ID(); ObCreateLSArg arg; ObLSService* ls_svr = MTL(ObLSService*); bool exist = false; bool waiting = false; bool need_break = false; ObLSID id_105(105); int64_t MAX_CREATE_STEP = 100; int cnt = 0; LOG_INFO("TestLSService::test_remove_ls"); ASSERT_EQ(OB_SUCCESS, gen_create_ls_arg(tenant_id, id_105, arg)); for (int64_t i = 1; i < MAX_CREATE_STEP; i++) { ls_svr->break_point = 0; ASSERT_EQ(OB_SUCCESS, ls_svr->create_ls(arg)); // create success and remove ls break test LOG_INFO("remove ls break point", K(i)); ls_svr->break_point = i; ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_exist(id_105, exist)); ASSERT_TRUE(exist); cnt = 0; while (OB_FAIL(ls_svr->remove_ls(id_105)) && OB_BREAK_BY_TEST == ret) { ls_svr->break_point = 0; cnt++; LOG_WARN("remove_ls failed, retry", K(ret), K(cnt)); } // remove ls does not failed, the test should break if (cnt == 0) { need_break = true; } // wait safe destroy cnt = 0; while (cnt++ < 20) { ASSERT_EQ(OB_SUCCESS, ls_svr->check_ls_waiting_safe_destroy(id_105, waiting)); if (waiting) { ::sleep(1); } else { break; } } ASSERT_FALSE(waiting); if (need_break) { break; } } } TEST_F(TestLSService, check_ls_iter_cnt) { int ret = OB_SUCCESS; int64_t start_time = 0; int64_t end_time = 0; EventItem item; item.trigger_freq_ = 1; item.error_code_ = 4013; EventTable::instance().set_event("ALLOC_LS_ITER_GUARD_FAIL", item); LOG_INFO("TestLSService::check_ls_iter_cnt"); ObLS *ls = NULL; ObLSService* ls_svr = MTL(ObLSService*); common::ObSharedGuard guard; // 1. get ls iter 100 times. for (int i = 0; i < 100; i++) { if (OB_FAIL(ls_svr->get_ls_iter(guard, ObLSGetMod::OBSERVER_MOD))) { LOG_WARN("get ls iter failed"); } } // 2. check the iter cnt, it should smaller than 100. ASSERT_EQ(0, ls_svr->iter_cnt_); // 3. get success 100 times. item.trigger_freq_ = 0; EventTable::instance().set_event("ALLOC_LS_ITER_GUARD_FAIL", item); for (int i = 0; i < 100; i++) { if (OB_FAIL(ls_svr->get_ls_iter(guard, ObLSGetMod::OBSERVER_MOD))) { LOG_WARN("get ls iter failed again"); } } // 4. check the iter cnt, it should smaller than 100. ASSERT_EQ(1, ls_svr->iter_cnt_); // 5. iter the ls. ObLSIterator *iter = NULL; if (OB_ISNULL(iter = guard.get_ptr())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("iter is NULL", K(ret), K(iter)); } else { LOG_INFO("iter cnt", K(ls_svr->iter_cnt_)); while (OB_SUCC(ret)) { if (OB_FAIL(iter->get_next(ls))) { if (OB_ITER_END != ret) { LOG_WARN("get next log stream failed", K(ret)); } } else if (OB_ISNULL(ls)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ls in null"); } else { LOG_INFO("there is a ls", KPC(ls)); } } } // 6. check ls service is empty ASSERT_EQ(true, ls_svr->is_empty()); // 7. stop ls service ls_svr->stop(); ASSERT_EQ(OB_NOT_RUNNING, ls_svr->get_ls_iter(guard, ObLSGetMod::OBSERVER_MOD)); ls_svr->is_inited_ = false; // 8. get iter failed. ASSERT_EQ(OB_NOT_INIT, ls_svr->get_ls_iter(guard, ObLSGetMod::OBSERVER_MOD)); // 9. destroy immediately guard.reset(); start_time = ObTimeUtil::current_time(); ls_svr->wait(); ls_svr->destroy(); end_time = ObTimeUtil::current_time(); ASSERT_TRUE(end_time - start_time <= 60 * 1000 * 1000); } } // namespace storage } // namespace oceanbase int main(int argc, char **argv) { int ret = 0; system("rm -f ./test_ls_service.log*"); OB_LOGGER.set_file_name("test_ls_service.log", true); OB_LOGGER.set_log_level("INFO"); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }