/** * 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 SHARE_PT #include #include #include "lib/stat/ob_session_stat.h" #include "share/config/ob_server_config.h" #include "share/schema/db_initializer.h" // TODO : rename .cpp to .h #include "share/schema/ob_schema_test_utils.cpp" #include "share/schema/ob_multi_version_schema_service.h" #include "share/schema/ob_schema_getter_guard.h" #include "share/schema/ob_table_iter.h" #include "share/partition_table/ob_partition_table_operator.h" #include "share/partition_table/ob_partition_table_iterator.h" #include "lib/allocator/page_arena.h" #include "lib/container/ob_array.h" #include "lib/container/ob_array_iterator.h" #include "fake_part_property_getter.h" #include "../mock_ob_rs_mgr.h" #include "rpc/mock_ob_common_rpc_proxy.h" #include "../../rootserver/fake_rs_list_change_cb.h" #include "rootserver/ob_root_service.h" namespace oceanbase { namespace share { using namespace common; using namespace schema; using namespace host; using namespace obrpc; using namespace std; static uint64_t& TEN = FakePartPropertyGetter::TEN(); using testing::_; using ::testing::Invoke; using ::testing::Return; ObServerConfig& config = ObServerConfig::get_instance(); class TestPartitionTableIterator : public ::testing::Test { public: TestPartitionTableIterator() : operator_(prop_getter_) {} int gen_tenant_schema(const uint64_t tenant_id, ObTenantSchema& tenant_schema); virtual void SetUp(); virtual void TearDown(); virtual int gen_table_schema(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, ObTableSchema& table_schema); void gen_schema_lack_partition_level_two(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, const int64_t lack_position, bool create_tanent, ObMetaTableMode mode); void gen_schema_lack_partition_level_one(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, const int64_t lack_position, bool create_tenant, ObMetaTableMode mode); void gen_partition_table_level_one(const uint64_t tenant_id, const uint64_t pure_id, const vector& part_ids, const vector& meta_part_projector); void gen_table_schema_with_specified_part_id(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id_, const vector& part_ids); int gen_tenant_space_schema(uint64_t tenant_id); int release_tenant_space_schema(uint64_t tenant_id); protected: DBInitializer db_initer_; FakePartPropertyGetter prop_getter_; MockObCommonRpcProxy rpc_proxy_; MockObRsMgr rs_mgr_; ObPartitionTableOperator operator_; // FakeSchemaService schema_service_; ObMultiVersionSchemaService multi_schema_service_; FakeRsListChangeCb cb_; FakeMergeErrorCb merge_error_cb_; }; int TestPartitionTableIterator::gen_table_schema(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, ObTableSchema& table_schema) { int ret = OB_SUCCESS; table_schema.reset(); ObInnerTableSchema::all_core_table_schema(table_schema); char table_name[64]; if (snprintf(table_name, 64, "table_%lu", combine_id(tenant_id, pure_id)) >= 64) { ret = OB_BUF_NOT_ENOUGH; SHARE_SCHEMA_LOG(WARN, "buf not enough", K(ret)); } else { table_schema.set_table_name(table_name); table_schema.set_tenant_id(tenant_id); table_schema.set_table_id(combine_id(tenant_id, pure_id)); table_schema.set_database_id(combine_id(tenant_id, pure_db_id)); table_schema.set_tablegroup_id(combine_id(tenant_id, pure_tg_id)); } return ret; } int TestPartitionTableIterator::gen_tenant_schema(const uint64_t tenant_id, ObTenantSchema& tenant_schema) { int ret = OB_SUCCESS; char tenant_name[64]; if (snprintf(tenant_name, 64, "tenant_%lu", tenant_id) >= 64) { ret = OB_BUF_NOT_ENOUGH; } else { tenant_schema.reset(); tenant_schema.set_tenant_id(tenant_id); tenant_schema.set_tenant_name(tenant_name); tenant_schema.set_comment("this is a test tenant"); tenant_schema.add_zone("zone"); tenant_schema.set_primary_zone("zone"); tenant_schema.set_locality(""); } return ret; } void TestPartitionTableIterator::gen_table_schema_with_specified_part_id(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, const vector& part_ids) { int ret = OB_SUCCESS; ObTableSchema table_schema; if (OB_FAIL(gen_table_schema(tenant_id, pure_id, pure_db_id, pure_tg_id, table_schema))) { LOG_WARN("fail to gen table schema", K(ret), K(tenant_id), K(pure_id)); } for (int i = 0; i < part_ids.size(); ++i) { ObPartition partition; int64_t value = i + 10; ObObj key(value); ObRowkey rowkey(&key, 1); partition.set_high_bound_val(rowkey); char part_name[50]; memset(part_name, '\0', 50); snprintf(part_name, 50, "range%d", i); ObString name = ObString::make_string(part_name); partition.set_part_id(part_ids[i]); partition.set_part_name(name); table_schema.add_partition(partition); } table_schema.set_table_type(USER_TABLE); table_schema.set_part_level(PARTITION_LEVEL_ONE); table_schema.get_part_option().set_part_num(part_ids.size()); table_schema.get_part_option().set_part_func_type(PARTITION_FUNC_TYPE_RANGE); table_schema.get_part_option().set_part_expr(ObString::make_string("table_id mod 111")); CREATE_USER_TABLE_SCHEMA(ret, table_schema); // ObMySQLTransaction trans; // ret = trans.start(&db_initer_.get_sql_proxy()); // ret = multi_schema_service_.get_schema_service()->get_table_sql_service().create_table(table_schema, trans); // const bool commit = true; // ret = trans.end(commit); multi_schema_service_.refresh_and_add_schema(); } void TestPartitionTableIterator::gen_schema_lack_partition_level_two(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, const int64_t lack_position, bool create_tenant, ObMetaTableMode mode) { int ret = OB_SUCCESS; ObTenantSchema tenant_schema; ObTableSchema table_schema; if (create_tenant) { if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) { LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id)); } CREATE_TENANT(ret, tenant_schema); if (mode >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_schema.get_tenant_id())); } } if (OB_SUCC(ret) && OB_FAIL(gen_table_schema(tenant_id, pure_id, pure_db_id, pure_tg_id, table_schema))) { LOG_WARN("fail to gen table schema", K(ret), K(tenant_id), K(pure_id)); } table_schema.set_table_type(USER_TABLE); table_schema.set_part_level(PARTITION_LEVEL_TWO); table_schema.get_part_option().set_part_num(2); table_schema.get_sub_part_option().set_part_func_type(PARTITION_FUNC_TYPE_RANGE); table_schema.get_sub_part_option().set_part_expr(ObString::make_string("table_id mod 111")); table_schema.get_sub_part_option().set_part_num(3); ObSubPartition subpartition; subpartition.set_part_id(0); subpartition.set_sub_part_id(0); ObString name1 = ObString::make_string("range1"); subpartition.set_part_name(name1); int64_t value = 5; ObObj key1(value); ObRowkey rowkey1(&key1, 1); subpartition.set_high_bound_val(rowkey1); table_schema.add_partition(subpartition); subpartition.reset(); ObString name2 = ObString::make_string("range2"); subpartition.set_part_id(0); subpartition.set_sub_part_id(1); subpartition.set_part_name(name2); value = 15; ObObj key2(value); ObRowkey rowkey2(&key2, 1); subpartition.set_high_bound_val(rowkey2); table_schema.add_partition(subpartition); subpartition.reset(); ObString name3 = ObString::make_string("range2"); subpartition.set_part_id(0); subpartition.set_sub_part_id(2); subpartition.set_part_name(name3); value = 150; ObObj key3(value); ObRowkey rowkey3(&key3, 1); subpartition.set_high_bound_val(rowkey3); table_schema.add_partition(subpartition); CREATE_USER_TABLE_SCHEMA(ret, table_schema); prop_getter_.clear(); // generate two level partitions 2 * 3 // 13 patterns // nothing --0 // <0,1>,<0,2>, <1,0>,<1,1>,<1,2> //lack of front --1 //<0,0>, <0,2>, <1,0>,<1,1>,<1,2> //lack of middle ---2 //<0,0>,<0,1>, , <1,0>,<1,1>,<1,2> //lack of middle ---3 //<0,0>,<0,1>,<0,2>,<0,3>,<1,0>,<1,1>,<1,2> //more in middle ---4 //<0,0>,<0,1>,<0,2>, <1,0>,<1,1>,<1,2> //normal ---5 //<0,0>,<0,1>,<0,2>,<0,3>, <1,1>,<1,2> //more in middle ---6 //<0,0>,<0,1>,<0,2>, <1,1>,<1,2> //lack of front ---7 //<0,0>,<0,1>,<0,2>, ---8 //<0,0>,<0,1>, <1,1>,<1,2> //lack of middle ---9 //<0,0>,<0,1>,<0,2>, <1,0> //the back is missing ----10 //<0,0>,<0,1>,<0,2>, <1,0>,<1,1>,<1,2><1,3>,<1,4> more in back ---11 // <1,0>,<1,1>,<1,2> ----12 //<0,0>,<0,1>,<0,2>,<0,3>, <0,5> <1,1>,<1,2> //more in middle----13 // for (int64_t i = 0; i < 13; i++) { int64_t i = lack_position; int64_t phy_part_id = 0; if (i == 0) { // nothing to do } else { if (i != 1 && i != 12) { phy_part_id = generate_phy_part_id(0, 0, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i != 2 && i != 12) { phy_part_id = generate_phy_part_id(0, 1, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i != 3 && i != 9 && i != 12) { phy_part_id = generate_phy_part_id(0, 2, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i == 4 || i == 6 || i == 13) { phy_part_id = generate_phy_part_id(0, 3, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i == 13) { phy_part_id = generate_phy_part_id(0, 5, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i != 6 && i != 7 && i != 8 && i != 9 && i != 13) { phy_part_id = generate_phy_part_id(1, 0, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i != 8 && i != 10) { phy_part_id = generate_phy_part_id(1, 1, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); phy_part_id = generate_phy_part_id(1, 2, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } if (i == 11) { phy_part_id = generate_phy_part_id(1, 3, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); phy_part_id = generate_phy_part_id(1, 4, PARTITION_LEVEL_TWO); prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER); } } //} for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) { GCONF.self_addr_ = prop_getter_.get_replicas().at(i).server_; operator_.update(prop_getter_.get_replicas().at(i)); } multi_schema_service_.refresh_and_add_schema(); } void TestPartitionTableIterator::gen_partition_table_level_one(const uint64_t tenant_id, const uint64_t pure_id, const vector& part_ids, const vector& meta_part_projector) { prop_getter_.clear(); for (int i = 0; i < meta_part_projector.size(); ++i) { int64_t part_id = meta_part_projector[i]; if (meta_part_projector[i] < part_ids.size()) { part_id = part_ids[meta_part_projector[i]]; } prop_getter_.add(combine_id(tenant_id, pure_id), part_id, A, LEADER) .add(combine_id(tenant_id, pure_id), part_id, B, FOLLOWER); } for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) { operator_.update(prop_getter_.get_replicas().at(i)); } } void TestPartitionTableIterator::gen_schema_lack_partition_level_one(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, const int64_t lack_position, bool create_tenant, ObMetaTableMode mode) { int ret = OB_SUCCESS; ObTenantSchema tenant_schema; ObTableSchema table_schema; if (create_tenant) { if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) { LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id)); } CREATE_TENANT(ret, tenant_schema); if (mode >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_schema.get_tenant_id())); } } if (OB_SUCC(ret) && OB_FAIL(gen_table_schema(tenant_id, pure_id, pure_db_id, pure_tg_id, table_schema))) { LOG_WARN("fail to gen table schema", K(ret), K(tenant_id), K(pure_id)); } // five replicas, five pattern // 1234 \ 0234 \ 0123 \ 01234 \ 0123456 \ empty\012367 table_schema.set_table_type(USER_TABLE); table_schema.set_part_level(PARTITION_LEVEL_ONE); table_schema.get_part_option().set_part_num(5); CREATE_USER_TABLE_SCHEMA(ret, table_schema); prop_getter_.clear(); if (lack_position != 0 && lack_position != 5) { prop_getter_.add(combine_id(tenant_id, pure_id), 0, A, LEADER).add(combine_id(tenant_id, pure_id), 0, B, FOLLOWER); } if (lack_position != 1 && lack_position != 5) { prop_getter_.add(combine_id(tenant_id, pure_id), 1, A, LEADER).add(combine_id(tenant_id, pure_id), 1, B, FOLLOWER); } if (lack_position != 5) { prop_getter_.add(combine_id(tenant_id, pure_id), 2, A, LEADER).add(combine_id(tenant_id, pure_id), 2, B, FOLLOWER); prop_getter_.add(combine_id(tenant_id, pure_id), 3, A, LEADER).add(combine_id(tenant_id, pure_id), 3, B, FOLLOWER); } if (lack_position != 2 && lack_position != 5 && lack_position != 6) { prop_getter_.add(combine_id(tenant_id, pure_id), 4, A, LEADER).add(combine_id(tenant_id, pure_id), 4, B, FOLLOWER); } if (lack_position == 4) { prop_getter_.add(combine_id(tenant_id, pure_id), 5, A, LEADER).add(combine_id(tenant_id, pure_id), 5, B, FOLLOWER); prop_getter_.add(combine_id(tenant_id, pure_id), 6, A, LEADER).add(combine_id(tenant_id, pure_id), 6, B, FOLLOWER); } if (lack_position == 6) { prop_getter_.add(combine_id(tenant_id, pure_id), 6, A, LEADER).add(combine_id(tenant_id, pure_id), 6, B, FOLLOWER); prop_getter_.add(combine_id(tenant_id, pure_id), 7, A, LEADER).add(combine_id(tenant_id, pure_id), 7, B, FOLLOWER); } for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) { GCONF.self_addr_ = prop_getter_.get_replicas().at(i).server_; operator_.update(prop_getter_.get_replicas().at(i)); } multi_schema_service_.refresh_and_add_schema(); } int TestPartitionTableIterator::gen_tenant_space_schema(uint64_t tenant_id) { int ret = OB_SUCCESS; int idx = 0; std::string db = db_initer_.get_db_name(); common::ObMySQLProxy& sql_proxy = db_initer_.get_sql_proxy(); ObSqlString sql; int64_t affect_rows = 0; LOG_INFO("create db", K(db.c_str()), K(tenant_id)); if (OB_FAIL(sql.assign_fmt("drop database if exists %s_%lu", db.c_str(), tenant_id))) { LOG_WARN("assign sql failed", K(ret)); } else if (OB_FAIL(sql_proxy.write(sql.ptr(), affect_rows))) { LOG_WARN("execute create database sql failed", K(ret), K(sql)); } else if (OB_FAIL(sql.assign_fmt("create database %s_%lu", db.c_str(), tenant_id))) { LOG_WARN("assign sql failed", K(ret)); } else if (OB_FAIL(sql_proxy.write(sql.ptr(), affect_rows))) { LOG_WARN("execute create database sql failed", K(ret), K(sql)); } else { const schema_create_func* creator_ptr_array[] = { share::core_table_schema_creators, share::sys_table_schema_creators}; ObTableSchema tables[ARRAYSIZEOF(core_table_schema_creators) + ARRAYSIZEOF(sys_table_schema_creators)]; // build system table schema to %tables for (int64_t i = 0; common::OB_SUCCESS == ret && i < ARRAYSIZEOF(creator_ptr_array); i++) { for (const schema_create_func* creator_ptr = creator_ptr_array[i]; common::OB_SUCCESS == ret && NULL != *creator_ptr; ++creator_ptr) { if (OB_FAIL((*creator_ptr)(tables[idx++]))) { LOG_WARN("create table schema fialed", K(ret)); ret = common::OB_SCHEMA_ERROR; } } } ObTableSchema table_schema; char csql[common::OB_MAX_SQL_LENGTH]; memset(csql, 0, sizeof(csql)); for (int64_t i = 0; OB_SUCC(ret) && i < ARRAYSIZEOF(tenant_space_tables); i++) { if (!is_virtual_table(tenant_space_tables[i])) { uint64_t tid = tenant_space_tables[i]; // found table schema for (idx = 0; idx < ARRAYSIZEOF(tables); ++idx) { if (extract_pure_id(tables[idx].get_table_id()) == tid) { LOG_INFO("", K(tid)); if (OB_FAIL(table_schema.assign(tables[idx]))) { LOG_WARN("fail to assign schema", K(ret)); } else { ObSchemaTestUtils::table_set_tenant(table_schema, tenant_id); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } if (OB_FAIL(ret)) { } else if (tables[idx].is_view_table()) { // skip } else if (OB_FAIL(rootserver::ObSchema2DDLSql::convert(table_schema, csql, sizeof(csql)))) { LOG_WARN("convert table schema to create table sql failed", K(ret)); } else if (OB_FAIL(sql_proxy.write(tenant_id, csql, affect_rows))) { ret = OB_SUCCESS; LOG_WARN("execute sql failed", K(ret), K(csql)); } break; } } } } } return ret; } int TestPartitionTableIterator::release_tenant_space_schema(uint64_t tenant_id) { int ret = OB_SUCCESS; std::string db = db_initer_.get_db_name(); common::ObMySQLProxy& sql_proxy = db_initer_.get_sql_proxy(); ObSqlString sql; int64_t affect_rows = 0; if (OB_FAIL(sql.assign_fmt("drop database if exists %s_%lu", db.c_str(), tenant_id))) { LOG_WARN("assign sql failed", K(ret)); } else if (OB_FAIL(sql_proxy.write(sql.ptr(), affect_rows))) { LOG_WARN("execute create database sql failed", K(ret), K(sql)); } return ret; } void TestPartitionTableIterator::TearDown() { ObKVGlobalCache::get_instance().destroy(); } void TestPartitionTableIterator::SetUp() { int ret = db_initer_.init(); ASSERT_EQ(OB_SUCCESS, ret); ObKVGlobalCache::get_instance().init(); GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_SYS_ONLY; GCONF.min_observer_version.set_value("2.0.0"); const bool only_core_tables = false; ret = db_initer_.create_system_table(only_core_tables); ASSERT_EQ(OB_SUCCESS, ret); ret = operator_.init(db_initer_.get_sql_proxy(), NULL); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(OB_SUCCESS, operator_.set_callback_for_rs(cb_, merge_error_cb_)); // init schema service // ASSERT_EQ(OB_SUCCESS, schema_service_.init()); ret = multi_schema_service_.init(&db_initer_.get_sql_proxy(), &db_initer_.get_config(), OB_MAX_VERSION_COUNT, OB_MAX_VERSION_COUNT_FOR_MERGE, false); ASSERT_EQ(OB_SUCCESS, ret); TEN = 1; // create sys tenant ObTenantSchema tenant_schema; tenant_schema.set_tenant_id(OB_SYS_TENANT_ID); tenant_schema.set_tenant_name(OB_SYS_TENANT_NAME); tenant_schema.set_locality(""); CREATE_TENANT(ret, tenant_schema); ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(TEN)); ObTableSchema table_schema; for (int64_t i = 0; OB_SUCC(ret) && NULL != share::sys_table_schema_creators[i]; ++i) { table_schema.reset(); ASSERT_EQ(OB_SUCCESS, (*share::sys_table_schema_creators[i])(table_schema)); ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } for (int64_t i = 0; OB_SUCC(ret) && NULL != share::core_table_schema_creators[i]; ++i) { table_schema.reset(); ASSERT_EQ(OB_SUCCESS, (*share::core_table_schema_creators[i])(table_schema)); ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } for (int64_t i = 0; OB_SUCC(ret) && NULL != share::virtual_table_schema_creators[i]; ++i) { table_schema.reset(); ASSERT_EQ(OB_SUCCESS, (*share::virtual_table_schema_creators[i])(table_schema)); ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } for (int64_t i = 0; OB_SUCC(ret) && NULL != share::sys_view_schema_creators[i]; ++i) { table_schema.reset(); ASSERT_EQ(OB_SUCCESS, (*share::sys_view_schema_creators[i])(table_schema)); ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } for (int64_t i = 0; OB_SUCC(ret) && NULL != share::information_schema_table_schema_creators[i]; ++i) { table_schema.reset(); ASSERT_EQ(OB_SUCCESS, (*share::information_schema_table_schema_creators[i])(table_schema)); ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } for (int64_t i = 0; OB_SUCC(ret) && NULL != share::mysql_table_schema_creators[i]; ++i) { table_schema.reset(); ASSERT_EQ(OB_SUCCESS, (*share::mysql_table_schema_creators[i])(table_schema)); ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID); CREATE_USER_TABLE_SCHEMA(ret, table_schema); } TEN = 2; ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(2, tenant_schema)); CREATE_TENANT(ret, tenant_schema); ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(TEN)); ASSERT_EQ(OB_SUCCESS, gen_table_schema(TEN, 50001, 1, 1, table_schema)); table_schema.set_table_type(USER_TABLE); table_schema.set_part_level(PARTITION_LEVEL_ONE); table_schema.get_part_option().set_part_num(2); CREATE_USER_TABLE_SCHEMA(ret, table_schema); ASSERT_EQ(OB_SUCCESS, gen_table_schema(TEN, 50002, 1, 1, table_schema)); table_schema.set_part_level(PARTITION_LEVEL_ZERO); CREATE_USER_TABLE_SCHEMA(ret, table_schema); // init partition table TEN = 1; prop_getter_.clear().add(combine_id(TEN, 1), 0, A, LEADER); GCONF.self_addr_ = prop_getter_.get_replicas().at(0).server_; ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(0))); prop_getter_.clear().add(combine_id(TEN, 2), 0, A, LEADER); GCONF.self_addr_ = prop_getter_.get_replicas().at(0).server_; ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(0))); TEN = 2; prop_getter_.clear() .add(combine_id(TEN, 50001), 0, A, LEADER) .add(combine_id(TEN, 50001), 0, B, FOLLOWER) .add(combine_id(TEN, 50001), 1, A, LEADER) .add(combine_id(TEN, 50001), 1, B, FOLLOWER); for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) { GCONF.self_addr_ = prop_getter_.get_replicas().at(i).server_; ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(i))); } ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema()); } TEST_F(TestPartitionTableIterator, table_partition_iterator_v2) { const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY, ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE, ObMetaTableMode::METATABLE_MODE_TENANT_ONLY}; for (int idx = 0; idx < ARRAYSIZEOF(modes); idx++) { LOG_INFO("case table_partition_iterator_v2: use mode ", K(modes[idx])); GCONF.meta_table_read_write_mode = modes[idx]; ObTablePartitionIterator iter; GCONF.partition_table_scan_batch_count = 4; ObSchemaGetterGuard schema_guard; EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(schema_guard)); ObPartitionInfo partition; // not init ASSERT_NE(OB_SUCCESS, iter.next(partition)); ASSERT_NE(OB_SUCCESS, iter.init(OB_INVALID_ID, schema_guard, operator_)); if (ObMetaTableMode::METATABLE_MODE_SYS_ONLY == modes[idx]) { // during setup, tenant 1,2 are created according to ObMetaTableRWMode::TENANT_RW // only verified in this mode ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(2, 50001), schema_guard, operator_)); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(2, partition.replica_count()); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(2, partition.replica_count()); ASSERT_EQ(OB_ITER_END, iter.next(partition)); ASSERT_EQ(OB_ITER_END, iter.next(partition)); // init again ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(2, 50001), schema_guard, operator_)); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(2, partition.replica_count()); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(2, partition.replica_count()); ASSERT_EQ(OB_ITER_END, iter.next(partition)); } LOG_INFO("table_iterator", K(iter)); // test exception, there is a hole in the partition table TEN = 20005 + idx * 10000; uint64_t table_id = 50005; // five replcias, 6 error pattern // 1234 \ 0234 \ 0123 \ 01234 \ 0123456 \ empty \012367 for (int64_t i = 0; i < 7; i++) { LOG_INFO("round", K(i)); ObSchemaGetterGuard tmp_schema_guard; gen_schema_lack_partition_level_one(TEN, table_id, 1, 1, i, true, modes[idx]); gen_schema_lack_partition_level_one(TEN, table_id + 1, 1, 1, i, false, modes[idx]); EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard)); ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(TEN, table_id), tmp_schema_guard, operator_)); partition.reuse(); // 1 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(0, partition.get_partition_id()); if (0 == i || 5 == i) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } partition.reuse(); // 2 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.get_partition_id()); if (1 == i || 5 == i) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 3 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(2, partition.get_partition_id()); if (i == 5) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { if (partition.replica_count() != 2) OB_ASSERT(0); ASSERT_EQ(2, partition.replica_count()); } // 4 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(3, partition.get_partition_id()); if (i == 5) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 5 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(4, partition.get_partition_id()); if (2 == i || 5 == i || 6 == i) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } ASSERT_EQ(OB_ITER_END, iter.next(partition)); table_id += 2; TEN++; } // generate two level partitions 2 * 3 // 13 patterns // nothing --0 // <0,1>,<0,2>, <1,0>,<1,1>,<1,2> //lack of front --1 //<0,0>, <0,2>, <1,0>,<1,1>,<1,2> //lack of middle ---2 //<0,0>,<0,1>, , <1,0>,<1,1>,<1,2> //lack of middle ---3 //<0,0>,<0,1>,<0,2>,<0,3>,<1,0>,<1,1>,<1,2> //more in middle ---4 //<0,0>,<0,1>,<0,2>, <1,0>,<1,1>,<1,2> //normal ---5 //<0,0>,<0,1>,<0,2>,<0,3>, <1,1>,<1,2> //more in middle ---6 //<0,0>,<0,1>,<0,2>, <1,1>,<1,2> //lack of front ---7 //<0,0>,<0,1>,<0,2>, ---8 //<0,0>,<0,1>, <1,1>,<1,2> //lack of middle ---9 //<0,0>,<0,1>,<0,2>, <1,0> //the back is missing ----10 //<0,0>,<0,1>,<0,2>, <1,0>,<1,1>,<1,2><1,3>,<1,4> more in back ---11 // <1,0>,<1,1>,<1,2> ----12 //<0,0>,<0,1>,<0,2>,<0,3>, <0,5> <1,1>,<1,2> //more in middle----13 for (int64_t i = 0; i < 14; i++) { ObSchemaGetterGuard tmp_schema_guard; gen_schema_lack_partition_level_two(TEN, table_id, 1, 1, i, true, modes[idx]); gen_schema_lack_partition_level_two(TEN, table_id + 1, 1, 1, i, false, modes[idx]); EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard)); ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(TEN, table_id), tmp_schema_guard, operator_)); // 1 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(generate_phy_part_id(0, 0, PARTITION_LEVEL_TWO), partition.get_partition_id()); if (i == 0 || i == 1 || i == 12) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 2 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(generate_phy_part_id(0, 1, PARTITION_LEVEL_TWO), partition.get_partition_id()); if (i == 2 || i == 12 || i == 0) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 3 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(generate_phy_part_id(0, 2, PARTITION_LEVEL_TWO), partition.get_partition_id()); if (i == 3 || i == 9 || i == 12 || i == 0) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 4 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(generate_phy_part_id(1, 0, PARTITION_LEVEL_TWO), partition.get_partition_id()); if (i == 0 || i == 6 || i == 7 || i == 8 || i == 9 || i == 13) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 5 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(generate_phy_part_id(1, 1, PARTITION_LEVEL_TWO), partition.get_partition_id()); if (i == 0 || i == 8 || i == 10) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 6 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(generate_phy_part_id(1, 2, PARTITION_LEVEL_TWO), partition.get_partition_id()); if (i == 0 || i == 8 || i == 10) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } ASSERT_EQ(OB_ITER_END, iter.next(partition)); table_id += 2; TEN++; } int ret = OB_SUCCESS; for (uint64_t i = 20005 + idx * 10000; i < TEN; i++) { if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(i)); } DROP_TENANT(ret, i); ASSERT_EQ(OB_SUCCESS, ret); } } } TEST_F(TestPartitionTableIterator, tenant_partition_iterator_for_non_continuous_partition_id) { const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY, ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE, ObMetaTableMode::METATABLE_MODE_TENANT_ONLY}; for (int idx = 0; idx < ARRAYSIZEOF(modes); idx++) { LOG_INFO("case tenant_partition_iterator_for_non_continuous_partition_id: use mode ", K(modes[idx])); GCONF.meta_table_read_write_mode = modes[idx]; int ret = OB_SUCCESS; int64_t tenant_id = 1001 + idx; uint64_t table_id = 50005; vector part_ids = {1, 3, 6, 7, 13}; vector> meta_part_projectors = {{0, 1, 2, 3, 4}}; ObTenantSchema tenant_schema; if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) { LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id)); } CREATE_TENANT(ret, tenant_schema); if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_schema.get_tenant_id())); } gen_table_schema_with_specified_part_id(tenant_id, table_id, 1, 1, part_ids); gen_partition_table_level_one(tenant_id, table_id, part_ids, meta_part_projectors[0]); ObSchemaGetterGuard tmp_schema_guard; EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard)); ObTenantPartitionIterator iter; ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, tenant_id, false)); ObPartitionInfo partition; int i = 0; while (OB_SUCC(iter.next(partition))) { const uint64_t tid = combine_id(tenant_id, table_id); if (partition.get_table_id() != tid) { continue; } else { ASSERT_EQ(part_ids[i], partition.get_partition_id()); ASSERT_EQ(2, partition.get_replicas_v2().count()); ++i; } } ASSERT_EQ(OB_ITER_END, ret); ASSERT_EQ(5, i); if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant_schema.get_tenant_id())); } DROP_TENANT(ret, tenant_id); } } TEST_F(TestPartitionTableIterator, table_partition_iterator_for_non_continuous_partition_id) { const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY, ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE, ObMetaTableMode::METATABLE_MODE_TENANT_ONLY}; for (int idx = 0; idx < ARRAYSIZEOF(modes); idx++) { LOG_INFO("case table_partition_iterator_for_non_continuous_partition_id: use mode ", K(modes[idx])); GCONF.meta_table_read_write_mode = modes[idx]; int ret = OB_SUCCESS; int64_t tenant_id = 2001 + idx; uint64_t table_id = 50005; vector part_ids = {1, 3, 6, 7, 13}; vector> meta_part_projectors = { {1, 2, 3, 4}, {0, 2, 3, 4}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4, 14, 15}, {}, {0, 1, 2, 3, 15, 16}, }; ObTenantSchema tenant_schema; if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) { LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id)); } CREATE_TENANT(ret, tenant_schema); if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_id)); } // test exception. there is a hole in the partition_table // 5 replicas, 6 error pattern // 1234 \ 0234 \ 0123 \ 01234 \ 0123456 \ empty \ 012367 for (int64_t i = 0; i < 7; i++) { LOG_INFO("round", K(i)); ObSchemaGetterGuard tmp_schema_guard; gen_table_schema_with_specified_part_id(tenant_id, table_id, 1, 1, part_ids); gen_partition_table_level_one(tenant_id, table_id, part_ids, meta_part_projectors[i]); EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard)); ObTablePartitionIterator iter; ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(tenant_id, table_id), tmp_schema_guard, operator_)); ObPartitionInfo partition; // 1 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(part_ids[0], partition.get_partition_id()); if (0 == i || 5 == i) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 2 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(part_ids[1], partition.get_partition_id()); if (1 == i || 5 == i) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 3 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(part_ids[2], partition.get_partition_id()); if (i == 5) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { if (partition.replica_count() != 2) OB_ASSERT(0); ASSERT_EQ(2, partition.replica_count()); } // 4 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(part_ids[3], partition.get_partition_id()); if (i == 5) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } // 5 partition.reuse(); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(part_ids[4], partition.get_partition_id()); if (2 == i || 5 == i || 6 == i) { LOG_INFO("expect error", K(partition.get_partition_id())); ASSERT_EQ(0, partition.replica_count()); } else { ASSERT_EQ(2, partition.replica_count()); } ASSERT_EQ(OB_ITER_END, iter.next(partition)); table_id += 2; } if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant_id)); } DROP_TENANT(ret, tenant_id); } } TEST_F(TestPartitionTableIterator, all_table_partition) { LOG_INFO("case TestPartitionTableIterator.all_table_partition"); GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_TENANT_ONLY; ObPartitionInfo partition; { ObPartitionTableIterator iter; LOG_INFO("partition table iterator", K(iter)); // not init ASSERT_NE(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); // init twice ASSERT_NE(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); // tid: 1 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); ASSERT_EQ(1UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_)); // tid: 2 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); ASSERT_EQ(2UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_)); // ignore non exist table (tid: 3), virtual table (tid: 5) // tid: OB_ALL_META_TABLE, no replica for (int64_t i = 0; i < 16; ++i) { ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(0, partition.replica_count()); } // tid: 50001 while (OB_SUCCESS == iter.next(partition)) { if (partition.get_table_id() == combine_id(2, 50001)) { // ASSERT_EQ(OB_SUCCESS, iter.next(partition)); LOG_INFO("xx", K(partition)); ASSERT_EQ(2, partition.replica_count()); ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_)); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(2, partition.replica_count()); ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_)); break; } } while (OB_SUCCESS == iter.next(partition)) { LOG_INFO("tingting", K(partition.get_table_id())); } // ignore non exist table (tid: 50002) ASSERT_EQ(OB_ITER_END, iter.next(partition)); ASSERT_EQ(OB_ITER_END, iter.next(partition)); } { // iterator with filter { ObPartitionTableIterator iter; ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_valid_version()); ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_server(A)); ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); // tid: 1 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); // tid: 2 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); // tid: 50001 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_)); ASSERT_EQ(A, partition.get_replicas_v2().at(0).server_); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_)); ASSERT_EQ(A, partition.get_replicas_v2().at(0).server_); } // iter empty partition { ObPartitionTableIterator iter; iter.get_filters().set_zone("1024"); // non exist zone ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); // tid: 1 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(0, partition.replica_count()); ASSERT_EQ(1UL, extract_pure_id(partition.get_table_id())); // tid: 2 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(0, partition.replica_count()); ASSERT_EQ(2UL, extract_pure_id(partition.get_table_id())); // tid: 50001 ... } // fitler empty partition { ObPartitionTableIterator iter; ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_valid_version()); ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_server(B)); ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); // tid: 50001 ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(1, partition.replica_count()); ASSERT_EQ(50001UL, extract_pure_id(partition.get_table_id())); ASSERT_EQ(B, partition.get_replicas_v2().at(0).server_); } { ObPartitionTableIterator iter; ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_valid_version()); ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_server(E)); // non exist server ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, false)); ASSERT_EQ(OB_ITER_END, iter.next(partition)); } } } class MockPartitionInfo : public ObPartitionInfo { public: MOCK_METHOD1(filter, int(const ObIReplicaFilter&)); }; class MockPartitionTableOperator : public ObPartitionTableOperator { public: MockPartitionTableOperator(ObIPartPropertyGetter& prop_getter, ObPartitionTableOperator& pt_operator) : ObPartitionTableOperator(prop_getter), pt_operator_(pt_operator), return_error_(false) {} MOCK_METHOD3(get, int(const uint64_t, const int64_t, ObPartitionInfo&)); int prefetch(const uint64_t tenant_id, const uint64_t start_table_id, const int64_t start_partition_id, ObIArray& partition_infos, bool ignore_row_checksum, bool use_sys_tenant) { UNUSED(ignore_row_checksum); if (return_error_) { return OB_ERR_UNEXPECTED; } else { return pt_operator_.prefetch( tenant_id, start_table_id, start_partition_id, partition_infos, false, use_sys_tenant); } } void set_return_error(const bool return_error) { return_error_ = return_error; } private: ObPartitionTableOperator& pt_operator_; bool return_error_; }; TEST_F(TestPartitionTableIterator, fail) { LOG_INFO("case TestPartitionTableIterator.fail"); GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_TENANT_ONLY; ObPartitionInfo partition; ObSchemaGetterGuard schema_guard; EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(schema_guard)); // table partition iterator { ObTablePartitionIterator iter; ASSERT_NE(OB_SUCCESS, iter.init(combine_id(1, OB_INVALID_ID), schema_guard, operator_)); ObPartitionTableOperator opt(prop_getter_); ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(1, 1), schema_guard, opt)); ASSERT_NE(OB_SUCCESS, iter.next(partition)); // fail: opt not init } // partition table iterator init { ObPartitionTableIterator iter; ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); ASSERT_EQ(OB_INIT_TWICE, iter.init(operator_, multi_schema_service_, true)); } // partition operator get fail { MockPartitionTableOperator opt(prop_getter_, operator_); ASSERT_EQ(OB_SUCCESS, opt.init(db_initer_.get_sql_proxy(), NULL)); // first call fail { opt.set_return_error(true); ObPartitionTableIterator iter; ASSERT_EQ(OB_SUCCESS, iter.init(opt, multi_schema_service_, true)); ASSERT_NE(OB_SUCCESS, iter.next(partition)); } // second call fail { opt.set_return_error(false); ObPartitionTableIterator iter; rootserver::ObRootService rs; rootserver::ObRootService::RsListChangeCb cb(rs); opt.set_callback_for_rs(cb, merge_error_cb_); ASSERT_EQ(OB_SUCCESS, iter.init(opt, multi_schema_service_, true)); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); ASSERT_EQ(OB_SUCCESS, iter.next(partition)); opt.set_return_error(true); ASSERT_NE(OB_SUCCESS, iter.next(partition)); } } // partition filter fail { MockPartitionInfo p; ObPartitionTableIterator iter; ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true)); EXPECT_CALL(p, filter(_)).WillOnce(Return(OB_ERR_UNEXPECTED)); ASSERT_NE(OB_SUCCESS, iter.next(p)); } } TEST_F(TestPartitionTableIterator, tenant) { int ret = OB_SUCCESS; const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY, ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE, ObMetaTableMode::METATABLE_MODE_TENANT_ONLY}; for (int i = 0; i < ARRAYSIZEOF(modes); i++) { LOG_INFO("case tenant: use mode ", K(modes[i])); GCONF.meta_table_read_write_mode = modes[i]; const uint64_t tenant_id = 3001 + i; const int64_t table_count = 100; ObTenantSchema tenant; ObTableSchema table; ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(tenant_id, tenant)); // ASSERT_EQ(OB_SUCCESS, schema_service_.add_tenant(tenant)); CREATE_TENANT(ret, tenant); if (modes[i] >= ObMetaTableMode::METATABLE_MODE_SYS_ONLY) { ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant.get_tenant_id())); } // replica count is 200 for (int64_t i = 0; i < table_count; ++i) { const uint64_t pure_id = 50001 + static_cast(i); ASSERT_EQ(OB_SUCCESS, gen_table_schema(tenant_id, pure_id, 1, 1, table)); table.set_part_level(PARTITION_LEVEL_ZERO); table.set_table_type(USER_TABLE); CREATE_USER_TABLE_SCHEMA(ret, table); // ASSERT_EQ(OB_SUCCESS, schema_service_.add_table(table)); prop_getter_.clear() .add(combine_id(tenant_id, pure_id), 0, A, LEADER) .add(combine_id(tenant_id, pure_id), 0, B, FOLLOWER); for (int64_t j = 0; j < prop_getter_.get_replicas().count(); j++) { GCONF.self_addr_ = prop_getter_.get_replicas().at(j).server_; ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(j))); } } ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema()); // case 1: one prefetch get all replicas // case 2: one prefetch can just get all replicas, but we don't konw whether last partition // is complete, trim last partition, prefetch again // case 3: one prefetch can't not get all replicas const int64_t prefetch_counts[] = {400, 200, 80}; for (int64_t idx = 0; idx < ARRAYSIZEOF(prefetch_counts); ++idx) { GCONF.partition_table_scan_batch_count = prefetch_counts[idx]; ObTenantPartitionIterator tenant_partition_iter; ASSERT_EQ(OB_SUCCESS, tenant_partition_iter.init(operator_, multi_schema_service_, tenant_id, false)); ObPartitionInfo partition; while (OB_SUCC(tenant_partition_iter.next(partition))) { if (partition.get_table_id() == combine_id(tenant_id, 50001)) { ASSERT_EQ(2, partition.get_replicas_v2().count()); break; } } for (int64_t i = 1; i < table_count; ++i) { const uint64_t pure_id = 50001 + static_cast(i); ASSERT_EQ(OB_SUCCESS, tenant_partition_iter.next(partition)); ASSERT_EQ(combine_id(tenant_id, pure_id), partition.get_table_id()); ASSERT_EQ(2, partition.get_replicas_v2().count()); } ASSERT_EQ(OB_ITER_END, tenant_partition_iter.next(partition)); } // iterator all partition ObPartitionTableIterator pt_iter; ASSERT_EQ(OB_SUCCESS, pt_iter.init(operator_, multi_schema_service_, true)); ret = OB_SUCCESS; while (OB_SUCC(ret)) { ObPartitionInfo partition; ret = pt_iter.next(partition); } ASSERT_EQ(OB_ITER_END, ret); if (modes[i] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant.get_tenant_id())); } DROP_TENANT(ret, tenant_id); } } TEST_F(TestPartitionTableIterator, by_partition) { LOG_INFO("case by_partition"); int ret = OB_SUCCESS; GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_TENANT_ONLY; // partition not in schema, full partition table iterator can still get them const uint64_t tenant_id = 1001; ObTenantSchema tenant; ObTableSchema table; ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(tenant_id, tenant)); // ASSERT_EQ(OB_SUCCESS, schema_service_.add_tenant(tenant)); CREATE_TENANT(ret, tenant); ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant.get_tenant_id())); ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema()); const int64_t table_count = 100; // replica count is 200 for (int64_t i = 0; i < table_count; ++i) { const uint64_t pure_id = 50001 + static_cast(i); prop_getter_.clear() .add(combine_id(tenant_id, pure_id), 0, A, LEADER) .add(combine_id(tenant_id, pure_id), 0, B, FOLLOWER); for (int64_t j = 0; j < prop_getter_.get_replicas().count(); j++) { GCONF.self_addr_ = prop_getter_.get_replicas().at(j).server_; ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(j))); } } // iterator all partition const int64_t prefetch_counts[] = {400, 200, 80}; for (int64_t idx = 0; idx < ARRAYSIZEOF(prefetch_counts); ++idx) { int ret = OB_SUCCESS; GCONF.partition_table_scan_batch_count = prefetch_counts[idx]; ObFullPartitionTableIterator pt_iter; ASSERT_EQ(OB_SUCCESS, pt_iter.init(operator_, multi_schema_service_)); ObPartitionInfo partition; int64_t sys_tenant_part_cnt = 0; int64_t normal_tenant_part_cnt = 0; while (OB_SUCC(ret)) { ObPartitionInfo partition; ret = pt_iter.next(partition); LOG_INFO("xx", K(partition)); if (OB_SUCC(ret)) { if (OB_SYS_TENANT_ID == partition.get_tenant_id()) { ++sys_tenant_part_cnt; } else { ++normal_tenant_part_cnt; } } } ASSERT_EQ(OB_ITER_END, ret); ASSERT_EQ(2, sys_tenant_part_cnt); ASSERT_EQ(2 + table_count, normal_tenant_part_cnt); } ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant.get_tenant_id())); DROP_TENANT(ret, tenant_id); } TEST_F(TestPartitionTableIterator, prefetch_second_fail) { int ret = OB_SUCCESS; GCONF.partition_table_scan_batch_count = 300; const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY, ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE, ObMetaTableMode::METATABLE_MODE_TENANT_ONLY}; for (int i = 0; i < ARRAYSIZEOF(modes); i++) { LOG_INFO("case prefetch_second_fail: use mode ", K(modes[i])); GCONF.meta_table_read_write_mode = modes[i]; const uint64_t tenant_id = 1001; const int64_t table_count = 3; for (int64_t i = 0; i < table_count; ++i) { const uint64_t pure_id = 50001 + static_cast(i); const int64_t part_num = 100; for (int64_t j = 0; j < part_num; ++j) { prop_getter_.clear() .add(combine_id(tenant_id, pure_id), j, A, LEADER) .add(combine_id(tenant_id, pure_id), j, B, FOLLOWER); for (int64_t k = 0; k < prop_getter_.get_replicas().count(); k++) { GCONF.self_addr_ = prop_getter_.get_replicas().at(k).server_; ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(k))); } } } ObTenantSchema tenant; ObTableSchema table; ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(tenant_id, tenant)); // ASSERT_EQ(OB_SUCCESS, schema_service_.add_tenant(tenant)); CREATE_TENANT(ret, tenant); if (modes[i] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant.get_tenant_id())); } for (int64_t i = 0; i < table_count; ++i) { const uint64_t pure_id = 50001 + static_cast(i); ASSERT_EQ(OB_SUCCESS, gen_table_schema(tenant_id, pure_id, 1, 1, table)); table.set_table_type(USER_TABLE); table.set_part_level(PARTITION_LEVEL_ONE); table.get_part_option().set_part_num(100); CREATE_USER_TABLE_SCHEMA(ret, table); // ASSERT_EQ(OB_SUCCESS, schema_service.add_table(table)); // user table } ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema()); common::ObMySQLProxy sql_proxy; MockPartitionTableOperator pt(prop_getter_, operator_); pt.init(sql_proxy, NULL); ObTenantPartitionIterator iter; ASSERT_EQ(OB_SUCCESS, iter.init(pt, multi_schema_service_, tenant_id, false)); for (int64_t i = 0; i < 100; ++i) { ObPartitionInfo partition; ASSERT_EQ(OB_SUCCESS, iter.next(partition)); } // ASSERT_EQ(OB_SUCCESS, schema_service.del_table(combine_id(tenant_id, 50002))); const ObTableSchema* table_schema = NULL; ObSchemaGetterGuard schema_guard; ASSERT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(schema_guard)); ASSERT_EQ(OB_SUCCESS, schema_guard.get_table_schema(combine_id(tenant_id, 50002), table_schema)); DROP_USER_TABLE_SCHEMA(ret, *table_schema); ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema()); ObPartitionInfo partition; ASSERT_EQ(OB_SUCCESS, iter.next(partition)); if (modes[i] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) { ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant.get_tenant_id())); } DROP_TENANT(ret, tenant_id); } } } // end namespace share } // end namespace oceanbase int main(int argc, char** argv) { system("rm -f test_partition_table_iterator.log"); oceanbase::common::ObLogger::get_logger().set_log_level("INFO"); OB_LOGGER.set_log_level("INFO"); OB_LOGGER.set_file_name("test_partition_table_iterator.log", true); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }