2371 lines
96 KiB
C++
2371 lines
96 KiB
C++
/**
|
|
* 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<uint64_t> &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<uint64_t> &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<ObZone> &zone_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
zone_list.reset();
|
|
if (locality_str.empty()) {
|
|
//nothing todo
|
|
} else {
|
|
ObArray<ObString> 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<ObString> 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<TenantNameGroup> &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<TenantNameGroup> &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<int32_t>(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<common::ObString> &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<TenantNameGroup> &tenant_groups)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
TenantNameGroup tenant_group;
|
|
common::ObArray<common::ObString> 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<TenantNameGroup> &tenant_groups)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
TenantNameGroup tenant_group;
|
|
common::ObArray<common::ObString> 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<share::ObResourcePoolName> &pools,
|
|
ObUnitManager &unit_mgr,
|
|
ObIArray<share::ObZoneReplicaNumSet> &zone_locality)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArray<ObUnitInfo> logonly_unit_infos;
|
|
ObArray<ObUnitInfo> 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<share::ObZoneReplicaNumSet> &zone_locality)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArray<ObUnitInfo> logonly_unit_infos;
|
|
const ObTenantSchema *tenant_schema = NULL;
|
|
zone_locality.reset();
|
|
common::ObArray<share::ObZoneReplicaAttrSet> 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<share::ObZoneReplicaAttrSet> &zone_locality)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArray<ObUnitInfo> 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<share::ObResourcePoolName> &pools,
|
|
const common::ObIArray<ObZoneReplicaNumSet> &zone_locality,
|
|
ObPartitionAddr &partition_addr)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArray<ObUnitInfo> logonly_units;
|
|
ObArray<ObUnitInfo> 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<share::ObZoneReplicaNumSet> &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<share::ObZoneReplicaNumSet> &pre_zone_locality,
|
|
const ObIArray<share::ObZoneReplicaNumSet> &cur_zone_locality,
|
|
ObIArray<AlterPaxosLocalityTask> &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<share::ObZoneReplicaAttrSet> &multi_pre_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &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<common::ObZone> &pre_zone_set = pre_locality.zone_set_;
|
|
const common::ObIArray<common::ObZone> &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<common::ObZone> &pre_zone_set,
|
|
const common::ObIArray<common::ObZone> &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<share::ObZoneReplicaAttrSet> &zone_locality,
|
|
common::ObIArray<share::ObZoneReplicaAttrSet> &single_zone_locality,
|
|
common::ObIArray<share::ObZoneReplicaAttrSet> &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<share::ObZoneReplicaAttrSet> &single_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &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<AlterPaxosLocalityTask> &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<share::ObZoneReplicaAttrSet> &single_pre_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &single_cur_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_cur_zone_locality,
|
|
common::ObArray<XyIndex> &pre_in_cur_multi_indexes,
|
|
common::ObIArray<AlterPaxosLocalityTask> &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<share::ObZoneReplicaAttrSet> &single_cur_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &single_pre_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_pre_zone_locality,
|
|
common::ObArray<XyIndex> &cur_in_pre_multi_indexes,
|
|
common::ObIArray<AlterPaxosLocalityTask> &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<AlterPaxosLocalityTask> &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<share::ObZoneReplicaAttrSet> &single_zone_locality,
|
|
const common::ObIArray<XyIndex> &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<share::ObZoneReplicaAttrSet> &single_left_zone_locality,
|
|
const common::ObIArray<XyIndex> &left_in_multi_indexes,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_right_zone_locality,
|
|
common::ObIArray<AlterPaxosLocalityTask> &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<XyIndex> &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<XyIndex> &pre_in_cur_multi_indexes,
|
|
const common::ObIArray<XyIndex> &cur_in_pre_multi_indexes,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_pre_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_cur_zone_locality,
|
|
common::ObIArray<AlterPaxosLocalityTask> &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<XyIndex> &pre_in_cur_multi_indexes,
|
|
const common::ObIArray<XyIndex> &cur_in_pre_multi_indexes,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_pre_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &multi_cur_zone_locality,
|
|
common::ObIArray<AlterPaxosLocalityTask> &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<share::ObZoneReplicaAttrSet> &pre_zone_locality,
|
|
const common::ObIArray<share::ObZoneReplicaAttrSet> &cur_zone_locality,
|
|
ObIArray<AlterPaxosLocalityTask> &alter_paxos_tasks,
|
|
bool &non_paxos_locality_modified)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
common::ObArray<share::ObZoneReplicaAttrSet> single_pre_zone_locality;
|
|
common::ObArray<share::ObZoneReplicaAttrSet> multi_pre_zone_locality;
|
|
common::ObArray<share::ObZoneReplicaAttrSet> single_cur_zone_locality;
|
|
common::ObArray<share::ObZoneReplicaAttrSet> multi_cur_zone_locality;
|
|
common::ObArray<XyIndex> pre_in_cur_multi_indexes;
|
|
common::ObArray<XyIndex> 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<AlterPaxosLocalityTask> &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<ReplicaAttr> &pre_readonly_replica = orig_locality.replica_attr_set_.get_readonly_replica_attr_array();
|
|
const ObIArray<ReplicaAttr> &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<ObServerInfoInTable> &servers_info,
|
|
ObIArray<ObAddr> &invalid_server_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
invalid_server_list.reset();
|
|
ObArray<ObAddr> stopped_server_list;
|
|
ObArray<ObZone> 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<share::ObServerInfoInTable> &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<share::ObServerInfoInTable> &servers_info,
|
|
const common::ObZone &zone,
|
|
ObIArray<common::ObAddr> &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<share::ObServerInfoInTable> &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<ObServerInfoInTable> &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<obrpc::ObGetServerResourceInfoResult> &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<ObZone> &stopped_zone_list,
|
|
ObIArray<ObAddr> &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<int32_t>(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<ObAddr> &this_server_list,
|
|
ObIArray<ObAddr> &other_server_list,
|
|
ObIArray<uint64_t> &tenant_ids)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
tenant_ids.reset();
|
|
ObHashSet<uint64_t> this_tenant_ids_set;
|
|
ObHashSet<uint64_t> 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<uint64_t>::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<class T>
|
|
bool ObRootUtils::has_intersection(const common::ObIArray<T> &this_array,
|
|
const common::ObIArray<T> &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<uint64_t> &tenant_ids,
|
|
const ObIArray<ObZone> &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<ObZone> 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<ObZoneScore> &zone_score_array,
|
|
ObIArray<ObZone> &primary_zone)
|
|
{
|
|
int ret= OB_SUCCESS;
|
|
int64_t first_score = -1;
|
|
ObArray<ObZone> 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<ObRegion> 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<ObZoneInfo> 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<ObZoneType>(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<class T>
|
|
int ObRootUtils::check_left_f_in_primary_zone(ObZoneManager &zone_mgr,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
const T &schema_info,
|
|
const ObIArray<ObZone> &zone_list,
|
|
bool &has)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
has = false;
|
|
ObArray<ObZoneReplicaAttrSet> zone_locality_array;
|
|
ObArenaAllocator allocator("PrimaryZone");
|
|
ObPrimaryZone primary_zone(allocator);
|
|
ObArray<ObZone> 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<ObAddr> 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<common::ObAddr> &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<ObZone> &orig_first_primary_zone,
|
|
ObIArray<ObZone> &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;
|
|
}
|