/** * 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 RS #include "ob_root_utils.h" #include "ob_balance_info.h" #include "ob_unit_manager.h" #include "lib/json/ob_json.h" #include "lib/string/ob_sql_string.h" #include "lib/hash/ob_hashset.h" #include "lib/mysqlclient/ob_mysql_result.h" #include "share/ob_rpc_struct.h" #include "share/ob_share_util.h" #include "share/ob_common_rpc_proxy.h" #include "share/schema/ob_table_schema.h" #include "share/schema/ob_schema_struct.h" #include "share/schema/ob_multi_version_schema_service.h" // ObMultiVersionSchemaService #include "share/schema/ob_schema_getter_guard.h" // ObSchemaGetterGuard #include "share/inner_table/ob_inner_table_schema_constants.h" #include "storage/tx/ob_ts_mgr.h" #include "rootserver/ob_unit_manager.h" #include "rootserver/ob_root_service.h" #include "rootserver/ob_ddl_service.h" #include "observer/ob_server_struct.h" #include "logservice/palf_handle_guard.h" #include "logservice/ob_log_service.h" #include "share/system_variable/ob_system_variable_alias.h" #include "share/ob_primary_zone_util.h" // ObPrimaryZoneUtil #include "share/ob_server_table_operator.h" #include "share/ob_zone_table_operation.h" #include "rootserver/ob_tenant_balance_service.h" // for ObTenantBalanceService using namespace oceanbase::rootserver; using namespace oceanbase::share; using namespace oceanbase::share::schema; using namespace oceanbase::common; using namespace oceanbase::common::hash; using namespace oceanbase::common::sqlclient; using namespace oceanbase::obrpc; int ObTenantUtils::get_tenant_ids( ObMultiVersionSchemaService *schema_service, ObIArray &tenant_ids) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; if (OB_ISNULL(schema_service)) { ret = OB_NOT_INIT; LOG_WARN("schema service not init", K(ret)); } else if (OB_FAIL(schema_service->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("get_schema_guard failed", K(ret)); } else if (OB_FAIL(schema_guard.get_tenant_ids(tenant_ids))) { LOG_WARN("get_tenant_ids failed", K(ret)); } return ret; } int ObTenantUtils::get_tenant_ids( ObMultiVersionSchemaService *schema_service, int64_t &sys_schema_version, ObIArray &tenant_ids) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; if (OB_ISNULL(schema_service)) { ret = OB_NOT_INIT; LOG_WARN("schema service not init", K(ret)); } else if (OB_FAIL(schema_service->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("get_schema_guard failed", K(ret)); } else if (OB_FAIL(schema_guard.get_tenant_ids(tenant_ids))) { LOG_WARN("get_tenant_ids failed", K(ret)); } else if (OB_FAIL(schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_schema_version))) { LOG_WARN("fail to get schema version", KR(ret)); } return ret; } bool ObTenantUtils::is_balance_target_schema( const share::schema::ObSimpleTableSchemaV2 &table_schema) { return USER_TABLE == table_schema.get_table_type() || TMP_TABLE == table_schema.get_table_type() || MATERIALIZED_VIEW == table_schema.get_table_type() || TMP_TABLE_ORA_SESS == table_schema.get_table_type() || TMP_TABLE_ORA_TRX == table_schema.get_table_type() || TMP_TABLE_ALL == table_schema.get_table_type() || AUX_VERTIAL_PARTITION_TABLE == table_schema.get_table_type() || table_schema.is_global_index_table(); } bool ObRootServiceRoleChecker::is_rootserver() { bool bret = false; int ret = OB_SUCCESS; const uint64_t tenant_id = OB_SYS_TENANT_ID; MTL_SWITCH(tenant_id) { int64_t proposal_id = -1; ObRole role = FOLLOWER; palf::PalfHandleGuard palf_handle_guard; logservice::ObLogService *log_service = nullptr; if (OB_ISNULL(log_service = MTL(logservice::ObLogService*))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("MTL ObLogService is null", KR(ret), K(tenant_id)); } else if (OB_FAIL(log_service->open_palf(SYS_LS, palf_handle_guard))) { LOG_WARN("open palf failed", KR(ret), K(tenant_id)); } else if (OB_FAIL(palf_handle_guard.get_role(role, proposal_id))) { LOG_WARN("get role failed", KR(ret), K(tenant_id)); } else { bret = (is_strong_leader(role)); LOG_DEBUG("get __all_core_table role", K(role), K(bret)); } } else { if (OB_TENANT_NOT_IN_SERVER == ret) { ret = OB_SUCCESS; } else { LOG_WARN("fail to get tenant storage", KR(ret), "tenant_id", OB_SYS_TENANT_ID); } } return bret; } const char *ObRootBalanceHelp::BalanceItem[] = { "ENABLE_REBUILD", "ENABLE_EMERGENCY_REPLICATE", "ENABLE_TYPE_TRANSFORM", "ENABLE_DELETE_REDUNDANT", "ENABLE_REPLICATE_TO_UNIT", "ENABLE_SHRINK", "ENABLE_REPLICATE", "ENABLE_COORDINATE_PG", "ENABLE_MIGRATE_TO_UNIT", "ENABLE_PARTITION_BALANCE", "ENABLE_UNIT_BALANCE", "ENABLE_SERVER_BALANCE", "ENABLE_CANCEL_UNIT_MIGRATION", "ENABLE_MODIFY_PAXOS_REPLICA_NUMBER", "ENABLE_STOP_SERVER", "" }; int ObRootBalanceHelp::parse_balance_info(const ObString &json_str, ObRootBalanceHelp::BalanceController &switch_info) { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::OB_JSON_PARSER); json::Parser parser; json::Value *data = NULL; switch_info.reset(); if (json_str.empty()) { switch_info.init(); } else if (OB_FAIL(parser.init(&allocator))) { LOG_WARN("json parser init failed", K(ret)); } else if (OB_FAIL(parser.parse(json_str.ptr(), json_str.length(), data))) { LOG_WARN("parse json failed", K(ret), K(json_str)); } else if (NULL == data) { ret = OB_ERR_UNEXPECTED; LOG_WARN("no root value", K(ret)); } else if (json::JT_OBJECT != data->get_type()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("error json format", K(ret), K(json_str)); } else { DLIST_FOREACH_X(it, data->get_object(), OB_SUCC(ret)) { bool find = false; for (int64_t i = 0; i < ARRAYSIZEOF(BalanceItem) - 1 && !find && OB_SUCC(ret); i++) { if (it->name_.case_compare(BalanceItem[i]) == 0) { find = true; if (json::JT_STRING != it->value_->get_type()) { ret = OB_INVALID_CONFIG; LOG_WARN("invalid config", K(ret), K(json_str)); } else if (it->value_->get_string().case_compare("true") == 0) { switch_info.set(i, true); } else if (it->value_->get_string().case_compare("false") == 0) { switch_info.set(i, false); } else { ret = OB_INVALID_CONFIG; LOG_WARN("invalid config", K(ret), K(json_str)); } } // if (it->name_.case_compare } //for (int64_t i = 0; if (!find) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("get invalid token", K(ret), K(*it)); } } //DLIST_FOREACH_X(it } return ret; } int ObLocalityUtil::parse_zone_list_from_locality_str(ObString &locality_str, ObIArray &zone_list) { int ret = OB_SUCCESS; zone_list.reset(); if (locality_str.empty()) { //nothing todo } else { ObArray sub_locality; ObString trimed_string = locality_str.trim(); if (OB_FAIL(split_on(trimed_string, ',', sub_locality))) { LOG_WARN("fail to split string", K(ret), "locality", trimed_string); } else { ObArray zone_infos; ObZone tmp_zone; for (int64_t i = 0; i < sub_locality.count() && OB_SUCC(ret); i++) { zone_infos.reset(); tmp_zone.reset(); ObString sub_trimed_string = sub_locality.at(i).trim(); if (OB_FAIL(split_on(sub_trimed_string, '@', zone_infos))) { LOG_WARN("fail to split on string", K(ret), "string", sub_trimed_string); } else if (zone_infos.count() != 2) { //FULL{1},READONLY{1}@z3; //nothing todo } else if (OB_FAIL(tmp_zone.assign(zone_infos.at(1)))) { LOG_WARN("fail to assign zone", K(ret), K(zone_infos)); } else if (has_exist_in_array(zone_list, tmp_zone)) { //nothint todo } else if (OB_FAIL(zone_list.push_back(tmp_zone))) { LOG_WARN("fail to push back", K(ret)); } LOG_DEBUG("split sub locality", K(ret), K(sub_trimed_string), K(tmp_zone), K(zone_infos), K(tmp_zone), K(zone_list)); } } } return ret; } int ObTenantGroupParser::parse_tenant_groups( const common::ObString &ttg_str, common::ObIArray &tenant_groups) { int ret = OB_SUCCESS; int64_t end = ttg_str.length(); int64_t pos = 0; while (OB_SUCC(ret) && pos < end) { if (OB_FAIL(get_next_tenant_group(pos, end, ttg_str, tenant_groups))) { LOG_WARN("fail to parse single tenant group", K(ret), K(ttg_str)); } else if (OB_FAIL(jump_to_next_ttg(pos, end, ttg_str))) { LOG_WARN("fail to jump to next", K(ret)); } } return ret; } int ObTenantGroupParser::get_next_tenant_group( int64_t &pos, const int64_t end, const common::ObString &ttg_str, common::ObIArray &tenant_groups) { int ret = OB_SUCCESS; jump_over_space(pos, end, ttg_str); if (pos >= end) { // reach to the end } else if ('(' != ttg_str[pos]) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else { // begin with a left brace ++pos; jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if ('"' == ttg_str[pos]) { ret = parse_vector_tenant_group(pos, end, ttg_str, tenant_groups); } else if ('(' == ttg_str[pos]) { ret = parse_matrix_tenant_group(pos, end, ttg_str, tenant_groups); } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } // end with a right brace if (OB_SUCC(ret)) { jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else if (')' != ttg_str[pos]) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else { ++pos; } } } return ret; } int ObTenantGroupParser::get_next_tenant_name( int64_t &pos, const int64_t end, const common::ObString &ttg_str, common::ObString &tenant_name) { int ret = OB_SUCCESS; jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if ('"' != ttg_str[pos]) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else { ++pos; // jump over the " symbol jump_over_space(pos, end, ttg_str); int64_t start = pos; while (pos < end && !isspace(ttg_str[pos]) && '"' != ttg_str[pos]) { ++pos; } if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else { tenant_name.assign_ptr(ttg_str.ptr() + start, static_cast(pos - start)); } // end with a " symbol if (OB_SUCC(ret)) { jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else if ('"' != ttg_str[pos]) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else { ++pos; } } } return ret; } int ObTenantGroupParser::jump_to_next_tenant_name( int64_t &pos, const int64_t end, const common::ObString &ttg_str) { int ret = OB_SUCCESS; jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else if (',' == ttg_str[pos]) { ++pos; jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else if ('"' != ttg_str[pos]) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } else {} // good, come across a " symbol } else if (')' == ttg_str[pos]) { // good, reach the end of this vector } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(pos)); } return ret; } int ObTenantGroupParser::parse_tenant_vector( int64_t &pos, const int64_t end, const common::ObString &ttg_str, common::ObIArray &tenant_names) { int ret = OB_SUCCESS; tenant_names.reset(); while (OB_SUCC(ret) && pos < end && ')' != ttg_str[pos]) { ObString tenant_name; if (OB_FAIL(get_next_tenant_name(pos, end, ttg_str, tenant_name))) { LOG_WARN("fail to get next tenant name", K(ret)); } else if (has_exist_in_array(all_tenant_names_, tenant_name)) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if (OB_FAIL(tenant_names.push_back(tenant_name))) { LOG_WARN("fail to push back", K(ret)); } else if (OB_FAIL(all_tenant_names_.push_back(tenant_name))) { LOG_WARN("fail to push back", K(ret)); } else if (OB_FAIL(jump_to_next_tenant_name(pos, end, ttg_str))) { LOG_WARN("fail to jump to next tenant name", K(ret)); } else {} // next loop round } return ret; } int ObTenantGroupParser::parse_vector_tenant_group( int64_t &pos, const int64_t end, const common::ObString &ttg_str, common::ObIArray &tenant_groups) { int ret = OB_SUCCESS; TenantNameGroup tenant_group; common::ObArray tenant_names; if (OB_FAIL(parse_tenant_vector(pos, end, ttg_str, tenant_names))) { LOG_WARN("fail to parse tenant vector", K(ret)); } else if (OB_FAIL(append(tenant_group.tenants_, tenant_names))) { LOG_WARN("fail to append", K(ret)); } else { tenant_group.row_ = 1; tenant_group.column_ = tenant_group.tenants_.count(); if (OB_FAIL(tenant_groups.push_back(tenant_group))) { LOG_WARN("fail to push back", K(ret)); } } return ret; } int ObTenantGroupParser::parse_matrix_tenant_group( int64_t &pos, const int64_t end, const common::ObString &ttg_str, common::ObIArray &tenant_groups) { int ret = OB_SUCCESS; TenantNameGroup tenant_group; common::ObArray tenant_names; bool first = true; // parse the second layer of two layer bracket structure while (OB_SUCC(ret) && pos < end && ')' != ttg_str[pos]) { tenant_names.reset(); jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if ('(' != ttg_str[pos]) { // start with left brace ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else { ++pos; // jump over left brace } if (OB_SUCC(ret)) { if (OB_FAIL(parse_tenant_vector(pos, end, ttg_str, tenant_names))) { LOG_WARN("fail to parse tenant vector", K(ret)); } else if (first) { tenant_group.column_ = tenant_names.count(); tenant_group.row_ = 0; first = false; } else if (tenant_group.column_ != tenant_names.count()) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } } if (OB_SUCC(ret)) { if (OB_FAIL(append(tenant_group.tenants_, tenant_names))) { LOG_WARN("fail to append", K(ret)); } else { ++tenant_group.row_; } } if (OB_SUCC(ret)) { jump_over_space(pos, end, ttg_str); if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if (')' != ttg_str[pos]) { // end up with right brace for a row tenant ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else { ++pos; } } if (OB_SUCC(ret)) { if (OB_FAIL(jump_to_next_tenant_vector(pos, end, ttg_str))) { LOG_WARN("fail to jump to next tenant vector", K(ret)); } } } if (OB_SUCC(ret)) { if (tenant_group.row_ <= 0 || tenant_group.column_ <= 0) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if (OB_FAIL(tenant_groups.push_back(tenant_group))) { LOG_WARN("fail to push back", K(ret)); } else {} // no more to do } return ret; } int ObTenantGroupParser::jump_to_next_tenant_vector( int64_t &pos, const int64_t end, const common::ObString &ttg_str) { int ret = OB_SUCCESS; while (pos < end && isspace(ttg_str[pos])) { ++pos; } if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if (')' == ttg_str[pos]) { // reach to the end of this tenant group } else if (',' == ttg_str[pos]) { ++pos; // good, and jump over the ',' symbol while (pos < end && isspace(ttg_str[pos])) { ++pos; } if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if ('(' == ttg_str[pos]) { // the next tenant vector left brace } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } return ret; } void ObTenantGroupParser::jump_over_space( int64_t &pos, const int64_t end, const common::ObString &ttg_str) { while (pos < end && isspace(ttg_str[pos])) { ++pos; } return; } int ObTenantGroupParser::jump_to_next_ttg( int64_t &pos, const int64_t end, const common::ObString &ttg_str) { int ret = OB_SUCCESS; while (pos < end && isspace(ttg_str[pos])) { ++pos; } if (pos >= end) { // good, reach end } else if (',' == ttg_str[pos]) { ++pos; // good, and jump over the ',' symbol while (pos < end && isspace(ttg_str[pos])) { ++pos; } if (pos >= end) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } else if ('(' == ttg_str[pos]) { // good, the next ttg left brace symbol } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("invalid tenantgroup string syntax", K(ret), K(ttg_str), K(pos)); } return ret; } int ObLocalityTaskHelp::filter_logonly_task(const common::ObIArray &pools, ObUnitManager &unit_mgr, ObIArray &zone_locality) { int ret = OB_SUCCESS; ObArray logonly_unit_infos; ObArray unit_infos; if (pools.count() <= 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(pools)); } else if (OB_FAIL(unit_mgr.get_unit_infos(pools, unit_infos))) { LOG_WARN("fail to get unit infos", K(ret), K(pools)); } else { for (int64_t i = 0; i < unit_infos.count() && OB_SUCC(ret); ++i) { if (REPLICA_TYPE_LOGONLY != unit_infos.at(i).unit_.replica_type_) { // only L unit is counted } else if (OB_FAIL(logonly_unit_infos.push_back(unit_infos.at(i)))) { LOG_WARN("fail to push back", K(ret), K(i), K(unit_infos)); } } for (int64_t i = 0; i < zone_locality.count() && OB_SUCC(ret); ++i) { share::ObZoneReplicaAttrSet &zone_replica_attr_set = zone_locality.at(i); if (zone_replica_attr_set.get_logonly_replica_num() + zone_replica_attr_set.get_encryption_logonly_replica_num() <= 0) { // no L replica : nothing todo } else if (zone_replica_attr_set.zone_set_.count() <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("zone set unexpected", K(ret), K(zone_replica_attr_set)); } else { for (int64_t j = 0; j < logonly_unit_infos.count(); j++) { const ObUnitInfo &unit_info = logonly_unit_infos.at(j); if (!has_exist_in_array(zone_replica_attr_set.zone_set_, unit_info.unit_.zone_)) { // bypass } else if (zone_replica_attr_set.get_logonly_replica_num() + zone_replica_attr_set.get_encryption_logonly_replica_num() <= 0) { // bypass } else if (zone_replica_attr_set.get_logonly_replica_num() > 0) { ret = zone_replica_attr_set.sub_logonly_replica_num(ReplicaAttr(1, 100)); } else { ret = zone_replica_attr_set.sub_encryption_logonly_replica_num(ReplicaAttr(1, 100)); } } } } } return ret; } int ObLocalityTaskHelp::get_logonly_task_with_logonly_unit(const uint64_t tenant_id, ObUnitManager &unit_mgr, share::schema::ObSchemaGetterGuard &schema_guard, ObIArray &zone_locality) { int ret = OB_SUCCESS; ObArray logonly_unit_infos; const ObTenantSchema *tenant_schema = NULL; zone_locality.reset(); common::ObArray tenant_zone_locality; if (OB_INVALID_ID == tenant_id) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_guard.get_tenant_info(tenant_id, tenant_schema))) { LOG_WARN("fail to get tenant info", K(ret), K(tenant_id)); } else if (OB_ISNULL(tenant_schema)) { ret = OB_TENANT_NOT_EXIST; LOG_WARN("get invalid tenant schema", K(ret), K(tenant_schema)); } else if (OB_FAIL(unit_mgr.get_logonly_unit_by_tenant(tenant_id, logonly_unit_infos))) { LOG_WARN("fail to get logonly unit infos", K(ret), K(tenant_id)); } else if (OB_FAIL(tenant_schema->get_zone_replica_attr_array(tenant_zone_locality))) { LOG_WARN("fail to get zone replica attr array", K(ret)); } else { share::ObZoneReplicaNumSet logonly_set; for (int64_t i = 0; i < logonly_unit_infos.count() && OB_SUCC(ret); i++) { const ObUnitInfo &unit = logonly_unit_infos.at(i); for (int64_t j = 0; j < tenant_zone_locality.count(); j++) { logonly_set.reset(); const ObZoneReplicaNumSet &zone_set = tenant_zone_locality.at(j); if (zone_set.zone_ == unit.unit_.zone_ && zone_set.get_logonly_replica_num() == 1) { logonly_set.zone_ = zone_set.zone_; if (OB_FAIL(logonly_set.replica_attr_set_.add_logonly_replica_num(ReplicaAttr(1, 100)))) { LOG_WARN("fail to add logonly replica num", K(ret)); } else if (OB_FAIL(zone_locality.push_back(logonly_set))) { LOG_WARN("fail to push back", K(ret)); } } else if (zone_set.zone_ == unit.unit_.zone_ && zone_set.get_encryption_logonly_replica_num() == 1) { logonly_set.zone_ = zone_set.zone_; if (OB_FAIL(logonly_set.replica_attr_set_.add_encryption_logonly_replica_num(ReplicaAttr(1, 100)))) { LOG_WARN("fail to add logonly replica num", K(ret)); } else if (OB_FAIL(zone_locality.push_back(logonly_set))) { LOG_WARN("fail to push back", K(ret)); } } } } } return ret; } int ObLocalityTaskHelp::filter_logonly_task(const uint64_t tenant_id, ObUnitManager &unit_mgr, share::schema::ObSchemaGetterGuard &schema_guard, ObIArray &zone_locality) { int ret = OB_SUCCESS; ObArray logonly_unit_infos; if (OB_FAIL(unit_mgr.get_logonly_unit_by_tenant(schema_guard, tenant_id, logonly_unit_infos))) { LOG_WARN("fail to get loggonly unit by tenant", K(ret), K(tenant_id)); } else { LOG_DEBUG("get all logonly unit", K(tenant_id), K(logonly_unit_infos), K(zone_locality)); for (int64_t i = 0; i < zone_locality.count() && OB_SUCC(ret); ++i) { share::ObZoneReplicaAttrSet &zone_replica_attr_set = zone_locality.at(i); if (zone_replica_attr_set.get_logonly_replica_num() + zone_replica_attr_set.get_encryption_logonly_replica_num() <= 0) { // no L replica : nothing todo } else if (zone_replica_attr_set.zone_set_.count() <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("zone set unexpected", K(ret), K(zone_replica_attr_set)); } else { for (int64_t j = 0; j < logonly_unit_infos.count(); j++) { const ObUnitInfo &unit_info = logonly_unit_infos.at(j); if (!has_exist_in_array(zone_replica_attr_set.zone_set_, unit_info.unit_.zone_)) { // bypass } else if (zone_replica_attr_set.get_logonly_replica_num() + zone_replica_attr_set.get_encryption_logonly_replica_num() <= 0) { // bypass } else if (zone_replica_attr_set.get_logonly_replica_num() > 0) { ret = zone_replica_attr_set.sub_logonly_replica_num(ReplicaAttr(1, 100)); } else { ret = zone_replica_attr_set.sub_encryption_logonly_replica_num(ReplicaAttr(1, 100)); } } } } } return ret; } int ObLocalityTaskHelp::alloc_logonly_replica(ObUnitManager &unit_mgr, const ObIArray &pools, const common::ObIArray &zone_locality, ObPartitionAddr &partition_addr) { int ret = OB_SUCCESS; ObArray logonly_units; ObArray unit_infos; if (OB_FAIL(unit_mgr.get_unit_infos(pools, unit_infos))) { LOG_WARN("fail to get unit infos", K(ret), K(pools)); } else { for (int64_t i = 0; i < unit_infos.count() && OB_SUCC(ret); i++) { if (REPLICA_TYPE_LOGONLY != unit_infos.at(i).unit_.replica_type_) { //nothing todo } else if (OB_FAIL(logonly_units.push_back(unit_infos.at(i)))) { LOG_WARN("fail to push back", K(ret), K(i), K(unit_infos)); } } } ObReplicaAddr raddr; for (int64_t i = 0; i < logonly_units.count() && OB_SUCC(ret); i++) { for (int64_t j = 0; j < zone_locality.count() && OB_SUCC(ret); j++) { if (zone_locality.at(j).zone_ == logonly_units.at(i).unit_.zone_ && (zone_locality.at(j).get_logonly_replica_num() == 1 || zone_locality.at(j).get_encryption_logonly_replica_num() == 1)) { raddr.reset(); raddr.unit_id_ = logonly_units.at(i).unit_.unit_id_; raddr.addr_ = logonly_units.at(i).unit_.server_; raddr.zone_ = logonly_units.at(i).unit_.zone_; raddr.replica_type_ = zone_locality.at(j).get_logonly_replica_num() == 1 ? REPLICA_TYPE_LOGONLY : REPLICA_TYPE_ENCRYPTION_LOGONLY; if (OB_FAIL(partition_addr.push_back(raddr))) { LOG_WARN("fail to push back", K(ret), K(raddr)); } else { LOG_INFO("alloc partition for logonly replica", K(raddr)); } } } } return ret; } int ObLocalityCheckHelp::calc_paxos_replica_num( const common::ObIArray &zone_locality, int64_t &paxos_num) { int ret = OB_SUCCESS; paxos_num = 0; for (int64_t i = 0; OB_SUCC(ret) && i < zone_locality.count(); i++) { if (0 > zone_locality.at(i).get_paxos_replica_num()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid paxos replica num", K(ret), "zone_locality_set", zone_locality.at(i)); } else { paxos_num += zone_locality.at(i).get_paxos_replica_num(); } } return ret; } /* * the laws of alter locality: * 1. each locality altering only allows to execute one operation: add paoxs, reduce paxos and paxos type transform(paxos->paxos, F->L). * paxos->non_paxos is reduce paxos, non_paxos->paxos is add paxos. * 2. in a locality altering: * 2.1 if add paxos, need the orig_locality's paxos num >= majority(new_locality's paxos num); * 2.2 if reduce paxos, need new_locality's paxos num >= majority(orig_locality's paxos num); * 2.3 if paxos type transform, only one type transform is allowed for a locality altering. * 3. the laws of type transform: * 3.1 for L-replica, it is not allowed to transform replica_type other than F->L, * and it is not allowed to transform L to other type. * 4. enable paxos num 1->2. must not paxos num 2->1 * 5. there is no restriction on non-paoxs type transform */ int ObLocalityCheckHelp::check_alter_locality( const ObIArray &pre_zone_locality, const ObIArray &cur_zone_locality, ObIArray &alter_paxos_tasks, bool &non_paxos_locality_modified, int64_t &pre_paxos_num, int64_t &cur_paxos_num, const share::ObArbitrationServiceStatus &arb_service_status) { int ret = OB_SUCCESS; pre_paxos_num = 0; cur_paxos_num = 0; alter_paxos_tasks.reset(); if (OB_UNLIKELY(pre_zone_locality.count() <= 0 || cur_zone_locality.count() <= 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), "pre_cnt", pre_zone_locality.count(), "cur_cnt", cur_zone_locality.count()); } else if (OB_FAIL(get_alter_paxos_replica_number_replica_task(pre_zone_locality, cur_zone_locality, alter_paxos_tasks, non_paxos_locality_modified))) { LOG_WARN("fail to get alter paxos replica task", K(ret)); } else if (OB_FAIL(calc_paxos_replica_num(pre_zone_locality, pre_paxos_num))) { LOG_WARN("fail to calc paxos replica num", K(ret)); } else if (OB_FAIL(calc_paxos_replica_num(cur_zone_locality, cur_paxos_num))) { LOG_WARN("fail to calc paxos replica num", K(ret)); } else if (OB_FAIL(check_alter_locality_valid(alter_paxos_tasks, pre_paxos_num, cur_paxos_num, arb_service_status))) { LOG_WARN("check alter locality valid failed", K(ret), K(alter_paxos_tasks), K(pre_paxos_num), K(cur_paxos_num), K(non_paxos_locality_modified), K(arb_service_status)); } return ret; } /* * Two zone set either are perfect matched or have intersection */ int ObLocalityCheckHelp::check_multi_zone_locality_intersect( const common::ObIArray &multi_pre_zone_locality, const common::ObIArray &multi_cur_zone_locality, bool &intersect) { int ret = OB_SUCCESS; intersect = false; for (int64_t i = 0; !intersect && OB_SUCC(ret) && i < multi_pre_zone_locality.count(); ++i) { for (int64_t j = 0; !intersect && OB_SUCC(ret) && j < multi_cur_zone_locality.count(); ++j) { const share::ObZoneReplicaAttrSet &pre_locality = multi_pre_zone_locality.at(i); const share::ObZoneReplicaAttrSet &cur_locality = multi_cur_zone_locality.at(j); const common::ObIArray &pre_zone_set = pre_locality.zone_set_; const common::ObIArray &cur_zone_set = cur_locality.zone_set_; if (pre_zone_set.count() <= 1 || cur_zone_set.count() <= 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("zone set count unexpected", K(ret)); } else { intersect = check_zone_set_intersect(pre_zone_set, cur_zone_set); } } } return ret; } bool ObLocalityCheckHelp::check_zone_set_intersect( const common::ObIArray &pre_zone_set, const common::ObIArray &cur_zone_set) { bool intersect = false; if (pre_zone_set.count() == cur_zone_set.count()) { // either there is no crossover or there is a perfect match int64_t counter = 0; for (int64_t i = 0; i < pre_zone_set.count(); ++i) { const common::ObZone &this_pre_zone = pre_zone_set.at(i); if (has_exist_in_array(cur_zone_set, this_pre_zone)) { counter++; } } if (0 == counter || pre_zone_set.count() == counter) { intersect = false; } else { intersect = true; } } else { // must no cross intersect = false; for (int64_t i = 0; !intersect && i < pre_zone_set.count(); ++i) { const common::ObZone &this_pre_zone = pre_zone_set.at(i); if (has_exist_in_array(cur_zone_set, this_pre_zone)) { intersect = true; } } } return intersect; } int ObLocalityCheckHelp::split_single_and_multi_zone_locality( const common::ObIArray &zone_locality, common::ObIArray &single_zone_locality, common::ObIArray &multi_zone_locality) { int ret = OB_SUCCESS; if (OB_UNLIKELY(zone_locality.count() <= 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), "zone_locality_cnt", zone_locality.count()); } else { single_zone_locality.reset(); multi_zone_locality.reset(); for (int64_t i = 0; OB_SUCC(ret) && i < zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_set = zone_locality.at(i); if (this_set.zone_set_.count() <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("zone set count unexpected", K(ret), "zone_set_cnt", this_set.zone_set_.count()); } else if (this_set.zone_set_.count() == 1) { if (OB_FAIL(single_zone_locality.push_back(this_set))) { LOG_WARN("fail to push back", K(ret)); } } else { if (OB_FAIL(multi_zone_locality.push_back(this_set))) { LOG_WARN("fail to push back", K(ret)); } } } } return ret; } int ObLocalityCheckHelp::single_zone_locality_search( const share::ObZoneReplicaAttrSet &this_locality, const common::ObIArray &single_zone_locality, const common::ObIArray &multi_zone_locality, SingleZoneLocalitySearch &search_flag, int64_t &search_index, const share::ObZoneReplicaAttrSet *&search_zone_locality) { int ret = OB_SUCCESS; if (OB_UNLIKELY(this_locality.zone_set_.count() != 1)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else { bool found = false; const common::ObZone &compare_zone = this_locality.zone_set_.at(0); for (int64_t i = 0; !found && OB_SUCC(ret) && i < single_zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_zone_locality = single_zone_locality.at(i); if (this_zone_locality.zone_set_.count() != 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("this zone set unexpected", K(ret), "zone_set_count", this_zone_locality.zone_set_.count()); } else if (compare_zone != this_zone_locality.zone_set_.at(0)) { // go on check next } else { found = true; search_flag = SingleZoneLocalitySearch::SZLS_IN_ASSOC_SINGLE; search_index = i; search_zone_locality = &this_zone_locality; } } for (int64_t i = 0; !found && OB_SUCC(ret) && i < multi_zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_zone_locality = multi_zone_locality.at(i); if (this_zone_locality.zone_set_.count() <= 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("this zone set unexpected", K(ret), "zone_set_count", this_zone_locality.zone_set_.count()); } else if (!has_exist_in_array(this_zone_locality.zone_set_, compare_zone)) { // go on check next } else { found = true; search_flag = SingleZoneLocalitySearch::SZLS_IN_ASSOC_MULTI; search_index = i; search_zone_locality = &this_zone_locality; } } if (OB_SUCC(ret)) { if (!found) { search_flag = SingleZoneLocalitySearch::SZLS_NOT_FOUND; search_index = -1; search_zone_locality = nullptr; } } } return ret; } int ObLocalityCheckHelp::try_add_single_zone_alter_paxos_task( const share::ObZoneReplicaAttrSet &pre_locality, const share::ObZoneReplicaAttrSet &cur_locality, common::ObIArray &alter_paxos_tasks, bool &non_paxos_locality_modified) { int ret = OB_SUCCESS; if (OB_UNLIKELY(pre_locality.zone_set_.count() != 1) || OB_UNLIKELY(cur_locality.zone_set_.count() != 1)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(pre_locality), K(cur_locality)); } else if (OB_FAIL(check_alter_single_zone_locality_valid( cur_locality, pre_locality, non_paxos_locality_modified))) { LOG_WARN("alter single zone locality is invalid", K(ret), K(cur_locality), K(pre_locality), K(non_paxos_locality_modified)); } else { AlterPaxosLocalityTask alter_paxos_task; if (pre_locality.get_paxos_replica_num() == cur_locality.get_paxos_replica_num()) { if (!pre_locality.is_paxos_locality_match(cur_locality)) { alter_paxos_task.reset(); alter_paxos_task.task_type_ = NOP_PAXOS_REPLICA_NUMBER; if (cur_locality.get_full_replica_num() > pre_locality.get_full_replica_num()) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_FULL))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && cur_locality.get_logonly_replica_num() > pre_locality.get_logonly_replica_num()) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_LOGONLY))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && cur_locality.get_encryption_logonly_replica_num() > pre_locality.get_encryption_logonly_replica_num()) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back( REPLICA_TYPE_ENCRYPTION_LOGONLY))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && cur_locality.get_logonly_replica_num() == pre_locality.get_logonly_replica_num() && cur_locality.get_encryption_logonly_replica_num() == pre_locality.get_encryption_logonly_replica_num() && cur_locality.get_full_replica_num() == pre_locality.get_full_replica_num()) { // memstore_percent changed if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_FULL))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(alter_paxos_task.zone_set_.assign(pre_locality.zone_set_))) { LOG_WARN("fail to assign array", K(ret)); } else if (OB_FAIL(alter_paxos_tasks.push_back(alter_paxos_task))) { LOG_WARN("fail to push back", K(ret)); } } else {} // paxos locality match } else { alter_paxos_task.reset(); const int64_t delta = cur_locality.get_paxos_replica_num() - pre_locality.get_paxos_replica_num(); alter_paxos_task.task_type_ = delta > 0 ? ADD_PAXOS_REPLICA_NUMBER : SUB_PAXOS_REPLICA_NUMBER; if (pre_locality.get_full_replica_num() != cur_locality.get_full_replica_num()) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_FULL))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && pre_locality.get_logonly_replica_num() != cur_locality.get_logonly_replica_num()) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_LOGONLY))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && pre_locality.get_encryption_logonly_replica_num() != cur_locality.get_encryption_logonly_replica_num()) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_ENCRYPTION_LOGONLY))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(alter_paxos_task.zone_set_.assign(pre_locality.zone_set_))) { LOG_WARN("fail to assign array", K(ret)); } else if (OB_FAIL(alter_paxos_tasks.push_back(alter_paxos_task))) { LOG_WARN("fail to push back", K(ret)); } } } return ret; } int ObLocalityCheckHelp::process_pre_single_zone_locality( const common::ObIArray &single_pre_zone_locality, const common::ObIArray &single_cur_zone_locality, const common::ObIArray &multi_cur_zone_locality, common::ObArray &pre_in_cur_multi_indexes, common::ObIArray &alter_paxos_tasks, bool &non_paxos_locality_modified) { int ret = OB_SUCCESS; pre_in_cur_multi_indexes.reset(); for (int64_t i = 0; OB_SUCC(ret) && i < single_pre_zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_locality = single_pre_zone_locality.at(i); SingleZoneLocalitySearch search_flag = SingleZoneLocalitySearch::SZLS_INVALID; int64_t search_index = -1; const share::ObZoneReplicaAttrSet *search_zone_locality = nullptr; if (OB_FAIL(single_zone_locality_search( this_locality, single_cur_zone_locality, multi_cur_zone_locality, search_flag, search_index, search_zone_locality))) { LOG_WARN("fail to search single zone locality", K(ret)); } else if (SingleZoneLocalitySearch::SZLS_IN_ASSOC_SINGLE == search_flag) { if (nullptr == search_zone_locality) { ret = OB_ERR_UNEXPECTED; LOG_WARN("search zone locality ptr is null", K(ret)); } else if (OB_FAIL(try_add_single_zone_alter_paxos_task( this_locality, *search_zone_locality, alter_paxos_tasks, non_paxos_locality_modified))) { LOG_WARN("fail to try add single zone alter paxos task", K(ret)); } } else if (SingleZoneLocalitySearch::SZLS_IN_ASSOC_MULTI == search_flag) { if (search_index >= multi_cur_zone_locality.count() || search_index < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("search index unexpected", K(ret), K(search_index), "multi_cur_zone_locality_cnt", multi_cur_zone_locality.count()); } else if (OB_FAIL(pre_in_cur_multi_indexes.push_back(XyIndex(i, search_index)))) { LOG_WARN("fail to push back", K(ret)); } } else if (SingleZoneLocalitySearch::SZLS_NOT_FOUND == search_flag) { // dealing with locality remove zone. ObZoneReplicaAttrSet cur_set; if (OB_FAIL(cur_set.zone_set_.assign(this_locality.zone_set_))) { LOG_WARN("fail to assign zone set", K(ret)); } else if (OB_FAIL(try_add_single_zone_alter_paxos_task( this_locality, cur_set, alter_paxos_tasks, non_paxos_locality_modified))) { LOG_WARN("fail to try add single zone alter paxos task", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("search flag unexpected", K(ret), K(search_flag)); } } if (OB_SUCC(ret)) { YIndexCmp cmp_operator; std::sort(pre_in_cur_multi_indexes.begin(), pre_in_cur_multi_indexes.end(), cmp_operator); } return ret; } int ObLocalityCheckHelp::process_cur_single_zone_locality( const common::ObIArray &single_cur_zone_locality, const common::ObIArray &single_pre_zone_locality, const common::ObIArray &multi_pre_zone_locality, common::ObArray &cur_in_pre_multi_indexes, common::ObIArray &alter_paxos_tasks, bool &non_paxos_locality_modified) { int ret = OB_SUCCESS; cur_in_pre_multi_indexes.reset(); for (int64_t i = 0; OB_SUCC(ret) && i < single_cur_zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_locality = single_cur_zone_locality.at(i); SingleZoneLocalitySearch search_flag = SingleZoneLocalitySearch::SZLS_INVALID; int64_t search_index = -1; const share::ObZoneReplicaAttrSet *search_zone_locality = nullptr; if (OB_FAIL(single_zone_locality_search( this_locality, single_pre_zone_locality, multi_pre_zone_locality, search_flag, search_index, search_zone_locality))) { LOG_WARN("fail to search single zone locality", K(ret)); } else if (SingleZoneLocalitySearch::SZLS_IN_ASSOC_SINGLE == search_flag) { // already process in process_pre_single_zone_locality } else if (SingleZoneLocalitySearch::SZLS_IN_ASSOC_MULTI == search_flag) { if (search_index >= multi_pre_zone_locality.count() || search_index < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("search index unexpected", K(ret), K(search_index), "multi_pre_zone_locality_cnt", multi_pre_zone_locality.count()); } else if (OB_FAIL(cur_in_pre_multi_indexes.push_back(XyIndex(i, search_index)))) { LOG_WARN("fail to push back", K(ret)); } } else if (SingleZoneLocalitySearch::SZLS_NOT_FOUND == search_flag) { // dealing with locality add zone ObZoneReplicaAttrSet pre_set; if (OB_FAIL(pre_set.zone_set_.assign(this_locality.zone_set_))) { LOG_WARN("fail to assign zone set", K(ret)); } else if (OB_FAIL(try_add_single_zone_alter_paxos_task( pre_set, this_locality, alter_paxos_tasks, non_paxos_locality_modified))) { LOG_WARN("fail to try add single zone alter paxos task", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("search flag unexpected", K(ret), K(search_flag)); } } if (OB_SUCC(ret)) { YIndexCmp cmp_operator; std::sort(cur_in_pre_multi_indexes.begin(), cur_in_pre_multi_indexes.end(), cmp_operator); } return ret; } int ObLocalityCheckHelp::add_multi_zone_locality_task( common::ObIArray &alter_paxos_tasks, const share::ObZoneReplicaAttrSet &multi_zone_locality, const PaxosReplicaNumberTaskType paxos_replica_number_task_type) { int ret = OB_SUCCESS; AlterPaxosLocalityTask alter_paxos_task; alter_paxos_task.reset(); alter_paxos_task.task_type_ = paxos_replica_number_task_type; if (OB_FAIL(alter_paxos_task.zone_set_.assign(multi_zone_locality.zone_set_))) { LOG_WARN("fail to assign zone set", K(ret)); } else { if (multi_zone_locality.get_full_replica_num() > 0) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_FULL))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && multi_zone_locality.get_logonly_replica_num() > 0) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_LOGONLY))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret) && multi_zone_locality.get_encryption_logonly_replica_num() > 0) { if (OB_FAIL(alter_paxos_task.associated_replica_type_set_.push_back(REPLICA_TYPE_ENCRYPTION_LOGONLY))) { LOG_WARN("fail to push back", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(alter_paxos_tasks.push_back(alter_paxos_task))) { LOG_WARN("fail to push back", K(ret)); } } } return ret; } int ObLocalityCheckHelp::check_alter_locality_match( const share::ObZoneReplicaAttrSet &in_locality, const share::ObZoneReplicaAttrSet &out_locality) { int ret = OB_SUCCESS; bool match = false; match = in_locality.is_alter_locality_match(out_locality); if (!match) { ret = OB_OP_NOT_ALLOW; LOG_WARN("too many locality changes are illegal", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "too many locality changes"); } return ret; } int ObLocalityCheckHelp::check_single_and_multi_zone_locality_match( const int64_t start, const int64_t end, const common::ObIArray &single_zone_locality, const common::ObIArray &in_multi_indexes, const share::ObZoneReplicaAttrSet &multi_zone_locality) { int ret = OB_SUCCESS; if (start >= end || start >= in_multi_indexes.count() || end > in_multi_indexes.count()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(start), K(end), "in_multi_indexes_cnt", in_multi_indexes.count()); } else { share::ObZoneReplicaAttrSet new_multi_zone_locality; for (int64_t i = start; OB_SUCC(ret) && i < end; ++i) { const int64_t x = in_multi_indexes.at(i).x_; if (x < 0 || x >= single_zone_locality.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("x unexpected", K(ret), K(x), "single_zone_locality_cnt", single_zone_locality.count()); } else if (OB_FAIL(new_multi_zone_locality.append(single_zone_locality.at(x)))) { LOG_WARN("fail to append", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(check_alter_locality_match( new_multi_zone_locality, multi_zone_locality))) { LOG_WARN("fail to check alter locality match", K(ret)); } } } return ret; } int ObLocalityCheckHelp::process_single_in_multi( const common::ObIArray &single_left_zone_locality, const common::ObIArray &left_in_multi_indexes, const common::ObIArray &multi_right_zone_locality, common::ObIArray &alter_paxos_tasks) { int ret = OB_SUCCESS; int64_t start = 0; int64_t end = left_in_multi_indexes.count(); while (OB_SUCC(ret) && start < end) { int64_t cursor = start; int64_t y_index = left_in_multi_indexes.at(start).y_; for (/*nop*/; cursor < end; ++cursor) { if (left_in_multi_indexes.at(start).y_ == left_in_multi_indexes.at(cursor).y_) { // go on } else { break; } } if (y_index < 0 || y_index >= multi_right_zone_locality.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("y_index unexpected", K(ret), K(y_index), "multi_zone_locality_cnt", multi_right_zone_locality.count()); } else if (OB_FAIL(check_single_and_multi_zone_locality_match( start, cursor, single_left_zone_locality, left_in_multi_indexes, multi_right_zone_locality.at(y_index)))) { } else if (OB_FAIL(add_multi_zone_locality_task( alter_paxos_tasks, multi_right_zone_locality.at(y_index), PaxosReplicaNumberTaskType::NOP_PAXOS_REPLICA_NUMBER))) { LOG_WARN("fail to add multi zone locality task", K(ret)); } else { start = cursor; } } return ret; } bool ObLocalityCheckHelp::has_exist_in_yindex_array( const common::ObIArray &index_array, const int64_t y) { bool found = false; for (int64_t i = 0; !found && i < index_array.count(); ++i) { const XyIndex &this_index = index_array.at(i); if (y == this_index.y_) { found = true; } } return found; } int ObLocalityCheckHelp::process_pre_multi_locality( const common::ObIArray &pre_in_cur_multi_indexes, const common::ObIArray &cur_in_pre_multi_indexes, const common::ObIArray &multi_pre_zone_locality, const common::ObIArray &multi_cur_zone_locality, common::ObIArray &alter_paxos_tasks) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < multi_pre_zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_pre_locality = multi_pre_zone_locality.at(i); if (has_exist_in_yindex_array(cur_in_pre_multi_indexes, i)) { // bypass, already processed } else { bool found = false; for (int64_t j = 0; !found && j < multi_cur_zone_locality.count(); ++j) { const share::ObZoneReplicaAttrSet &this_cur_locality = multi_cur_zone_locality.at(j); if (has_exist_in_yindex_array(pre_in_cur_multi_indexes, j)) { found = true; // bypass, already processed } else if (this_pre_locality == this_cur_locality) { found = true; // locality not modified } else if (this_cur_locality.is_zone_set_match(this_pre_locality)) { // is processing in process_cur_multi_locality found = true; } else { /* go on check next */ } if (OB_SUCC(ret)) { if (OB_FAIL(check_alter_locality_match( this_pre_locality, this_cur_locality))) { LOG_WARN("fail to check locality match", K(ret)); } } } if (!found && OB_SUCC(ret)) { if (OB_FAIL(add_multi_zone_locality_task( alter_paxos_tasks, this_pre_locality, PaxosReplicaNumberTaskType::SUB_PAXOS_REPLICA_NUMBER))) { LOG_WARN("fail to add multi zone locality task", K(ret)); } } } } return ret; } int ObLocalityCheckHelp::process_cur_multi_locality( const common::ObIArray &pre_in_cur_multi_indexes, const common::ObIArray &cur_in_pre_multi_indexes, const common::ObIArray &multi_pre_zone_locality, const common::ObIArray &multi_cur_zone_locality, common::ObIArray &alter_paxos_tasks) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < multi_cur_zone_locality.count(); ++i) { const share::ObZoneReplicaAttrSet &this_cur_locality = multi_cur_zone_locality.at(i); if (has_exist_in_yindex_array(pre_in_cur_multi_indexes, i)) { // bypass, already process } else { bool found = false; for (int64_t j = 0; !found && j < multi_pre_zone_locality.count(); ++j) { const share::ObZoneReplicaAttrSet &this_pre_locality = multi_pre_zone_locality.at(j); if (has_exist_in_yindex_array(cur_in_pre_multi_indexes, j)) { found = true; // bypass, already processed } else if (this_cur_locality == this_pre_locality) { found = true; // locality not modified } else if (this_cur_locality.is_zone_set_match(this_pre_locality)) { found = true; if (OB_FAIL(add_multi_zone_locality_task( alter_paxos_tasks, this_cur_locality, PaxosReplicaNumberTaskType::NOP_PAXOS_REPLICA_NUMBER))) { LOG_WARN("fail to add multi zone locality task", K(ret)); } } else { /* go on check next */ } if (OB_SUCC(ret)) { if (OB_FAIL(check_alter_locality_match( this_cur_locality, this_pre_locality))) { LOG_WARN("fail to check alter locality match", K(ret)); } } } if (!found && OB_SUCC(ret)) { if (OB_FAIL(add_multi_zone_locality_task( alter_paxos_tasks, this_cur_locality, PaxosReplicaNumberTaskType::ADD_PAXOS_REPLICA_NUMBER))) { LOG_WARN("fail to add multi zone locality task", K(ret)); } } } } return ret; } int ObLocalityCheckHelp::get_alter_paxos_replica_number_replica_task( const common::ObIArray &pre_zone_locality, const common::ObIArray &cur_zone_locality, ObIArray &alter_paxos_tasks, bool &non_paxos_locality_modified) { int ret = OB_SUCCESS; common::ObArray single_pre_zone_locality; common::ObArray multi_pre_zone_locality; common::ObArray single_cur_zone_locality; common::ObArray multi_cur_zone_locality; common::ObArray pre_in_cur_multi_indexes; common::ObArray cur_in_pre_multi_indexes; bool intersect = false; if (OB_UNLIKELY(pre_zone_locality.count() <= 0) || OB_UNLIKELY(cur_zone_locality.count() <= 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), "pre_cnt", pre_zone_locality.count(), "cur_cnt", cur_zone_locality.count()); } else if (OB_FAIL(split_single_and_multi_zone_locality( pre_zone_locality, single_pre_zone_locality, multi_pre_zone_locality))) { LOG_WARN("fail to split single and multi zone locality", K(ret)); } else if (OB_FAIL(split_single_and_multi_zone_locality( cur_zone_locality, single_cur_zone_locality, multi_cur_zone_locality))) { LOG_WARN("fail to split single and multi zone locality", K(ret)); } else if (OB_FAIL(check_multi_zone_locality_intersect( multi_pre_zone_locality, multi_cur_zone_locality, intersect))) { LOG_WARN("fail to check multi zone locality intersect", K(ret)); } else if (intersect) { ret = OB_OP_NOT_ALLOW; LOG_WARN("multi zone locality intersect before and after is not allowed", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "multi zone locality intersect before and after"); } else if (OB_FAIL(process_pre_single_zone_locality( single_pre_zone_locality, single_cur_zone_locality, multi_cur_zone_locality, pre_in_cur_multi_indexes, alter_paxos_tasks, non_paxos_locality_modified))) { LOG_WARN("fail to process pre single zone locality", K(ret)); } else if (OB_FAIL(process_cur_single_zone_locality( single_cur_zone_locality, single_pre_zone_locality, multi_pre_zone_locality, cur_in_pre_multi_indexes, alter_paxos_tasks, non_paxos_locality_modified))) { LOG_WARN("fail to process cur single zone locality", K(ret)); } else if (OB_FAIL(process_single_in_multi( single_pre_zone_locality, pre_in_cur_multi_indexes, multi_cur_zone_locality, alter_paxos_tasks))) { LOG_WARN("fail to process pre single in cur multi", K(ret)); } else if (OB_FAIL(process_single_in_multi( single_cur_zone_locality, cur_in_pre_multi_indexes, multi_pre_zone_locality, alter_paxos_tasks))) { LOG_WARN("fail to process cur single in pre multi", K(ret)); } else if (OB_FAIL(process_pre_multi_locality( pre_in_cur_multi_indexes, cur_in_pre_multi_indexes, multi_pre_zone_locality, multi_cur_zone_locality, alter_paxos_tasks))) { LOG_WARN("fail to process pre multi locality", K(ret)); } else if (OB_FAIL(process_cur_multi_locality( pre_in_cur_multi_indexes, cur_in_pre_multi_indexes, multi_pre_zone_locality, multi_cur_zone_locality, alter_paxos_tasks))) { LOG_WARN("fail to process cur multi locality", K(ret)); } return ret; } int ObLocalityCheckHelp::check_alter_locality_valid( ObIArray &alter_paxos_tasks, int64_t pre_paxos_num, int64_t cur_paxos_num, const share::ObArbitrationServiceStatus &arb_service_status) { int ret = OB_SUCCESS; if (pre_paxos_num <= 0 || cur_paxos_num <= 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("pre_paxos_num or cur_paxos_num is invalid", K(ret), K(pre_paxos_num), K(cur_paxos_num)); } else { // ensure only has ADD_PAXOS_REPLICA_NUMBER task or only SUB_PAXOS_REPLICA_NUMBER task or only one NOP_PAXOS_REPLICA_NUMBER task. int64_t add_task_num = 0; int64_t remove_task_num = 0; int64_t nop_task_num = 0; for (int64_t i = 0; OB_SUCC(ret) && i < alter_paxos_tasks.count(); i++) { const AlterPaxosLocalityTask &this_alter_paxos_task = alter_paxos_tasks.at(i); if (OB_FAIL(ret)) { } else if (SUB_PAXOS_REPLICA_NUMBER == this_alter_paxos_task.task_type_) { if (nop_task_num != 0 || add_task_num != 0) { ret = OB_OP_NOT_ALLOW; LOG_WARN("should only has one nop_task", K(ret), K(alter_paxos_tasks)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter locality with multi task"); } else { remove_task_num++; } } else if (ADD_PAXOS_REPLICA_NUMBER == alter_paxos_tasks.at(i).task_type_) { if (nop_task_num != 0 || remove_task_num != 0) { ret = OB_OP_NOT_ALLOW; LOG_WARN("should only has add_tasks", K(ret), K(alter_paxos_tasks)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter locality with multi task"); } else { add_task_num++; } } else if (NOP_PAXOS_REPLICA_NUMBER == alter_paxos_tasks.at(i).task_type_) { if (nop_task_num != 0 || add_task_num != 0 || remove_task_num != 0) { ret = OB_OP_NOT_ALLOW; LOG_WARN("should only has one nop_task", K(ret), K(alter_paxos_tasks)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter locality with multi task"); } else { nop_task_num++; } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid task_type", K(ret), "alter_paxos_task", alter_paxos_tasks.at(i)); } } // 2. Locality's paxos member change need to meet the following principles: // 1) only add paxos member and pre_paxos_num >= majority(cur_paxos_num) // 2) only remove paxos member and cur_paxos_num >= majority(pre_paxos_num) // 3) only has a paxos -> paxos's type transform task. // non_paxos -> paxos's type transform is add paxos member. // paxos -> non_paxos's type transform is remove paxos member if (OB_SUCC(ret)) { bool passed = true; ObSqlString message_to_user; if (0 != nop_task_num) { // only has paxos->paxos's type transform task, no quorum value change. } else if (0 != add_task_num) { if (arb_service_status.is_enable_like()) { if (2 == pre_paxos_num && 2 == add_task_num) { // special process: tenant with arb service should only support 2->4 } else if (OB_FAIL(message_to_user.assign("paxos replica number should be 2 or 4 when arbitration service is enabled, " "alter tenant locality"))) { LOG_WARN("fail to construct message to user", KR(ret)); } else { passed = false; } } else if (1 == pre_paxos_num && 1 == add_task_num) { // special process: enable locality's paxos member 1 -> 2 } else if (pre_paxos_num >= majority(cur_paxos_num)) { // passed } else if (OB_FAIL(message_to_user.assign("violate locality principal"))) { LOG_WARN("fail to construct message to user", KR(ret)); } else { passed = false; } } else if (0 != remove_task_num) { if (arb_service_status.is_enable_like()) { if (4 == pre_paxos_num && 2 == remove_task_num) { // special process: tenant with arb service should only support 4->2 } else if (OB_FAIL(message_to_user.assign("paxos replica number should be 2 or 4 when arbitration service is enabled, " "alter tenant locality"))) { LOG_WARN("fail to construct message to user", KR(ret)); } else { passed = false; } } else if (cur_paxos_num >= majority(pre_paxos_num)) { // passed } else if (OB_FAIL(message_to_user.assign("violate locality principal"))) { LOG_WARN("fail to construct message to user", KR(ret)); } else { passed = false; } } if (!passed) { ret = OB_OP_NOT_ALLOW; LOG_WARN("violate locality principal", K(ret), K(pre_paxos_num), K(cur_paxos_num), K(add_task_num), K(remove_task_num), K(nop_task_num)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, message_to_user.ptr()); } } } return ret; } int ObLocalityCheckHelp::check_alter_single_zone_locality_valid( const ObZoneReplicaAttrSet &new_locality, const ObZoneReplicaAttrSet &orig_locality, bool &non_paxos_locality_modified) { int ret = OB_SUCCESS; bool is_legal = true; // 1. check whether non_paxos member change if (!non_paxos_locality_modified) { const ObIArray &pre_readonly_replica = orig_locality.replica_attr_set_.get_readonly_replica_attr_array(); const ObIArray &cur_readonly_replica = new_locality.replica_attr_set_.get_readonly_replica_attr_array(); if (pre_readonly_replica.count() != cur_readonly_replica.count()) { non_paxos_locality_modified = true; } else { for (int64_t i = 0; !non_paxos_locality_modified && i < pre_readonly_replica.count(); ++i) { const ReplicaAttr &pre_replica_attr = pre_readonly_replica.at(i); const ReplicaAttr &cur_replica_attr = cur_readonly_replica.at(i); if (pre_replica_attr != cur_replica_attr) { non_paxos_locality_modified = true; } } } } // 2. check whether alter locality is legal. if (new_locality.get_logonly_replica_num() < orig_locality.get_logonly_replica_num()) { // L-replica must not transfrom to other replica type. if (new_locality.get_full_replica_num() > orig_locality.get_full_replica_num()) { is_legal = false; // maybe L->F } else if (ObLocalityDistribution::ALL_SERVER_CNT == new_locality.get_readonly_replica_num() || ObLocalityDistribution::ALL_SERVER_CNT == orig_locality.get_readonly_replica_num() || new_locality.get_readonly_replica_num() > orig_locality.get_readonly_replica_num()) { if (0 != new_locality.get_readonly_replica_num()) { is_legal = false; // maybe L->R } } else {} // good } else if (new_locality.get_logonly_replica_num() > orig_locality.get_logonly_replica_num()) { // only enable F transform to L if (new_locality.get_full_replica_num() < orig_locality.get_full_replica_num()) { if (ObLocalityDistribution::ALL_SERVER_CNT == new_locality.get_readonly_replica_num() && ObLocalityDistribution::ALL_SERVER_CNT != orig_locality.get_readonly_replica_num()) { if (0 != orig_locality.get_readonly_replica_num()) { is_legal = false; // maybe R->L } } else if (ObLocalityDistribution::ALL_SERVER_CNT != new_locality.get_readonly_replica_num() && ObLocalityDistribution::ALL_SERVER_CNT == orig_locality.get_readonly_replica_num()) { is_legal = false; // maybe R->L } else if (new_locality.get_readonly_replica_num() < orig_locality.get_readonly_replica_num()) { is_legal = false; // maybe R->L } } else { if (ObLocalityDistribution::ALL_SERVER_CNT == new_locality.get_readonly_replica_num() || ObLocalityDistribution::ALL_SERVER_CNT == orig_locality.get_readonly_replica_num() || new_locality.get_readonly_replica_num() < orig_locality.get_readonly_replica_num()) { if (0 != orig_locality.get_readonly_replica_num()) { is_legal = false; // maybe R->L } } else {} // good } } if (!is_legal) { ret = OB_OP_NOT_ALLOW; LOG_WARN("invalid replica_type transformation", K(ret), K(new_locality), K(orig_locality)); } return ret; } int ObRootUtils::get_rs_default_timeout_ctx(ObTimeoutCtx &ctx) { int ret = OB_SUCCESS; const int64_t DEFAULT_TIMEOUT_US = 2 * 1000 * 1000; // 2s if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, DEFAULT_TIMEOUT_US))) { LOG_WARN("fail to set default_timeout_ctx", KR(ret)); } return ret; } //get all observer that is stopeed, start_service_time<=0 and lease expire int ObRootUtils::get_invalid_server_list( const ObIArray &servers_info, ObIArray &invalid_server_list) { int ret = OB_SUCCESS; invalid_server_list.reset(); ObArray stopped_server_list; ObArray stopped_zone_list; ObZone empty_zone; if (OB_FAIL(get_stopped_zone_list(stopped_zone_list, stopped_server_list))) { LOG_WARN("fail to get stopped zone list", KR(ret)); } else if (OB_FAIL(invalid_server_list.assign(stopped_server_list))) { LOG_WARN("fail to assign array", KR(ret), K(stopped_zone_list)); } else { for (int64_t i = 0; i < servers_info.count() && OB_SUCC(ret); i++) { const ObServerInfoInTable &server_info = servers_info.at(i); if ((!server_info.is_alive() || !server_info.in_service()) && !has_exist_in_array(invalid_server_list, server_info.get_server())) { if (OB_FAIL(invalid_server_list.push_back(server_info.get_server()))) { LOG_WARN("fail to push back", KR(ret), K(server_info)); } } } } return ret; } int ObRootUtils::find_server_info( const ObIArray &servers_info, const common::ObAddr &server, share::ObServerInfoInTable &server_info) { int ret = OB_SUCCESS; bool server_exists = false; server_info.reset(); if (OB_UNLIKELY(!server.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", KR(ret), K(server)); } else { for (int64_t i = 0; OB_SUCC(ret) && !server_exists && i < servers_info.count(); i++) { const ObServerInfoInTable & server_info_i = servers_info.at(i); if (OB_UNLIKELY(!server_info_i.is_valid())) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("server_info_i is not valid", KR(ret), K(server_info_i)); } else if (server == server_info_i.get_server()) { server_exists = true; if (OB_FAIL(server_info.assign(server_info_i))) { LOG_WARN("fail to assign server_info", KR(ret), K(server_info_i)); } } } } if (OB_SUCC(ret) && !server_exists) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("server not exists", KR(ret), K(server)); } return ret; } int ObRootUtils::get_servers_of_zone( const ObIArray &servers_info, const common::ObZone &zone, ObIArray &servers, bool only_active_servers) { int ret = OB_SUCCESS; servers.reset(); if (OB_UNLIKELY(zone.is_empty())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid zone", KR(ret), K(zone)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < servers_info.count(); i++) { const ObServerInfoInTable &server_info = servers_info.at(i); if (OB_UNLIKELY(!server_info.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server_info", KR(ret), K(server_info)); } else if (zone != server_info.get_zone() || (only_active_servers && !server_info.is_active())) { // do nothing } else if (OB_FAIL(servers.push_back(server_info.get_server()))) { LOG_WARN("fail to push an element into servers", KR(ret), K(server_info)); } } } return ret; } int ObRootUtils::get_server_count( const ObIArray &servers_info, const ObZone &zone, int64_t &alive_count, int64_t ¬_alive_count) { int ret = OB_SUCCESS; alive_count = 0; not_alive_count = 0; for (int64_t i = 0; OB_SUCC(ret) && i < servers_info.count(); ++i) { const ObServerInfoInTable &server_info = servers_info.at(i); if (server_info.get_zone() == zone || zone.is_empty()) { if (server_info.is_alive()) { ++alive_count; } else { ++not_alive_count; } } } return ret; } int ObRootUtils::check_server_alive( const ObIArray &servers_info, const ObAddr &server, bool &is_alive) { int ret = OB_SUCCESS; is_alive = false; ObServerInfoInTable server_info; if (OB_UNLIKELY(!server.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", KR(ret), K(server)); } else if (OB_FAIL(find_server_info(servers_info, server, server_info))) { LOG_WARN("fail to find server_info", KR(ret), K(servers_info), K(server)); } else { is_alive = server_info.is_alive(); } return ret; } int ObRootUtils::get_server_resource_info( const ObIArray &server_resources_info, const ObAddr &server, share::ObServerResourceInfo &resource_info) { int ret = OB_SUCCESS; bool server_exists = false; resource_info.reset(); if (OB_UNLIKELY(!server.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", KR(ret), K(server)); } else { for (int64_t i = 0; OB_SUCC(ret) && !server_exists && i < server_resources_info.count(); i++) { const obrpc::ObGetServerResourceInfoResult &server_resource_info_i = server_resources_info.at(i); if (OB_UNLIKELY(!server_resource_info_i.is_valid())){ ret = OB_ERR_UNEXPECTED; LOG_ERROR("server_resource_info_i is not valid", KR(ret), K(server_resource_info_i)); } else if (server == server_resource_info_i.get_server()) { server_exists = true; resource_info = server_resource_info_i.get_resource_info(); } } } if (OB_SUCC(ret) && !server_exists) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("server not exists", KR(ret), K(server)); } return ret; } int ObRootUtils::get_stopped_zone_list( ObIArray &stopped_zone_list, ObIArray &stopped_server_list) { int ret = OB_SUCCESS; ObSqlString sql; ObTimeoutCtx ctx; stopped_zone_list.reset(); stopped_server_list.reset(); if (OB_ISNULL(GCTX.sql_proxy_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("GCTX.sql_proxy_ is null", KR(ret), KP(GCTX.sql_proxy_)); } else if (OB_FAIL(ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", K(ret), K(ctx)); } else if (OB_FAIL(sql.assign_fmt("SELECT s.svr_ip, s.svr_port, s.zone " "FROM %s AS s JOIN (SELECT zone, info FROM %s WHERE name = 'status') AS z " "ON s.zone = z.zone WHERE s.stop_time > 0 OR z.info = 'INACTIVE'", OB_ALL_SERVER_TNAME, OB_ALL_ZONE_TNAME))) { LOG_WARN("fail to append sql", KR(ret)); } else if (OB_FAIL(ObZoneTableOperation::get_inactive_zone_list(*GCTX.sql_proxy_, stopped_zone_list))) { LOG_WARN("fail to get inactive zone_list", KR(ret), KP(GCTX.sql_proxy_)); } else { SMART_VAR(ObMySQLProxy::MySQLResult, res) { int tmp_ret = OB_SUCCESS; ObMySQLResult *result = NULL; if (OB_FAIL(GCTX.sql_proxy_->read(res, OB_SYS_TENANT_ID, sql.ptr()))) { LOG_WARN("fail to execute sql", KR(ret), K(sql)); } else if (OB_ISNULL(result = res.get_result())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get sql result", KR(ret), K(sql)); } else { ObZone zone; ObAddr server; ObString tmp_zone; ObString svr_ip; while (OB_SUCC(ret)) { if (OB_FAIL(result->next())) { if (OB_ITER_END != ret) { LOG_WARN("result next failed", KR(ret)); } else { ret = OB_SUCCESS; break; } } else { int64_t svr_port = 0; server.reset(); zone.reset(); svr_ip.reset(); tmp_zone.reset(); EXTRACT_VARCHAR_FIELD_MYSQL(*result, "svr_ip", svr_ip); EXTRACT_INT_FIELD_MYSQL(*result, "svr_port", svr_port, int64_t); EXTRACT_VARCHAR_FIELD_MYSQL(*result, "zone", tmp_zone); if (OB_UNLIKELY(!server.set_ip_addr(svr_ip, static_cast(svr_port)))) { ret = OB_INVALID_DATA; LOG_WARN("fail to set ip addr", KR(ret), K(svr_ip), K(svr_port)); } else if (OB_FAIL(zone.assign(tmp_zone))) { LOG_WARN("fail to assign zone", KR(ret), K(tmp_zone)); } else if (OB_FAIL(stopped_server_list.push_back(server))) { LOG_WARN("fail to push an element into stopped_server_list", KR(ret), K(server)); } else if (has_exist_in_array(stopped_zone_list, zone)) { // do nothing } else if (OB_FAIL(stopped_zone_list.push_back(zone))) { LOG_WARN("fail to push an element into stopped_zone_list", KR(ret), K(zone)); } } } } } } LOG_INFO("get stopped zone list", KR(ret), K(stopped_server_list), K(stopped_zone_list)); return ret; } bool ObRootUtils::have_other_stop_task(const ObZone &zone) { int ret = OB_SUCCESS; bool bret = true; int64_t cnt = 0; ObSqlString sql; ObTimeoutCtx ctx; if (OB_ISNULL(GCTX.sql_proxy_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("GCTX.sql_proxy_ is null", KR(ret), KP(GCTX.sql_proxy_)); } else if (OB_FAIL(ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx)); } else if (OB_FAIL(sql.assign_fmt("SELECT COUNT(*) AS cnt FROM " "(SELECT zone FROM %s WHERE stop_time > 0 AND zone != '%s' UNION " "SELECT zone FROM %s WHERE name = 'status' AND info = 'INACTIVE' AND zone != '%s')", OB_ALL_SERVER_TNAME, zone.ptr(), OB_ALL_ZONE_TNAME, zone.ptr()))) { LOG_WARN("fail to append sql", KR(ret), K(zone)); } else { SMART_VAR(ObMySQLProxy::MySQLResult, res) { int tmp_ret = OB_SUCCESS; ObMySQLResult *result = NULL; if (OB_FAIL(GCTX.sql_proxy_->read(res, OB_SYS_TENANT_ID, sql.ptr()))) { LOG_WARN("fail to execute sql", KR(ret), K(sql)); } else if (OB_ISNULL(result = res.get_result())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get sql result", KR(ret), K(sql)); } else if (OB_FAIL(result->next())) { LOG_WARN("fail to get next", KR(ret), K(sql));; } else { EXTRACT_INT_FIELD_MYSQL(*result, "cnt", cnt, int64_t); } if (OB_SUCC(ret) && (OB_ITER_END != (tmp_ret = result->next()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get more row than one", KR(ret), KR(tmp_ret), K(sql)); } } } if (OB_SUCC(ret) && 0 == cnt) { bret = false; } LOG_INFO("have other stop task", KR(ret), K(bret), K(zone), K(cnt)); return bret; } int ObRootUtils::get_tenant_intersection(ObUnitManager &unit_mgr, ObIArray &this_server_list, ObIArray &other_server_list, ObIArray &tenant_ids) { int ret = OB_SUCCESS; tenant_ids.reset(); ObHashSet this_tenant_ids_set; ObHashSet other_tenant_ids_set; const int64_t TENANT_BUCKET_NUM = 1000; if (OB_FAIL(this_tenant_ids_set.create(TENANT_BUCKET_NUM))) { LOG_WARN("fail to create hashset", KR(ret)); } else if (OB_FAIL(other_tenant_ids_set.create(TENANT_BUCKET_NUM))) { LOG_WARN("fail to create hashset", KR(ret)); } for (int64_t i = 0; i < this_server_list.count() && OB_SUCC(ret); i++) { const ObAddr &server = this_server_list.at(i); if (OB_FAIL(unit_mgr.get_tenants_of_server(server, this_tenant_ids_set))) { LOG_WARN("fail to get tenant unit", KR(ret), K(server)); } } for (int64_t i = 0; i < other_server_list.count() && OB_SUCC(ret); i++) { const ObAddr &server = other_server_list.at(i); if (OB_FAIL(unit_mgr.get_tenants_of_server(server, other_tenant_ids_set))) { LOG_WARN("fail to get tenant unit", KR(ret), K(server)); } } ObHashSet::const_iterator iter; for (iter = this_tenant_ids_set.begin(); iter != this_tenant_ids_set.end() && OB_SUCC(ret); iter++) { if (OB_FAIL(other_tenant_ids_set.exist_refactored(iter->first))) { if (OB_HASH_EXIST == ret) { if (OB_FAIL(tenant_ids.push_back(iter->first))) { LOG_WARN("fail to push back", KR(ret)); } } else if (OB_HASH_NOT_EXIST == ret) { ret = OB_SUCCESS; } else { LOG_WARN("fail to check exist", KR(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected error", KR(ret)); } } //end for iter return ret; } template bool ObRootUtils::has_intersection(const common::ObIArray &this_array, const common::ObIArray &other_array) { bool bret = false; for (int64_t i = 0; i < this_array.count() && !bret; i++) { if (has_exist_in_array(other_array, this_array.at(i))) { bret = true; } } return bret; } //iter the tenant, table's primary_zone is covered by zone_list int ObRootUtils::check_primary_region_in_zonelist(ObMultiVersionSchemaService *schema_service, ObDDLService *ddl_service, ObUnitManager &unit_mgr, ObZoneManager &zone_mgr, const ObIArray &tenant_ids, const ObIArray &zone_list, bool &is_in) { int ret = OB_SUCCESS; is_in = false; if (0 >= zone_list.count() || OB_ISNULL(schema_service) || OB_ISNULL(ddl_service)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(zone_list)); } else if (0 == tenant_ids.count()) { is_in = false; } else { ObSchemaGetterGuard tenant_schema_guard; ObArray tenant_zone_list; const ObTenantSchema *tenant_info = NULL; for (int64_t i = 0; i < tenant_ids.count() && !is_in; i++) { const uint64_t tenant_id = tenant_ids.at(i); tenant_zone_list.reset(); if (OB_FAIL(unit_mgr.get_tenant_pool_zone_list(tenant_id, tenant_zone_list))) { LOG_WARN("fail to get tenant pool zone list", KR(ret), K(tenant_id)); } else if (is_subset(zone_list, tenant_zone_list)) { //all zones of tenant is in the zone_list is_in = true; } else if (OB_FAIL(schema_service->get_tenant_schema_guard(tenant_id, tenant_schema_guard))) { LOG_WARN("get_schema_guard failed", K(ret)); } else if (OB_FAIL(tenant_schema_guard.get_tenant_info(tenant_id, tenant_info))) { LOG_WARN("fail to get tenant info", KR(ret), K(tenant_id)); } else if (OB_ISNULL(tenant_info)) { ret = OB_TENANT_NOT_EXIST; LOG_WARN("invalid tenant info", KR(ret), K(tenant_id)); } else { bool has = false; if (OB_FAIL(check_left_f_in_primary_zone(zone_mgr, tenant_schema_guard, *tenant_info, zone_list, has))) { LOG_WARN("fail to check tenant locality", KR(ret), K(tenant_id)); } else if (!has) { is_in = true; LOG_INFO("tenant primary zone has no full replica exist", K(tenant_id), K(zone_list)); } } } //end for tenant_ids } //end else LOG_INFO("check primary region in zonelist", KR(ret), K(tenant_ids), K(zone_list), K(is_in)); return ret; } int ObRootUtils::get_primary_zone(ObZoneManager &zone_mgr, const ObIArray &zone_score_array, ObIArray &primary_zone) { int ret= OB_SUCCESS; int64_t first_score = -1; ObArray zone_list; if (OB_UNLIKELY(0 >= zone_score_array.count())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(zone_score_array)); } else { for (int64_t i = 0; i < zone_score_array.count() && OB_SUCC(ret); i++) { const ObZoneScore &score = zone_score_array.at(i); if (-1 == first_score) { first_score = score.score_; if (OB_FAIL(zone_list.push_back(score.zone_))) { LOG_WARN("fail to push back", KR(ret), K(score)); } } else if (first_score == score.score_) { if (OB_FAIL(zone_list.push_back(score.zone_))) { LOG_WARN("fail to push back", KR(ret), "zone", zone_score_array.at(i).zone_); } } } //get all zones in one region ObArray region_list; ObRegion region; for (int64_t i = 0; i < zone_list.count() && OB_SUCC(ret); i++) { if (OB_FAIL(zone_mgr.get_region(zone_list.at(i), region))) { LOG_WARN("fail to get region", KR(ret), KR(i), K(zone_list)); } else if (has_exist_in_array(region_list, region)) { //nothing todo } else if (OB_FAIL(region_list.push_back(region))) { LOG_WARN("fail to push region", KR(ret), K(region)); } } //get all read_write zone ObArray all_zones; if (OB_FAIL(ret)) { } else if (OB_FAIL(zone_mgr.get_zone(all_zones))) { LOG_WARN("fail to get zone", KR(ret)); } else { for (int64_t i = 0; i < all_zones.count() && OB_SUCC(ret); i++) { const ObZoneInfo &zone = all_zones.at(i); ObZoneType zone_type = static_cast(zone.zone_type_.value_); ObRegion region(zone.region_.info_.ptr()); if (has_exist_in_array(region_list, region) && common::ZONE_TYPE_READWRITE == zone_type) { if (OB_FAIL(primary_zone.push_back(zone.zone_))) { LOG_WARN("fail to push back", KR(ret), K(zone)); } } } } } return ret; } template int ObRootUtils::check_left_f_in_primary_zone(ObZoneManager &zone_mgr, ObSchemaGetterGuard &schema_guard, const T &schema_info, const ObIArray &zone_list, bool &has) { int ret = OB_SUCCESS; has = false; ObArray zone_locality_array; ObArenaAllocator allocator("PrimaryZone"); ObPrimaryZone primary_zone(allocator); ObArray primary_zone_array; if (OB_UNLIKELY(!schema_info.is_valid()) || OB_UNLIKELY(0 >= zone_list.count())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(schema_info), K(zone_list)); } else if (OB_FAIL(schema_info.get_primary_zone_inherit(schema_guard, primary_zone))) { LOG_WARN("fail to get primary zone", KR(ret)); } else if (ObPrimaryZoneUtil::no_need_to_check_primary_zone(primary_zone.get_primary_zone())) { //if primary_zone is random, no need to check left f in primary zone has = true; LOG_INFO("primary zone is RANDOM or empty, no need to check", KR(ret), K(primary_zone)); } else if (OB_FAIL(schema_info.get_zone_replica_attr_array_inherit(schema_guard, zone_locality_array))) { LOG_WARN("fail to get zone replica array", KR(ret)); } else if (OB_FAIL(get_primary_zone(zone_mgr, primary_zone.get_primary_zone_array(), primary_zone_array))) { LOG_WARN("fail to get primary zone", KR(ret), K(primary_zone)); } else { for (int64_t i = 0; i < primary_zone_array.count() && OB_SUCC(ret) && !has; i++) { const ObZone &zone = primary_zone_array.at(i); for (int64_t j = 0; j < zone_locality_array.count() && OB_SUCC(ret) && !has; j++) { const ObZoneReplicaAttrSet &set = zone_locality_array.at(j); int64_t full_replica_num = set.get_full_replica_num(); if (0 < full_replica_num && (has_exist_in_array(set.zone_set_, zone) || zone == set.zone_) && !has_intersection(set.zone_set_, zone_list)) { //there is F replica in the zone_set where the primary_zone is located, //and, no zone of the zone_set is in zone_list(stopped). has = true; } } //end for zone_locality_array } //end primary_zone_array } LOG_INFO("check left f in primary zone", KR(ret), K(zone_list), K(has)); return ret; } int ObRootUtils::get_proposal_id_from_sys_ls(int64_t &proposal_id, ObRole &role) { int ret = OB_SUCCESS; storage::ObLSHandle ls_handle; logservice::ObLogHandler *handler = nullptr; MTL_SWITCH(OB_SYS_TENANT_ID) { if (OB_FAIL(MTL(ObLSService*)->get_ls(SYS_LS, ls_handle, ObLSGetMod::RS_MOD))) { LOG_WARN("fail to get ls", KR(ret)); } else if (OB_UNLIKELY(!ls_handle.is_valid()) || OB_ISNULL(ls_handle.get_ls()) || OB_ISNULL(handler = ls_handle.get_ls()->get_log_handler())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected error", KR(ret), KP(ls_handle.get_ls()), KP(ls_handle.get_ls()->get_log_handler())); } else if (OB_FAIL(handler->get_role(role, proposal_id))) { LOG_WARN("fail to get role", KR(ret)); } } return ret; } int ObRootUtils::try_notify_switch_ls_leader( obrpc::ObSrvRpcProxy *rpc_proxy, const share::ObLSInfo &ls_info, const obrpc::ObNotifySwitchLeaderArg::SwitchLeaderComment &comment) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!ls_info.is_valid()) || OB_ISNULL(rpc_proxy)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(ls_info), K(rpc_proxy)); } else { ObArray server_list; obrpc::ObNotifySwitchLeaderArg arg; const uint64_t tenant_id = ls_info.get_tenant_id(); for (int64_t i = 0; OB_SUCC(ret) && i < ls_info.get_replicas_cnt(); ++i) { if (OB_FAIL(server_list.push_back(ls_info.get_replicas().at(i).get_server()))) { LOG_WARN("failed to push back server", KR(ret), K(i), K(ls_info)); } } if (FAILEDx(arg.init(tenant_id, ls_info.get_ls_id(), ObAddr(), comment))) { LOG_WARN("failed to init switch leader arg", KR(ret), K(tenant_id), K(ls_info), K(comment)); } else if (OB_FAIL(notify_switch_leader(rpc_proxy, tenant_id, arg, server_list))) { LOG_WARN("failed to notify switch leader", KR(ret), K(arg), K(tenant_id), K(server_list)); } } return ret; } int ObRootUtils::notify_switch_leader( obrpc::ObSrvRpcProxy *rpc_proxy, const uint64_t tenant_id, const obrpc::ObNotifySwitchLeaderArg &arg, const ObIArray &addr_list) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || !arg.is_valid() || 0 == addr_list.count()) || OB_ISNULL(rpc_proxy)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(arg), K(addr_list), KP(rpc_proxy)); } else { ObTimeoutCtx ctx; int tmp_ret = OB_SUCCESS; if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, GCONF.rpc_timeout))) { LOG_WARN("fail to set timeout ctx", KR(ret)); } else { ObNotifySwitchLeaderProxy proxy(*rpc_proxy, &obrpc::ObSrvRpcProxy::notify_switch_leader); for (int64_t i = 0; i < addr_list.count(); ++i) { const int64_t timeout = ctx.get_timeout(); if (OB_TMP_FAIL(proxy.call(addr_list.at(i), timeout, GCONF.cluster_id, tenant_id, arg))) { ret = OB_SUCC(ret) ? tmp_ret : ret; LOG_WARN("failed to send rpc", KR(ret), K(i), K(tenant_id), K(arg), K(addr_list)); } }//end for if (OB_TMP_FAIL(proxy.wait())) { ret = OB_SUCC(ret) ? tmp_ret : ret; LOG_WARN("failed to wait all result", KR(ret), KR(tmp_ret)); } } } return ret; } int ObRootUtils::check_tenant_ls_balance(uint64_t tenant_id, int &check_ret) { int ret = OB_SUCCESS; uint64_t tenant_data_version = 0; bool pass = false; check_ret = OB_NEED_WAIT; if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid tenant id", KR(ret), K(tenant_id)); } else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) { LOG_WARN("fail to get min data version", KR(ret), K(tenant_id)); } else if (tenant_data_version < DATA_VERSION_4_2_1_0 || !is_user_tenant(tenant_id)) { // in v4.1 no need to check ls balance // to let rs jobs' return_code be OB_SUCCESS, we set has_checked true // non-user tenant has no ls balance check_ret = OB_SUCCESS; } else if (!ObShareUtil::is_tenant_enable_rebalance(tenant_id)) { check_ret = OB_SKIP_CHECKING_LS_STATUS; } else if (OB_FAIL(ObTenantBalanceService::is_ls_balance_finished(tenant_id, pass))) { LOG_WARN("fail to execute is_ls_balance_finished", KR(ret), K(tenant_id)); } else if (pass) { check_ret = OB_SUCCESS; } else { check_ret = OB_NEED_WAIT; } return ret; } int ObRootUtils::is_first_priority_primary_zone_changed( const share::schema::ObTenantSchema &orig_tenant_schema, const share::schema::ObTenantSchema &new_tenant_schema, ObIArray &orig_first_primary_zone, ObIArray &new_first_primary_zone, bool &is_changed) { int ret = OB_SUCCESS; orig_first_primary_zone.reset(); new_first_primary_zone.reset(); is_changed = false; if (OB_UNLIKELY(orig_tenant_schema.get_tenant_id() != new_tenant_schema.get_tenant_id())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input tenant schema", KR(ret), K(orig_tenant_schema), K(new_tenant_schema)); } else if (OB_FAIL(ObPrimaryZoneUtil::get_tenant_primary_zone_array( orig_tenant_schema, orig_first_primary_zone))) { LOG_WARN("fail to get tenant primary zone array", KR(ret), K(orig_tenant_schema), K(orig_first_primary_zone)); } else if (OB_FAIL(ObPrimaryZoneUtil::get_tenant_primary_zone_array( new_tenant_schema, new_first_primary_zone))) { LOG_WARN("fail to get tenant primary zone array", KR(ret), K(new_tenant_schema), K(new_first_primary_zone)); } else if (orig_first_primary_zone.count() != new_first_primary_zone.count()) { is_changed = true; } else { ARRAY_FOREACH(new_first_primary_zone, idx) { const ObZone &zone = new_first_primary_zone.at(idx); if (!common::has_exist_in_array(orig_first_primary_zone, zone)) { is_changed = true; break; } } } return ret; } int ObRootUtils::check_and_commit_rs_job(const uint64_t tenant_id, const ObRsJobType rs_job_type) { int ret = OB_SUCCESS; int64_t rs_job_id = 0; int check_ret = OB_NEED_WAIT; const char* rs_job_type_str = NULL; if (OB_ISNULL(GCTX.sql_proxy_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("GCTX.sql_proxy_ is null", KR(ret), KP(GCTX.sql_proxy_)); } else if (OB_UNLIKELY(!ObRsJobTableOperator::is_valid_job_type(rs_job_type) || NULL == (rs_job_type_str = ObRsJobTableOperator::get_job_type_str(rs_job_type)))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid job type", KR(ret), K(rs_job_type), KP(rs_job_type_str)); } else if (OB_FAIL(find_rs_job(tenant_id, rs_job_type, rs_job_id))) { // find the corresponding rs job at first, then check if we can complete it // if we only find the rs job at the committing period, // we do not know whether the job has been changed during checking process // e.g. job 1 is the rs job before checking, // right after checking, job 2 is created and job 1 is canceled by job 2, // then committing process will find job 2 and complete job 2 immediately, // which means, job 2 is completed without checking. if (OB_ENTRY_NOT_EXIST == ret) { ret = OB_SUCCESS; } else { LOG_WARN("fail to find rs job", KR(ret), K(tenant_id), K(rs_job_type), K(rs_job_type_str)); } } else if (OB_FAIL(ObRootUtils::check_tenant_ls_balance(tenant_id, check_ret))) { LOG_WARN("fail to execute check_tenant_ls_balance", KR(ret), K(tenant_id)); } else if (OB_NEED_WAIT != check_ret) { if (OB_SUCC(RS_JOB_COMPLETE(rs_job_id, check_ret, *GCTX.sql_proxy_))) { FLOG_INFO("[CHECK_AND_COMMIT_RS_JOB NOTICE] complete an inprogress rs job", KR(ret), K(tenant_id), K(rs_job_id), K(check_ret), K(rs_job_type), K(rs_job_type_str)); } else { LOG_WARN("fail to complete rs job", KR(ret), K(tenant_id), K(rs_job_id), K(check_ret), K(rs_job_type), K(rs_job_type_str)); if (OB_EAGAIN == ret) { FLOG_WARN("[CHECK_AND_COMMIT_RS_JOB NOTICE] the specified rs job might has " "been already completed due to a new job or deleted in table manually", KR(ret), K(tenant_id), K(rs_job_id), K(check_ret), K(rs_job_type), K(rs_job_type_str)); ret = OB_SUCCESS; // no need to return the error code } } } return ret; } int ObRootUtils::find_rs_job(const uint64_t tenant_id, const ObRsJobType rs_job_type, int64_t &rs_job_id) { int ret = OB_SUCCESS; rs_job_id = 0; if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || !ObRsJobTableOperator::is_valid_job_type(rs_job_type))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(rs_job_type)); } else if (OB_ISNULL(GCTX.sql_proxy_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("GCTX.sql_proxy_ is null", KR(ret), KP(GCTX.sql_proxy_)); } else { switch (rs_job_type) { case ObRsJobType::JOB_TYPE_ALTER_TENANT_LOCALITY: ret = ObAlterLocalityFinishChecker::find_rs_job(tenant_id, rs_job_id, *GCTX.sql_proxy_); break; case ObRsJobType::JOB_TYPE_ALTER_RESOURCE_TENANT_UNIT_NUM: ret = ObUnitManager::find_alter_resource_tenant_unit_num_rs_job(tenant_id, rs_job_id, *GCTX.sql_proxy_); break; default: ret = OB_NOT_SUPPORTED; } if (OB_FAIL(ret)) { LOG_WARN("fail to find rs job", KR(ret), K(tenant_id), K(rs_job_type)); } } return ret; } /////////////////////////////// ObClusterRole ObClusterInfoGetter::get_cluster_role_v2() { ObClusterRole cluster_role = PRIMARY_CLUSTER; return cluster_role; } ObClusterRole ObClusterInfoGetter::get_cluster_role() { ObClusterRole cluster_role = PRIMARY_CLUSTER; return cluster_role; } const char *oceanbase::rootserver::resource_type_to_str(const ObResourceType &t) { const char* str = "UNKNOWN"; if (RES_CPU == t) { str = "CPU"; } else if (RES_MEM == t) { str = "MEMORY"; } else if (RES_LOG_DISK == t) { str = "LOG_DISK"; } else { str = "NONE"; } return str; }