Files
oceanbase/src/rootserver/ob_migrate_unit_finish_checker.cpp

332 lines
12 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_migrate_unit_finish_checker.h"
#include "lib/container/ob_array.h"
#include "lib/container/ob_array_iterator.h"
#include "lib/container/ob_se_array.h"
#include "lib/container/ob_se_array_iterator.h"
#include "share/ls/ob_ls_status_operator.h"
#include "share/ls/ob_ls_table_operator.h"
#include "ob_unit_manager.h"
#include "ob_server_manager.h"
#include "ob_zone_manager.h"
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::rootserver;
ObMigrateUnitFinishChecker::ObMigrateUnitFinishChecker(volatile bool &stop)
: inited_(false),
unit_mgr_(nullptr),
server_mgr_(nullptr),
zone_mgr_(nullptr),
schema_service_(nullptr),
sql_proxy_(nullptr),
lst_operator_(nullptr),
stop_(stop)
{
}
ObMigrateUnitFinishChecker::~ObMigrateUnitFinishChecker()
{
}
int ObMigrateUnitFinishChecker::check_stop() const
{
int ret = OB_SUCCESS;
if (stop_) {
ret = OB_CANCELED;
LOG_WARN("ObMigrateUnitFinishChecker stopped", KR(ret), K(stop_));
}
return ret;
}
int ObMigrateUnitFinishChecker::init(
ObUnitManager &unit_mgr,
ObServerManager &server_mgr,
ObZoneManager &zone_mgr,
share::schema::ObMultiVersionSchemaService &schema_service,
common::ObMySQLProxy &sql_proxy,
share::ObLSTableOperator &lst_operator)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("init twice", KR(ret));
} else {
unit_mgr_ = &unit_mgr;
server_mgr_ = &server_mgr;
zone_mgr_ = &zone_mgr;
schema_service_ = &schema_service;
sql_proxy_ = &sql_proxy;
lst_operator_ = &lst_operator;
inited_ = true;
}
return ret;
}
int ObMigrateUnitFinishChecker::check()
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
LOG_INFO("start check unit migrate finish");
ObArray<uint64_t> tenant_id_array;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", K(ret));
} else if (OB_FAIL(check_stop())) {
LOG_WARN("ObMigrateUnitFinishChecker stopped", KR(ret));
} else if (OB_UNLIKELY(ObTenantUtils::get_tenant_ids(schema_service_, tenant_id_array))) {
LOG_WARN("fail to get tenant id array", KR(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < tenant_id_array.count(); ++i) {
const uint64_t tenant_id = tenant_id_array.at(i);
if (is_meta_tenant(tenant_id)) {
// bypass
} else {
// check unit belongs to existed tenant
if (OB_SUCCESS != (tmp_ret = try_check_migrate_unit_finish_by_tenant(tenant_id))) {
LOG_WARN("fail to try check migrate unit finish by tenant", KR(tmp_ret), K(tenant_id));
}
// check unit not in locality but in zone list
if (OB_SUCCESS != (tmp_ret = try_check_migrate_unit_finish_not_in_locality(tenant_id))) {
LOG_WARN("fail to try check migrate unit finish not in locality", KR(tmp_ret), K(tenant_id));
}
}
}
}
// check unit not in tenant
if (OB_SUCCESS != (tmp_ret = try_check_migrate_unit_finish_not_in_tenant())) {
LOG_WARN("fail to try check migrate unit finish not in tenant", KR(tmp_ret));
}
return ret;
}
int ObMigrateUnitFinishChecker::try_check_migrate_unit_finish_not_in_locality(
const uint64_t &tenant_id)
{
int ret = OB_SUCCESS;
ObArray<common::ObZone> zone_list;
ObSchemaGetterGuard schema_guard;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (OB_FAIL(check_stop())) {
LOG_WARN("ObMigrateUnitFinishChecker stopped", KR(ret));
} else if (OB_FAIL(unit_mgr_->get_tenant_pool_zone_list(tenant_id, zone_list))) {
LOG_WARN("fail to get tenant pool zone list", KR(ret));
} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("get schema guard failed", KR(ret), K(tenant_id));
} else if (OB_FAIL(unit_mgr_->finish_migrate_unit_not_in_locality(
tenant_id, &schema_guard, zone_list))) {
LOG_WARN("fail to finish migrat eunit not in locality", KR(ret), K(tenant_id), K(zone_list));
}
return ret;
}
int ObMigrateUnitFinishChecker::try_check_migrate_unit_finish_not_in_tenant()
{
int ret = OB_SUCCESS;
ObArray<share::ObResourcePool> pools;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (OB_FAIL(check_stop())) {
LOG_WARN("ObMigrateUnitFinishChecker stopped", KR(ret));
} else if (OB_FAIL(unit_mgr_->get_pools(pools))) {
LOG_WARN("fail to get pools", KR(ret));
} else {
FOREACH_CNT_X(pool, pools, OB_SUCC(ret)) {
if (OB_FAIL(unit_mgr_->finish_migrate_unit_not_in_tenant(pool))) {
LOG_WARN("fail to finish migrate unit not in tenant", KR(ret));
}
ret = OB_SUCCESS; //ignore ret 保证所有的pool都能运行
}
}
return ret;
}
int ObMigrateUnitFinishChecker::get_all_tenant_related_ls_status_info(
const uint64_t tenant_id,
common::ObIArray<share::ObLSStatusInfo> &ls_status_info_array)
{
int ret = OB_SUCCESS;
ls_status_info_array.reset();
share::ObLSStatusOperator ls_status_operator;
if (OB_UNLIKELY(is_meta_tenant(tenant_id))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id));
} else if (OB_ISNULL(sql_proxy_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sql proxy is null", KR(ret), KP(sql_proxy_));
} else if (is_sys_tenant(tenant_id)) {
if (OB_FAIL(ls_status_operator.get_all_ls_status_by_order(
tenant_id, ls_status_info_array, *sql_proxy_))) {
LOG_WARN("fail to get all ls status", KR(ret), K(tenant_id));
}
} else { // user tenant
const uint64_t user_tenant_id = tenant_id;
const uint64_t meta_tenant_id = gen_meta_tenant_id(tenant_id);
common::ObArray<share::ObLSStatusInfo> user_ls_status_info_array;
common::ObArray<share::ObLSStatusInfo> meta_ls_status_info_array;
if (OB_FAIL(ls_status_operator.get_all_ls_status_by_order(
user_tenant_id, user_ls_status_info_array, *sql_proxy_))) {
LOG_WARN("fail to get all ls status by order", KR(ret), K(user_tenant_id));
} else if (OB_FAIL(ls_status_operator.get_all_ls_status_by_order(
meta_tenant_id, meta_ls_status_info_array, *sql_proxy_))) {
LOG_WARN("fail to get all ls status by order", KR(ret), K(meta_tenant_id));
} else if (OB_FAIL(append(ls_status_info_array, user_ls_status_info_array))) {
LOG_WARN("fail to append", KR(ret));
} else if (OB_FAIL(append(ls_status_info_array, meta_ls_status_info_array))) {
LOG_WARN("fail to append", KR(ret));
}
}
return ret;
}
int ObMigrateUnitFinishChecker::try_check_migrate_unit_finish_by_tenant(
const uint64_t tenant_id)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (OB_FAIL(check_stop())) {
LOG_WARN("ObMigrateUnitFinishChecker stopped", KR(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id));
} else {
LOG_INFO("try check migrate unit finish by tenant", K(tenant_id));
DRLSInfo dr_ls_info(gen_user_tenant_id(tenant_id),
unit_mgr_,
server_mgr_,
zone_mgr_,
schema_service_);
common::ObArray<share::ObLSStatusInfo> ls_status_info_array;
if (OB_FAIL(get_all_tenant_related_ls_status_info(tenant_id, ls_status_info_array))) {
LOG_WARN("fail to get all ls status", KR(ret), K(tenant_id));
} else if (OB_FAIL(dr_ls_info.init())) {
LOG_WARN("fail to init disaster log stream info", KR(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < ls_status_info_array.count(); ++i) {
share::ObLSInfo ls_info;
share::ObLSStatusInfo &ls_status_info = ls_status_info_array.at(i);
if (OB_FAIL(check_stop())) {
LOG_WARN("DRWorker stopped", KR(ret));
} else if (OB_FAIL(lst_operator_->get(
GCONF.cluster_id,
ls_status_info.tenant_id_,
ls_status_info.ls_id_,
share::ObLSTable::COMPOSITE_MODE,
ls_info))) {
LOG_WARN("fail to get log stream info", KR(ret));
} else if (OB_FAIL(dr_ls_info.build_disaster_ls_info(
ls_info,
ls_status_info))) {
LOG_WARN("fail to generate dr log stream info", KR(ret));
} else if (OB_FAIL(statistic_migrate_unit_by_ls(
dr_ls_info,
ls_status_info))) {
LOG_WARN("fail to try log stream disaster recovery", KR(ret));
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(try_finish_migrate_unit(
dr_ls_info.get_unit_stat_info_map()))) {
LOG_WARN("fail to try finish migrate unit", KR(ret));
}
}
}
return ret;
}
int ObMigrateUnitFinishChecker::statistic_migrate_unit_by_ls(
DRLSInfo &dr_ls_info,
share::ObLSStatusInfo &ls_status_info)
{
int ret = OB_SUCCESS;
int64_t ls_replica_cnt = 0;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (OB_FAIL(check_stop())) {
LOG_WARN("ObMigrateUnitFinishChecker stopped", KR(ret));
} else if (OB_FAIL(dr_ls_info.get_replica_cnt(ls_replica_cnt))) {
LOG_WARN("fail to get replica cnt", KR(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < ls_replica_cnt; ++i) {
share::ObLSReplica *ls_replica = nullptr;
DRServerStatInfo *server_stat_info = nullptr;
DRUnitStatInfo *unit_stat_info = nullptr;
DRUnitStatInfo *unit_in_group_stat_info = nullptr;
if (OB_FAIL(dr_ls_info.get_replica_stat(
i,
ls_replica,
server_stat_info,
unit_stat_info,
unit_in_group_stat_info))) {
LOG_WARN("fail to get replica stat", KR(ret));
} else if (OB_UNLIKELY(nullptr == ls_replica
|| nullptr == server_stat_info
|| nullptr == unit_stat_info
|| nullptr == unit_in_group_stat_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("replica stat unexpected", KR(ret),
KP(ls_replica),
KP(server_stat_info),
KP(unit_stat_info),
KP(unit_in_group_stat_info));
} else if (server_stat_info->get_server() != unit_stat_info->get_unit_info().unit_.server_
&& (ls_replica->is_in_service() || ls_status_info.ls_is_creating())) {
unit_stat_info->inc_outside_replica_cnt();
if (unit_stat_info->get_outside_replica_cnt() <= 2) { // print the first two outside replica
LOG_INFO("outside replica", KPC(ls_replica), "unit", unit_stat_info->get_unit_info().unit_);
}
}
}
}
return ret;
}
int ObMigrateUnitFinishChecker::try_finish_migrate_unit(
const UnitStatInfoMap &unit_stat_info_map)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObMigrateUnitFinishChecker not init", KR(ret));
} else if (OB_UNLIKELY(nullptr == unit_mgr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unit mgr ptr is null", KR(ret), KP(unit_mgr_));
} else {
const UnitStatInfoMap::HashTable &inner_hash_table = unit_stat_info_map.get_hash_table();
UnitStatInfoMap::HashTable::const_iterator iter = inner_hash_table.begin();
for (; OB_SUCC(ret) && iter != inner_hash_table.end(); ++iter) {
const DRUnitStatInfo &unit_stat_info = iter->v_;
if (unit_stat_info.is_in_pool()
&& unit_stat_info.get_unit_info().unit_.migrate_from_server_.is_valid()
&& 0 == unit_stat_info.get_outside_replica_cnt()) {
if (OB_FAIL(unit_mgr_->finish_migrate_unit(
unit_stat_info.get_unit_info().unit_.unit_id_))) {
LOG_WARN("fail to set unit migrate finish", KR(ret),
"unit_id", unit_stat_info.get_unit_info().unit_.unit_id_);
}
}
}
}
return ret;
}