// owner: weixiaoxian.wxx // 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. */ #include #include #define USING_LOG_PREFIX SERVER #define protected public #define private public #include "env/ob_fast_bootstrap.h" #include "env/ob_multi_replica_util.h" #include "lib/mysqlclient/ob_mysql_result.h" #include "storage/tx/ob_dup_table_lease.h" using namespace oceanbase::transaction; using namespace oceanbase::storage; #define CUR_TEST_CASE_NAME ObDupTableTabletGC DEFINE_MULTI_ZONE_TEST_CASE_CLASS MULTI_REPLICA_TEST_MAIN_FUNCTION(test_dup_table_tablet_gc_); #define DEFAULT_LOAD_ROW_CNT 30 namespace oceanbase { namespace unittest { struct DupTableBasicArg { uint64_t tenant_id_; int64_t ls_id_num_; int64_t table_id_; int64_t tablet_count_; ObSEArray tablet_id_array_; TO_STRING_KV(K(tenant_id_), K(ls_id_num_), K(table_id_), K(tablet_count_), K(tablet_id_array_)); OB_UNIS_VERSION(1); }; OB_SERIALIZE_MEMBER(DupTableBasicArg, tenant_id_, ls_id_num_, table_id_, tablet_count_, tablet_id_array_); static DupTableBasicArg static_basic_arg_; TEST_F(GET_ZONE_TEST_CLASS_NAME(1), create_and_drop_dup_table) { int ret = OB_SUCCESS; CREATE_TEST_TENANT(test_tenant_id); SERVER_LOG(INFO, "[ObMultiReplicaTestBase] create test tenant success", K(test_tenant_id)); common::ObMySQLProxy &test_tenant_sql_proxy = get_curr_simple_server().get_sql_proxy2(); ACQUIRE_CONN_FROM_SQL_PROXY(test_conn, test_tenant_sql_proxy); ACQUIRE_CONN_FROM_SQL_PROXY(sys_conn, get_curr_simple_server().get_sql_proxy()); std::vector ths; std::set create_table_set; std::mutex w_lock; uint64_t loop_cnt = 30; uint64_t worker_cnt = 3; uint64_t create_times = 0; uint64_t drop_times = 0; auto do_worker = [&] (uint64_t uid) { ACQUIRE_CONN_FROM_SQL_PROXY(thread_test_conn, test_tenant_sql_proxy); uint64_t rand = 0; uint64_t name_rand = 0; std::srand((unsigned)std::time(NULL)); for (int i = 1; i <= loop_cnt; i++) { rand = std::rand() % 10 + 1; name_rand = std::rand() % 13331 + uid; if (rand <= 7) { w_lock.lock(); std::pair::iterator, bool> insert_res = create_table_set.insert(name_rand); if (insert_res.second) { create_times++; } w_lock.unlock(); if (insert_res.second) { std::string create_table_sql = "CREATE TABLE test_tt" + std::to_string(name_rand) + " ( " + "id_x int, " + "id_y int, " + "id_z int, " + "PRIMARY KEY(id_x)" + ") duplicate_scope='cluster' PARTITION BY hash(id_x) partitions 10;"; WRITE_SQL_BY_CONN(thread_test_conn, create_table_sql.c_str()); } } else { w_lock.lock(); drop_times++; auto table_num = create_table_set.begin(); create_table_set.erase(table_num); w_lock.unlock(); std::string drop_table_sql = "DROP TABLE IF EXISTS test_tt" + std::to_string(*table_num) + ";"; WRITE_SQL_BY_CONN(thread_test_conn, drop_table_sql.c_str()); } } LOG_STDOUT("Thread %lu finish Loop Work\n", uid); }; for (int i = 0; i < worker_cnt; i++) { std::thread th(do_worker, i); ths.push_back(std::move(th)); } for (auto &th : ths) { th.join(); } LOG_STDOUT("Finish create and drop table, create times:%lu, drop times:%lu\n", create_times, drop_times); sleep(10); uint64_t remain_tablets = create_table_set.size() * 10; READ_SQL_BY_CONN(test_conn, ls_info, "select * from oceanbase.DBA_OB_LS where flag like \"%DUPLICATE%\";"); ASSERT_EQ(OB_SUCCESS, ls_info->next()); int64_t ls_id = 0; ASSERT_EQ(OB_SUCCESS, ls_info->get_int("LS_ID", ls_id)); LOG_STDOUT("Check dup ls:%lu\n", ls_id); std::string check_tablet_to_ls_sql = "select count(*) from oceanbase.__all_tablet_to_ls where ls_id = " + std::to_string(ls_id); READ_SQL_BY_CONN(test_conn, tablet_info_result, check_tablet_to_ls_sql.c_str()); ASSERT_EQ(OB_SUCCESS, tablet_info_result->next()); int64_t dup_tablet_cnt = 0; ASSERT_EQ(OB_SUCCESS, tablet_info_result->get_int("count(*)", dup_tablet_cnt)); LOG_STDOUT("Check tablet, remain_tablets:%lu, remain_schema_tablets:%lu\n", remain_tablets, dup_tablet_cnt); // ASSERT_EQ(true, dup_tablet_cnt == remain_tablets); std::string primary_zone_sql = "ALTER TENANT " + std::string(DEFAULT_TEST_TENANT_NAME) + " set primary_zone='zone1, zone3; zone2';"; WRITE_SQL_BY_CONN(test_conn, primary_zone_sql.c_str()); sleep(200); READ_SQL_BY_CONN(test_conn, remain_tablet_count_result, "select count(*) from " "oceanbase.__all_virtual_dup_ls_tablets where ls_state = 'LEADER'"); uint64_t tablet_count = 0; ASSERT_EQ(OB_SUCCESS, remain_tablet_count_result->next()); ASSERT_EQ(OB_SUCCESS, remain_tablet_count_result->get_uint("count(*)", tablet_count)); LOG_STDOUT("Check tablet, remain_schema:%lu, remain_dup_table_mgr:%lu\n", dup_tablet_cnt, tablet_count); ASSERT_EQ(true, tablet_count == dup_tablet_cnt); for (auto create_table_num : create_table_set) { std::string drop_table_sql = "DROP TABLE IF EXISTS test_tt" + std::to_string(create_table_num) + ";"; WRITE_SQL_BY_CONN(test_conn, drop_table_sql.c_str()); } LOG_STDOUT("Drop all dup table\n"); sleep(300); READ_SQL_BY_CONN(test_conn, after_drop_all_tablet_info_result, check_tablet_to_ls_sql.c_str()); ASSERT_EQ(OB_SUCCESS, after_drop_all_tablet_info_result->next()); ASSERT_EQ(OB_SUCCESS, after_drop_all_tablet_info_result->get_int("count(*)", dup_tablet_cnt)); LOG_STDOUT("Check tablet, remain_tablets:%lu\n", dup_tablet_cnt); ASSERT_EQ(true, dup_tablet_cnt == 0); READ_SQL_BY_CONN(test_conn, after_drop_all_tablet_result, "select count(*) as res from " "oceanbase.__all_virtual_dup_ls_tablets where ls_state = 'LEADER'"); ASSERT_EQ(OB_SUCCESS, after_drop_all_tablet_result->next()); ASSERT_EQ(OB_SUCCESS, after_drop_all_tablet_result->get_uint("res", tablet_count)); LOG_STDOUT("Check tablet, remain_tablets:%lu, real_tablets:%lu\n", dup_tablet_cnt, tablet_count); ASSERT_EQ(true, tablet_count == dup_tablet_cnt); std::string tmp_str; ASSERT_EQ(OB_SUCCESS, EventArgSerTool::serialize_arg(static_basic_arg_, tmp_str)); ASSERT_EQ(OB_SUCCESS, finish_event("CREATE_DUP_TABLE", tmp_str)); } } // namespace unittest } // namespace oceanbase