/** * 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 "observer/ob_server.h" #include "rootserver/ob_root_service.h" #include "share/ob_define.h" #include "lib/time/ob_time_utility.h" #include "lib/string/ob_sql_string.h" #include "lib/utility/ob_preload.h" #include "lib/worker.h" #include "lib/oblog/ob_log_module.h" #include "lib/container/ob_se_array_iterator.h" #include "lib/container/ob_array_iterator.h" #include "lib/file/file_directory_utils.h" #include "lib/encrypt/ob_encrypted_helper.h" #include "share/ob_srv_rpc_proxy.h" #include "share/ob_thread_mgr.h" #include "common/ob_timeout_ctx.h" #include "common/object/ob_object.h" #include "share/ob_cluster_version.h" #include "share/ob_define.h" #include "share/ob_version.h" #include "share/schema/ob_schema_service.h" #include "share/schema/ob_multi_version_schema_service.h" #include "share/schema/ob_schema_utils.h" #include "share/schema/ob_schema_mgr.h" #include "share/ob_lease_struct.h" #include "share/ob_common_rpc_proxy.h" #include "share/config/ob_config_helper.h" #include "share/config/ob_config_manager.h" #include "share/inner_table/ob_inner_table_schema.h" #include "share/schema/ob_part_mgr_util.h" #include "share/ob_web_service_root_addr.h" #include "share/ob_inner_config_root_addr.h" #include "share/ob_global_stat_proxy.h" #include "share/ob_autoincrement_service.h" #include "share/ob_time_zone_info_manager.h" #include "share/ob_server_status.h" #include "share/ob_index_builder_util.h" #include "observer/ob_server_struct.h" #include "observer/omt/ob_tenant_config_mgr.h" #include "observer/ob_server_event_history_table_operator.h" #include "share/ob_upgrade_utils.h" #include "share/deadlock/ob_deadlock_inner_table_service.h" #include "share/ob_max_id_fetcher.h" // ObMaxIdFetcher #include "share/backup/ob_backup_config.h" #include "share/backup/ob_backup_helper.h" #include "share/scheduler/ob_sys_task_stat.h" #include "sql/executor/ob_executor_rpc_proxy.h" #include "sql/engine/cmd/ob_user_cmd_executor.h" #include "sql/engine/px/ob_px_util.h" #include "observer/dbms_job/ob_dbms_job_master.h" #include "observer/dbms_scheduler/ob_dbms_sched_job_master.h" #include "rootserver/ob_bootstrap.h" #include "rootserver/ob_schema2ddl_sql.h" #include "rootserver/ob_index_builder.h" #include "rootserver/ob_update_rs_list_task.h" #include "rootserver/ob_resource_weight_parser.h" #include "rootserver/ob_rs_job_table_operator.h" #include "rootserver/restore/ob_restore_util.h" #include "rootserver/ob_root_utils.h" #include "rootserver/ob_vertical_partition_builder.h" #include "rootserver/ob_ddl_sql_generator.h" #include "rootserver/ddl_task/ob_ddl_task.h" #include "rootserver/ddl_task/ob_constraint_task.h" #include "storage/ob_file_system_router.h" #include "storage/tx/ob_ts_mgr.h" #include "lib/stat/ob_diagnose_info.h" #include "rootserver/ob_cluster_event.h" // CLUSTER_EVENT_ADD_CONTROL #include "observer/omt/ob_tenant_timezone_mgr.h" #include "share/backup/ob_backup_io_adapter.h" #include "share/ob_global_context_operator.h" #include "share/ls/ob_ls_table_operator.h" // for ObLSTableOperator #include "share/ls/ob_ls_status_operator.h"//ls_status_operator #include "share/ob_max_id_fetcher.h" //ObMaxIdFetcher #include "observer/ob_service.h" #include "storage/ob_file_system_router.h" #include "storage/ddl/ob_ddl_heart_beat_task.h" #include "rootserver/freeze/ob_major_freeze_helper.h" #include "share/restore/ob_physical_restore_table_operator.h"//ObPhysicalRestoreTableOperator #include "share/ob_cluster_event_history_table_operator.h"//CLUSTER_EVENT_INSTANCE #include "share/scn.h" #include "rootserver/backup/ob_backup_proxy.h" //ObBackupServiceProxy #include "logservice/palf_handle_guard.h" #include "logservice/ob_log_service.h" #include "rootserver/ob_heartbeat_service.h" namespace oceanbase { using namespace common; using namespace obrpc; using namespace share; using namespace share::schema; using namespace storage; using namespace dbms_job; namespace rootserver { #define PUSH_BACK_TO_ARRAY_AND_SET_RET(array, msg) \ do { \ if (OB_FAIL(array.push_back(msg))) { \ LOG_WARN("push reason array error", KR(ret), K(array), K(msg)); \ } \ } while(0) ObRootService::ObStatusChangeCallback::ObStatusChangeCallback(ObRootService &root_service) : root_service_(root_service) { } ObRootService::ObStatusChangeCallback::~ObStatusChangeCallback() { } int ObRootService::ObStatusChangeCallback::wakeup_balancer() { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root_service not init", K(ret)); } else { root_service_.get_root_balancer().wakeup(); } return ret; } int ObRootService::ObStatusChangeCallback::wakeup_daily_merger() { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root_service not init", K(ret)); } else { //root_service_.get_daily_merge_scheduler().wakeup(); } return ret; } int ObRootService::ObStatusChangeCallback::on_server_status_change(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root service not inited", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(server), K(ret)); } else if (OB_FAIL(root_service_.submit_update_all_server_task(server))) { LOG_WARN("root service commit task failed", K(server), K(ret)); } LOG_INFO("on_server_status_change finish", KR(ret), K(server)); return ret; } int ObRootService::ObStatusChangeCallback::on_start_server(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root service not inited", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(ret), K(server)); } else if (OB_FAIL(root_service_.submit_start_server_task(server))) { LOG_WARN("fail to submit start server task", K(ret)); } return ret; } int ObRootService::ObStatusChangeCallback::on_stop_server(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root service not inited", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(ret), K(server)); } else if (OB_FAIL(root_service_.submit_stop_server_task(server))) { LOG_WARN("fail to submit stop server task", K(ret)); } return ret; } int ObRootService::ObStatusChangeCallback::on_offline_server(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root service not inited", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(ret), K(server)); } else if (OB_FAIL(root_service_.submit_offline_server_task(server))) { LOG_WARN("fail to submit stop server task", K(ret)); } return ret; } int ObRootService::ObServerChangeCallback::on_server_change() { int ret = OB_SUCCESS; if (!root_service_.is_inited()) { ret = OB_NOT_INIT; LOG_WARN("root service not inited", K(ret)); } else if (OB_FAIL(root_service_.submit_update_all_server_config_task())) { LOG_WARN("root service commit task failed", K(ret)); } return ret; } int ObRootService::ObStartStopServerTask::process() { int ret = OB_SUCCESS; bool exist = false; if (!server_.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(server_)); // still use server manager here, since this func. will be called only in version < 4.2 } else if (OB_FAIL(root_service_.get_server_mgr().is_server_exist(server_, exist))) { LOG_WARN("fail to check server exist", KR(ret), K(server_)); } else if (!exist) { // server does not exist, ignore } else { obrpc::ObAdminServerArg arg; if (OB_FAIL(arg.servers_.push_back(server_))) { LOG_WARN("fail to push back", K(ret), K(server_)); } else if (start_) { if (OB_FAIL(root_service_.start_server(arg))) { LOG_WARN("fail to start server", K(ret), K(arg)); } } else { if (OB_FAIL(root_service_.stop_server(arg))) { LOG_WARN("fail to stop server", K(ret), K(arg)); } } } return ret; } int64_t ObRootService::ObStartStopServerTask::get_deep_copy_size() const { return sizeof(*this); } ObAsyncTask *ObRootService::ObStartStopServerTask::deep_copy( char *buf, const int64_t buf_size) const { ObAsyncTask *task = NULL; int ret = OB_SUCCESS; const int64_t need_size = get_deep_copy_size(); if (NULL == buf) { ret = OB_INVALID_ARGUMENT; LOG_WARN("buf is null", K(ret)); } else if (buf_size < need_size) { ret = OB_INVALID_ARGUMENT; LOG_WARN("buf is not long enough", K(need_size), K(buf_size), K(ret)); } else { task = new (buf) ObStartStopServerTask(root_service_, server_, start_); } return task; } int ObRootService::ObOfflineServerTask::process() { int ret = OB_SUCCESS; ObRsListArg arg; ObLSInfo ls_info; const int64_t cluster_id = GCONF.cluster_id; const int64_t tenant_id = OB_SYS_TENANT_ID; if (!server_.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(server_)); } else if (OB_FAIL(root_service_.get_lst_operator().get( cluster_id, tenant_id, SYS_LS, share::ObLSTable::DEFAULT_MODE, ls_info))) { LOG_WARN("fail to get", KR(ret)); } else { arg.master_rs_ = GCONF.self_addr_; FOREACH_CNT_X(replica, ls_info.get_replicas(), OB_SUCCESS == ret) { if (replica->get_server() == GCONF.self_addr_ || (replica->is_in_service() && ObReplicaTypeCheck::is_paxos_replica_V2(replica->get_replica_type()))) { if (OB_FAIL(arg.rs_list_.push_back(replica->get_server()))) { LOG_WARN("fail to push back", KR(ret)); } } } if (OB_FAIL(ret)) { } else if (OB_FAIL(root_service_.get_rpc_proxy().to(server_).broadcast_rs_list(arg))) { LOG_DEBUG("fail to broadcast rs list", KR(ret)); } else { LOG_INFO("broadcast rs list success", K(arg), K_(server)); } } return ret; } int64_t ObRootService::ObOfflineServerTask::get_deep_copy_size() const { return sizeof(*this); } ObAsyncTask *ObRootService::ObOfflineServerTask::deep_copy( char *buf, const int64_t buf_size) const { ObAsyncTask *task = NULL; int ret = OB_SUCCESS; const int64_t need_size = get_deep_copy_size(); if (NULL == buf) { ret = OB_INVALID_ARGUMENT; LOG_WARN("buf is null", K(ret)); } else if (buf_size < need_size) { ret = OB_INVALID_ARGUMENT; LOG_WARN("buf is not long enough", K(need_size), K(buf_size), K(ret)); } else { task = new (buf) ObOfflineServerTask(root_service_, server_); } return task; } int ObRootService::ObMinorFreezeTask::process() { int ret = OB_SUCCESS; ObAddr rs_addr; DEBUG_SYNC(BEFORE_DO_MINOR_FREEZE); if (OB_ISNULL(GCTX.rs_rpc_proxy_) || OB_ISNULL(GCTX.rs_mgr_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid global context", K(ret)); } else if (OB_FAIL(GCTX.rs_mgr_->get_master_root_server(rs_addr))) { LOG_WARN("get rootservice address failed", K(ret)); } else if (OB_FAIL(GCTX.rs_rpc_proxy_->to(rs_addr).timeout(GCONF.rpc_timeout) .root_minor_freeze(arg_))) { LOG_WARN("minor freeze rpc failed", K(ret), K_(arg)); } else { LOG_INFO("minor freeze rpc success", K(ret), K_(arg)); } return ret; } int64_t ObRootService::ObMinorFreezeTask::get_deep_copy_size() const { return sizeof(*this); } ObAsyncTask *ObRootService::ObMinorFreezeTask::deep_copy(char *buf, const int64_t buf_size) const { ObAsyncTask *task = NULL; int ret = OB_SUCCESS; const int64_t need_size = get_deep_copy_size(); if (NULL == buf) { ret = OB_INVALID_ARGUMENT; LOG_WARN("buf is null", K(ret)); } else if (buf_size < need_size) { ret = OB_INVALID_ARGUMENT; LOG_WARN("buf is not long enough", K(need_size), K(buf_size), K(ret)); } else { task = new(buf) ObMinorFreezeTask(arg_); } return task; } //////////////////////////////////////////////////////////////// bool ObRsStatus::can_start_service() const { bool bret = false; SpinRLockGuard guard(lock_); status::ObRootServiceStatus rs_status = ATOMIC_LOAD(&rs_status_); if (status::INIT == rs_status) { bret = true; } return bret; } bool ObRsStatus::is_start() const { bool bret = false; SpinRLockGuard guard(lock_); status::ObRootServiceStatus stat = ATOMIC_LOAD(&rs_status_); if (status::STARTING == stat || status::IN_SERVICE == stat || status::FULL_SERVICE == stat || status::STARTED == stat) { bret = true; } return bret; } bool ObRsStatus::is_stopping() const { bool bret = false; SpinRLockGuard guard(lock_); status::ObRootServiceStatus stat = ATOMIC_LOAD(&rs_status_); if (status::STOPPING == stat) { bret = true; } return bret; } bool ObRsStatus::need_do_restart() const { bool bret = false; SpinRLockGuard guard(lock_); status::ObRootServiceStatus stat = ATOMIC_LOAD(&rs_status_); if (status::IN_SERVICE == stat) { bret = true; } return bret; } bool ObRsStatus::is_full_service() const { SpinRLockGuard guard(lock_); bool bret = false; status::ObRootServiceStatus stat = ATOMIC_LOAD(&rs_status_); if (status::FULL_SERVICE == stat || status::STARTED == stat) { bret = true; } return bret; } bool ObRsStatus::in_service() const { bool bret = false; SpinRLockGuard guard(lock_); status::ObRootServiceStatus stat = ATOMIC_LOAD(&rs_status_); if (status::IN_SERVICE == stat || status::FULL_SERVICE == stat || status::STARTED == stat) { bret = true; } return bret; } bool ObRsStatus::is_need_stop() const { SpinRLockGuard guard(lock_); status::ObRootServiceStatus stat = ATOMIC_LOAD(&rs_status_); return status::NEED_STOP == stat; } status::ObRootServiceStatus ObRsStatus::get_rs_status() const { SpinRLockGuard guard(lock_); return ATOMIC_LOAD(&rs_status_); } //RS need stop after leader revoke int ObRsStatus::revoke_rs() { int ret = OB_SUCCESS; FLOG_INFO("[ROOTSERVICE_NOTICE] try to revoke rs"); SpinWLockGuard guard(lock_); if (status::IN_SERVICE == rs_status_ || status::FULL_SERVICE == rs_status_) { rs_status_ = status::NEED_STOP; FLOG_INFO("[ROOTSERVICE_NOTICE] rs_status is setted to need_stop", K_(rs_status)); } else if (status::STOPPING != rs_status_) { rs_status_ = status::STOPPING; FLOG_INFO("[ROOTSERVICE_NOTICE] rs_status is setted to stopping", K_(rs_status)); } return ret; } int ObRsStatus::try_set_stopping() { int ret = OB_SUCCESS; FLOG_INFO("[ROOTSERVICE_NOTICE] try set rs_status to stopping"); SpinWLockGuard guard(lock_); if (status::NEED_STOP == rs_status_) { rs_status_ = status::STOPPING; FLOG_INFO("[ROOTSERVICE_NOTICE] rs_status is setted to stopping"); } return ret; } int ObRsStatus::set_rs_status(const status::ObRootServiceStatus status) { int ret = OB_SUCCESS; SpinWLockGuard guard(lock_); const char* new_status_str = NULL; const char* old_status_str = NULL; if (OB_FAIL(get_rs_status_str(status, new_status_str))) { FLOG_WARN("fail to get rs status", KR(ret), K(status)); } else if (OB_FAIL(get_rs_status_str(rs_status_, old_status_str))) { FLOG_WARN("fail to get rs status", KR(ret), K(rs_status_)); } else if (OB_ISNULL(new_status_str) || OB_ISNULL(old_status_str)) { ret = OB_ERR_UNEXPECTED; FLOG_WARN("error unexpect", KR(ret), K(new_status_str), K(old_status_str)); } if (OB_SUCC(ret)) { switch(rs_status_) { case status::INIT: { if (status::STARTING == status || status::STOPPING == status) { //rs.stop() will be executed while obs exit rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } case status::STARTING: { if (status::IN_SERVICE == status || status::STOPPING == status) { rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } case status::IN_SERVICE: { if (status::FULL_SERVICE == status || status::NEED_STOP == status || status::STOPPING == status) { rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } case status::FULL_SERVICE: { if (status::STARTED == status || status::NEED_STOP == status || status::STOPPING == status) { rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } case status::STARTED: { if (status::STOPPING == status) { rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } case status::NEED_STOP: { if (status::STOPPING == status) { rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } case status::STOPPING: { if (status::INIT == status || status::STOPPING == status) { rs_status_ = status; FLOG_INFO("[ROOTSERVICE_NOTICE] success to set rs status", K(new_status_str), K(old_status_str), K(rs_status_)); } else { ret = OB_OP_NOT_ALLOW; FLOG_WARN("can't set rs status", KR(ret)); } break; } default: ret = OB_ERR_UNEXPECTED; FLOG_WARN("invalid rs status", KR(ret), K(rs_status_)); } } return ret; } //////////////////////////////////////////////////////////////// ObRootService::ObRootService() : inited_(false), server_refreshed_(false), debug_(false), self_addr_(), config_(NULL), config_mgr_(NULL), rpc_proxy_(), common_proxy_(), sql_proxy_(), restore_ctx_(NULL), rs_mgr_(NULL), schema_service_(NULL), status_change_cb_(*this), server_change_callback_(*this), server_manager_(), hb_checker_(), server_checker_(), rs_list_change_cb_(*this), server_zone_op_service_(), root_minor_freeze_(), lst_operator_(NULL), zone_manager_(), ddl_service_(), unit_manager_(server_manager_, zone_manager_), root_balancer_(), empty_server_checker_(), lost_replica_checker_(), thread_checker_(), vtable_location_getter_(unit_manager_), addr_agent_(NULL), root_inspection_(), upgrade_executor_(), upgrade_storage_format_executor_(), create_inner_schema_executor_(), bootstrap_lock_(), broadcast_rs_list_lock_(ObLatchIds::RS_BROADCAST_LOCK), task_queue_(), inspect_task_queue_(), restart_task_(*this), refresh_server_task_(*this), check_server_task_(task_queue_, server_checker_), self_check_task_(*this), load_ddl_task_(*this), refresh_io_calibration_task_(*this), event_table_clear_task_(ROOTSERVICE_EVENT_INSTANCE, SERVER_EVENT_INSTANCE, DEALOCK_EVENT_INSTANCE, task_queue_), inspector_task_(*this), purge_recyclebin_task_(*this), ddl_scheduler_(), snapshot_manager_(), core_meta_table_version_(0), update_rs_list_timer_task_(*this), update_all_server_config_task_(*this), baseline_schema_version_(0), start_service_time_(0), rs_status_(), fail_count_(0), schema_history_recycler_(), disaster_recovery_task_executor_(), disaster_recovery_task_mgr_(), global_ctx_task_(*this) { } ObRootService::~ObRootService() { if (inited_) { destroy(); } } int ObRootService::fake_init(ObServerConfig &config, ObConfigManager &config_mgr, ObSrvRpcProxy &srv_rpc_proxy, ObCommonRpcProxy &common_proxy, ObAddr &self, ObMySQLProxy &sql_proxy, ObRsMgr &rs_mgr, ObMultiVersionSchemaService *schema_service, ObLSTableOperator &lst_operator) { int ret = OB_SUCCESS; if (inited_) { ret = OB_INIT_TWICE; LOG_WARN("rootservice already inited", K(ret)); } else if (!self.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid self address", K(self), K(ret)); } else if (NULL == schema_service) { ret = OB_INVALID_ARGUMENT; LOG_WARN("schema_service must not null", KP(schema_service), K(ret)); } else { LOG_INFO("start to init rootservice"); config_ = &config; config_mgr_ = &config_mgr; rpc_proxy_ = srv_rpc_proxy; common_proxy_ = common_proxy; const bool rpc_active = false; common_proxy_.active(rpc_active); rpc_proxy_.active(rpc_active); self_addr_ = self; sql_proxy_.assign(sql_proxy); sql_proxy_.set_inactive(); oracle_sql_proxy_.set_inactive(); rs_mgr_ = &rs_mgr; addr_agent_ = &rs_mgr.get_addr_agent(); schema_service_ = schema_service; lst_operator_ = &lst_operator; } // init server management related if (OB_SUCC(ret)) { if (OB_FAIL(server_manager_.init( status_change_cb_, server_change_callback_, sql_proxy_, unit_manager_, zone_manager_, config, self, rpc_proxy_))) { LOG_WARN("init server manager failed", K(ret)); } else if (OB_FAIL(hb_checker_.init(server_manager_))) { LOG_WARN("init heartbeat checker failed", K(ret)); } else if (OB_FAIL(server_checker_.init(server_manager_, self))) { LOG_WARN("init server checker failed", K(self), K(ret)); } } // init ddl service if (OB_SUCC(ret)) { if (OB_FAIL(ddl_service_.init(rpc_proxy_, common_proxy_, sql_proxy_, *schema_service, lst_operator, zone_manager_, unit_manager_, snapshot_manager_))) { LOG_WARN("ddl_service_ init failed", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(dbms_job::ObDBMSJobMaster::get_instance() .init(&sql_proxy_, schema_service_))) { LOG_WARN("failed to init ObDBMSJobMaster", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(dbms_scheduler::ObDBMSSchedJobMaster::get_instance() .init(&unit_manager_, &sql_proxy_, schema_service_))) { LOG_WARN("failed to init ObDBMSSchedJobMaster", K(ret)); } } if (OB_SUCC(ret)) { inited_ = true; } LOG_INFO("init rootservice", K(ret)); return ret; } int ObRootService::init(ObServerConfig &config, ObConfigManager &config_mgr, ObSrvRpcProxy &srv_rpc_proxy, ObCommonRpcProxy &common_proxy, ObAddr &self, ObMySQLProxy &sql_proxy, observer::ObRestoreCtx &restore_ctx, ObRsMgr &rs_mgr, ObMultiVersionSchemaService *schema_service, ObLSTableOperator &lst_operator) { int ret = OB_SUCCESS; FLOG_INFO("[ROOTSERVICE_NOTICE] begin to init rootservice"); if (inited_) { ret = OB_INIT_TWICE; FLOG_WARN("rootservice already inited", KR(ret)); } else if (!self.is_valid()) { ret = OB_INVALID_ARGUMENT; FLOG_WARN("invalid self address", K(self), KR(ret)); } else if (NULL == schema_service) { ret = OB_INVALID_ARGUMENT; FLOG_WARN("schema_service must not null", KP(schema_service), KR(ret)); } else { config_ = &config; config_mgr_ = &config_mgr; rpc_proxy_ = srv_rpc_proxy; common_proxy_ = common_proxy; const bool rpc_active = false; common_proxy_.active(rpc_active); rpc_proxy_.active(rpc_active); self_addr_ = self; restore_ctx_ = &restore_ctx; sql_proxy_.assign(sql_proxy); sql_proxy_.set_inactive(); if (OB_FAIL(oracle_sql_proxy_.init(sql_proxy.get_pool()))) { FLOG_WARN("init oracle sql proxy failed", KR(ret)); } else { oracle_sql_proxy_.set_inactive(); } rs_mgr_ = &rs_mgr; addr_agent_ = &rs_mgr.get_addr_agent(); schema_service_ = schema_service; lst_operator_ = &lst_operator; } // init inner queue if (FAILEDx(task_queue_.init( config_->rootservice_async_task_thread_count, config_->rootservice_async_task_queue_size, "RSAsyncTask"))) { FLOG_WARN("init inner queue failed", "thread_count", static_cast(config_->rootservice_async_task_thread_count), "queue_size", static_cast(config_->rootservice_async_task_queue_size), KR(ret)); } else if (OB_FAIL(inspect_task_queue_.init(1/*only for the inspection of RS*/, config_->rootservice_async_task_queue_size, "RSInspectTask"))) { FLOG_WARN("init inner queue failed", "thread_count", 1, "queue_size", static_cast(config_->rootservice_async_task_queue_size), KR(ret)); } else if (OB_FAIL(zone_manager_.init(sql_proxy_))) { // init zone manager FLOG_WARN("init zone manager failed", KR(ret)); } else if (OB_FAIL(server_manager_.init(status_change_cb_, server_change_callback_, sql_proxy_, unit_manager_, zone_manager_, config, self, rpc_proxy_))) { // init server management related FLOG_WARN("init server manager failed", KR(ret)); } else if (OB_FAIL(server_zone_op_service_.init( server_change_callback_, rpc_proxy_, lst_operator, unit_manager_, sql_proxy_ ))) { FLOG_WARN("init server zone op service failed", KR(ret)); } else if (OB_FAIL(hb_checker_.init(server_manager_))) { FLOG_WARN("init heartbeat checker failed", KR(ret)); } else if (OB_FAIL(server_checker_.init(server_manager_, self))) { FLOG_WARN("init server checker failed", KR(ret), K(self)); } else if (OB_FAIL(root_minor_freeze_.init(rpc_proxy_, unit_manager_))) { // init root minor freeze FLOG_WARN("init root_minor_freeze_ failed", KR(ret)); } else if (OB_FAIL(ddl_service_.init(rpc_proxy_, common_proxy_, sql_proxy_, *schema_service, lst_operator, zone_manager_, unit_manager_, snapshot_manager_))) { // init ddl service FLOG_WARN("init ddl_service_ failed", KR(ret)); } else if (OB_FAIL(unit_manager_.init(sql_proxy_, *config_, rpc_proxy_, *schema_service, root_balancer_))) { // init unit manager FLOG_WARN("init unit_manager failed", KR(ret)); } else if (OB_FAIL(snapshot_manager_.init(self_addr_))) { FLOG_WARN("init snapshot manager failed", KR(ret)); } else if (OB_FAIL(root_inspection_.init(*schema_service_, zone_manager_, sql_proxy_, &common_proxy_))) { FLOG_WARN("init root inspection failed", KR(ret)); } else if (OB_FAIL(upgrade_executor_.init(*schema_service_, root_inspection_, sql_proxy_, rpc_proxy_, common_proxy_))) { FLOG_WARN("init upgrade_executor failed", KR(ret)); } else if (OB_FAIL(upgrade_storage_format_executor_.init(*this, ddl_service_))) { FLOG_WARN("init upgrade storage format executor failed", KR(ret)); } else if (OB_FAIL(create_inner_schema_executor_.init(*schema_service_, sql_proxy_, common_proxy_))) { FLOG_WARN("init create inner role executor failed", KR(ret)); } else if (OB_FAIL(thread_checker_.init())) { FLOG_WARN("init thread checker failed", KR(ret)); } else if (OB_FAIL(empty_server_checker_.init( server_manager_, unit_manager_, *lst_operator_, *schema_service_, server_zone_op_service_))) { FLOG_WARN("init empty server checker failed", KR(ret)); } else if (OB_FAIL(lost_replica_checker_.init(*lst_operator_, *schema_service_))) { FLOG_WARN("init empty server checker failed", KR(ret)); } else if (OB_FAIL(root_balancer_.init(*config_, *schema_service_, unit_manager_, server_manager_, zone_manager_, rpc_proxy_, self_addr_, sql_proxy, disaster_recovery_task_mgr_))) { FLOG_WARN("init root balancer failed", KR(ret)); } else if (OB_FAIL(ROOTSERVICE_EVENT_INSTANCE.init(sql_proxy, self_addr_))) { FLOG_WARN("init rootservice event history failed", KR(ret)); } else if (OB_FAIL(THE_RS_JOB_TABLE.init(&sql_proxy, self_addr_))) { FLOG_WARN("init THE_RS_JOB_TABLE failed", KR(ret)); } else if (OB_FAIL(ddl_scheduler_.init(this))) { FLOG_WARN("init ddl task scheduler failed", KR(ret)); } else if (OB_FAIL(schema_history_recycler_.init(*schema_service_, zone_manager_, sql_proxy_))) { FLOG_WARN("fail to init schema history recycler failed", KR(ret)); } else if (OB_FAIL(dbms_job::ObDBMSJobMaster::get_instance().init(&sql_proxy_, schema_service_))) { FLOG_WARN("init ObDBMSJobMaster failed", KR(ret)); } else if (OB_FAIL(dbms_scheduler::ObDBMSSchedJobMaster::get_instance().init(&unit_manager_, &sql_proxy_, schema_service_))) { FLOG_WARN("init ObDBMSSchedJobMaster failed", KR(ret)); } else if (OB_FAIL(disaster_recovery_task_executor_.init(lst_operator, rpc_proxy_))) { FLOG_WARN("init disaster recovery task executor failed", KR(ret)); } else if (OB_FAIL(disaster_recovery_task_mgr_.init(self, *config_, disaster_recovery_task_executor_, &rpc_proxy_, &sql_proxy_, schema_service_))) { FLOG_WARN("init disaster recovery task mgr failed", KR(ret)); } if (OB_SUCC(ret)) { inited_ = true; FLOG_INFO("[ROOTSERVICE_NOTICE] init rootservice success", KR(ret), K_(inited)); } else { LOG_ERROR("[ROOTSERVICE_NOTICE] fail to init root service", KR(ret)); LOG_DBA_ERROR(OB_ERR_ROOTSERVICE_START, "msg", "rootservice init() has failure", KR(ret)); } return ret; } void ObRootService::destroy() { int ret = OB_SUCCESS; int fail_ret = OB_SUCCESS; FLOG_INFO("[ROOTSERVICE_NOTICE] start to destroy rootservice"); if (in_service()) { if (OB_FAIL(stop_service())) { FLOG_WARN("stop service failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } } if (OB_FAIL(lost_replica_checker_.destroy())) { FLOG_WARN("lost replica checker failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("lost replica checker destroy"); } // continue executing while error happen if (OB_FAIL(root_balancer_.destroy())) { FLOG_WARN("root balance destroy failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("root balance destroy"); } if (OB_FAIL(empty_server_checker_.destroy())) { FLOG_WARN("empty server checker destroy failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("empty server checker destroy"); } if (OB_FAIL(thread_checker_.destroy())) { FLOG_WARN("rs_monitor_check : thread checker destroy failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("rs_monitor_check : thread checker destroy"); } if (OB_FAIL(schema_history_recycler_.destroy())) { FLOG_WARN("schema history recycler destroy failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("schema history recycler destroy"); } task_queue_.destroy(); FLOG_INFO("inner queue destroy"); inspect_task_queue_.destroy(); FLOG_INFO("inspect queue destroy"); ddl_builder_.destroy(); FLOG_INFO("ddl builder destroy"); if (OB_FAIL(hb_checker_.destroy())) { FLOG_WARN("heartbeat checker destroy failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("heartbeat checker destroy"); } ROOTSERVICE_EVENT_INSTANCE.destroy(); FLOG_INFO("event table operator destroy"); dbms_job::ObDBMSJobMaster::get_instance().destroy(); FLOG_INFO("ObDBMSJobMaster destroy"); ddl_scheduler_.destroy(); FLOG_INFO("ddl task scheduler destroy"); if (OB_FAIL(disaster_recovery_task_mgr_.destroy())) { FLOG_WARN("disaster recovery task mgr destroy failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("disaster recovery task mgr destroy"); } dbms_scheduler::ObDBMSSchedJobMaster::get_instance().destroy(); FLOG_INFO("ObDBMSSchedJobMaster destroy"); TG_DESTROY(lib::TGDefIDs::GlobalCtxTimer); FLOG_INFO("global ctx timer destroyed"); if (OB_SUCC(ret)) { if (inited_) { inited_ = false; } } FLOG_INFO("[ROOTSERVICE_NOTICE] destroy rootservice end", KR(ret)); if (OB_SUCCESS != fail_ret) { LOG_DBA_WARN(OB_ERR_ROOTSERVICE_STOP, "msg", "rootservice destroy() has failure", KR(fail_ret)); } } int ObRootService::start_service() { int ret = OB_SUCCESS; start_service_time_ = ObTimeUtility::current_time(); ROOTSERVICE_EVENT_ADD("root_service", "start_rootservice", K_(self_addr)); FLOG_INFO("[ROOTSERVICE_NOTICE] start to start rootservice", K_(start_service_time)); if (!inited_) { ret = OB_NOT_INIT; FLOG_WARN("rootservice not inited", KR(ret)); } else if (OB_FAIL(rs_status_.set_rs_status(status::STARTING))) { FLOG_WARN("fail to set rs status", KR(ret)); } else if (!ObRootServiceRoleChecker::is_rootserver()) { ret = OB_NOT_MASTER; FLOG_WARN("not master", KR(ret)); } else { sql_proxy_.set_active(); oracle_sql_proxy_.set_active(); const bool rpc_active = true; common_proxy_.active(rpc_active); rpc_proxy_.active(rpc_active); ddl_service_.restart(); server_manager_.reset(); zone_manager_.reset(); OTC_MGR.reset_version_has_refreshed(); if (OB_FAIL(hb_checker_.start())) { FLOG_WARN("hb checker start failed", KR(ret)); } else if (OB_FAIL(task_queue_.start())) { FLOG_WARN("inner queue start failed", KR(ret)); } else if (OB_FAIL(inspect_task_queue_.start())) { FLOG_WARN("inspect queue start failed", KR(ret)); } else if (OB_FAIL(ddl_builder_.start())) { FLOG_WARN("start ddl builder failed", KR(ret)); } else if (OB_FAIL(TG_START(lib::TGDefIDs::GlobalCtxTimer))) { FLOG_WARN("init global ctx timer fail", KR(ret)); } else if (OB_FAIL(global_ctx_task_.schedule(lib::TGDefIDs::GlobalCtxTimer))) { FLOG_WARN("failed to schedule global ctx task", KR(ret)); } else if (OB_FAIL(lst_operator_->set_callback_for_rs(rs_list_change_cb_))) { FLOG_WARN("lst_operator set as rs leader failed", KR(ret)); } else if (OB_FAIL(rs_status_.set_rs_status(status::IN_SERVICE))) { FLOG_WARN("fail to set rs status", KR(ret)); } else if (OB_FAIL(schedule_refresh_server_timer_task(0))) { FLOG_WARN("failed to schedule refresh_server task", KR(ret)); } else if (OB_FAIL(schedule_restart_timer_task(0))) { FLOG_WARN("failed to schedule restart task", KR(ret)); } else if (OB_FAIL(schema_service_->get_ddl_epoch_mgr().remove_all_ddl_epoch())) { FLOG_WARN("fail to remove ddl epoch", KR(ret)); } else if (debug_) { if (OB_FAIL(init_debug_database())) { FLOG_WARN("init_debug_database failed", KR(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "finish_start_rootservice", "result", ret, K_(self_addr)); if (OB_FAIL(ret)) { // increase fail count for self checker and print log. update_fail_count(ret); FLOG_WARN("start service failed, do stop service", KR(ret)); int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = rs_status_.set_rs_status(status::STOPPING))) { FLOG_WARN("fail to set status", KR(tmp_ret)); } else if (OB_SUCCESS != (tmp_ret = stop_service())) { FLOG_WARN("stop service failed", KR(tmp_ret)); } } FLOG_INFO("[ROOTSERVICE_NOTICE] rootservice start_service finished", KR(ret)); return ret; } int ObRootService::stop_service() { int ret = OB_SUCCESS; FLOG_INFO("[ROOTSERVICE_NOTICE] stop service begin"); if (OB_FAIL(stop())) { FLOG_WARN("fail to stop thread", KR(ret)); } else { wait(); } if (FAILEDx(rs_status_.set_rs_status(status::INIT))) { FLOG_WARN("fail to set rs status", KR(ret)); } FLOG_INFO("[ROOTSERVICE_NOTICE] stop service finished", KR(ret)); return ret; } int ObRootService::stop() { int ret = OB_SUCCESS; int fail_ret = OB_SUCCESS; start_service_time_ = 0; int64_t start_time = ObTimeUtility::current_time(); ROOTSERVICE_EVENT_ADD("root_service", "stop_rootservice", K_(self_addr)); FLOG_INFO("[ROOTSERVICE_NOTICE] start to stop rootservice", K(start_time)); if (!inited_) { ret = OB_NOT_INIT; FLOG_WARN("rootservice not inited", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else if (OB_FAIL(rs_status_.set_rs_status(status::STOPPING))) { FLOG_WARN("fail to set rs status", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { // set to rpc ls table as soon as possible if (OB_FAIL(lst_operator_->set_callback_for_obs( common_proxy_, rpc_proxy_, *rs_mgr_, sql_proxy_))) { FLOG_WARN("set as rs follower failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("set old rs to follower finished"); } //full_service_ = false; server_refreshed_ = false; //in_service_ = false; sql_proxy_.set_inactive(); FLOG_INFO("sql_proxy set inactive finished"); oracle_sql_proxy_.set_inactive(); FLOG_INFO("oracle_sql_proxy set inactive finished"); const bool rpc_active = false; common_proxy_.active(rpc_active); FLOG_INFO("commom_proxy set inactive finished"); rpc_proxy_.active(rpc_active); FLOG_INFO("rpc_proxy set inactive finished"); int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = upgrade_executor_.stop())) { FLOG_WARN("upgrade_executor stop failed", KR(tmp_ret)); fail_ret = OB_SUCCESS == fail_ret ? tmp_ret : fail_ret; } else { FLOG_INFO("upgrade_executor stop finished"); } if (OB_SUCCESS != (tmp_ret = upgrade_storage_format_executor_.stop())) { FLOG_WARN("fail to stop upgrade storage format executor", KR(tmp_ret)); fail_ret = OB_SUCCESS == fail_ret ? tmp_ret : fail_ret; } else { FLOG_INFO("upgrade_storage_format_executor stop finished"); } if (OB_SUCCESS != (tmp_ret = create_inner_schema_executor_.stop())) { FLOG_WARN("fail to stop create inner schema executor", KR(tmp_ret)); fail_ret = OB_SUCCESS == fail_ret ? tmp_ret : fail_ret; } else { FLOG_INFO("create_inner_schema_executor stop finished"); } if (OB_SUCC(ret)) { if (OB_FAIL(stop_timer_tasks())) { FLOG_WARN("stop timer tasks failed", KR(ret)); fail_ret = OB_SUCCESS == fail_ret ? ret : fail_ret; } else { FLOG_INFO("stop timer tasks success"); } } if (OB_SUCC(ret)) { // ddl_service may be trying refresh schema, stop it ddl_service_.stop(); FLOG_INFO("ddl service stop"); root_minor_freeze_.stop(); FLOG_INFO("minor freeze stop"); root_inspection_.stop(); FLOG_INFO("root inspection stop"); } if (OB_SUCC(ret)) { ddl_builder_.stop(); FLOG_INFO("ddl builder stop"); task_queue_.stop(); FLOG_INFO("task_queue stop"); inspect_task_queue_.stop(); FLOG_INFO("inspect queue stop"); root_balancer_.stop(); FLOG_INFO("root_balancer stop"); empty_server_checker_.stop(); FLOG_INFO("empty_server_checker stop"); lost_replica_checker_.stop(); FLOG_INFO("lost_replica_checker stop"); thread_checker_.stop(); FLOG_INFO("rs_monitor_check : thread_checker stop"); schema_history_recycler_.stop(); FLOG_INFO("schema_history_recycler stop"); hb_checker_.stop(); FLOG_INFO("hb_checker stop"); ddl_scheduler_.stop(); FLOG_INFO("ddl task scheduler stop"); dbms_job::ObDBMSJobMaster::get_instance().stop(); FLOG_INFO("dbms job master stop"); disaster_recovery_task_mgr_.stop(); FLOG_INFO("disaster_recovery_task_mgr stop"); dbms_scheduler::ObDBMSSchedJobMaster::get_instance().stop(); FLOG_INFO("dbms sched job master stop"); TG_STOP(lib::TGDefIDs::GlobalCtxTimer); FLOG_INFO("global ctx timer stop"); } } ROOTSERVICE_EVENT_ADD("root_service", "finish_stop_thread", KR(ret), K_(self_addr)); FLOG_INFO("[ROOTSERVICE_NOTICE] finish stop rootservice", KR(ret)); if (OB_SUCCESS != fail_ret) { LOG_DBA_WARN(OB_ERR_ROOTSERVICE_STOP, "msg", "rootservice stop() has failure", KR(fail_ret)); } return ret; } void ObRootService::wait() { FLOG_INFO("[ROOTSERVICE_NOTICE] wait rootservice begin"); int64_t start_time = ObTimeUtility::current_time(); FLOG_INFO("start to wait all thread exit"); root_balancer_.wait(); FLOG_INFO("root balancer exit success"); empty_server_checker_.wait(); FLOG_INFO("empty server checker exit success"); lost_replica_checker_.wait(); FLOG_INFO("lost replica checker exit success"); thread_checker_.wait(); FLOG_INFO("rs_monitor_check : thread checker exit success"); schema_history_recycler_.wait(); FLOG_INFO("schema_history_recycler exit success"); hb_checker_.wait(); FLOG_INFO("hb checker exit success"); task_queue_.wait(); FLOG_INFO("task queue exit success"); inspect_task_queue_.wait(); FLOG_INFO("inspect queue exit success"); ddl_scheduler_.wait(); FLOG_INFO("ddl task scheduler exit success"); disaster_recovery_task_mgr_.wait(); FLOG_INFO("rebalance task mgr exit success"); TG_WAIT(lib::TGDefIDs::GlobalCtxTimer); FLOG_INFO("global ctx timer exit success"); ObUpdateRsListTask::clear_lock(); THE_RS_JOB_TABLE.reset_max_job_id(); int64_t cost = ObTimeUtility::current_time() - start_time; ROOTSERVICE_EVENT_ADD("root_service", "finish_wait_stop", K(cost)); FLOG_INFO("[ROOTSERVICE_NOTICE] rootservice wait finished", K(start_time), K(cost)); if (cost > 10 * 60 * 1000 * 1000L) { // 10min int ret = OB_ERROR; LOG_ERROR("cost too much time to wait rs stop", KR(ret), K(start_time), K(cost)); } } int ObRootService::reload_config() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { if (OB_FAIL(addr_agent_->reload())) { LOG_WARN("root address agent reload failed", K(ret)); } } return ret; } int ObRootService::submit_update_all_server_config_task() { int ret = OB_SUCCESS; ObUpdateAllServerConfigTask task(*this); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("fail to add async task", K(ret)); } else { LOG_INFO("ass async task for update all server config"); } return ret; } int ObRootService::submit_ddl_single_replica_build_task(ObAsyncTask &task) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("ObRootService has not been inited", K(ret)); } else if (OB_FAIL(ddl_builder_.push_task(task))) { LOG_WARN("add task to ddl builder failed", K(ret)); } return ret; } int ObRootService::submit_update_all_server_task(const ObAddr &server) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(server), K(ret)); } else { const bool with_rootserver = (server == self_addr_); if (!ObHeartbeatService::is_service_enabled()) { ObAllServerTask task(server_manager_, disaster_recovery_task_mgr_, server, with_rootserver); if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push task failed", K(ret)); } } } // FIXME: @wanhong.wwh: If self is RS and self status change, submit_update_rslist_task if (OB_SUCC(ret)) { if (!in_service()) { LOG_INFO("self is not RS, need not submit update rslist task in update_all_server_task", K(server)); } else { LOG_INFO("self is RS and self status change, submit update rslist task", K(server)); if (OB_FAIL(submit_update_rslist_task())) { LOG_WARN("submit update rslist task failed", KR(ret)); } } } return ret; } int ObRootService::submit_start_server_task(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(ret), K(server)); } else { const bool start = true; ObStartStopServerTask task(*this, server, start); if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push task failed", K(ret)); } } return ret; } int ObRootService::submit_stop_server_task(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(ret), K(server)); } else { const bool start = false; ObStartStopServerTask task(*this, server, start); if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push task failed", K(ret)); } } return ret; } int ObRootService::submit_offline_server_task(const common::ObAddr &server) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!server.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", K(ret), K(server)); } else { ObOfflineServerTask task(*this, server); if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push task failed", K(ret)); } } return ret; } int ObRootService::submit_upgrade_task( const obrpc::ObUpgradeJobArg &arg) { int ret = OB_SUCCESS; ObUpgradeTask task(upgrade_executor_); task.set_retry_times(0); //not repeat if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_FAIL(task.init(arg))) { LOG_WARN("task init failed", KR(ret), K(arg)); } else if (OB_FAIL(upgrade_executor_.can_execute())) { LOG_WARN("can't run task now", KR(ret), K(arg)); } else if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("submit upgrade task fail", KR(ret), K(arg)); } else { LOG_INFO("submit upgrade task success", KR(ret), K(arg)); } return ret; } int ObRootService::submit_upgrade_storage_format_version_task() { int ret = OB_SUCCESS; ObUpgradeStorageFormatVersionTask task(upgrade_storage_format_executor_); task.set_retry_times(0); if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("ObRootService has not been inited", K(ret)); } else if (OB_FAIL(upgrade_storage_format_executor_.can_execute())) { LOG_WARN("cannot run task now", K(ret)); } else if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("submit upgrade storage format version", K(ret)); } else { LOG_INFO("submit upgrade storage format version success", K(ret), K(common::lbt())); } return ret; } int ObRootService::submit_create_inner_schema_task() { int ret = OB_SUCCESS; ObCreateInnerSchemaTask task(create_inner_schema_executor_); task.set_retry_times(0); if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("ObRootService has not been inited", K(ret)); } else if (OB_FAIL(create_inner_schema_executor_.can_execute())) { LOG_WARN("cannot run task now", K(ret)); } else if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("submit create inner role task", K(ret)); } else { LOG_INFO("submit create inner role task success", K(ret), K(common::lbt())); } return ret; } int ObRootService::schedule_check_server_timer_task() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!ObHeartbeatService::is_service_enabled()) { if (OB_FAIL(task_queue_.add_timer_task(check_server_task_, config_->server_check_interval, true))) { LOG_WARN("failed to add check_server task", K(ret)); } } else { LOG_TRACE("no need to schedule ObCheckServerTask in version >= 4.2"); } return ret; } int ObRootService::schedule_recyclebin_task(int64_t delay) { int ret = OB_SUCCESS; const bool did_repeat = false; if (OB_FAIL(get_inspect_task_queue().add_timer_task( purge_recyclebin_task_, delay, did_repeat))) { if (OB_CANCELED != ret) { LOG_ERROR("schedule purge recyclebin task failed", KR(ret), K(delay), K(did_repeat)); } else { LOG_WARN("schedule purge recyclebin task failed", KR(ret), K(delay), K(did_repeat)); } } return ret; } int ObRootService::schedule_inspector_task() { int ret = OB_SUCCESS; int64_t inspect_interval = ObInspector::INSPECT_INTERVAL; int64_t delay = 1 * 60 * 1000 * 1000; int64_t purge_interval = GCONF._recyclebin_object_purge_frequency; int64_t expire_time = GCONF.recyclebin_object_expire_time; if (purge_interval > 0 && expire_time > 0) { delay = purge_interval; } if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (!inspect_task_queue_.exist_timer_task(inspector_task_) && OB_FAIL(inspect_task_queue_.add_timer_task(inspector_task_, inspect_interval, true))) { LOG_WARN("failed to add inspect task", KR(ret)); } else if (!inspect_task_queue_.exist_timer_task(purge_recyclebin_task_) && OB_FAIL(inspect_task_queue_.add_timer_task(purge_recyclebin_task_, delay, false))) { LOG_WARN("failed to add purge recyclebin task", KR(ret)); } else { LOG_INFO("schedule inspector task", K(inspect_interval), K(purge_interval)); } return ret; } int ObRootService::schedule_self_check_task() { int ret = OB_SUCCESS; const bool did_repeat = false; const int64_t delay = 5L * 1000L * 1000L; //5s if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (task_queue_.exist_timer_task(self_check_task_)) { // ignore error LOG_WARN("already have one self_check_task, ignore this"); } else if (OB_FAIL(task_queue_.add_timer_task(self_check_task_, delay, did_repeat))) { LOG_WARN("fail to add timer task", K(ret)); } else { LOG_INFO("add self_check task success"); } return ret; } int ObRootService::schedule_update_rs_list_task() { int ret = OB_SUCCESS; const bool did_repeat = true; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (task_queue_.exist_timer_task(update_rs_list_timer_task_)) { // ignore error LOG_WARN("already have one update rs list timer task , ignore this"); } else if (OB_FAIL(task_queue_.add_timer_task(update_rs_list_timer_task_, ObUpdateRsListTimerTask::RETRY_INTERVAL, did_repeat))) { LOG_WARN("fail to add timer task", K(ret)); } else { LOG_INFO("add update rs list task success"); } return ret; } ERRSIM_POINT_DEF(ALL_SERVER_SCHEDULE_ERROR); int ObRootService::schedule_update_all_server_config_task() { int ret = OB_SUCCESS; const bool did_repeat = true; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(inited_)); } else if (task_queue_.exist_timer_task(update_all_server_config_task_)) { // ignore error LOG_WARN("already have one update_all_server_config task , ignore this"); } else if (OB_FAIL(task_queue_.add_timer_task( update_all_server_config_task_, ALL_SERVER_SCHEDULE_ERROR ? (ObUpdateAllServerConfigTask::RETRY_INTERVAL / 2) : ObUpdateAllServerConfigTask::RETRY_INTERVAL, did_repeat))) { LOG_WARN("fail to add timer task", KR(ret)); } else { LOG_INFO("add update server config task success"); } return ret; } int ObRootService::schedule_load_ddl_task() { int ret = OB_SUCCESS; const bool did_repeat = false; const int64_t delay = 5L * 1000L * 1000L; //5s if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (task_queue_.exist_timer_task(load_ddl_task_)) { // ignore error LOG_WARN("load ddl task already exist", K(ret)); } else if (OB_FAIL(task_queue_.add_timer_task(load_ddl_task_, delay, did_repeat))) { LOG_WARN("fail to add timer task", K(ret)); } else { LOG_INFO("succeed to add load ddl task"); } return ret; } int ObRootService::schedule_refresh_io_calibration_task() { int ret = OB_SUCCESS; const bool did_repeat = false; const int64_t delay = 5L * 1000L * 1000L; //5s if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (task_queue_.exist_timer_task(refresh_io_calibration_task_)) { // ignore error LOG_WARN("refresh io calibration task already exist", K(ret)); } else if (OB_FAIL(task_queue_.add_timer_task(refresh_io_calibration_task_, delay, did_repeat))) { LOG_WARN("fail to add timer task", K(ret)); } else { LOG_INFO("succeed to add refresh io calibration task"); } return ret; } int ObRootService::submit_update_rslist_task(const bool force_update) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else { if (ObUpdateRsListTask::try_lock()) { bool task_added = false; ObUpdateRsListTask task; if (OB_FAIL(task.init(*lst_operator_, addr_agent_, zone_manager_, broadcast_rs_list_lock_, force_update, self_addr_))) { LOG_WARN("task init failed", KR(ret)); } else if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push task failed", K(ret)); } else { task_added = true; LOG_INFO("added async task to update rslist", K(force_update)); } if (!task_added) { ObUpdateRsListTask::unlock(); } } else { LOG_WARN("fail to submit update rslist task, need retry", K(force_update)); } } return ret; } int ObRootService::submit_report_core_table_replica_task() { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObReportCoreTableReplicaTask task(*this); if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push task failed", K(ret)); } else {} // no more to do } return ret; } int ObRootService::submit_reload_unit_manager_task() { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObReloadUnitManagerTask task(*this, unit_manager_); if (OB_FAIL(task_queue_.add_async_task(task))) { LOG_WARN("inner queue push reload_unit task failed", K(ret)); } else { LOG_INFO("submit reload unit task success", K(ret)); } } return ret; } int ObRootService::schedule_restart_timer_task(const int64_t delay) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { const bool did_repeat = false; if (OB_FAIL(task_queue_.add_timer_task(restart_task_, delay, did_repeat))) { LOG_WARN("schedule restart task failed", K(ret), K(delay), K(did_repeat)); } else { LOG_INFO("submit restart task success", K(delay)); } } return ret; } int ObRootService::schedule_refresh_server_timer_task(const int64_t delay) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { const bool did_repeat = false; if (OB_FAIL(task_queue_.add_timer_task(refresh_server_task_, delay, did_repeat))) { LOG_WARN("schedule restart task failed", K(ret), K(delay), K(did_repeat)); } else { LOG_INFO("schedule refresh server timer task", K(delay)); } } return ret; } int ObRootService::update_rslist() { int ret = OB_SUCCESS; ObUpdateRsListTask task; ObTimeoutCtx ctx; ctx.set_timeout(config_->rpc_timeout); const bool force_update = true; if (OB_FAIL(task.init(*lst_operator_, addr_agent_, zone_manager_, broadcast_rs_list_lock_, force_update, self_addr_))) { LOG_WARN("task init failed", K(ret), K(force_update)); } else if (OB_FAIL(task.process_without_lock())) { LOG_WARN("failed to update rslist", K(ret)); } else { LOG_INFO("broadcast root address succeed"); } return ret; } //only used in bootstrap int ObRootService::update_all_server_and_rslist() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { SpinWLockGuard rs_list_guard(broadcast_rs_list_lock_); ret = update_rslist(); if (OB_FAIL(ret)) { LOG_INFO("fail to update rslist, ignore it", KR(ret)); ret = OB_SUCCESS; } } if (OB_SUCC(ret)) { ObArray servers; ObZone empty_zone; // empty zone for all servers if (OB_FAIL(SVR_TRACER.get_servers_of_zone(empty_zone, servers))) { LOG_WARN("get server list failed", K(ret)); } else { FOREACH_X(s, servers, OB_SUCC(ret)) { const bool with_rootserver = (*s == self_addr_); ObAllServerTask task(server_manager_, disaster_recovery_task_mgr_, *s, with_rootserver); if (OB_FAIL(task.process())) { LOG_WARN("sync server status to __all_server table failed", K(ret), "server", *s); } } } } return ret; } int ObRootService::request_heartbeats() { int ret = OB_SUCCESS; ObServerManager::ObServerStatusArray statuses; ObZone zone; // empty zone means all zone if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(server_manager_.get_server_statuses(zone, statuses))) { LOG_WARN("get_server_statuses failed", K(zone), K(ret)); } else { const int64_t rpc_timeout = 250 * 1000; // 250ms ObLeaseRequest lease_request; // should continue even some failed, so don't look at condition OB_SUCCESS == ret FOREACH_CNT(status, statuses) { if (ObServerStatus::OB_HEARTBEAT_LEASE_EXPIRED == status->hb_status_ || (ObServerStatus::OB_SERVER_ADMIN_DELETING == status->admin_status_ && !status->is_alive())) { uint64_t server_id = OB_INVALID_ID; lease_request.reset(); int temp_ret = OB_SUCCESS; bool to_alive = false; if (OB_SUCCESS != (temp_ret = rpc_proxy_.to(status->server_).timeout(rpc_timeout) .request_heartbeat(lease_request))) { LOG_WARN("request_heartbeat failed", "server", status->server_, K(rpc_timeout), K(temp_ret)); } else if (OB_SUCCESS != (temp_ret = server_manager_.receive_hb( lease_request, server_id, to_alive))) { LOG_WARN("receive hb failed", K(lease_request), K(temp_ret)); } ret = (OB_SUCCESS != ret) ? ret : temp_ret; } } } return ret; } int ObRootService::self_check() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!in_service()) { // nothing todo } else if (GCONF.in_upgrade_mode()) { // nothing todo } else if (OB_FAIL(root_inspection_.check_all())) { //ignore failed LOG_WARN("root_inspection check_all failed", K(ret)); if (OB_FAIL(schedule_self_check_task())) { if (OB_CANCELED != ret) { LOG_ERROR("fail to schedule self check task", K(ret)); } } } return ret; } int ObRootService::after_restart() { ObCurTraceId::init(GCONF.self_addr_); // avoid concurrent with bootstrap FLOG_INFO("[ROOTSERVICE_NOTICE] try to get lock for bootstrap in after_restart"); ObLatchRGuard guard(bootstrap_lock_, ObLatchIds::RS_BOOTSTRAP_LOCK); // NOTE: Following log print after lock FLOG_INFO("[ROOTSERVICE_NOTICE] start to do restart task"); int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; FLOG_WARN("rootservice not init", KR(ret)); } else if (!ObRootServiceRoleChecker::is_rootserver()) { ret = OB_NOT_MASTER; FLOG_WARN("not master", KR(ret)); } else if (need_do_restart() && OB_FAIL(do_restart())) { FLOG_WARN("do restart failed, retry again", KR(ret)); } else if (OB_FAIL(do_after_full_service())) { FLOG_WARN("fail to do after full service", KR(ret)); } int64_t cost = ObTimeUtility::current_time() - start_service_time_; if (OB_FAIL(ret)) { FLOG_WARN("do restart task failed, retry again", KR(ret), K(cost)); } else if (OB_FAIL(rs_status_.set_rs_status(status::STARTED))) { FLOG_WARN("fail to set rs status", KR(ret)); } else { FLOG_INFO("do restart task success, finish restart", KR(ret), K(cost), K_(start_service_time)); } if (OB_FAIL(ret)) { rs_status_.try_set_stopping(); if (rs_status_.is_stopping()) { // need stop FLOG_INFO("rs_status_ is set to stopping"); } else { const int64_t RETRY_TIMES = 3; int64_t tmp_ret = OB_SUCCESS; for (int64_t i = 0; i < RETRY_TIMES; ++i) { if (OB_SUCCESS != (tmp_ret = schedule_restart_timer_task(config_->rootservice_ready_check_interval))) { FLOG_WARN("fail to schedule_restart_timer_task at this retry", KR(tmp_ret), K(i)); } else { FLOG_INFO("success to schedule_restart_timer_task"); break; } } if (OB_SUCCESS != tmp_ret) { LOG_ERROR("fatal error, fail to add restart task", KR(tmp_ret)); if (OB_FAIL(rs_status_.set_rs_status(status::STOPPING))) { LOG_ERROR("fail to set rs status", KR(ret)); } } } } // NOTE: Following log print after lock FLOG_INFO("[ROOTSERVICE_NOTICE] finish do restart task", KR(ret)); return ret; } int ObRootService::do_after_full_service() { int ret = OB_SUCCESS; ObGlobalStatProxy global_proxy(sql_proxy_, OB_SYS_TENANT_ID); if (OB_FAIL(global_proxy.get_baseline_schema_version(baseline_schema_version_))) { LOG_WARN("fail to get baseline schema version", KR(ret)); } if (OB_FAIL(ret)) { } else if (OB_FAIL(schedule_self_check_task())) { LOG_WARN("fail to schedule self check task", K(ret)); } else { LOG_INFO("schedule self check to root_inspection success"); } // force broadcast rs list again to make sure rootserver list be updated if (OB_SUCC(ret)) { int tmp_ret = update_rslist(); if (OB_SUCCESS != tmp_ret) { LOG_WARN("broadcast root address failed", K(tmp_ret)); } } return ret; } //////////////////////////////////////////////////////////////// int ObRootService::execute_bootstrap(const obrpc::ObBootstrapArg &arg) { int ret = OB_SUCCESS; const obrpc::ObServerInfoList &server_list = arg.server_list_; BOOTSTRAP_LOG(INFO, "STEP_1.1:execute_bootstrap start to executor."); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("root_service not inited", K(ret)); } else if (!sql_proxy_.is_inited() || !sql_proxy_.is_active()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("sql_proxy not inited or not active", "sql_proxy inited", sql_proxy_.is_inited(), "sql_proxy active", sql_proxy_.is_active(), K(ret)); } else if (server_list.count() <= 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("server_list is empty", K(server_list), K(ret)); } else if (OB_UNLIKELY(nullptr == lst_operator_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("lst_operator_ ptr is null", KR(ret), KP(lst_operator_)); } else { update_cpu_quota_concurrency_in_memory_(); // avoid bootstrap and do_restart run concurrently FLOG_INFO("[ROOTSERVICE_NOTICE] try to get lock for bootstrap in execute_bootstrap"); ObLatchWGuard guard(bootstrap_lock_, ObLatchIds::RS_BOOTSTRAP_LOCK); FLOG_INFO("[ROOTSERVICE_NOTICE] success to get lock for bootstrap in execute_bootstrap"); ObBootstrap bootstrap(rpc_proxy_, *lst_operator_, ddl_service_, unit_manager_, *config_, arg, common_proxy_); if (OB_FAIL(bootstrap.execute_bootstrap(server_zone_op_service_))) { LOG_ERROR("failed to execute_bootstrap", K(server_list), K(ret)); } BOOTSTRAP_LOG(INFO, "start to do_restart"); ObGlobalStatProxy global_proxy(sql_proxy_, OB_SYS_TENANT_ID); ObArray self_addr; if (OB_FAIL(ret)) { } else if (OB_FAIL(do_restart())) { LOG_WARN("do restart task failed", K(ret)); } else if (OB_FAIL(check_ddl_allowed())) { LOG_WARN("fail to check ddl allowed", K(ret)); } else if (OB_FAIL(update_all_server_and_rslist())) { LOG_WARN("failed to update all_server and rslist", K(ret)); } else if (OB_FAIL(zone_manager_.reload())) { LOG_WARN("failed to reload zone manager", K(ret)); } else if (OB_FAIL(set_cluster_version())) { LOG_WARN("set cluster version failed", K(ret)); } else if (OB_FAIL(pl::ObPLPackageManager::load_all_sys_package(sql_proxy_))) { LOG_WARN("load all system package failed", K(ret)); } else if (OB_FAIL(finish_bootstrap())) { LOG_WARN("failed to finish bootstrap", K(ret)); } else if (OB_FAIL(update_baseline_schema_version())) { LOG_WARN("failed to update baseline schema version", K(ret)); } else if (OB_FAIL(global_proxy.get_baseline_schema_version( baseline_schema_version_))) { LOG_WARN("fail to get baseline schema version", KR(ret)); } else if (OB_FAIL(set_cpu_quota_concurrency_config_())) { LOG_WARN("failed to update cpu_quota_concurrency", K(ret)); } if (OB_SUCC(ret)) { char ori_min_server_version[OB_SERVER_VERSION_LENGTH] = {'\0'}; uint64_t ori_cluster_version = GET_MIN_CLUSTER_VERSION(); if (OB_INVALID_INDEX == ObClusterVersion::print_version_str( ori_min_server_version, OB_SERVER_VERSION_LENGTH, ori_cluster_version)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("fail to print version str", KR(ret), K(ori_cluster_version)); } else { CLUSTER_EVENT_SYNC_ADD("BOOTSTRAP", "BOOTSTRAP_SUCCESS", "cluster_version", ori_min_server_version); } } //clear bootstrap flag, regardless failure or success int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = clear_special_cluster_schema_status())) { LOG_WARN("failed to clear special cluster schema status", KR(ret), K(tmp_ret)); } ret = OB_SUCC(ret) ? tmp_ret : ret; } BOOTSTRAP_LOG(INFO, "execute_bootstrap finished", K(ret)); return ret; } int ObRootService::check_config_result(const char *name, const char* value) { int ret = OB_SUCCESS; const int64_t start = ObTimeUtility::current_time(); const uint64_t DEFAULT_WAIT_US = 120 * 1000 * 1000L; //120s int64_t timeout = DEFAULT_WAIT_US; if (INT64_MAX != THIS_WORKER.get_timeout_ts()) { timeout = MAX(DEFAULT_WAIT_US, THIS_WORKER.get_timeout_remain()); } ObSqlString sql; HEAP_VAR(ObMySQLProxy::MySQLResult, res) { common::sqlclient::ObMySQLResult *result = NULL; if (OB_FAIL(sql.assign_fmt("SELECT count(*) as count FROM %s " "WHERE name = '%s' and value != '%s'", "__all_virtual_tenant_parameter_stat", name, value))) { LOG_WARN("fail to append sql", K(ret)); } while(OB_SUCC(ret) || OB_ERR_WAIT_REMOTE_SCHEMA_REFRESH == ret /* remote schema not ready, return -4029 on remote */) { if (ObTimeUtility::current_time() - start > timeout) { ret = OB_TIMEOUT; LOG_WARN("sync config info use too much time", K(ret), K(name), K(value), "cost_us", ObTimeUtility::current_time() - start); } else { if (OB_FAIL(sql_proxy_.read(res, sql.ptr()))) { LOG_WARN("fail to execute sql", K(ret), K(sql)); } else if (NULL == (result = res.get_result())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get sql result", K(ret)); } else if (OB_FAIL(result->next())) { LOG_WARN("fail to get result", K(ret)); } else { int32_t count = OB_INVALID_COUNT; EXTRACT_INT_FIELD_MYSQL(*result, "count", count, int32_t); if (OB_SUCC(ret)) { if (count == 0) { break; } } } } } // while end } return ret; } // DDL exection depends on full_service & major_freeze_done state. the sequence of these two status in bootstrap is: // 1.rs do_restart: major_freeze_launcher start // 2.rs do_restart success: full_service is true // 3.root_major_freeze success: major_freeze_done is true (need full_service is true) // the success of do_restart does not mean to execute DDL, therefor, add wait to bootstrap, to avoid bootstrap failure cause by DDL failure int ObRootService::check_ddl_allowed() { int ret = OB_SUCCESS; const int64_t SLEEP_INTERVAL_US = 1 * 1000 * 1000; //1s while (OB_SUCC(ret) && !is_ddl_allowed()) { if (!in_service() && !is_start()) { ret = OB_RS_SHUTDOWN; LOG_WARN("rs shutdown", K(ret)); } else if (THIS_WORKER.is_timeout()) { ret = OB_TIMEOUT; LOG_WARN("wait too long", K(ret)); } else { ob_usleep(SLEEP_INTERVAL_US); } } return ret; } // used by bootstrap int ObRootService::update_baseline_schema_version() { int ret = OB_SUCCESS; ObMySQLTransaction trans; int64_t baseline_schema_version = OB_INVALID_VERSION; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(trans.start(&sql_proxy_, OB_SYS_TENANT_ID))) { LOG_WARN("trans start failed", K(ret)); } else if (OB_FAIL(ddl_service_.get_schema_service(). get_tenant_refreshed_schema_version(OB_SYS_TENANT_ID, baseline_schema_version))) { LOG_WARN("fail to get refreshed schema version", K(ret)); } else { ObGlobalStatProxy proxy(trans, OB_SYS_TENANT_ID); if (OB_FAIL(proxy.set_baseline_schema_version(baseline_schema_version))) { LOG_WARN("set_baseline_schema_version failed", K(baseline_schema_version), K(ret)); } } int temp_ret = OB_SUCCESS; if (!trans.is_started()) { } else if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCCESS == ret))) { LOG_WARN("trans end failed", "commit", OB_SUCCESS == ret, K(temp_ret)); ret = (OB_SUCCESS == ret) ? temp_ret : ret; } LOG_DEBUG("update_baseline_schema_version finish", K(ret), K(temp_ret), K(baseline_schema_version)); return ret; } int ObRootService::finish_bootstrap() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { const int64_t tenant_id = OB_SYS_TENANT_ID; int64_t new_schema_version = OB_INVALID_VERSION; ObMultiVersionSchemaService &multi_schema_service = ddl_service_.get_schema_service(); share::schema::ObSchemaService *tmp_schema_service = multi_schema_service.get_schema_service(); if (OB_ISNULL(tmp_schema_service)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", K(ret), KP(tmp_schema_service)); } else { ObMySQLProxy &sql_proxy = ddl_service_.get_sql_proxy(); share::schema::ObDDLSqlService ddl_sql_service(*tmp_schema_service); share::schema::ObSchemaOperation schema_operation; schema_operation.op_type_ = share::schema::OB_DDL_FINISH_BOOTSTRAP; schema_operation.tenant_id_ = tenant_id; if (OB_FAIL(multi_schema_service.gen_new_schema_version(tenant_id, new_schema_version))) { LOG_WARN("fail to gen new schema_version", K(ret), K(tenant_id), K(new_schema_version)); } else if (OB_FAIL(ddl_sql_service.log_nop_operation(schema_operation, new_schema_version, schema_operation.ddl_stmt_str_, sql_proxy))) { LOG_WARN("log finish bootstrap operation failed", K(ret), K(schema_operation)); } else if (OB_FAIL(ddl_service_.refresh_schema(OB_SYS_TENANT_ID))) { LOG_WARN("failed to refresh_schema", K(ret)); } else { LOG_INFO("finish bootstrap", K(ret), K(new_schema_version)); } } } return ret; } void ObRootService::construct_lease_expire_time( const ObLeaseRequest &lease_request, share::ObLeaseResponse &lease_response, const share::ObServerStatus &server_status) { UNUSED(lease_request); const int64_t now = ObTimeUtility::current_time(); // if force_stop_hb is true, // then lease_expire_time_ won't be changed lease_response.heartbeat_expire_time_ = is_full_service() && server_status.force_stop_hb_ ? server_status.last_hb_time_ + config_->lease_time : now + config_->lease_time; lease_response.lease_expire_time_ = lease_response.heartbeat_expire_time_; } int ObRootService::renew_lease(const ObLeaseRequest &lease_request, ObLeaseResponse &lease_response) { int ret = OB_SUCCESS; ObServerStatus server_stat; uint64_t server_id = OB_INVALID_ID; bool to_alive = false; DEBUG_SYNC(HANG_HEART_BEAT_ON_RS); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!lease_request.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid lease_request", K(lease_request), K(ret)); } else if (OB_FAIL(server_manager_.receive_hb(lease_request, server_id, to_alive))) { LOG_WARN("server manager receive hb failed", K(lease_request), K(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", K(ret)); } else { // before __all_zone load, it may fail, ignore it int temp_ret = OB_SUCCESS; int64_t lease_info_version = 0; bool is_stopped = false; lease_response.rs_server_status_ = RSS_INVALID; if (is_full_service()) { if (OB_FAIL(zone_manager_.get_lease_info_version(lease_info_version))) { LOG_WARN("get_lease_info_version failed", K(ret)); } else if (OB_FAIL(server_manager_.get_server_status( lease_request.server_, server_stat))) { // get server_stat for construct_lease_expire_time only! LOG_WARN("get server status failed", K(ret), "server", lease_request.server_); } if (!ObHeartbeatService::is_service_enabled()) { if (FAILEDx(server_manager_.is_server_stopped(lease_request.server_, is_stopped))) { LOG_WARN("check_server_stopped failed", KR(ret), "server", lease_request.server_); } else { lease_response.rs_server_status_ = is_stopped ? RSS_IS_STOPPED : RSS_IS_WORKING; } } } if (OB_SUCC(ret)) { lease_response.version_ = ObLeaseResponse::LEASE_VERSION; construct_lease_expire_time(lease_request, lease_response, server_stat); lease_response.lease_info_version_ = lease_info_version; lease_response.server_id_ = server_id; lease_response.force_frozen_status_ = to_alive; lease_response.baseline_schema_version_ = baseline_schema_version_; (void)OTC_MGR.get_lease_response(lease_response); // after split schema, the schema_version is not used, but for the legality detection, set schema_version to sys's schema_version if (OB_SUCCESS != (temp_ret = schema_service_->get_tenant_schema_version(OB_SYS_TENANT_ID, lease_response.schema_version_))) { LOG_WARN("fail to get tenant schema version", K(temp_ret)); } if (OB_SUCCESS != (temp_ret = schema_service_->get_refresh_schema_info( lease_response.refresh_schema_info_))) { LOG_WARN("fail to get refresh_schema_info", K(temp_ret)); } LOG_TRACE("lease_request", K(lease_request), K(lease_response)); } } return ret; } int ObRootService::report_sys_ls(const share::ObLSReplica &replica) { int ret = OB_SUCCESS; ObInMemoryLSTable *inmemory_ls = NULL; ObRole role = FOLLOWER; bool inner_table_only = false; LOG_INFO("receive request to report sys ls", K(replica)); if (OB_UNLIKELY(!inited_) || OB_ISNULL(lst_operator_)) { ret = OB_NOT_INIT; LOG_WARN("rootservice not inited", KR(ret)); } else if (OB_FAIL(lst_operator_->get_role(OB_SYS_TENANT_ID, SYS_LS, role))) { LOG_WARN("fail to get local role by lst_operator", KR(ret)); } else if (OB_UNLIKELY(!is_strong_leader(role))) { ret = OB_RS_NOT_MASTER; LOG_WARN("local role is not leader", KR(ret), K(role)); } else if (OB_UNLIKELY(!replica.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid replica", KR(ret), K(replica)); } else if (OB_ISNULL(inmemory_ls = lst_operator_->get_inmemory_ls())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get inmemory ls", KR(ret), K(replica)); } else if (OB_FAIL(inmemory_ls->update(replica, inner_table_only))) { LOG_WARN("update sys ls failed", KR(ret), K(replica)); } else { LOG_INFO("update sys ls on rs success", K(replica)); } return ret; } int ObRootService::remove_sys_ls(const obrpc::ObRemoveSysLsArg &arg) { int ret = OB_SUCCESS; ObInMemoryLSTable *inmemory_ls = NULL; ObRole role = FOLLOWER; bool inner_table_only = false; LOG_INFO("receive request to remove sys ls", K(arg)); if (OB_UNLIKELY(!inited_) || OB_ISNULL(lst_operator_)) { ret = OB_NOT_INIT; LOG_WARN("rootservice not inited", KR(ret)); } else if (OB_FAIL(lst_operator_->get_role(OB_SYS_TENANT_ID, SYS_LS, role))) { LOG_WARN("fail to get local role by lst_operator", KR(ret)); } else if (OB_UNLIKELY(!is_strong_leader(role))) { ret = OB_RS_NOT_MASTER; LOG_WARN("local role is not leader", KR(ret), K(role)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid server", KR(ret), K(arg)); } else if (OB_ISNULL(inmemory_ls = lst_operator_->get_inmemory_ls())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get inmemory ls", KR(ret), K(arg)); } else if (OB_FAIL(inmemory_ls->remove( OB_SYS_TENANT_ID, SYS_LS, arg.server_, inner_table_only))) { LOG_WARN("remove sys ls failed", KR(ret), K(arg)); } else { LOG_INFO("remove sys ls on rs success", K(arg)); } return ret; } int ObRootService::fetch_location( const obrpc::ObFetchLocationArg &arg, obrpc::ObFetchLocationResult &res) { int ret = OB_SUCCESS; const ObVtableLocationType &vtable_type = arg.get_vtable_type(); ObSArray servers; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("rootservice not init", KR(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(vtable_location_getter_.get(vtable_type, servers))) { LOG_WARN("vtable_location_getter get failed", KR(ret), K(arg)); } else if (OB_FAIL(res.set_servers(servers))) { LOG_WARN("fail to assign servers", KR(ret), K(servers), K(arg)); } return ret; } //////////////////////////////////////////////////////////////// int ObRootService::create_resource_unit(const obrpc::ObCreateResourceUnitArg &arg) { int ret = OB_SUCCESS; const bool if_not_exist = arg.get_if_not_exist(); LOG_INFO("receive create_resource_unit request", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(unit_manager_.create_unit_config(arg.get_unit_config(), if_not_exist))) { LOG_WARN("create_unit_config failed", K(arg), K(if_not_exist), KR(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_manager, please try 'alter system reload unit', please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish create_resource_unit", K(arg), KR(ret)); ROOTSERVICE_EVENT_ADD("root_service", "create_resource_unit", K(ret), K(arg)); return ret; } int ObRootService::alter_resource_unit(const obrpc::ObAlterResourceUnitArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { LOG_INFO("receive alter_resource_unit request", K(arg)); if (OB_FAIL(unit_manager_.alter_unit_config(arg.get_unit_config()))) { LOG_WARN("alter_unit_config failed", K(arg), KR(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_manager, please try 'alter system reload unit', please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish alter_resource_unit", K(arg), KR(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "alter_resource_unit", K(ret), K(arg)); return ret; } int ObRootService::drop_resource_unit(const obrpc::ObDropResourceUnitArg &arg) { int ret = OB_SUCCESS; const bool if_exist = arg.if_exist_; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { LOG_INFO("receive drop_resource_unit request", K(arg)); if (OB_FAIL(unit_manager_.drop_unit_config(arg.unit_name_, if_exist))) { LOG_WARN("drop_unit_config failed", "unit_config", arg.unit_name_, K(if_exist), K(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_manager, please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish drop_resource_unit", K(arg), K(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "drop_resource_unit", K(ret), K(arg)); return ret; } int ObRootService::create_resource_pool(const obrpc::ObCreateResourcePoolArg &arg) { int ret = OB_SUCCESS; const bool if_not_exist = arg.if_not_exist_; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_MISS_ARGUMENT; if (arg.pool_name_.empty()) { LOG_USER_ERROR(OB_MISS_ARGUMENT, "resource pool name"); } else if (arg.unit_.empty()) { LOG_USER_ERROR(OB_MISS_ARGUMENT, "unit"); } else if (arg.unit_num_ <= 0) { LOG_USER_ERROR(OB_MISS_ARGUMENT, "unit_num"); } LOG_WARN("missing arg to create resource pool", K(arg), K(ret)); } else if (REPLICA_TYPE_LOGONLY != arg.replica_type_ && REPLICA_TYPE_FULL != arg.replica_type_) { ret = OB_NOT_SUPPORTED; LOG_WARN("only full/logonly pool are supported", K(ret), K(arg)); } else if (REPLICA_TYPE_LOGONLY == arg.replica_type_ && arg.unit_num_> 1) { ret = OB_NOT_SUPPORTED; LOG_WARN("logonly resource pool should only have one unit on one zone", K(ret), K(arg)); } else if (0 == arg.unit_.case_compare(OB_STANDBY_UNIT_CONFIG_TEMPLATE_NAME)) { ret = OB_OP_NOT_ALLOW; LOG_WARN("can not create resource pool use standby unit config template", K(ret), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "create resource pool use stanby unit config template"); } else { LOG_INFO("receive create_resource_pool request", K(arg)); share::ObResourcePool pool; pool.name_ = arg.pool_name_; pool.unit_count_ = arg.unit_num_; pool.replica_type_ = arg.replica_type_; if (OB_FAIL(pool.zone_list_.assign(arg.zone_list_))) { LOG_WARN("assign failed", K(ret)); } else if (OB_FAIL(unit_manager_.create_resource_pool(pool, arg.unit_, if_not_exist))) { LOG_WARN("create_resource_pool failed", K(pool), "unit_config", arg.unit_, K(if_not_exist), K(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_manager, please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish create_resource_pool", K(arg), K(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "create_resource_pool", K(ret), K(arg)); return ret; } int ObRootService::split_resource_pool(const obrpc::ObSplitResourcePoolArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } else { LOG_INFO("receive split resource pool request", K(arg)); share::ObResourcePoolName pool_name = arg.pool_name_; const common::ObIArray &split_pool_list = arg.split_pool_list_; const common::ObIArray &zone_list = arg.zone_list_; if (OB_FAIL(unit_manager_.split_resource_pool(pool_name, split_pool_list, zone_list))) { LOG_WARN("fail to split resource pool", K(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_mgr, please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish split_resource_pool", K(ret), K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "split_resource_pool", K(ret), K(arg)); return ret; } int ObRootService::alter_resource_tenant(const obrpc::ObAlterResourceTenantArg &arg) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(arg)); } else if (OB_UNLIKELY(nullptr == schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service ptr is null", KR(ret)); } else { LOG_INFO("receive alter resource tenant request", K(arg)); const ObString &target_tenant_name = arg.tenant_name_; const int64_t new_unit_num = arg.unit_num_; const common::ObIArray &delete_unit_group_id_array = arg.unit_group_id_array_; share::schema::ObSchemaGetterGuard schema_guard; uint64_t target_tenant_id = OB_INVALID_ID; int tmp_ret = OB_SUCCESS; if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("fail to get tenant schema guard", KR(ret), "tenant_id", OB_SYS_TENANT_ID); } else if (OB_FAIL(schema_guard.get_tenant_id(target_tenant_name, target_tenant_id))) { LOG_WARN("fail to get tenant id", KR(ret), K(target_tenant_name)); } else if (OB_UNLIKELY(OB_INVALID_ID == target_tenant_id)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("target_tenant_id value unexpected", KR(ret), K(target_tenant_name), K(target_tenant_id)); } else if (OB_FAIL(unit_manager_.alter_resource_tenant( target_tenant_id, new_unit_num, delete_unit_group_id_array))) { LOG_WARN("fail to alter resource tenant", KR(ret), K(target_tenant_id), K(new_unit_num), K(delete_unit_group_id_array)); if (OB_TMP_FAIL(submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_mgr, please try 'alter system reload unit'", KR(ret), KR(tmp_ret)); } } } LOG_INFO("finish alter_resource_tenant", KR(ret), K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "alter_resource_tenant", K(ret), K(arg)); return ret; } int ObRootService::merge_resource_pool(const obrpc::ObMergeResourcePoolArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } else { LOG_INFO("receive merge resource pool request", K(arg)); const common::ObIArray &old_pool_list = arg.old_pool_list_; const common::ObIArray &new_pool_list = arg.new_pool_list_; if (OB_FAIL(unit_manager_.merge_resource_pool(old_pool_list, new_pool_list))) { LOG_WARN("fail to merge resource pool", K(ret)); int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) {//ensure submit task all case if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_mgr, please try 'alter system reload unit'", KR(ret), K(tmp_ret)); } } } LOG_INFO("finish merge_resource_pool", K(ret), K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "merge_resource_pool", K(ret), K(arg)); return ret; } int ObRootService::alter_resource_pool(const obrpc::ObAlterResourcePoolArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_MISS_ARGUMENT; if (arg.pool_name_.empty()) { LOG_USER_ERROR(OB_MISS_ARGUMENT, "resource pool name"); } LOG_WARN("missing arg to alter resource pool", K(arg), K(ret)); } else if (0 == arg.unit_.case_compare(OB_STANDBY_UNIT_CONFIG_TEMPLATE_NAME)) { ret = OB_OP_NOT_ALLOW; LOG_WARN("can not alter resource pool use standby unit config template", K(ret), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter resource pool use stanby unit config template"); } else { LOG_INFO("receive alter_resource_pool request", K(arg)); share::ObResourcePool pool; pool.name_ = arg.pool_name_; pool.unit_count_ = arg.unit_num_; if (OB_FAIL(pool.zone_list_.assign(arg.zone_list_))) { LOG_WARN("assign failed", K(ret)); } else if (OB_FAIL(unit_manager_.alter_resource_pool( pool, arg.unit_, arg.delete_unit_id_array_))) { LOG_WARN("alter_resource_pool failed", K(pool), K(arg), "resource unit", arg.unit_, K(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_manager, please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish alter_resource_pool", K(arg), K(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "alter_resource_pool", K(ret), K(arg)); return ret; } int ObRootService::drop_resource_pool(const obrpc::ObDropResourcePoolArg &arg) { int ret = OB_SUCCESS; const bool if_exist = arg.if_exist_; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_MISS_ARGUMENT; if (arg.pool_name_.empty()) { LOG_USER_ERROR(OB_MISS_ARGUMENT, "resource pool name"); } LOG_WARN("missing arg to drop resource pool", K(arg), K(ret)); } else { LOG_INFO("receive drop_resource_pool request", K(arg)); if (OB_FAIL(unit_manager_.drop_resource_pool(arg.pool_name_, if_exist))) { LOG_WARN("drop_resource_pool failed", "pool", arg.pool_name_, K(if_exist), K(ret)); int mysql_error = -common::ob_mysql_errno(ret); if (OB_TIMEOUT == ret || OB_TIMEOUT == mysql_error) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_manager, please try 'alter system reload unit'", K(tmp_ret)); } } } } LOG_INFO("finish drop_resource_pool", K(arg), K(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "drop_resource_pool", K(ret), K(arg)); return ret; } int ObRootService::check_tenant_in_alter_locality( const uint64_t tenant_id, bool &in_alter_locality) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else if (OB_FAIL(ddl_service_.check_tenant_in_alter_locality(tenant_id, in_alter_locality))) { LOG_WARN("fail to check tenant in alter locality", K(ret)); } else {} // no more to do return ret; } int ObRootService::create_tenant(const ObCreateTenantArg &arg, UInt64 &tenant_id) { LOG_INFO("receive create tenant arg", K(arg), "timeout_ts", THIS_WORKER.get_timeout_ts()); int ret = OB_SUCCESS; int tmp_ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_FAIL(ddl_service_.create_tenant(arg, tenant_id))) { LOG_WARN("fail to create tenant", KR(ret), K(arg)); if (OB_TMP_FAIL(submit_reload_unit_manager_task())) { if (OB_CANCELED != tmp_ret) { LOG_ERROR("fail to reload unit_mgr, please try 'alter system reload unit'", KR(ret), KR(tmp_ret)); } } } else {} LOG_INFO("finish create tenant", KR(ret), K(tenant_id), K(arg), "timeout_ts", THIS_WORKER.get_timeout_ts()); return ret; } int ObRootService::create_tenant_end(const ObCreateTenantEndArg &arg) { LOG_DEBUG("receive create tenant end arg", K(arg)); int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret)); } else if (OB_FAIL(ddl_service_.create_tenant_end(arg.tenant_id_))) { LOG_WARN("fail to create tenant end", K(ret), K(arg)); } else { LOG_INFO("success to create tenant end", K(ret), K(arg)); } return ret; } int ObRootService::commit_alter_tenant_locality( const rootserver::ObCommitAlterTenantLocalityArg &arg) { int ret = OB_SUCCESS; LOG_INFO("commit alter tenant locality", K(arg)); if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } else if (OB_FAIL(ddl_service_.commit_alter_tenant_locality(arg))) { LOG_WARN("fail to commit alter tenant locality", K(ret)); } else { LOG_INFO("commit alter tenant locality succeed", K(ret)); } return ret; } int ObRootService::drop_tenant(const ObDropTenantArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.drop_tenant(arg))) { LOG_WARN("ddl_service_ drop_tenant failed", K(arg), K(ret)); } return ret; } int ObRootService::flashback_tenant(const ObFlashBackTenantArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.flashback_tenant(arg))) { LOG_WARN("failed to flash back tenant", K(ret)); } LOG_INFO("flashback tenant success"); return ret; } int ObRootService::purge_tenant(const ObPurgeTenantArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.purge_tenant(arg))) { LOG_WARN("failed to purge tenant", K(ret)); } LOG_INFO("purge tenant success"); return ret; } int ObRootService::modify_tenant(const ObModifyTenantArg &arg) { LOG_DEBUG("receive modify tenant arg", K(arg)); int ret = OB_NOT_SUPPORTED; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.modify_tenant(arg))) { LOG_WARN("ddl service modify tenant failed", K(arg), K(ret)); } else { root_balancer_.wakeup(); } // weak leader coordinator while modify primary zone //if (OB_SUCC(ret) // && arg.alter_option_bitset_.has_member(obrpc::ObModifyTenantArg::PRIMARY_ZONE)) { // leader_coordinator_.signal(); //} return ret; } int ObRootService::lock_tenant(const obrpc::ObLockTenantArg &arg) { int ret = OB_SUCCESS; LOG_INFO("receive lock tenant request", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.lock_tenant(arg.tenant_name_, arg.is_locked_))) { LOG_WARN("ddl_service lock_tenant failed", K(arg), K(ret)); } LOG_INFO("finish lock tenant", K(arg), K(ret)); return ret; } int ObRootService::add_system_variable(const ObAddSysVarArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid sysvar arg", K(arg)); } else if (OB_FAIL(ddl_service_.add_system_variable(arg))) { LOG_WARN("add system variable failed", K(ret)); } return ret; } int ObRootService::modify_system_variable(const obrpc::ObModifySysVarArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid sysvar arg", K(arg)); } else if (OB_FAIL(ddl_service_.modify_system_variable(arg))) { LOG_WARN("modify system variable failed", K(ret)); } return ret; } int ObRootService::create_database(const ObCreateDatabaseArg &arg, UInt64 &db_id) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObDatabaseSchema copied_db_schema = arg.database_schema_; if (OB_FAIL(ddl_service_.create_database(arg.if_not_exist_, copied_db_schema, &arg.ddl_stmt_str_))) { LOG_WARN("create_database failed", "if_not_exist", arg.if_not_exist_, K(copied_db_schema), "ddl_stmt_str", arg.ddl_stmt_str_, K(ret)); } else { db_id = copied_db_schema.get_database_id(); } } return ret; } int ObRootService::alter_database(const ObAlterDatabaseArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (common::STANDBY_CLUSTER == ObClusterInfoGetter::get_cluster_role_v2()) { const int64_t tenant_id = arg.database_schema_.get_tenant_id(); ObSchemaGetterGuard schema_guard; uint64_t database_id = OB_INVALID_ID; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table( tenant_id, schema_guard))) { LOG_WARN("get_schema_guard with version in inner table failed", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_guard.get_database_id(tenant_id, arg.database_schema_.get_database_name_str(), database_id))) { LOG_WARN("failed to get database id", K(ret), K(tenant_id), K(arg)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(ddl_service_.alter_database(arg))) { LOG_WARN("alter database failed", K(arg), K(ret)); } return ret; } int ObRootService::create_tablegroup(const ObCreateTablegroupArg &arg, UInt64 &tg_id) { LOG_INFO("receive create tablegroup arg", K(arg)); int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObTablegroupSchema copied_tg_schema; if (OB_FAIL(copied_tg_schema.assign(arg.tablegroup_schema_))) { LOG_WARN("failed to assign tablegroup schema", K(ret), K(arg)); } else if (OB_FAIL(ddl_service_.create_tablegroup( arg.if_not_exist_, copied_tg_schema, &arg.ddl_stmt_str_))) { LOG_WARN("create_tablegroup failed", "if_not_exist", arg.if_not_exist_, K(copied_tg_schema), "ddl_stmt_str", arg.ddl_stmt_str_, K(ret)); } else { tg_id = copied_tg_schema.get_tablegroup_id(); } } return ret; } int ObRootService::handle_security_audit(const ObSecurityAuditArg &arg) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.handle_security_audit(arg))) { LOG_WARN("handle audit request failed", K(ret), K(arg)); } return ret; } int ObRootService::create_table(const ObCreateTableArg &arg, ObCreateTableRes &res) { LOG_DEBUG("receive create table arg", K(arg)); int ret = OB_SUCCESS; int64_t begin_time = ObTimeUtility::current_time(); LOG_INFO("receive create table ddl", K(begin_time)); RS_TRACE(create_table_begin); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObArray table_schemas; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; schema_guard.set_session_id(arg.schema_.get_session_id()); ObSchemaService *schema_service = schema_service_->get_schema_service(); ObTableSchema table_schema; bool is_oracle_mode = false; // generate base table schema if (OB_FAIL(table_schema.assign(arg.schema_))) { LOG_WARN("fail to assign schema", K(ret)); } else if (OB_ISNULL(schema_service)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", KP(schema_service), K(ret)); } else if (OB_FAIL(generate_table_schema_in_tenant_space(arg, table_schema))) { LOG_WARN("fail to generate table schema in tenant space", K(ret), K(arg)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table( table_schema.get_tenant_id(), schema_guard))) { LOG_WARN("get_schema_guard with version in inner table failed", K(ret)); } else if (OB_FAIL(check_parallel_ddl_conflict(schema_guard, arg))) { LOG_WARN("check parallel ddl conflict failed", K(ret)); } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id( table_schema.get_tenant_id(), is_oracle_mode))) { LOG_WARN("fail to check is oracle mode", K(ret)); } else if (OB_INVALID_ID == table_schema.get_database_id()) { ObString database_name = arg.db_name_; if (OB_FAIL(schema_guard.get_database_schema(table_schema.get_tenant_id(), database_name, db_schema))) { LOG_WARN("get databas schema failed", K(arg)); } else if (OB_ISNULL(db_schema)) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); } else if (!arg.is_inner_ && db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create table of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", "tenant_id", table_schema.get_tenant_id(), K(database_name), K(*db_schema), K(ret)); } else { table_schema.set_database_id(db_schema->get_database_id()); } } else { // for view, database_id must be filled } if (OB_SUCC(ret)) { bool table_exist = false; bool object_exist = false; uint64_t synonym_id = OB_INVALID_ID; ObSchemaGetterGuard::CheckTableType check_type = ObSchemaGetterGuard::ALL_NON_HIDDEN_TYPES; if (table_schema.is_mysql_tmp_table()) { check_type = ObSchemaGetterGuard::TEMP_TABLE_TYPE; } else if (0 == table_schema.get_session_id()) { //if session_id <> 0 during create table, need to exclude the existence of temporary table with the same table_name, //if there is, need to throw error. check_type = ObSchemaGetterGuard::NON_TEMP_WITH_NON_HIDDEN_TABLE_TYPE; } if (OB_SUCC(ret)) { ObArray conflict_schema_types; if (!arg.is_alter_view_ && OB_FAIL(schema_guard.check_oracle_object_exist(table_schema.get_tenant_id(), table_schema.get_database_id(), table_schema.get_table_name_str(), TABLE_SCHEMA, INVALID_ROUTINE_TYPE, arg.if_not_exist_, conflict_schema_types))) { LOG_WARN("fail to check oracle_object exist", K(ret), K(table_schema)); } else if (conflict_schema_types.count() > 0) { ret = OB_ERR_EXIST_OBJECT; LOG_WARN("Name is already used by an existing object", K(ret), K(table_schema), K(conflict_schema_types)); } } if (FAILEDx(schema_guard.check_synonym_exist_with_name(table_schema.get_tenant_id(), table_schema.get_database_id(), table_schema.get_table_name_str(), object_exist, synonym_id))) { LOG_WARN("fail to check synonym exist", K(table_schema), K(ret)); } else if (object_exist) { ret = OB_ERR_EXIST_OBJECT; LOG_WARN("Name is already used by an existing object", K(table_schema), K(ret)); } else if (OB_FAIL(schema_guard.check_table_exist(table_schema.get_tenant_id(), table_schema.get_database_id(), table_schema.get_table_name_str(), false, /*is index*/ check_type, table_exist))) { LOG_WARN("check table exist failed", K(ret), K(table_schema)); } else if (table_exist) { if (table_schema.is_view_table() && arg.if_not_exist_) { //create or replace view ... //create user table will drop the old view and recreate it in trans const ObSimpleTableSchemaV2 *simple_table_schema = nullptr; if (OB_FAIL(schema_guard.get_simple_table_schema( table_schema.get_tenant_id(), table_schema.get_database_id(), table_schema.get_table_name_str(), false, /*is index*/ simple_table_schema))) { LOG_WARN("failed to get table schema", K(ret)); } else if (OB_ISNULL(simple_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("simple_table_schema is null", K(ret)); } else if (simple_table_schema->get_table_type() == SYSTEM_VIEW || simple_table_schema->get_table_type() == USER_VIEW || simple_table_schema->get_table_type() == MATERIALIZED_VIEW) { ret = OB_SUCCESS; } else { if (is_oracle_mode) { ret = OB_ERR_EXIST_OBJECT; LOG_WARN("name is already used by an existing object", K(ret), K(table_schema.get_table_name_str())); } else { // mysql mode const ObDatabaseSchema *db_schema = nullptr; if (OB_FAIL(schema_guard.get_database_schema( table_schema.get_tenant_id(), table_schema.get_database_id(), db_schema))) { LOG_WARN("get db schema failed", K(ret), K(table_schema.get_database_id())); } else if (OB_ISNULL(db_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("db schema is null", K(ret)); } else { ret = OB_ERR_WRONG_OBJECT; LOG_USER_ERROR(OB_ERR_WRONG_OBJECT, to_cstring(db_schema->get_database_name_str()), to_cstring(table_schema.get_table_name_str()), "VIEW"); LOG_WARN("table exist", K(ret), K(table_schema)); } } } } else { ret = OB_ERR_TABLE_EXIST; LOG_WARN("table exist", K(ret), K(table_schema), K(arg.if_not_exist_)); } } else if (!table_exist && table_schema.is_view_table() && arg.is_alter_view_) { // the origin view must exist while alter view const ObSimpleDatabaseSchema *simple_db_schema = nullptr; if (OB_FAIL(schema_guard.get_database_schema( table_schema.get_tenant_id(), table_schema.get_database_id(), simple_db_schema))) { LOG_WARN("get db schema failed", K(ret), K(table_schema.get_database_id())); } else if (OB_ISNULL(simple_db_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("db schema is null", K(ret)); } else { ret = OB_TABLE_NOT_EXIST; LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(simple_db_schema->get_database_name_str()), to_cstring(table_schema.get_table_name_str())); LOG_WARN("table not exist", K(ret), K(table_schema)); } } } RS_TRACE(generate_schema_start); //bool can_hold_new_table = false; common::hash::ObHashMap mock_fk_parent_table_map; // name, count ObArray tmp_mock_fk_parent_table_schema_array; ObArray mock_fk_parent_table_schema_array; if (OB_FAIL(ret)) { //do nothing } else if (OB_FAIL(mock_fk_parent_table_map.create(16, "MockFKParentTbl"))) { LOG_WARN("fail to create mock_fk_parent_table_map", K(ret)); } else if (OB_FAIL(ddl_service_.generate_schema(arg, table_schema))) { LOG_WARN("generate_schema for table failed", K(ret)); //} else if (OB_FAIL(check_rs_capacity(table_schema, can_hold_new_table))) { // LOG_WARN("fail to check rs capacity", K(ret), K(table_schema)); //} else if (!can_hold_new_table) { // ret = OB_PARTITION_CNT_REACH_ROOTSERVER_LIMIT; // LOG_WARN("reach rs's limits, rootserver can only hold limited replicas"); } else if (OB_FAIL(table_schemas.push_back(table_schema))) { LOG_WARN("push_back failed", K(ret)); } else { RS_TRACE(generate_schema_index); res.table_id_ = table_schema.get_table_id(); // generate index schemas ObIndexBuilder index_builder(ddl_service_); ObTableSchema index_schema; for (int64_t i = 0; OB_SUCC(ret) && i < arg.index_arg_list_.size(); ++i) { index_schema.reset(); ObCreateIndexArg &index_arg = const_cast(arg.index_arg_list_.at(i)); //if we pass the table_schema argument, the create_index_arg can not set database_name //and table_name, which will used from get data table schema in generate_schema if (!index_arg.index_schema_.is_partitioned_table() && !table_schema.is_partitioned_table()) { if (INDEX_TYPE_NORMAL_GLOBAL == index_arg.index_type_) { index_arg.index_type_ = INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE; } else if (INDEX_TYPE_UNIQUE_GLOBAL == index_arg.index_type_) { index_arg.index_type_ = INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE; } else if (INDEX_TYPE_SPATIAL_GLOBAL == index_arg.index_type_) { index_arg.index_type_ = INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE; } } // the global index has generated column schema during resolve, RS no need to generate index schema, // just assign column schema if (INDEX_TYPE_NORMAL_GLOBAL == index_arg.index_type_ || INDEX_TYPE_UNIQUE_GLOBAL == index_arg.index_type_ || INDEX_TYPE_SPATIAL_GLOBAL == index_arg.index_type_) { if (OB_FAIL(index_schema.assign(index_arg.index_schema_))) { LOG_WARN("fail to assign schema", K(ret)); } } const bool global_index_without_column_info = false; ObSEArray gen_columns; ObIAllocator *allocator = index_arg.index_schema_.get_allocator(); if (OB_FAIL(ret)) { } else if (OB_ISNULL(allocator)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid allocator", K(ret)); } else if (OB_FAIL(ObIndexBuilderUtil::adjust_expr_index_args(index_arg, table_schema, *allocator, gen_columns))) { LOG_WARN("fail to adjust expr index args", K(ret)); } else if (OB_FAIL(index_builder.generate_schema(index_arg, table_schema, global_index_without_column_info, index_schema))) { LOG_WARN("generate_schema for index failed", K(index_arg), K(table_schema), K(ret)); } if (OB_SUCC(ret)) { uint64_t new_table_id = OB_INVALID_ID; if (OB_FAIL(schema_service->fetch_new_table_id(table_schema.get_tenant_id(), new_table_id))) { LOG_WARN("failed to fetch_new_table_id", "tenant_id", table_schema.get_tenant_id(), K(ret)); } else { index_schema.set_table_id(new_table_id); //index_schema.set_data_table_id(table_id); if (OB_FAIL(table_schemas.push_back(index_schema))) { LOG_WARN("push_back failed", K(ret)); } } } } RS_TRACE(generate_schema_lob); if (OB_FAIL(ret) || table_schema.is_view_table() || table_schema.is_external_table()) { // do nothing } else if (OB_FAIL(ddl_service_.build_aux_lob_table_schema_if_need(table_schema, table_schemas))) { LOG_WARN("fail to build_aux_lob_table_schema_if_need", K(ret), K(table_schema)); } if (OB_SUCC(ret)) { for (int64_t i = 0; OB_SUCC(ret) && i < arg.foreign_key_arg_list_.count(); i++) { const ObCreateForeignKeyArg &foreign_key_arg = arg.foreign_key_arg_list_.at(i); ObForeignKeyInfo foreign_key_info; // check for duplicate constraint names of foregin key if (foreign_key_arg.foreign_key_name_.empty()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fk name is empty", K(ret)); } else { bool is_foreign_key_name_exist = true; if (OB_FAIL(ddl_service_.check_constraint_name_is_exist( schema_guard, table_schema, foreign_key_arg.foreign_key_name_, true, is_foreign_key_name_exist))) { LOG_WARN("fail to check foreign key name is exist or not", K(ret), K(foreign_key_arg.foreign_key_name_)); } else if(is_foreign_key_name_exist) { if (is_oracle_mode) { ret = OB_ERR_CONSTRAINT_NAME_DUPLICATE; LOG_WARN("fk name is duplicate", K(ret), K(foreign_key_arg.foreign_key_name_)); } else { // mysql mode ret = OB_ERR_DUP_KEY; LOG_USER_ERROR(OB_ERR_DUP_KEY, table_schema.get_table_name_str().length(), table_schema.get_table_name_str().ptr()); } } } // end of check for duplicate constraint names of foregin key const ObTableSchema *parent_schema = NULL; if (OB_SUCC(ret)) { // get parent table schema. // TODO: is it necessory to determine whether it is case sensitive by check sys variable // check whether it belongs to self reference, if so, the parent schema is child schema. if (0 == foreign_key_arg.parent_table_.case_compare(table_schema.get_table_name_str()) && 0 == foreign_key_arg.parent_database_.case_compare(arg.db_name_)) { parent_schema = &table_schema; if (CONSTRAINT_TYPE_PRIMARY_KEY == foreign_key_arg.ref_cst_type_) { if (is_oracle_mode) { for (ObTableSchema::const_constraint_iterator iter = parent_schema->constraint_begin(); iter != parent_schema->constraint_end(); ++iter) { if (CONSTRAINT_TYPE_PRIMARY_KEY == (*iter)->get_constraint_type()) { foreign_key_info.ref_cst_type_ = CONSTRAINT_TYPE_PRIMARY_KEY; foreign_key_info.ref_cst_id_ = (*iter)->get_constraint_id(); break; } } } else { foreign_key_info.ref_cst_type_ = CONSTRAINT_TYPE_PRIMARY_KEY; foreign_key_info.ref_cst_id_ = common::OB_INVALID_ID; } } else if (CONSTRAINT_TYPE_UNIQUE_KEY == foreign_key_arg.ref_cst_type_) { if (OB_FAIL(ddl_service_.get_uk_cst_id_for_self_ref(table_schemas, foreign_key_arg, foreign_key_info))) { LOG_WARN("failed to get uk cst id for self ref", K(ret), K(foreign_key_arg)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid foreign key ref cst type", K(ret), K(foreign_key_arg)); } } else if (OB_FAIL(schema_guard.get_table_schema(table_schema.get_tenant_id(), foreign_key_arg.parent_database_, foreign_key_arg.parent_table_, false, parent_schema))) { LOG_WARN("failed to get parent table schema", K(ret), K(foreign_key_arg)); } else { foreign_key_info.ref_cst_type_ = foreign_key_arg.ref_cst_type_; foreign_key_info.ref_cst_id_ = foreign_key_arg.ref_cst_id_; } } const ObMockFKParentTableSchema *tmp_mock_fk_parent_table_ptr = NULL; ObMockFKParentTableSchema mock_fk_parent_table_schema; if (OB_SUCC(ret)) { if (foreign_key_arg.is_parent_table_mock_) { uint64_t dup_name_mock_fk_parent_table_count = 0; if (NULL != parent_schema) { ret = OB_ERR_PARALLEL_DDL_CONFLICT; LOG_WARN("the mock parent table is conflict with the real parent table, need retry", K(ret), K(foreign_key_arg), K(parent_schema->get_table_id())); } else if (OB_FAIL(mock_fk_parent_table_map.get_refactored(foreign_key_arg.parent_table_, dup_name_mock_fk_parent_table_count))) { if (OB_HASH_NOT_EXIST == ret) { ret = OB_SUCCESS; if (OB_FAIL(mock_fk_parent_table_map.set_refactored(foreign_key_arg.parent_table_, ++dup_name_mock_fk_parent_table_count))) { LOG_WARN("failed to insert into mock_fk_parent_table_map", K(ret), K(foreign_key_arg), K(dup_name_mock_fk_parent_table_count)); } } else { LOG_WARN("get_refactored from mock_fk_parent_table_map failed", K(ret), K(foreign_key_arg)); } } else { //already had dup name mock_fk_parent_table in tmp_mock_fk_parent_table_schema_array int64_t count = 0; for (int64_t i = 0; i < tmp_mock_fk_parent_table_schema_array.count(); ++i) { if (0 == tmp_mock_fk_parent_table_schema_array.at(i).get_mock_fk_parent_table_name().case_compare(foreign_key_arg.parent_table_)) { if (++count == dup_name_mock_fk_parent_table_count) { tmp_mock_fk_parent_table_ptr = &tmp_mock_fk_parent_table_schema_array.at(i); break; } } } if (OB_ISNULL(tmp_mock_fk_parent_table_ptr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("tmp_mock_fk_parent_table_ptr is null", K(ret), K(foreign_key_arg), K(tmp_mock_fk_parent_table_schema_array)); } else if (OB_FAIL(mock_fk_parent_table_map.set_refactored(foreign_key_arg.parent_table_, ++dup_name_mock_fk_parent_table_count, true/*overwrite*/))) { LOG_WARN("failed to insert into mock_fk_parent_table_map", K(ret), K(foreign_key_arg), K(dup_name_mock_fk_parent_table_count)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(ddl_service_.gen_mock_fk_parent_table_for_create_fk( schema_guard, table_schema.get_tenant_id(), foreign_key_arg, tmp_mock_fk_parent_table_ptr, foreign_key_info, mock_fk_parent_table_schema))) { LOG_WARN("failed to generate_mock_fk_parent_table_schema", K(ret), K(table_schema.get_tenant_id()), K(foreign_key_arg)); } } else if (OB_ISNULL(parent_schema)) { ret = OB_TABLE_NOT_EXIST; LOG_WARN("parent table is not exist", K(ret), K(foreign_key_arg)); } else if (false == parent_schema->is_tmp_table() && 0 != parent_schema->get_session_id() && OB_INVALID_ID != schema_guard.get_session_id()) { ret = OB_TABLE_NOT_EXIST; LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(foreign_key_arg.parent_database_), to_cstring(foreign_key_arg.parent_table_)); } else if (!arg.is_inner_ && parent_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("parent table is in recyclebin", K(ret), K(foreign_key_arg)); } else if (parent_schema->get_table_id() != table_schema.get_table_id()) { // no need to update sync_versin_for_cascade_table while the refrence table is itself if (OB_FAIL(table_schema.add_depend_table_id(parent_schema->get_table_id()))) { LOG_WARN("failed to add depend table id", K(ret), K(foreign_key_arg)); } } } // get child column schema. if (OB_SUCC(ret)) { foreign_key_info.child_table_id_ = res.table_id_; foreign_key_info.parent_table_id_ = foreign_key_arg.is_parent_table_mock_ ? mock_fk_parent_table_schema.get_mock_fk_parent_table_id() : parent_schema->get_table_id(); for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_arg.child_columns_.count(); j++) { const ObString &column_name = foreign_key_arg.child_columns_.at(j); const ObColumnSchemaV2 *column_schema = table_schema.get_column_schema(column_name); if (OB_ISNULL(column_schema)) { ret = OB_ERR_COLUMN_NOT_FOUND; LOG_WARN("child column is not exist", K(ret), K(column_name)); } else if (OB_FAIL(foreign_key_info.child_column_ids_.push_back(column_schema->get_column_id()))) { LOG_WARN("failed to push child column id", K(ret), K(column_name)); } } } // get parent column schema. if (OB_SUCC(ret) && !foreign_key_arg.is_parent_table_mock_) { for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_arg.parent_columns_.count(); j++) { const ObString &column_name = foreign_key_arg.parent_columns_.at(j); const ObColumnSchemaV2 *column_schema = parent_schema->get_column_schema(column_name); if (OB_ISNULL(column_schema)) { ret = OB_ERR_COLUMN_NOT_FOUND; LOG_WARN("parent column is not exist", K(ret), K(column_name)); } else if (OB_FAIL(foreign_key_info.parent_column_ids_.push_back(column_schema->get_column_id()))) { LOG_WARN("failed to push parent column id", K(ret), K(column_name)); } } } // get reference option and foreign key name. if (OB_SUCC(ret)) { foreign_key_info.update_action_ = foreign_key_arg.update_action_; foreign_key_info.delete_action_ = foreign_key_arg.delete_action_; foreign_key_info.foreign_key_name_ = foreign_key_arg.foreign_key_name_; foreign_key_info.enable_flag_ = foreign_key_arg.enable_flag_; foreign_key_info.validate_flag_ = foreign_key_arg.validate_flag_; foreign_key_info.rely_flag_ = foreign_key_arg.rely_flag_; foreign_key_info.is_parent_table_mock_ = foreign_key_arg.is_parent_table_mock_; } // add foreign key info. if (OB_SUCC(ret)) { if (OB_FAIL(schema_service->fetch_new_constraint_id(table_schema.get_tenant_id(), foreign_key_info.foreign_key_id_))) { LOG_WARN("failed to fetch new foreign key id", K(ret), K(foreign_key_arg)); } else if (OB_FAIL(table_schema.add_foreign_key_info(foreign_key_info))) { LOG_WARN("failed to push foreign key info", K(ret), K(foreign_key_info)); } else if (foreign_key_info.is_parent_table_mock_ && MOCK_FK_PARENT_TABLE_OP_INVALID != mock_fk_parent_table_schema.get_operation_type()) { if (OB_FAIL(mock_fk_parent_table_schema.add_foreign_key_info(foreign_key_info))) { LOG_WARN("failed to push foreign key info", K(ret), K(foreign_key_info)); } else if (ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_CREATE_TABLE_BY_ADD_FK_IN_CHILD_TBALE == mock_fk_parent_table_schema.get_operation_type()) { if (OB_FAIL(tmp_mock_fk_parent_table_schema_array.push_back(mock_fk_parent_table_schema))) { LOG_WARN("failed to push mock_fk_parent_table_schema to tmp_mock_fk_parent_table_schema_array", K(ret), K(mock_fk_parent_table_schema)); } } else { // ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_CREATE_TABLE_BY_ADD_FK_IN_CHILD_TBALE != mock_fk_parent_table_schema.get_operation_type() if (OB_FAIL(mock_fk_parent_table_schema_array.push_back(mock_fk_parent_table_schema))) { LOG_WARN("failed to push mock_fk_parent_table_schema to mock_fk_parent_table_schema_array", K(ret), K(mock_fk_parent_table_schema)); } else if (OB_FAIL(mock_fk_parent_table_map.erase_refactored(mock_fk_parent_table_schema.get_mock_fk_parent_table_name()))) { LOG_WARN("failed to delete from mock_fk_parent_table_map", K(ret), K(mock_fk_parent_table_schema.get_mock_fk_parent_table_name())); } } } } } // for if (OB_SUCC(ret)) { // push back to mock_fk_parent_table_schema_array with the last one of all dup name mock_fk_parent_table_schema if (!tmp_mock_fk_parent_table_schema_array.empty()) { for (int64_t i = 0; OB_SUCC(ret) && i < tmp_mock_fk_parent_table_schema_array.count(); ++i) { uint64_t dup_name_mock_fk_parent_table_count = 0; ObString mock_fk_parent_table_name; if (OB_FAIL(mock_fk_parent_table_map.get_refactored(tmp_mock_fk_parent_table_schema_array.at(i).get_mock_fk_parent_table_name(), dup_name_mock_fk_parent_table_count))) { if (OB_HASH_NOT_EXIST == ret) { ret = OB_SUCCESS; continue; } else { LOG_WARN("get_refactored from mock_fk_parent_table_map failed", K(ret), K(tmp_mock_fk_parent_table_schema_array.at(i))); } } else { mock_fk_parent_table_name = tmp_mock_fk_parent_table_schema_array.at(i).get_mock_fk_parent_table_name(); int64_t j = i; uint64_t count = 0; for (; count < dup_name_mock_fk_parent_table_count && j < tmp_mock_fk_parent_table_schema_array.count(); ++j) { if (0 == mock_fk_parent_table_name.case_compare(tmp_mock_fk_parent_table_schema_array.at(j).get_mock_fk_parent_table_name())) { ++count; } } if (--j >= tmp_mock_fk_parent_table_schema_array.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("j >= tmp_mock_fk_parent_table_schema_array.count()", K(ret), K(j), K(tmp_mock_fk_parent_table_schema_array.count())); } else { for (int64_t k = 0; OB_SUCC(ret) && k < tmp_mock_fk_parent_table_schema_array.at(j).get_foreign_key_infos().count(); ++k) { tmp_mock_fk_parent_table_schema_array.at(j).get_foreign_key_infos().at(k).parent_table_id_ = tmp_mock_fk_parent_table_schema_array.at(j).get_mock_fk_parent_table_id(); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(mock_fk_parent_table_schema_array.push_back(tmp_mock_fk_parent_table_schema_array.at(j)))) { LOG_WARN("fail to push back to mock_fk_parent_table_schema_array", K(ret), K(tmp_mock_fk_parent_table_schema_array.at(j))); } else if (OB_FAIL(mock_fk_parent_table_map.erase_refactored(mock_fk_parent_table_name))) { LOG_WARN("failed to delete from mock_fk_parent_table_map", K(mock_fk_parent_table_name), K(ret)); } } } } } if (OB_SUCC(ret)) { // deal with new table name which is the same to mock_fk_parent_table_name, replace mock_parent_table with this new table const ObMockFKParentTableSchema *ori_mock_parent_table_schema_ptr = NULL; if (OB_FAIL(schema_guard.get_mock_fk_parent_table_schema_with_name( table_schema.get_tenant_id(), table_schema.get_database_id(), table_schema.get_table_name_str(), ori_mock_parent_table_schema_ptr))) { LOG_WARN("failed to check_mock_fk_parent_table_exist_with_name"); } else if (OB_NOT_NULL(ori_mock_parent_table_schema_ptr)) { ObMockFKParentTableSchema mock_fk_parent_table_schema; ObArray index_schemas; for (int64_t i = 1; OB_SUCC(ret) && i < table_schemas.count(); ++i) { if (table_schemas.at(i).is_unique_index() && OB_FAIL(index_schemas.push_back(&table_schemas.at(i)))) { LOG_WARN("failed to push back index_schemas", K(ret)); } } if (FAILEDx(ddl_service_.gen_mock_fk_parent_table_for_replacing_mock_fk_parent_table( schema_guard, ori_mock_parent_table_schema_ptr->get_mock_fk_parent_table_id(), table_schema, index_schemas, mock_fk_parent_table_schema))) { LOG_WARN("failed to gen_mock_fk_parent_table_for_replacing_mock_fk_parent_table", K(ret)); } else if (OB_FAIL(mock_fk_parent_table_schema_array.push_back(mock_fk_parent_table_schema))) { LOG_WARN("failed to push mock_fk_parent_table_schema", K(ret), K(mock_fk_parent_table_schema)); } } } } // check foreign key info end. } RS_TRACE(generate_schema_finish); if (OB_SUCC(ret)) { //table schema may be updated during analyse index schema, so reset table_schema const bool is_standby = PRIMARY_CLUSTER != ObClusterInfoGetter::get_cluster_role_v2(); if (OB_FAIL(table_schemas.at(0).assign(table_schema))) { LOG_WARN("fail to assign schema", K(ret)); } else if (OB_FAIL(ddl_service_.create_user_tables( arg.if_not_exist_, arg.ddl_stmt_str_, arg.error_info_, table_schemas, schema_guard, arg.sequence_ddl_arg_, arg.last_replay_log_id_, &arg.dep_infos_, mock_fk_parent_table_schema_array))) { LOG_WARN("create_user_tables failed", "if_not_exist", arg.if_not_exist_, "ddl_stmt_str", arg.ddl_stmt_str_, K(ret)); } } if (OB_ERR_TABLE_EXIST == ret) { //create table xx if not exist (...) //create or replace view xx as ... if (arg.if_not_exist_) { ret = OB_SUCCESS; LOG_INFO("table is exist, no need to create again, ", "tenant_id", table_schema.get_tenant_id(), "database_id", table_schema.get_database_id(), "table_name", table_schema.get_table_name()); } else { ret = OB_ERR_TABLE_EXIST; LOG_USER_ERROR(OB_ERR_TABLE_EXIST, table_schema.get_table_name_str().length(), table_schema.get_table_name_str().ptr()); LOG_WARN("table is exist, cannot create it twice,", "tenant_id", table_schema.get_tenant_id(), "database_id", table_schema.get_database_id(), "table_name", table_schema.get_table_name(), K(ret)); } } // check vertical partition // is_primary_vp_table() // get_aux_vp_tid_array() // is_aux_vp_table() // get_vp_store_column_ids // get_vp_column_ids_without_rowkey if (OB_SUCC(ret)) { ObSchemaGetterGuard new_schema_guard; const ObTableSchema *new_table_schema = NULL; const uint64_t arg_vp_cnt = arg.vertical_partition_arg_list_.count(); if (arg_vp_cnt == 0) { LOG_INFO("avg_vp_cnt is 0"); // do-nothing } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table( table_schema.get_tenant_id(), new_schema_guard))) { LOG_WARN("fail to get schema guard with version in inner table", K(ret), K(table_schema.get_tenant_id())); } else if (OB_FAIL(new_schema_guard.get_table_schema(table_schema.get_tenant_id(), table_schema.get_table_id(), new_table_schema))) { LOG_WARN("fail to get table schema", K(ret), K(table_schema)); } else if (NULL == new_table_schema) { ret = OB_ERR_UNEXPECTED; LOG_WARN("NULL ptr", K(ret)); } else if (!new_table_schema->is_primary_vp_table()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("is_primary_vp_table is invalid", K(ret), K(arg_vp_cnt), K(new_table_schema->is_primary_vp_table())); } else { ObSEArray aux_vp_tid_array; if (OB_FAIL(new_table_schema->get_aux_vp_tid_array(aux_vp_tid_array))) { LOG_WARN("failed to get_aux_vp_tid_array", K(*new_table_schema)); } else if (!((arg_vp_cnt == (aux_vp_tid_array.count()+ 1) || (arg_vp_cnt == aux_vp_tid_array.count())))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("arg_vp_cnt is not equal to aux_vp_cnt_ or (aux_vp_cnt_+1)", K(ret), K(arg_vp_cnt), K(aux_vp_tid_array.count())); } else { // check primary partition table include get_vp_store_column_ids and vertical partition column information ObArray columns; const ObColumnSchemaV2 *column_schema = NULL; const ObCreateVertialPartitionArg primary_vp_arg = arg.vertical_partition_arg_list_.at(0); int64_t arg_pri_vp_col_cnt = primary_vp_arg.vertical_partition_columns_.count(); if (OB_FAIL(new_table_schema->get_vp_store_column_ids(columns))) { LOG_WARN("get_vp_store_column_ids failed", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); ++i) { LOG_INFO("column info", K(columns.at(i).col_id_), K(columns.at(i).col_type_)); if (NULL == (column_schema = new_table_schema->get_column_schema(columns.at(i).col_id_))) { ret = OB_ERR_BAD_FIELD_ERROR; LOG_WARN("get_column_schema failed", K(columns.at(i)), K(ret)); } else { ObString column_name = column_schema->get_column_name(); LOG_INFO("column info", K(column_name), K(column_schema->get_column_id()), K(column_schema->get_table_id())); if (column_schema->is_primary_vp_column()) { for (int64_t j = 0; OB_SUCC(ret) && j < primary_vp_arg.vertical_partition_columns_.count(); ++j) { ObString pri_vp_col = primary_vp_arg.vertical_partition_columns_.at(j); if (0 == column_name.case_compare(pri_vp_col)) { arg_pri_vp_col_cnt--; LOG_INFO("primary vp", K(column_name)); break; } } } else { LOG_INFO("non-primary vp", K(column_name)); } } } if (OB_SUCC(ret) && (0 != arg_pri_vp_col_cnt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("mismatch primary vp column", K(ret)); for (int64_t j = 0; j < arg_pri_vp_col_cnt; ++j) { ObString pri_vp_col = primary_vp_arg.vertical_partition_columns_.at(j); LOG_INFO("arg primary vp", K(pri_vp_col)); } } // verify secondary partition table if (OB_SUCC(ret)) { int64_t N = aux_vp_tid_array.count(); for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) { const ObTableSchema *aux_vp_table_schema = NULL; ObArray vp_columns; ObArray store_columns; if (OB_FAIL(new_schema_guard.get_table_schema(table_schema.get_tenant_id(), aux_vp_tid_array.at(i), aux_vp_table_schema))) { LOG_WARN("get_table_schema failed", "table id", aux_vp_tid_array.at(i), K(ret)); } else if (NULL == aux_vp_table_schema) { ret = OB_ERR_UNEXPECTED; LOG_WARN("aux vp table is null", K(ret)); } else if (!aux_vp_table_schema->is_aux_vp_table() || AUX_VERTIAL_PARTITION_TABLE != aux_vp_table_schema->get_table_type()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("aux vp table type is incorrect", K(ret), K(aux_vp_table_schema->is_aux_vp_table())); } else if (OB_FAIL(aux_vp_table_schema->get_vp_column_ids(vp_columns))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to get aux vp table columns", K(ret), K(*aux_vp_table_schema)); } else if (OB_FAIL(aux_vp_table_schema->get_vp_store_column_ids(store_columns))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to get aux vp table columns", K(ret), K(*aux_vp_table_schema)); } else { LOG_INFO("table info", K(aux_vp_table_schema->get_table_name()), K(aux_vp_table_schema->get_table_id()), K(aux_vp_table_schema->get_data_table_id()), K(ret)); const ObColumnSchemaV2 *column_schema = NULL; for (int64_t k = 0; OB_SUCC(ret) && k < vp_columns.count(); ++k) { LOG_INFO("column info", K(vp_columns.at(k).col_id_), K(vp_columns.at(k).col_type_)); if (NULL == (column_schema = aux_vp_table_schema->get_column_schema(vp_columns.at(k).col_id_))) { ret = OB_ERR_BAD_FIELD_ERROR; LOG_WARN("get_column_schema failed", K(vp_columns.at(k)), K(ret)); } else { LOG_INFO("column info", K(column_schema->get_column_name()), K(column_schema->get_column_id()), K(column_schema->get_table_id()), K(ret)); } } // verify get_vp_store_column_ids return all vertical partition columns, // include vertical partition columns of primary key. for (int64_t k = 0; OB_SUCC(ret) && k < store_columns.count(); ++k) { LOG_INFO("column info", K(store_columns.at(k).col_id_), K(store_columns.at(k).col_type_)); if (NULL == (column_schema = aux_vp_table_schema->get_column_schema(store_columns.at(k).col_id_))) { ret = OB_ERR_BAD_FIELD_ERROR; LOG_WARN("get_column_schema failed", K(store_columns.at(k)), K(ret)); } else { LOG_INFO("column info", K(column_schema->get_column_name()), K(column_schema->get_column_id()), K(column_schema->get_table_id()), K(ret)); } } } } } } } } if (OB_SUCC(ret)) { uint64_t tenant_id = table_schema.get_tenant_id(); if (OB_FAIL(schema_service_->get_tenant_schema_version(tenant_id, res.schema_version_))) { LOG_WARN("failed to get tenant schema version", K(ret)); } } } RS_TRACE(create_table_end); FORCE_PRINT_TRACE(THE_RS_TRACE, "[create table]"); int64_t cost = ObTimeUtility::current_time() - begin_time; ROOTSERVICE_EVENT_ADD("ddl", "create_table", K(ret), "table_id", res.table_id_, K(cost)); return ret; } // create sys_table by specify table_id for tenant: // 1. can not create table cross tenant except sys tenant. // 2. part_type of sys table only support non-partition or only level hash_like part type. // 3. sys table's tablegroup and database must be oceanbase int ObRootService::generate_table_schema_in_tenant_space( const ObCreateTableArg &arg, ObTableSchema &table_schema) { int ret = OB_SUCCESS; const uint64_t tenant_id = arg.exec_tenant_id_; const uint64_t table_id = table_schema.get_table_id(); const ObPartitionLevel part_level = table_schema.get_part_level(); const ObPartitionFuncType part_func_type = table_schema.get_part_option().get_part_func_type(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_INVALID_ID == table_id || !is_inner_table(table_id)) { // skip } else if (OB_SYS_TENANT_ID != arg.exec_tenant_id_) { //FIXME: this restriction should be removed later. // only enable sys tenant create sys table ret = OB_OP_NOT_ALLOW; LOG_WARN("only sys tenant can create tenant space table", K(ret), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "non-sys tenant creating system tables"); } else if (table_schema.is_view_table()) { // no need specify tenant_id while specify table_id creating sys table if (OB_SYS_TENANT_ID != tenant_id) { ret = OB_OP_NOT_ALLOW; LOG_WARN("create sys view with ordinary tenant not allowed", K(ret), K(table_schema)); } } else if (part_level > ObPartitionLevel::PARTITION_LEVEL_ONE || !is_hash_like_part(part_func_type)) { // sys tables do not write __all_part table, so sys table only support non-partition or only level hash_like part type. ret = OB_OP_NOT_ALLOW; LOG_WARN("sys table's partition option is invalid", K(ret), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "invalid partition option to system table"); } else if (0 != table_schema.get_tablegroup_name().case_compare(OB_SYS_TABLEGROUP_NAME)) { // sys tables's tablegroup must be oceanbase ret = OB_OP_NOT_ALLOW; LOG_WARN("sys table's tablegroup should be oceanbase", K(ret), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "invalid tablegroup to system table"); } else if (0 != arg.db_name_.case_compare(OB_SYS_DATABASE_NAME)) { // sys tables's database must be oceanbase ret = OB_OP_NOT_ALLOW; LOG_WARN("sys table's database should be oceanbase", K(ret), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "invalid database to sys table"); } else { table_schema.set_tenant_id(tenant_id); table_schema.set_table_id(table_id); table_schema.set_tablegroup_id(OB_SYS_TABLEGROUP_ID); table_schema.set_tablegroup_name(OB_SYS_TABLEGROUP_NAME); table_schema.set_database_id(OB_SYS_DATABASE_ID); } return ret; } int ObRootService::maintain_obj_dependency_info(const obrpc::ObDependencyObjDDLArg &arg) { LOG_DEBUG("receive maintain obj dependency info arg", K(arg)); int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.maintain_obj_dependency_info(arg))) { LOG_WARN("failed to maintain obj dependency info", K(ret), K(arg)); } return ret; } int ObRootService::execute_ddl_task(const obrpc::ObAlterTableArg &arg, common::ObSArray &obj_ids) { LOG_DEBUG("receive execute ddl task arg", K(arg)); int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { switch (arg.ddl_task_type_) { case share::REBUILD_INDEX_TASK: { if (OB_FAIL(ddl_service_.rebuild_hidden_table_index( const_cast(arg), obj_ids))) { LOG_WARN("failed to rebuild hidden table index", K(ret)); } break; } case share::REBUILD_CONSTRAINT_TASK: { if (OB_FAIL(ddl_service_.rebuild_hidden_table_constraints( const_cast(arg), obj_ids))) { LOG_WARN("failed to rebuild hidden table constraints", K(ret)); } break; } case share::REBUILD_FOREIGN_KEY_TASK: { if (OB_FAIL(ddl_service_.rebuild_hidden_table_foreign_key( const_cast(arg), obj_ids))) { LOG_WARN("failed to rebuild hidden table foreign key", K(ret)); } break; } case share::MAKE_DDL_TAKE_EFFECT_TASK: { if (OB_FAIL(ddl_service_.swap_orig_and_hidden_table_state( const_cast(arg)))) { LOG_WARN("failed to swap orig and hidden table state", K(ret)); } break; } case share::CLEANUP_GARBAGE_TASK: { if (OB_FAIL(ddl_service_.cleanup_garbage( const_cast(arg)))) { LOG_WARN("failed to cleanup garbage", K(ret)); } break; } case share::MODIFY_FOREIGN_KEY_STATE_TASK: { if (OB_FAIL(ddl_service_.modify_hidden_table_fk_state( const_cast(arg)))) { LOG_WARN("failed to modify hidden table fk state", K(ret)); } break; } case share::DELETE_COLUMN_FROM_SCHEMA: { if (OB_FAIL(ddl_service_.delete_column_from_schema(const_cast(arg)))) { LOG_WARN("fail to set column to no minor status", K(ret), K(arg)); } break; } // remap all index tables to hidden table and take effect concurrently. case share::REMAP_INDEXES_AND_TAKE_EFFECT_TASK: { if (OB_FAIL(ddl_service_.remap_index_tablets_and_take_effect( const_cast(arg)))) { LOG_WARN("fail to remap index tables to hidden table and take effect", K(ret)); } break; } case share::UPDATE_AUTOINC_SCHEMA: { if (OB_FAIL(ddl_service_.update_autoinc_schema(const_cast(arg)))) { LOG_WARN("fail to update autoinc schema", K(ret), K(arg)); } break; } case share::MODIFY_NOT_NULL_COLUMN_STATE_TASK: { if (OB_FAIL(ddl_service_.modify_hidden_table_not_null_column_state(arg))) { LOG_WARN("failed to modify hidden table cst state", K(ret)); } break; } default: ret = OB_ERR_UNEXPECTED; LOG_WARN("unknown ddl task type", K(ret), K(arg.ddl_task_type_)); } } return ret; } int ObRootService::precheck_interval_part(const obrpc::ObAlterTableArg &arg) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; const ObAlterTableArg::AlterPartitionType op_type = arg.alter_part_type_; const ObSimpleTableSchemaV2 *simple_table_schema = NULL; const AlterTableSchema &alter_table_schema = arg.alter_table_schema_; int64_t tenant_id = alter_table_schema.get_tenant_id(); if (!alter_table_schema.is_interval_part() || obrpc::ObAlterTableArg::ADD_PARTITION != op_type) { } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("error unexpected, schema service must not be NULL", K(ret)); } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) { LOG_WARN("fail to get schema guard", K(ret)); } else if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, alter_table_schema.get_table_id(), simple_table_schema))) { LOG_WARN("get table schema failed", KR(ret), K(tenant_id), K(alter_table_schema)); } else if (OB_ISNULL(simple_table_schema)) { ret = OB_TABLE_NOT_EXIST; LOG_WARN("simple_table_schema is null", K(ret), K(alter_table_schema)); } else if (simple_table_schema->get_schema_version() < alter_table_schema.get_schema_version()) { } else if (simple_table_schema->get_interval_range() != alter_table_schema.get_interval_range() || simple_table_schema->get_transition_point() != alter_table_schema.get_transition_point()) { ret = OB_ERR_INTERVAL_PARTITION_ERROR; LOG_WARN("interval_range or transition_point is changed", KR(ret), \ KPC(simple_table_schema), K(alter_table_schema)); } else { int64_t j = 0; const ObRowkey *rowkey_orig= NULL; bool is_all_exist = true; ObPartition **inc_part_array = alter_table_schema.get_part_array(); ObPartition **orig_part_array = simple_table_schema->get_part_array(); if (OB_ISNULL(inc_part_array)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ptr is null", K(ret), K(alter_table_schema), KPC(simple_table_schema)); } else if (OB_ISNULL(orig_part_array)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ptr is null", K(ret), K(alter_table_schema), KPC(simple_table_schema)); } for (int64_t i = 0; is_all_exist && OB_SUCC(ret) && i < alter_table_schema.get_part_option().get_part_num(); ++i) { const ObRowkey *rowkey_cur = NULL; if (OB_ISNULL(inc_part_array[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ptr is null", K(ret), K(alter_table_schema), KPC(simple_table_schema)); } else if (OB_UNLIKELY(NULL == (rowkey_cur = &inc_part_array[i]->get_high_bound_val()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ptr is null", K(ret), K(alter_table_schema), KPC(simple_table_schema)); } while (is_all_exist && OB_SUCC(ret) && j < simple_table_schema->get_part_option().get_part_num()) { if (OB_ISNULL(orig_part_array[j])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ptr is null", K(ret), K(alter_table_schema), KPC(simple_table_schema)); } else if (OB_UNLIKELY(NULL == (rowkey_orig = &orig_part_array[j]->get_high_bound_val()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ptr is null", K(ret), K(alter_table_schema), KPC(simple_table_schema)); } else if (*rowkey_orig < *rowkey_cur) { j++; } else { break; } } if (OB_FAIL(ret)) { } else if (*rowkey_orig != *rowkey_cur) { is_all_exist = false; } } if (OB_FAIL(ret)) { } else if (is_all_exist) { LOG_INFO("all interval part for add is exist", K(alter_table_schema), KPC(simple_table_schema)); ret = OB_ERR_INTERVAL_PARTITION_EXIST; } } return ret; } int ObRootService::create_hidden_table(const obrpc::ObCreateHiddenTableArg &arg, obrpc::ObCreateHiddenTableRes &res) { LOG_DEBUG("receive create hidden table arg", K(arg)); int ret = OB_SUCCESS; const uint64_t tenant_id = arg.tenant_id_; uint64_t compat_version = 0; if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", K(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("version 4.0 does not support this operation", K(ret)); } else if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(arg)); } else if (OB_FAIL(ddl_service_.create_hidden_table(arg, res))) { LOG_WARN("do create hidden table in trans failed", K(ret)); } return ret; } int ObRootService::update_ddl_task_active_time(const obrpc::ObUpdateDDLTaskActiveTimeArg &arg) { LOG_DEBUG("receive recv ddl task status arg", K(arg)); int ret = OB_SUCCESS; const int64_t task_id = arg.task_id_; const uint64_t tenant_id = arg.tenant_id_; uint64_t compat_version = 0; if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", K(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("version 4.0 does not support this operation", K(ret)); } else if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.update_ddl_task_active_time(ObDDLTaskID(tenant_id, task_id)))) { LOG_WARN("fail to set RegTaskTime map", K(ret), K(tenant_id), K(task_id)); } return ret; } int ObRootService::abort_redef_table(const obrpc::ObAbortRedefTableArg &arg) { LOG_DEBUG("receive abort redef table arg", K(arg)); int ret = OB_SUCCESS; const int64_t task_id = arg.task_id_; const uint64_t tenant_id = arg.tenant_id_; uint64_t compat_version = 0; if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", K(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("version 4.0 does not support this operation", K(ret)); } else if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.abort_redef_table(ObDDLTaskID(tenant_id, task_id)))) { LOG_WARN("cancel task failed", K(ret), K(tenant_id), K(task_id)); } return ret; } int ObRootService::finish_redef_table(const obrpc::ObFinishRedefTableArg &arg) { LOG_DEBUG("receive finish redef table arg", K(arg)); int ret = OB_SUCCESS; const int64_t task_id = arg.task_id_; const uint64_t tenant_id = arg.tenant_id_; uint64_t compat_version = 0; if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", K(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("version 4.0 does not support this operation", K(ret)); } else if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.finish_redef_table(ObDDLTaskID(tenant_id, task_id)))) { LOG_WARN("failed to finish redef table", K(ret), K(task_id), K(tenant_id)); } return ret; } int ObRootService::copy_table_dependents(const obrpc::ObCopyTableDependentsArg &arg) { LOG_INFO("receive copy table dependents arg", K(arg)); int ret = OB_SUCCESS; const int64_t task_id = arg.task_id_; const uint64_t tenant_id = arg.tenant_id_; const bool is_copy_indexes = arg.copy_indexes_; const bool is_copy_triggers = arg.copy_triggers_; const bool is_copy_constraints = arg.copy_constraints_; const bool is_copy_foreign_keys = arg.copy_foreign_keys_; const bool is_ignore_errors = arg.ignore_errors_; uint64_t compat_version = 0; if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", K(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("version 4.0 does not support this operation", K(ret)); } else if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.copy_table_dependents(ObDDLTaskID(tenant_id, task_id), is_copy_constraints, is_copy_indexes, is_copy_triggers, is_copy_foreign_keys, is_ignore_errors))) { LOG_WARN("failed to copy table dependents", K(ret), K(arg)); } return ret; } int ObRootService::start_redef_table(const obrpc::ObStartRedefTableArg &arg, obrpc::ObStartRedefTableRes &res) { LOG_DEBUG("receive start redef table arg", K(arg)); int ret = OB_SUCCESS; const uint64_t tenant_id = arg.orig_tenant_id_; uint64_t compat_version = 0; if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", K(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("version 4.0 does not support this operation", K(ret)); } else if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.start_redef_table(arg, res))) { LOG_WARN("start redef table failed", K(ret)); } return ret; } int ObRootService::alter_table(const obrpc::ObAlterTableArg &arg, obrpc::ObAlterTableRes &res) { LOG_DEBUG("receive alter table arg", K(arg)); int ret = OB_SUCCESS; bool is_oracle_mode = false; ObSchemaGetterGuard schema_guard; const uint64_t tenant_id = arg.alter_table_schema_.get_tenant_id(); ObAlterTableArg &nonconst_arg = const_cast(arg); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(precheck_interval_part(arg))) { if (ret != OB_ERR_INTERVAL_PARTITION_EXIST) { LOG_WARN("fail to precheck_interval_part", K(arg), KR(ret)); } } else { if (OB_FAIL(ret)) { } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(check_parallel_ddl_conflict(schema_guard, arg))) { LOG_WARN("check parallel ddl conflict failed", K(ret)); } else if (OB_FAIL(table_allow_ddl_operation(arg))) { LOG_WARN("table can't do ddl now", K(ret)); } else if (nonconst_arg.is_add_to_scheduler_) { ObDDLTaskRecord task_record; ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp")); ObDDLType ddl_type = ObDDLType::DDL_INVALID; const ObTableSchema *orig_table_schema = nullptr; schema_guard.set_session_id(arg.session_id_); if (obrpc::ObAlterTableArg::DROP_PARTITION == nonconst_arg.alter_part_type_) { ddl_type = ObDDLType::DDL_DROP_PARTITION; } else if (obrpc::ObAlterTableArg::DROP_SUB_PARTITION == nonconst_arg.alter_part_type_) { ddl_type = ObDDLType::DDL_DROP_SUB_PARTITION; } else if (obrpc::ObAlterTableArg::TRUNCATE_PARTITION == nonconst_arg.alter_part_type_) { ddl_type = ObDDLType::DDL_TRUNCATE_PARTITION; } else if (obrpc::ObAlterTableArg::TRUNCATE_SUB_PARTITION == nonconst_arg.alter_part_type_) { ddl_type = ObDDLType::DDL_TRUNCATE_SUB_PARTITION; } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected ddl type", K(ret), K(nonconst_arg.alter_part_type_), K(nonconst_arg)); } if (OB_FAIL(ret)) { } else if (OB_FAIL(schema_guard.get_table_schema(tenant_id, nonconst_arg.alter_table_schema_.get_database_name(), nonconst_arg.alter_table_schema_.get_origin_table_name(), false /* is_index */, orig_table_schema))) { LOG_WARN("fail to get and check table schema", K(ret)); } else if (OB_ISNULL(orig_table_schema)) { ret = OB_TABLE_NOT_EXIST; LOG_WARN("table not exist", K(ret), K(tenant_id), K(nonconst_arg.alter_table_schema_)); } else { ObCreateDDLTaskParam param(tenant_id, ddl_type, nullptr, nullptr, orig_table_schema->get_table_id(), orig_table_schema->get_schema_version(), arg.parallelism_, arg.consumer_group_id_, &allocator, &arg, 0 /* parent task id*/); if (OB_FAIL(ddl_scheduler_.create_ddl_task(param, sql_proxy_, task_record))) { LOG_WARN("submit ddl task failed", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.schedule_ddl_task(task_record))) { LOG_WARN("fail to schedule ddl task", K(ret), K(task_record)); } else { res.ddl_type_ = ddl_type; res.task_id_ = task_record.task_id_; } } } else if (OB_FAIL(ddl_service_.alter_table(nonconst_arg, res))) { LOG_WARN("alter_user_table failed", K(arg), K(ret)); } else { const ObSimpleTableSchemaV2 *simple_table_schema = NULL; // there are multiple DDL except alter table, ctas, comment on, eg. // but only alter_table specify table_id, so if no table_id, it indicates DDL is not alter table, skip. if (OB_INVALID_ID == arg.alter_table_schema_.get_table_id()) { // skip } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, arg.alter_table_schema_.get_table_id(), simple_table_schema))) { LOG_WARN("fail to get table schema", K(ret), K(arg.alter_table_schema_.get_table_id())); } else if (OB_ISNULL(simple_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("simple_table_schema is NULL ptr", K(ret), K(simple_table_schema), K(ret)); } else { res.schema_version_ = simple_table_schema->get_schema_version(); } } } return ret; } int ObRootService::create_index(const ObCreateIndexArg &arg, obrpc::ObAlterTableRes &res) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; LOG_DEBUG("receive create index arg", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObIndexBuilder index_builder(ddl_service_); if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(arg.tenant_id_, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(check_parallel_ddl_conflict(schema_guard, arg))) { LOG_WARN("check parallel ddl conflict failed", K(ret)); } else if (OB_FAIL(index_builder.create_index(arg, res))) { LOG_WARN("create_index failed", K(arg), K(ret)); } } return ret; } int ObRootService::drop_table(const obrpc::ObDropTableArg &arg, obrpc::ObDDLRes &res) { int ret = OB_SUCCESS; uint64_t target_object_id = OB_INVALID_ID; int64_t schema_version = OB_INVALID_SCHEMA_VERSION; bool need_add_to_ddl_scheduler = arg.is_add_to_scheduler_; const uint64_t tenant_id = arg.tenant_id_; ObSchemaGetterGuard schema_guard; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("fail to get schema guard with version in inner table", K(ret), K(arg)); } else if (need_add_to_ddl_scheduler) { // to decide wherther to add to ddl scheduler. // 1. do not add to scheduler if all tables do not exist. // 2. do not add to scheduler if all existed tables are temporary tables. need_add_to_ddl_scheduler = arg.tables_.count() == 0 ? false : true; for (int64_t i = 0; OB_SUCC(ret) && need_add_to_ddl_scheduler && i < arg.tables_.count(); ++i) { int tmp_ret = OB_SUCCESS; const ObTableItem &table_item = arg.tables_.at(i); const ObTableSchema *table_schema = nullptr; if (OB_SUCCESS != (tmp_ret = ddl_service_.check_table_exists(tenant_id, table_item, arg.table_type_, schema_guard, &table_schema))) { LOG_INFO("check table exist failed, generate error msg in ddl service later", K(ret), K(tmp_ret)); } if (OB_FAIL(ret)) { } else if (nullptr != table_schema) { if (table_schema->is_tmp_table()) { // do nothing. } else if (OB_INVALID_ID == target_object_id || OB_INVALID_SCHEMA_VERSION == schema_version) { // regard table_id, schema_version of the the first table as the tag to submit ddl task. target_object_id = table_schema->get_table_id(); schema_version = table_schema->get_schema_version(); } } } // all tables do not exist, or all existed tables are temporary tables. if (OB_INVALID_ID == target_object_id || OB_INVALID_SCHEMA_VERSION == schema_version) { need_add_to_ddl_scheduler = false; } } if (OB_FAIL(ret)) { } else if (need_add_to_ddl_scheduler) { ObDDLTaskRecord task_record; ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp")); ObCreateDDLTaskParam param(tenant_id, ObDDLType::DDL_DROP_TABLE, nullptr, nullptr, target_object_id, schema_version, arg.parallelism_, arg.consumer_group_id_, &allocator, &arg, 0 /* parent task id*/); if (OB_UNLIKELY(OB_INVALID_ID == target_object_id || OB_INVALID_SCHEMA_VERSION == schema_version)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("error unexpected", K(ret), K(arg), K(target_object_id), K(schema_version)); } else if (OB_FAIL(ddl_scheduler_.create_ddl_task(param, sql_proxy_, task_record))) { LOG_WARN("submit ddl task failed", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.schedule_ddl_task(task_record))) { LOG_WARN("fail to schedule ddl task", K(ret), K(task_record)); } else { res.tenant_id_ = tenant_id; res.schema_id_ = target_object_id; res.task_id_ = task_record.task_id_; } } else if (OB_FAIL(ddl_service_.drop_table(arg, res))) { LOG_WARN("ddl service failed to drop table", K(ret), K(arg), K(res)); } return ret; } int ObRootService::drop_database(const obrpc::ObDropDatabaseArg &arg, ObDropDatabaseRes &drop_database_res) { int ret = OB_SUCCESS; uint64_t database_id = 0; int64_t schema_version = 0; bool need_add_to_scheduler = arg.is_add_to_scheduler_; const uint64_t tenant_id = arg.tenant_id_; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (need_add_to_scheduler) { ObSchemaGetterGuard schema_guard; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_guard.get_schema_version(tenant_id, schema_version))) { LOG_WARN("fail to get schema version", K(ret), K(arg)); } else if (OB_FAIL(schema_guard.get_database_id(tenant_id, arg.database_name_, database_id))) { LOG_WARN("fail to get database id"); } else if (OB_INVALID_ID == database_id) { // drop database if exists xxx. need_add_to_scheduler = false; } } if (OB_FAIL(ret)) { } else if (need_add_to_scheduler) { ObDDLTaskRecord task_record; ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp")); ObCreateDDLTaskParam param(tenant_id, ObDDLType::DDL_DROP_DATABASE, nullptr, nullptr, database_id, schema_version, arg.parallelism_, arg.consumer_group_id_, &allocator, &arg, 0 /* parent task id*/); if (OB_FAIL(ddl_scheduler_.create_ddl_task(param, sql_proxy_, task_record))) { LOG_WARN("submit ddl task failed", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.schedule_ddl_task(task_record))) { LOG_WARN("fail to schedule ddl task", K(ret), K(task_record)); } else { drop_database_res.ddl_res_.tenant_id_ = tenant_id; drop_database_res.ddl_res_.schema_id_ = database_id; drop_database_res.ddl_res_.task_id_ = task_record.task_id_; } } else if (OB_FAIL(ddl_service_.drop_database(arg, drop_database_res))) { LOG_WARN("ddl_service_ drop_database failed", K(arg), K(ret)); } return ret; } int ObRootService::drop_tablegroup(const obrpc::ObDropTablegroupArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.drop_tablegroup(arg))) { LOG_WARN("ddl_service_ drop_tablegroup failed", K(arg), K(ret)); } return ret; } int ObRootService::alter_tablegroup(const obrpc::ObAlterTablegroupArg &arg) { LOG_DEBUG("receive alter tablegroup arg", K(arg)); const ObTablegroupSchema *tablegroup_schema = NULL; ObSchemaGetterGuard schema_guard; uint64_t tablegroup_id = OB_INVALID_ID; const uint64_t tenant_id = arg.tenant_id_; int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_tablegroup_id(tenant_id, arg.tablegroup_name_, tablegroup_id))) { LOG_WARN("fail to get tablegroup id", K(ret)); } else if (OB_INVALID_ID == tablegroup_id) { ret = OB_TABLEGROUP_NOT_EXIST; LOG_WARN("get invalid tablegroup schema", KR(ret), K(arg)); } else if (OB_FAIL(schema_guard.get_tablegroup_schema(tenant_id, tablegroup_id, tablegroup_schema))) { LOG_WARN("fail to get tablegroup schema", K(ret), K(tenant_id), K(ret)); } else if (OB_ISNULL(tablegroup_schema)) { ret = OB_TABLEGROUP_NOT_EXIST; LOG_WARN("get invalid tablegroup schema", K(ret)); } else if (tablegroup_schema->is_in_splitting()) { ret = OB_OP_NOT_ALLOW; LOG_WARN("tablegroup is splitting, refuse to alter now", K(ret), K(tablegroup_id)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "tablegroup is splitting, alter tablegroup"); } if (OB_FAIL(ret)) { } else if (OB_FAIL(ddl_service_.alter_tablegroup(arg))) { LOG_WARN("ddl_service_ alter tablegroup failed", K(arg), K(ret)); } else { } return ret; } int ObRootService::drop_index(const obrpc::ObDropIndexArg &arg, obrpc::ObDropIndexRes &res) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObIndexBuilder index_builder(ddl_service_); if (OB_FAIL(index_builder.drop_index(arg, res))) { LOG_WARN("index_builder drop_index failed", K(arg), K(ret)); } } return ret; } int ObRootService::rebuild_index(const obrpc::ObRebuildIndexArg &arg, obrpc::ObAlterTableRes &res) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.rebuild_index(arg, res))) { LOG_WARN("ddl_service rebuild index failed", K(arg), K(ret)); } return ret; } int ObRootService::flashback_index(const ObFlashBackIndexArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.flashback_index(arg))) { LOG_WARN("failed to flashback index", K(ret)); } return ret; } int ObRootService::purge_index(const ObPurgeIndexArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.purge_index(arg))) { LOG_WARN("failed to purge index", K(ret)); } return ret; } int ObRootService::rename_table(const obrpc::ObRenameTableArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.rename_table(arg))){ LOG_WARN("rename table failed", K(ret)); } return ret; } int ObRootService::truncate_table(const obrpc::ObTruncateTableArg &arg, obrpc::ObDDLRes &res) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { SCN frozen_scn; if (OB_FAIL(ObMajorFreezeHelper::get_frozen_scn(arg.tenant_id_, frozen_scn))) { LOG_WARN("get_frozen_scn failed", K(ret)); } else if (arg.is_add_to_scheduler_) { ObDDLTaskRecord task_record; ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp")); ObSchemaGetterGuard schema_guard; const ObTableSchema *table_schema = nullptr; const uint64_t tenant_id = arg.tenant_id_; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_table_schema(tenant_id, arg.database_name_, arg.table_name_, false /* is_index */, table_schema))) { LOG_WARN("fail to get table schema", K(ret)); } else if (OB_ISNULL(table_schema)) { ret = OB_TABLE_NOT_EXIST; LOG_WARN("table not exist", K(ret), K(arg)); } else { ObCreateDDLTaskParam param(tenant_id, ObDDLType::DDL_TRUNCATE_TABLE, nullptr, nullptr, table_schema->get_table_id(), table_schema->get_schema_version(), arg.parallelism_, arg.consumer_group_id_, &allocator, &arg, 0 /* parent task id*/); if (OB_FAIL(GCTX.root_service_->get_ddl_scheduler().create_ddl_task(param, sql_proxy_, task_record))) { LOG_WARN("submit ddl task failed", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.schedule_ddl_task(task_record))) { LOG_WARN("fail to schedule ddl task", K(ret), K(task_record)); } else { res.tenant_id_ = tenant_id; res.schema_id_ = table_schema->get_table_id(); res.task_id_ = task_record.task_id_; } } } else if (OB_FAIL(ddl_service_.truncate_table(arg, res, frozen_scn))) { LOG_WARN("ddl service failed to truncate table", K(arg), K(ret), K(frozen_scn)); } } return ret; } /* * new parallel truncate table */ int ObRootService::truncate_table_v2(const obrpc::ObTruncateTableArg &arg, obrpc::ObDDLRes &res) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { SCN frozen_scn; if (OB_FAIL(ObMajorFreezeHelper::get_frozen_scn(arg.tenant_id_, frozen_scn))) { LOG_WARN("get_frozen_scn failed", K(ret)); } else if (OB_FAIL(ddl_service_.new_truncate_table(arg, res, frozen_scn))) { LOG_WARN("ddl service failed to truncate table", K(arg), K(ret)); } } return ret; } int ObRootService::create_table_like(const ObCreateTableLikeArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { if (OB_FAIL(ddl_service_.create_table_like(arg))) { if (OB_ERR_TABLE_EXIST == ret) { //create table xx if not exist like if (arg.if_not_exist_) { LOG_USER_NOTE(OB_ERR_TABLE_EXIST, arg.new_table_name_.length(), arg.new_table_name_.ptr()); LOG_WARN("table is exist, no need to create again", K(arg), K(ret)); ret = OB_SUCCESS; } else { ret = OB_ERR_TABLE_EXIST; LOG_USER_ERROR(OB_ERR_TABLE_EXIST, arg.new_table_name_.length(), arg.new_table_name_.ptr()); LOG_WARN("table is exist, cannot create it twice", K(arg), K(ret)); } } } } return ret; } /** * recyclebin related */ int ObRootService::flashback_table_from_recyclebin(const ObFlashBackTableFromRecyclebinArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.flashback_table_from_recyclebin(arg))) { LOG_WARN("failed to flash back table", K(ret)); } return ret; } int ObRootService::flashback_table_to_time_point(const obrpc::ObFlashBackTableToScnArg &arg) { int ret = OB_SUCCESS; LOG_INFO("receive flashback table arg", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } else if (OB_FAIL(ddl_service_.flashback_table_to_time_point(arg))) { LOG_WARN("failed to flash back table", K(ret)); } return ret; } int ObRootService::purge_table(const ObPurgeTableArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.purge_table(arg))) { LOG_WARN("failed to purge table", K(ret)); } return ret; } int ObRootService::flashback_database(const ObFlashBackDatabaseArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.flashback_database(arg))) { LOG_WARN("failed to flash back database", K(ret)); } return ret; } int ObRootService::purge_database(const ObPurgeDatabaseArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.purge_database(arg))) { LOG_WARN("failed to purge database", K(ret)); } return ret; } int ObRootService::purge_expire_recycle_objects(const ObPurgeRecycleBinArg &arg, Int64 &affected_rows) { int ret = OB_SUCCESS; int64_t purged_objects = 0; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.purge_tenant_expire_recycle_objects(arg, purged_objects))) { LOG_WARN("failed to purge expire recyclebin objects", K(ret), K(arg)); } else { affected_rows = purged_objects; } return ret; } int ObRootService::optimize_table(const ObOptimizeTableArg &arg) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; LOG_INFO("receive optimize table request", K(arg)); lib::Worker::CompatMode mode; if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(arg)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("error unexpected, schema service must not be NULL", K(ret)); } else if (OB_FAIL(ObCompatModeGetter::get_tenant_mode(arg.tenant_id_, mode))) { LOG_WARN("fail to get tenant mode", K(ret)); } else { const int64_t all_core_table_id = OB_ALL_CORE_TABLE_TID; for (int64_t i = 0; OB_SUCC(ret) && i < arg.tables_.count(); ++i) { SMART_VAR(obrpc::ObAlterTableArg, alter_table_arg) { ObSqlString sql; const obrpc::ObTableItem &table_item = arg.tables_.at(i); const ObTableSchema *table_schema = nullptr; alter_table_arg.is_alter_options_ = true; alter_table_arg.alter_table_schema_.set_origin_database_name(table_item.database_name_); alter_table_arg.alter_table_schema_.set_origin_table_name(table_item.table_name_); alter_table_arg.alter_table_schema_.set_tenant_id(arg.tenant_id_); alter_table_arg.skip_sys_table_check_ = true; //exec_tenant_id_ is used in standby cluster alter_table_arg.exec_tenant_id_ = arg.exec_tenant_id_; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(arg.tenant_id_, schema_guard))) { LOG_WARN("fail to get tenant schema guard", K(ret)); } else if (OB_FAIL(schema_guard.get_table_schema(arg.tenant_id_, table_item.database_name_, table_item.table_name_, false/*is index*/, table_schema))) { LOG_WARN("fail to get table schema", K(ret)); } else if (nullptr == table_schema) { // skip deleted table } else if (all_core_table_id == table_schema->get_table_id()) { // do nothing } else { if (lib::Worker::CompatMode::MYSQL == mode) { if (OB_FAIL(sql.append_fmt("OPTIMIZE TABLE `%.*s`", table_item.table_name_.length(), table_item.table_name_.ptr()))) { LOG_WARN("fail to assign sql stmt", K(ret)); } } else if (lib::Worker::CompatMode::ORACLE == mode) { if (OB_FAIL(sql.append_fmt("ALTER TABLE \"%.*s\" SHRINK SPACE", table_item.table_name_.length(), table_item.table_name_.ptr()))) { LOG_WARN("fail to append fmt", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("error unexpected, unknown mode", K(ret), K(mode)); } if (OB_SUCC(ret)) { alter_table_arg.ddl_stmt_str_ = sql.string(); obrpc::ObAlterTableRes res; if (OB_FAIL(alter_table_arg.alter_table_schema_.alter_option_bitset_.add_member(ObAlterTableArg::PROGRESSIVE_MERGE_ROUND))) { LOG_WARN("fail to add member", K(ret)); } else if (OB_FAIL(alter_table(alter_table_arg, res))) { LOG_WARN("fail to alter table", K(ret), K(alter_table_arg)); } } } } } } return ret; } int ObRootService::calc_column_checksum_repsonse(const obrpc::ObCalcColumnChecksumResponseArg &arg) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not inited", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.on_column_checksum_calc_reply( arg.tablet_id_, ObDDLTaskKey(arg.tenant_id_, arg.target_table_id_, arg.schema_version_), arg.ret_code_))) { LOG_WARN("handle column checksum calc response failed", K(ret), K(arg)); } return ret; } int ObRootService::refresh_config() { int ret = OB_SUCCESS; int64_t local_config_version = 0; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(zone_manager_.get_config_version(local_config_version))) { LOG_WARN("get_config_version failed", K(ret)); } else { LOG_INFO("receive refresh config"); const int64_t now = ObTimeUtility::current_time(); const int64_t new_config_version = max(local_config_version + 1, now); if (OB_FAIL(zone_manager_.update_config_version(new_config_version))) { LOG_WARN("update_config_version failed", K(new_config_version), K(ret)); } else if (OB_FAIL(config_mgr_->got_version(new_config_version))) { LOG_WARN("got_version failed", K(new_config_version), K(ret)); } else { LOG_INFO("root service refresh_config succeed", K(new_config_version)); } } ROOTSERVICE_EVENT_ADD("root_service", "refresh_config", K(ret)); return ret; } int ObRootService::root_minor_freeze(const ObRootMinorFreezeArg &arg) { int ret = OB_SUCCESS; LOG_INFO("receive minor freeze request", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(root_minor_freeze_.try_minor_freeze(arg))) { LOG_WARN("minor freeze failed", K(ret), K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "root_minor_freeze", K(ret), K(arg)); return ret; } int ObRootService::update_index_status(const obrpc::ObUpdateIndexStatusArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.update_index_status(arg))) { LOG_WARN("update index table status failed", K(ret), K(arg)); } return ret; } int ObRootService::init_debug_database() { const schema_create_func *creator_ptr_array[] = { core_table_schema_creators, sys_table_schema_creators, NULL}; int ret = OB_SUCCESS; HEAP_VAR(char[OB_MAX_SQL_LENGTH], sql) { if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } ObTableSchema table_schema; ObSqlString create_func_sql; ObSqlString del_sql; for (const schema_create_func **creator_ptr_ptr = creator_ptr_array; OB_SUCCESS == ret && NULL != *creator_ptr_ptr; ++creator_ptr_ptr) { for (const schema_create_func *creator_ptr = *creator_ptr_ptr; OB_SUCCESS == ret && NULL != *creator_ptr; ++creator_ptr) { table_schema.reset(); create_func_sql.reset(); del_sql.reset(); if (OB_FAIL((*creator_ptr)(table_schema))) { LOG_WARN("create table schema failed", K(ret)); ret = OB_SCHEMA_ERROR; } else { int64_t affected_rows = 0; // ignore create function result int temp_ret = OB_SUCCESS; if (OB_SUCCESS != (temp_ret = create_func_sql.assign( "create function time_to_usec(t timestamp) " "returns bigint(20) deterministic begin return unix_timestamp(t); end;"))) { LOG_WARN("create_func_sql assign failed", K(temp_ret)); } else if (OB_SUCCESS != (temp_ret = sql_proxy_.write( create_func_sql.ptr(), affected_rows))) { LOG_WARN("execute sql failed", K(create_func_sql), K(temp_ret)); } else if (OB_SUCCESS != (temp_ret = create_func_sql.assign( "create function usec_to_time(u bigint(20)) " "returns timestamp deterministic begin return from_unixtime(u); end;"))) { LOG_WARN("create_func_sql assign failed", K(temp_ret)); } else if (OB_SUCCESS != (temp_ret = sql_proxy_.write( create_func_sql.ptr(), affected_rows))) { LOG_WARN("execute sql failed", K(create_func_sql), K(temp_ret)); } memset(sql, 0, sizeof(sql)); if (OB_FAIL(del_sql.assign_fmt( "DROP table IF EXISTS %s", table_schema.get_table_name()))) { LOG_WARN("assign sql failed", K(ret)); } else if (OB_FAIL(sql_proxy_.write(del_sql.ptr(), affected_rows))) { LOG_WARN("execute sql failed", K(ret)); } else if (OB_FAIL(ObSchema2DDLSql::convert( table_schema, sql, sizeof(sql)))) { LOG_WARN("convert table schema to create table sql failed", K(ret)); } else if (OB_FAIL(sql_proxy_.write(sql, affected_rows))) { LOG_WARN("execute sql failed", K(ret), K(sql)); } } } } LOG_INFO("init debug database finish.", K(ret)); } return ret; } int ObRootService::do_restart() { int ret = OB_SUCCESS; const int64_t tenant_id = OB_SYS_TENANT_ID; SpinWLockGuard rs_list_guard(broadcast_rs_list_lock_); // NOTE: following log print after lock FLOG_INFO("[ROOTSERVICE_NOTICE] start do_restart"); if (!inited_) { ret = OB_NOT_INIT; FLOG_WARN("not init", KR(ret)); } else if (!ObRootServiceRoleChecker::is_rootserver()) { ret = OB_NOT_MASTER; FLOG_WARN("not master", KR(ret)); } // renew master rootservice, ignore error if (OB_SUCC(ret)) { int tmp_ret = rs_mgr_->renew_master_rootserver(); if (OB_SUCCESS != tmp_ret) { FLOG_WARN("renew master rootservice failed", KR(tmp_ret)); } } //fetch root partition info if (FAILEDx(fetch_sys_tenant_ls_info())) { FLOG_WARN("fetch root partition info failed", KR(ret)); } else { FLOG_INFO("fetch root partition info succeed", KR(ret)); } // broadcast root server address, ignore error if (OB_SUCC(ret)) { int tmp_ret = update_rslist(); if (OB_SUCCESS != tmp_ret) { FLOG_WARN("failed to update rslist but ignored", KR(tmp_ret)); } } if (OB_SUCC(ret)) { //standby cluster trigger load_refresh_schema_status by heartbeat. //due to switchover, primary cluster need to load schema_status too. ObSchemaStatusProxy *schema_status_proxy = GCTX.schema_status_proxy_; if (OB_ISNULL(schema_status_proxy)) { ret = OB_ERR_UNEXPECTED; FLOG_WARN("schema_status_proxy is null", KR(ret)); } else if (OB_FAIL(schema_status_proxy->load_refresh_schema_status())) { FLOG_WARN("fail to load refresh schema status", KR(ret)); } else { FLOG_INFO("load schema status success"); } } bool load_frozen_status = true; const bool refresh_server_need_retry = false; // no need retry // try fast recover if (OB_SUCC(ret)) { int tmp_ret = refresh_server(load_frozen_status, refresh_server_need_retry); if (OB_SUCCESS != tmp_ret) { FLOG_WARN("refresh server failed", KR(tmp_ret), K(load_frozen_status)); } tmp_ret = refresh_schema(load_frozen_status); if (OB_SUCCESS != tmp_ret) { FLOG_WARN("refresh schema failed", KR(tmp_ret), K(load_frozen_status)); } } load_frozen_status = false; // refresh schema if (FAILEDx(refresh_schema(load_frozen_status))) { FLOG_WARN("refresh schema failed", KR(ret), K(load_frozen_status)); } else { FLOG_INFO("success to refresh schema", K(load_frozen_status)); } // refresh server manager if (FAILEDx(refresh_server(load_frozen_status, refresh_server_need_retry))) { FLOG_WARN("refresh server failed", KR(ret), K(load_frozen_status)); } else { FLOG_INFO("success to refresh server", K(load_frozen_status)); } // add other reload logic here if (FAILEDx(zone_manager_.reload())) { FLOG_WARN("zone_manager_ reload failed", KR(ret)); } else { FLOG_INFO("success to reload zone_manager_"); } // start timer tasks if (FAILEDx(start_timer_tasks())) { FLOG_WARN("start timer tasks failed", KR(ret)); } else { FLOG_INFO("success to start timer tasks"); } DEBUG_SYNC(BEFORE_UNIT_MANAGER_LOAD); if (FAILEDx(unit_manager_.load())) { FLOG_WARN("unit_manager_ load failed", KR(ret)); } else { FLOG_INFO("load unit_manager success"); } /* * FIXME: wanhong.wwh: need re-implement if (OB_SUCC(ret)) { if (OB_FAIL(set_core_table_unit_id())) { LOG_WARN("START_SERVICE: set core table partition unit failed", K(ret)); } else { ObTaskController::get().allow_next_syslog(); LOG_INFO("START_SERVICE: set core table unit id success"); } } */ if (FAILEDx(schema_history_recycler_.start())) { FLOG_WARN("schema_history_recycler start failed", KR(ret)); } else { FLOG_INFO("success to start schema_history_recycler"); } if (FAILEDx(root_balancer_.start())) { FLOG_WARN("root balancer start failed", KR(ret)); } else { FLOG_INFO("success to start root balancer"); } if (FAILEDx(thread_checker_.start())) { FLOG_WARN("rs_monitor_check: start thread checker failed", KR(ret)); } else { FLOG_INFO("success to start thread checker"); } if (FAILEDx(empty_server_checker_.start())) { FLOG_WARN("start empty server checker failed", KR(ret)); } else { FLOG_INFO("success to start empty server checker"); } if (FAILEDx(lost_replica_checker_.start())) { FLOG_WARN("start lost replica checker failed", KR(ret)); } else { FLOG_INFO("start lost replica checker success"); } // broadcast root server address again, this task must be in the end part of do_restart, // because system may work properly without it. if (FAILEDx(update_rslist())) { FLOG_WARN("broadcast root address failed but ignored", KR(ret)); // it's ok ret be overwritten, update_rslist_task will retry until succeed if (OB_FAIL(submit_update_rslist_task(true))) { FLOG_WARN("submit_update_rslist_task failed", KR(ret)); } else { FLOG_INFO("submit_update_rslist_task succeed"); } } else { FLOG_INFO("broadcast root address succeed"); } if (FAILEDx(report_single_replica(tenant_id, SYS_LS))) { FLOG_WARN("report all_core_table replica failed, but ignore", KR(ret), K(tenant_id), K(SYS_LS)); // it's ok ret be overwritten, report single all_core will retry until succeed if (OB_FAIL(submit_report_core_table_replica_task())) { FLOG_WARN("submit all core table replica task failed", KR(ret)); } else { FLOG_INFO("submit all core table replica task succeed"); } } else { FLOG_INFO("report all_core_table replica finish"); } if (FAILEDx(ddl_scheduler_.start())) { FLOG_WARN("fail to start ddl task scheduler", KR(ret)); } else { FLOG_INFO("success to start ddl task scheduler"); } if (FAILEDx(dbms_job::ObDBMSJobMaster::get_instance().start())) { FLOG_WARN("failed to start dbms job master", KR(ret)); } else { FLOG_INFO("success to start dbms job master"); } if (FAILEDx(dbms_scheduler::ObDBMSSchedJobMaster::get_instance().start())) { FLOG_WARN("failed to start dbms sched job master", KR(ret)); } else { FLOG_INFO("success to start dbms sched job mstart"); } if (OB_SUCC(ret)) { upgrade_executor_.start(); FLOG_INFO("success to start upgrade_executor_", KR(ret)); upgrade_storage_format_executor_.start(); FLOG_INFO("success to start upgrade_storage_format_executor_", KR(ret)); create_inner_schema_executor_.start(); FLOG_INFO("success to start create_inner_schema_executor_", KR(ret)); } // to avoid increase rootservice_epoch while fail to restart RS, // put it and the end of restart RS. if (FAILEDx(init_sequence_id())) { FLOG_WARN("fail to init sequence id", KR(ret)); } else { FLOG_INFO("success to init sequenxe id"); } if (FAILEDx(disaster_recovery_task_mgr_.start())) { FLOG_WARN("disaster recovery task manager start failed", KR(ret)); } else { FLOG_INFO("success to start disaster recovery task manager"); } if (FAILEDx(rs_status_.set_rs_status(status::FULL_SERVICE))) { FLOG_WARN("fail to set rs status", KR(ret)); } else { FLOG_INFO("full_service !!! start to work!!"); ROOTSERVICE_EVENT_ADD("root_service", "full_rootservice", "result", ret, K_(self_addr)); root_balancer_.set_active(); root_minor_freeze_.start(); FLOG_INFO("root_minor_freeze_ started"); root_inspection_.start(); FLOG_INFO("root_inspection_ started"); int64_t now = ObTimeUtility::current_time(); core_meta_table_version_ = now; EVENT_SET(RS_START_SERVICE_TIME, now); // reset fail count for self checker and print log. reset_fail_count(); } if (OB_FAIL(ret)) { update_fail_count(ret); } FLOG_INFO("[ROOTSERVICE_NOTICE] finish do_restart", KR(ret)); return ret; } bool ObRootService::in_service() const { return rs_status_.in_service(); } bool ObRootService::is_full_service() const { return rs_status_.is_full_service(); } bool ObRootService::is_start() const { return rs_status_.is_start(); } bool ObRootService::is_stopping() const { return rs_status_.is_stopping(); } bool ObRootService::is_need_stop() const { return rs_status_.is_need_stop(); } bool ObRootService::can_start_service() const { return rs_status_.can_start_service(); } int ObRootService::set_rs_status(const status::ObRootServiceStatus status) { return rs_status_.set_rs_status(status); } bool ObRootService::need_do_restart() const { return rs_status_.need_do_restart(); } int ObRootService::revoke_rs() { return rs_status_.revoke_rs(); } int ObRootService::check_parallel_ddl_conflict( share::schema::ObSchemaGetterGuard &schema_guard, const obrpc::ObDDLArg &arg) { int ret = OB_SUCCESS; int64_t schema_version = OB_INVALID_VERSION; if (arg.is_need_check_based_schema_objects()) { for (int64_t i = 0; OB_SUCC(ret) && (i < arg.based_schema_object_infos_.count()); ++i) { const ObBasedSchemaObjectInfo &info = arg.based_schema_object_infos_.at(i); if (OB_FAIL(schema_guard.get_schema_version(info.schema_type_, arg.exec_tenant_id_, info.schema_id_, schema_version))) { LOG_WARN("failed to get_schema_version", K(ret), K(arg.exec_tenant_id_), K(info)); } else if (OB_INVALID_VERSION == schema_version) { ret = OB_ERR_PARALLEL_DDL_CONFLICT; LOG_WARN("schema_version is OB_INVALID_VERSION", K(ret), K(info)); } else if (schema_version != info.schema_version_) { ret = OB_ERR_PARALLEL_DDL_CONFLICT; LOG_WARN("schema_version is not equal to info.schema_version_", K(ret), K(schema_version), K(info)); } } } return ret; } int ObRootService::init_sequence_id() { int ret = OB_SUCCESS; ObMySQLTransaction trans; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", K(ret), K(schema_service_)); } else if (OB_FAIL(trans.start(&sql_proxy_, OB_SYS_TENANT_ID))) { LOG_WARN("trans start failed", K(ret)); } else { ObGlobalStatProxy proxy(trans, OB_SYS_TENANT_ID); ObSchemaService *schema_service = schema_service_->get_schema_service(); int64_t rootservice_epoch = 0; int64_t schema_version = OB_INVALID_VERSION; ObRefreshSchemaInfo schema_info; //increase sequence_id can trigger every observer refresh schema while restart RS if (OB_FAIL(proxy.inc_rootservice_epoch())) { LOG_WARN("fail to increase rootservice_epoch", K(ret)); } else if (OB_FAIL(proxy.get_rootservice_epoch(rootservice_epoch))) { LOG_WARN("fail to get rootservice start times", K(ret), K(rootservice_epoch)); } else if (rootservice_epoch <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid rootservice_epoch", K(ret), K(rootservice_epoch)); } else if (OB_FAIL(schema_service->init_sequence_id(rootservice_epoch))) { LOG_WARN("init sequence id failed", K(ret), K(rootservice_epoch)); } else if (OB_FAIL(schema_service_->get_tenant_refreshed_schema_version(OB_SYS_TENANT_ID, schema_version))) { LOG_WARN("fail to get sys tenant refreshed schema version", K(ret)); } else if (schema_version <= OB_CORE_SCHEMA_VERSION + 1) { // in bootstrap and new schema mode, to avoid write failure while schema_version change, // only actively refresh schema at the end of bootstrap, and make heartbeat'srefresh_schema_info effective. } else if (OB_FAIL(schema_service->set_refresh_schema_info(schema_info))) { LOG_WARN("fail to set refresh schema info", K(ret), K(schema_info)); } int temp_ret = OB_SUCCESS; if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCCESS == ret))) { LOG_WARN("trans end failed", "commit", OB_SUCCESS == ret, K(temp_ret)); ret = (OB_SUCCESS == ret) ? temp_ret : ret; } } return ret; } int ObRootService::load_server_manager() { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(server_manager_.load_server_manager())) { LOG_WARN("fail to load server manager", K(ret)); } else {} // no more to do return ret; } int ObRootService::start_timer_tasks() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } if (OB_SUCCESS == ret && !task_queue_.exist_timer_task(event_table_clear_task_)) { const int64_t delay = ObEventHistoryTableOperator::EVENT_TABLE_CLEAR_INTERVAL; if (OB_FAIL(task_queue_.add_repeat_timer_task_schedule_immediately(event_table_clear_task_, delay))) { LOG_WARN("start event table clear task failed", K(delay), K(ret)); } else { LOG_INFO("added event_table_clear_task"); } } if (OB_SUCC(ret) && !task_queue_.exist_timer_task(update_rs_list_timer_task_)) { if (OB_FAIL(schedule_update_rs_list_task())) { LOG_WARN("failed to schedule update rs list task", K(ret)); } else { LOG_INFO("add update rs list timer task"); } } if (OB_SUCC(ret) && !task_queue_.exist_timer_task(update_all_server_config_task_)) { if (OB_FAIL(schedule_update_all_server_config_task())) { LOG_WARN("fail to schedule update_all_server_config_task", KR(ret)); } else { LOG_INFO("add update_all_server_config_task"); } } if (OB_SUCC(ret)) { if (OB_FAIL(schedule_inspector_task())) { LOG_WARN("start inspector fail", K(ret)); } else { LOG_INFO("start inspector success"); } } if (OB_SUCC(ret) && !task_queue_.exist_timer_task(check_server_task_)) { if (OB_FAIL(schedule_check_server_timer_task())) { LOG_WARN("start all server checker fail", K(ret)); } else { LOG_INFO("start all server checker success"); } } if (OB_SUCC(ret)) { if (OB_FAIL(schedule_load_ddl_task())) { LOG_WARN("schedule load ddl task failed", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(schedule_refresh_io_calibration_task())) { LOG_WARN("schedule refresh io calibration task failed", K(ret)); } } LOG_INFO("start all timer tasks finish", K(ret)); return ret; } int ObRootService::stop_timer_tasks() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { task_queue_.cancel_timer_task(restart_task_); task_queue_.cancel_timer_task(check_server_task_); task_queue_.cancel_timer_task(event_table_clear_task_); task_queue_.cancel_timer_task(self_check_task_); task_queue_.cancel_timer_task(update_rs_list_timer_task_); task_queue_.cancel_timer_task(update_all_server_config_task_); inspect_task_queue_.cancel_timer_task(inspector_task_); inspect_task_queue_.cancel_timer_task(purge_recyclebin_task_); } //stop other timer tasks here LOG_INFO("stop all timer tasks finish", K(ret)); return ret; } int ObRootService::fetch_sys_tenant_ls_info() { int ret = OB_SUCCESS; ObLSReplica replica; ObRole role = FOLLOWER; bool inner_table_only = false; ObMemberList member_list; // TODO: automatically decide to use rpc or inmemory ObLSTable* inmemory_ls; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_ISNULL(GCTX.ob_service_) || OB_ISNULL(GCTX.lst_operator_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ob_service is null", KR(ret)); } else { inmemory_ls = GCTX.lst_operator_->get_inmemory_ls(); if (OB_ISNULL(inmemory_ls)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("inmemory ls_table is null", KR(ret), KP(inmemory_ls)); } else if (OB_FAIL(inmemory_ls->get_role( OB_SYS_TENANT_ID, SYS_LS, role))) { LOG_WARN("get role from ObLS failed", KR(ret)); } else if (OB_FAIL(inmemory_ls->get_member_list( OB_SYS_TENANT_ID, SYS_LS, member_list))) { LOG_WARN("get sys_tenant ls member list failed", KR(ret)); } else if (!is_strong_leader(role)) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("local role should be leader now", KR(ret), K(role)); } else if (OB_FAIL(GCTX.ob_service_->fill_ls_replica( OB_SYS_TENANT_ID, SYS_LS, replica))) { LOG_WARN("fail to fill log stream replica", KR(ret), K(replica)); } else if (OB_FAIL(inmemory_ls->update(replica, inner_table_only))) { LOG_WARN("fail to update ls replica", KR(ret), K(replica)); } } for (int64_t i = 0; OB_SUCC(ret) && i < member_list.get_member_number(); i++) { ObAddr addr; if (OB_FAIL(member_list.get_server_by_index(i, addr))) { LOG_WARN("fail to get server", KR(ret), K(i), K(member_list)); } else if (self_addr_ == addr){ continue; } else { replica.reset(); int temp_ret = OB_SUCCESS; if (OB_SUCCESS != (temp_ret = rpc_proxy_.to(addr).timeout(config_->rpc_timeout) .by(OB_SYS_TENANT_ID).fetch_sys_ls(replica))) { LOG_WARN("fetch sys_ls failed", K(temp_ret), "server", addr); } else if (replica.is_strong_leader()) { ret = OB_ENTRY_EXIST; LOG_WARN("role should be follower", KR(ret), K(replica)); } else if (OB_FAIL(inmemory_ls->update(replica, inner_table_only))) { LOG_WARN("update sys_ls info failed", KR(ret), K(replica)); } else { LOG_INFO("update sys_tenant ls replica succeed", K(replica), "server", addr); } } } return ret; } int ObRootService::not_implement() { int ret = OB_NOT_IMPLEMENT; bt("not implement"); LOG_WARN("rpc not implemented", K(ret)); return ret; } ObRootService::ObRestartTask::ObRestartTask(ObRootService &root_service) :ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(0); // don't retry when failed } ObRootService::ObRestartTask::~ObRestartTask() { } int ObRootService::ObRestartTask::process() { int ret = OB_SUCCESS; FLOG_INFO("after_restart task begin to process"); if (OB_FAIL(root_service_.after_restart())) { LOG_WARN("root service after restart failed", K(ret)); } FLOG_INFO("after_restart task process finish", KR(ret)); return ret; } ObAsyncTask *ObRootService::ObRestartTask::deep_copy(char *buf, const int64_t buf_size) const { ObRestartTask *task = NULL; if (NULL == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size)); } else { task = new(buf) ObRestartTask(root_service_); } return task; } ObRootService::ObRefreshServerTask::ObRefreshServerTask(ObRootService &root_service) :ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(0); // don't retry when process failed } int ObRootService::ObRefreshServerTask::process() { int ret = OB_SUCCESS; const bool load_frozen_status = true; const bool need_retry = true; FLOG_INFO("refresh server task process"); ObLatchRGuard guard(root_service_.bootstrap_lock_, ObLatchIds::RS_BOOTSTRAP_LOCK); if (OB_FAIL(root_service_.refresh_server(load_frozen_status, need_retry))) { FLOG_WARN("refresh server failed", K(ret), K(load_frozen_status)); } else {} return ret; } ObAsyncTask *ObRootService::ObRefreshServerTask::deep_copy(char *buf, const int64_t buf_size) const { ObRefreshServerTask *task = NULL; if (NULL == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size)); } else { task = new(buf) ObRefreshServerTask(root_service_); } return task; } //-----Functions for managing privileges------ int ObRootService::create_user(obrpc::ObCreateUserArg &arg, common::ObSArray &failed_index) { int ret = OB_SUCCESS; failed_index.reset(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.create_user(arg, failed_index))){ LOG_WARN("create user failed", K(ret), K(arg)); } return ret; } int ObRootService::drop_user(const ObDropUserArg &arg, common::ObSArray &failed_index) { int ret = OB_SUCCESS; failed_index.reset(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.drop_user(arg, failed_index))) { LOG_WARN("drop user failed", K(ret), K(arg)); } return ret; } int ObRootService::rename_user(const obrpc::ObRenameUserArg &arg, common::ObSArray &failed_index) { int ret = OB_SUCCESS; failed_index.reset(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.rename_user(arg, failed_index))){ LOG_WARN("rename user failed", K(arg), K(ret)); } return ret; } int ObRootService::alter_role(const obrpc::ObAlterRoleArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if(!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.alter_role(arg))) { LOG_WARN("alter role failed", K(arg), K(ret)); } return ret; } int ObRootService::set_passwd(const obrpc::ObSetPasswdArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.set_passwd(arg))){ LOG_WARN("set passwd failed", K(arg), K(ret)); } return ret; } int ObRootService::grant(const ObGrantArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { if (OB_FAIL(ddl_service_.grant(arg))) { LOG_WARN("Grant user failed", K(arg), K(ret)); } } return ret; } int ObRootService::revoke_user(const ObRevokeUserArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.revoke(arg))) { LOG_WARN("revoke privilege failed", K(ret), K(arg)); } return ret; } int ObRootService::lock_user(const ObLockUserArg &arg, ObSArray &failed_index) { int ret = OB_SUCCESS; failed_index.reset(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.lock_user(arg, failed_index))){ LOG_WARN("lock user failed", K(arg), K(ret)); } return ret; } int ObRootService::alter_user_profile(const ObAlterUserProfileArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.alter_user_profile(arg))){ LOG_WARN("lock user failed", K(arg), K(ret)); } return ret; } int ObRootService::create_directory(const obrpc::ObCreateDirectoryArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.create_directory(arg, &arg.ddl_stmt_str_))) { LOG_WARN("create directory failed", K(arg.schema_), K(ret)); } return ret; } int ObRootService::drop_directory(const obrpc::ObDropDirectoryArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.drop_directory(arg, &arg.ddl_stmt_str_))) { LOG_WARN("drop directory failed", K(arg.directory_name_), K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // row level security //////////////////////////////////////////////////////////////// int ObRootService::handle_rls_policy_ddl(const obrpc::ObRlsPolicyDDLArg &arg) { int ret = OB_SUCCESS; uint64_t data_version = 0; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(GET_MIN_DATA_VERSION(arg.exec_tenant_id_, data_version))) { LOG_WARN("failed to get min data version", K(ret)); } else if (data_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "dbms_rls"); } else if (OB_FAIL(ddl_service_.handle_rls_policy_ddl(arg))) { LOG_WARN("do rls policy ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::handle_rls_group_ddl(const obrpc::ObRlsGroupDDLArg &arg) { int ret = OB_SUCCESS; uint64_t data_version = 0; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(GET_MIN_DATA_VERSION(arg.exec_tenant_id_, data_version))) { LOG_WARN("failed to get min data version", K(ret)); } else if (data_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "dbms_rls"); } else if (OB_FAIL(ddl_service_.handle_rls_group_ddl(arg))) { LOG_WARN("do rls group ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::handle_rls_context_ddl(const obrpc::ObRlsContextDDLArg &arg) { int ret = OB_SUCCESS; uint64_t data_version = 0; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(GET_MIN_DATA_VERSION(arg.exec_tenant_id_, data_version))) { LOG_WARN("failed to get min data version", K(ret)); } else if (data_version < DATA_VERSION_4_1_0_0) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "dbms_rls"); } else if (OB_FAIL(ddl_service_.handle_rls_context_ddl(arg))) { LOG_WARN("do rls context ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::revoke_database(const ObRevokeDBArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObOriginalDBKey db_key(arg.tenant_id_, arg.user_id_, arg.db_); if (OB_FAIL(ddl_service_.revoke_database(db_key, arg.priv_set_))) { LOG_WARN("Revoke db failed", K(arg), K(ret)); } } return ret; } int ObRootService::revoke_table(const ObRevokeTableArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObTablePrivSortKey table_priv_key(arg.tenant_id_, arg.user_id_, arg.db_, arg.table_); ObObjPrivSortKey obj_priv_key(arg.tenant_id_, arg.obj_id_, arg.obj_type_, OBJ_LEVEL_FOR_TAB_PRIV, arg.grantor_id_, arg.user_id_); OZ (ddl_service_.revoke_table(table_priv_key, arg.priv_set_, obj_priv_key, arg.obj_priv_array_, arg.revoke_all_ora_)); } return ret; } int ObRootService::revoke_syspriv(const ObRevokeSysPrivArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.revoke_syspriv(arg.tenant_id_, arg.grantee_id_, arg.sys_priv_array_, arg.role_ids_, &arg.ddl_stmt_str_))) { LOG_WARN("revoke privilege failed", K(ret), K(arg)); } return ret; } //-----End of functions for managing privileges----- //-----Functions for managing outlines----- int ObRootService::create_outline(const ObCreateOutlineArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObOutlineInfo outline_info = arg.outline_info_; const bool is_or_replace = arg.or_replace_; uint64_t tenant_id = outline_info.get_tenant_id(); ObString database_name = arg.db_name_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (database_name == OB_OUTLINE_DEFAULT_DATABASE_NAME) { // if not specify database, set default database name and database id; outline_info.set_database_id(OB_OUTLINE_DEFAULT_DATABASE_ID); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, database_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create outline of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } else { outline_info.set_database_id(db_schema->get_database_id()); } bool is_update = false; if (OB_SUCC(ret)) { if (OB_FAIL(ddl_service_.check_outline_exist(outline_info, is_or_replace, is_update))) { LOG_WARN("failed to check_outline_exist", K(outline_info), K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(ddl_service_.create_outline(outline_info, is_update, &arg.ddl_stmt_str_, schema_guard))) { LOG_WARN("create_outline failed", K(outline_info), K(is_update), K(ret)); } } } return ret; } int ObRootService::create_user_defined_function(const obrpc::ObCreateUserDefinedFunctionArg &arg) { int ret = OB_SUCCESS; bool exist = false; uint64_t udf_id = OB_INVALID_ID; ObUDF udf_info_ = arg.udf_; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.check_udf_exist(arg.udf_.get_tenant_id(), arg.udf_.get_name_str(), exist, udf_id))) { LOG_WARN("failed to check_udf_exist", K(arg.udf_.get_tenant_id()), K(arg.udf_.get_name_str()), K(exist), K(ret)); } else if (exist) { ret = OB_UDF_EXISTS; LOG_USER_ERROR(OB_UDF_EXISTS, arg.udf_.get_name_str().length(), arg.udf_.get_name_str().ptr()); } else if (OB_FAIL(ddl_service_.create_user_defined_function(udf_info_, arg.ddl_stmt_str_))) { LOG_WARN("failed to create udf", K(arg), K(ret)); } else {/*do nothing*/} return ret; } int ObRootService::drop_user_defined_function(const obrpc::ObDropUserDefinedFunctionArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.drop_user_defined_function(arg))) { LOG_WARN("failed to alter udf", K(arg), K(ret)); } else {/*do nothing*/} return ret; } bool ObRootService::is_sys_tenant(const ObString &tenant_name) { return (0 == tenant_name.case_compare(OB_SYS_TENANT_NAME) || 0 == tenant_name.case_compare(OB_DIAG_TENANT_NAME) || 0 == tenant_name.case_compare(OB_GTS_TENANT_NAME)); } int ObRootService::alter_outline(const ObAlterOutlineArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.alter_outline(arg))) { LOG_WARN("failed to alter outline", K(arg), K(ret)); } else {/*do nothing*/} return ret; } int ObRootService::drop_outline(const obrpc::ObDropOutlineArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { if (OB_FAIL(ddl_service_.drop_outline(arg))) { LOG_WARN("ddl service failed to drop outline", K(arg), K(ret)); } } return ret; } //-----End of functions for managing outlines----- int ObRootService::create_routine(const ObCreateRoutineArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObRoutineInfo routine_info = arg.routine_info_; const ObRoutineInfo* old_routine_info = NULL; uint64_t tenant_id = routine_info.get_tenant_id(); ObString database_name = arg.db_name_; bool is_or_replace = lib::is_oracle_mode() ? arg.is_or_replace_ : arg.is_need_alter_; bool is_inner = lib::is_mysql_mode() ? arg.is_or_replace_ : false; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; const ObUserInfo *user_info = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, database_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); } else if (!is_inner && db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create routine of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } else { routine_info.set_database_id(db_schema->get_database_id()); } if (OB_SUCC(ret) && database_name.case_compare(OB_SYS_DATABASE_NAME) != 0 && lib::is_oracle_mode()) { if (OB_FAIL(schema_guard.get_user_info( tenant_id, database_name, ObString(OB_DEFAULT_HOST_NAME), user_info))) { LOG_WARN("failed to get user info", K(ret), K(database_name)); } else if (OB_ISNULL(user_info)) { ret = OB_USER_NOT_EXIST; LOG_WARN("user is does not exist", K(ret), K(database_name)); } else if (OB_INVALID_ID == user_info->get_user_id()) { ret = OB_USER_NOT_EXIST; LOG_WARN("user id is invalid", K(ret), K(database_name)); } else { routine_info.set_owner_id(user_info->get_user_id()); } } if (OB_SUCC(ret)) { ObArray conflict_schema_types; if (OB_FAIL(schema_guard.check_oracle_object_exist(tenant_id, db_schema->get_database_id(), routine_info.get_routine_name(), ROUTINE_SCHEMA, routine_info.get_routine_type(), is_or_replace, conflict_schema_types))) { LOG_WARN("fail to check oracle_object exist", K(ret), K(routine_info.get_routine_name())); } else if (conflict_schema_types.count() > 0) { // 这里检查 oracle 模式下新对象的名字是否已经被其他对象占用了 ret = OB_ERR_EXIST_OBJECT; LOG_WARN("Name is already used by an existing object in oralce mode", K(ret), K(routine_info.get_routine_name()), K(conflict_schema_types)); } } bool exist = false; if (OB_SUCC(ret)) { if (routine_info.get_routine_type() == ROUTINE_PROCEDURE_TYPE) { if (OB_FAIL(schema_guard.check_standalone_procedure_exist(tenant_id, db_schema->get_database_id(), routine_info.get_routine_name(), exist))) { LOG_WARN("failed to check procedure info exist", K(routine_info), K(ret)); } else if (exist && !is_or_replace) { ret = OB_ERR_SP_ALREADY_EXISTS; LOG_USER_ERROR(OB_ERR_SP_ALREADY_EXISTS, "PROCEDURE", routine_info.get_routine_name().length(), routine_info.get_routine_name().ptr()); } else if (exist && is_or_replace) { if (OB_FAIL(schema_guard.get_standalone_procedure_info(tenant_id, db_schema->get_database_id(), routine_info.get_routine_name(), old_routine_info))) { LOG_WARN("failed to get standalone procedure info", K(routine_info), K(ret)); } else if (OB_ISNULL(old_routine_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("old routine info is NULL", K(ret)); } } } else { if (OB_FAIL(schema_guard.check_standalone_function_exist(tenant_id, db_schema->get_database_id(), routine_info.get_routine_name(), exist))) { LOG_WARN("failed to check function info exist", K(routine_info), K(ret)); } else if (exist && !is_or_replace) { ret = OB_ERR_SP_ALREADY_EXISTS; LOG_USER_ERROR(OB_ERR_SP_ALREADY_EXISTS, "FUNCTION", routine_info.get_routine_name().length(), routine_info.get_routine_name().ptr()); } else if (exist && is_or_replace) { if (OB_FAIL(schema_guard.get_standalone_function_info(tenant_id, db_schema->get_database_id(), routine_info.get_routine_name(), old_routine_info))) { LOG_WARN("failed to get standalone function info", K(routine_info), K(ret)); } else if (OB_ISNULL(old_routine_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("old routine info is NULL", K(ret)); } } } if (OB_SUCC(ret)) { ObErrorInfo error_info = arg.error_info_; ObSArray &dep_infos = const_cast &>(arg.dependency_infos_); if (OB_FAIL(ddl_service_.create_routine(routine_info, old_routine_info, (exist && is_or_replace), error_info, dep_infos, &arg.ddl_stmt_str_, schema_guard))) { LOG_WARN("failed to replace routine", K(routine_info), K(ret)); } } } } return ret; } int ObRootService::alter_routine(const ObCreateRoutineArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObErrorInfo error_info = arg.error_info_; const ObRoutineInfo *routine_info = NULL; ObSchemaGetterGuard schema_guard; const uint64_t tenant_id = arg.routine_info_.get_tenant_id(); if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table( tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_guard.get_routine_info( tenant_id, arg.routine_info_.get_routine_id(), routine_info))) { LOG_WARN("failed to get routine info", K(ret), K(tenant_id)); } else if (OB_ISNULL(routine_info)) { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_WARN("routine info is not exist!", K(ret), K(arg.routine_info_)); } if (OB_FAIL(ret)) { } else if ((lib::is_oracle_mode() && arg.is_or_replace_) || (lib::is_mysql_mode() && arg.is_need_alter_)) { if (OB_FAIL(create_routine(arg))) { LOG_WARN("failed to alter routine with create", K(ret)); } } else { if (OB_FAIL(ddl_service_.alter_routine(*routine_info, error_info, &arg.ddl_stmt_str_, schema_guard))) { LOG_WARN("alter routine failed", K(ret), K(arg.routine_info_), K(error_info)); } } } return ret; } int ObRootService::drop_routine(const ObDropRoutineArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { uint64_t tenant_id = arg.tenant_id_; const ObString &db_name = arg.db_name_; const ObString &routine_name = arg.routine_name_; ObRoutineType routine_type = arg.routine_type_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; /*! * 兼容mysql行为: * create database test; * use test; * drop database test; * drop function if exists no_such_func; -- warning 1035 * drop procedure if exists no_such_proc; -- error 1046 * drop function no_such_func; --error 1035 * drop procedure no_such_proc; --error 1046 */ if (db_name.empty()) { ret = OB_ERR_NO_DB_SELECTED; LOG_WARN("no database selected", K(ret), K(db_name)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, db_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, db_name.length(), db_name.ptr()); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create procedure of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } if (OB_SUCC(ret)) { bool exist = false; const ObRoutineInfo *routine_info = NULL; if (ROUTINE_PROCEDURE_TYPE == routine_type) { if (OB_FAIL(schema_guard.check_standalone_procedure_exist(tenant_id, db_schema->get_database_id(), routine_name, exist))) { LOG_WARN("failed to check standalone procedure info exist", K(routine_name), K(ret)); } else if (exist) { if (OB_FAIL(schema_guard.get_standalone_procedure_info(tenant_id, db_schema->get_database_id(), routine_name, routine_info))) { LOG_WARN("get procedure info failed", K(ret)); } } else if (!arg.if_exist_) { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_USER_ERROR(OB_ERR_SP_DOES_NOT_EXIST, "PROCEDURE", db_name.length(), db_name.ptr(), routine_name.length(), routine_name.ptr()); } } else { if (OB_FAIL(schema_guard.check_standalone_function_exist(tenant_id, db_schema->get_database_id(), routine_name, exist))) { LOG_WARN("failed to check standalone function info exist", K(routine_name), K(ret)); } else if (exist) { if (OB_FAIL(schema_guard.get_standalone_function_info(tenant_id, db_schema->get_database_id(), routine_name, routine_info))) { LOG_WARN("get function info failed", K(ret)); } } else if (!arg.if_exist_) { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_USER_ERROR(OB_ERR_SP_DOES_NOT_EXIST, "FUNCTION", db_name.length(), db_name.ptr(), routine_name.length(), routine_name.ptr()); } } if (OB_SUCC(ret) && !OB_ISNULL(routine_info)) { ObErrorInfo error_info = arg.error_info_; if (OB_FAIL(ddl_service_.drop_routine(*routine_info, error_info, &arg.ddl_stmt_str_, schema_guard))) { LOG_WARN("drop routine failed", K(ret), K(routine_name), K(routine_info)); } } } if (OB_ERR_NO_DB_SELECTED == ret && ROUTINE_FUNCTION_TYPE == routine_type) { if (arg.if_exist_) { ret = OB_SUCCESS; LOG_USER_WARN(OB_ERR_SP_DOES_NOT_EXIST, "FUNCTION (UDF)", db_name.length(), db_name.ptr(), routine_name.length(), routine_name.ptr()); } else { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_USER_ERROR(OB_ERR_SP_DOES_NOT_EXIST, "FUNCTION (UDF)", db_name.length(), db_name.ptr(), routine_name.length(), routine_name.ptr()); LOG_WARN("FUNCTION (UDF) does not exists", K(ret), K(routine_name), K(db_name)); } } } return ret; } int ObRootService::create_udt(const ObCreateUDTArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObUDTTypeInfo udt_info = arg.udt_info_; const ObUDTTypeInfo* old_udt_info = NULL; uint64_t tenant_id = udt_info.get_tenant_id(); ObString database_name = arg.db_name_; bool is_or_replace = arg.is_or_replace_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, database_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create udt of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } else { udt_info.set_database_id(db_schema->get_database_id()); } if (OB_SUCC(ret)) { ObArray conflict_schema_types; if (OB_FAIL(schema_guard.check_oracle_object_exist(tenant_id, db_schema->get_database_id(), udt_info.get_type_name(), UDT_SCHEMA, INVALID_ROUTINE_TYPE, is_or_replace, conflict_schema_types))) { LOG_WARN("fail to check oracle_object exist", K(ret), K(udt_info.get_type_name())); } else if (1 == conflict_schema_types.count() && UDT_SCHEMA == conflict_schema_types.at(0) && udt_info.is_object_type()) { // skip } else if (conflict_schema_types.count() > 0) { ret = OB_ERR_EXIST_OBJECT; LOG_WARN("Name is already used by an existing object", K(ret), K(udt_info.get_type_name()), K(conflict_schema_types)); } } bool exist = false; ObUDTTypeCode type_code = udt_info.is_object_body_ddl() ? UDT_TYPE_OBJECT_BODY : static_cast(udt_info.get_typecode()); if (OB_SUCC(ret)) { if (OB_FAIL(schema_guard.check_udt_exist(tenant_id, db_schema->get_database_id(), OB_INVALID_ID, type_code, udt_info.get_type_name(), exist))) { LOG_WARN("failed to check udt info exist", K(udt_info), K(ret)); } else if (exist && !is_or_replace) { if (!udt_info.is_object_type()) { ret = OB_ERR_SP_ALREADY_EXISTS; LOG_USER_ERROR(OB_ERR_SP_ALREADY_EXISTS, "UDT", udt_info.get_type_name().length(), udt_info.get_type_name().ptr()); } } else { // do nothing } if (exist && OB_SUCC(ret)) { if (OB_FAIL(schema_guard.get_udt_info(tenant_id, db_schema->get_database_id(), OB_INVALID_ID, udt_info.get_type_name(), type_code, old_udt_info))) { LOG_WARN("failed to get udt info", K(udt_info), K(ret)); } else if (OB_ISNULL(old_udt_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("old udt info is NULL", K(ret)); } } if (OB_SUCC(ret) && is_inner_pl_udt_id(udt_info.get_type_id()) && type_code != UDT_TYPE_OBJECT_BODY) { if (!exist) { if (OB_FAIL(schema_guard.get_udt_info(tenant_id, udt_info.get_type_id(), old_udt_info))) { LOG_WARN("failed to get udt info", K(ret), K(tenant_id), K(udt_info.get_type_id())); } else if (OB_NOT_NULL(old_udt_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type id already used by other udt", K(ret), KPC(old_udt_info)); } } else { CK (OB_NOT_NULL(old_udt_info)); OV (old_udt_info->get_type_id() == udt_info.get_type_id(), OB_ERR_UNEXPECTED, KPC(old_udt_info), K(udt_info)); } } // 这儿检查object是否能插入,当name相同,且不是replace的时候,只有一种情况可以插入 // 新的body不为空,但是老的body为空,这说明需要增加body信息 if (OB_SUCC(ret) && exist && !is_or_replace) { ret = OB_ERR_SP_ALREADY_EXISTS; LOG_USER_ERROR(OB_ERR_SP_ALREADY_EXISTS, "UDT", udt_info.get_type_name().length(), udt_info.get_type_name().ptr()); } if (OB_SUCC(ret)) { ObErrorInfo error_info = arg.error_info_; ObSArray &public_routine_infos = const_cast &>(arg.public_routine_infos_); ObSArray &dep_infos = const_cast &>(arg.dependency_infos_); if (OB_FAIL(ddl_service_.create_udt(udt_info, old_udt_info, (exist && is_or_replace), public_routine_infos, error_info, schema_guard, dep_infos, &arg.ddl_stmt_str_))) { LOG_WARN("failed to create udt", K(udt_info), K(ret)); } } } } return ret; } int ObRootService::drop_udt(const ObDropUDTArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { uint64_t tenant_id = arg.tenant_id_; const ObString &db_name = arg.db_name_; const ObString &udt_name = arg.udt_name_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; if (db_name.empty()) { ret = OB_ERR_NO_DB_SELECTED; LOG_WARN("no database selected", K(ret), K(db_name)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, db_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, db_name.length(), db_name.ptr()); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create udt of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } if (OB_SUCC(ret)) { if (!arg.is_type_body_) { bool exist = false; const ObUDTTypeInfo *udt_info = NULL; ObUDTTypeInfo udt; const ObUDTTypeCode type_code = ObUDTTypeCode::UDT_TYPE_OBJECT; if (OB_FAIL(schema_guard.check_udt_exist(tenant_id, db_schema->get_database_id(), OB_INVALID_ID, type_code, udt_name, exist))) { LOG_WARN("failed to check udt info exist", K(udt_name), K(ret)); } else if (exist) { if (OB_FAIL(schema_guard.get_udt_info(tenant_id, db_schema->get_database_id(), OB_INVALID_ID, udt_name, type_code, udt_info))) { LOG_WARN("get udt info failed", K(ret)); } } else if (!arg.if_exist_) { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_USER_ERROR(OB_ERR_SP_DOES_NOT_EXIST, "UDT", db_name.length(), db_name.ptr(), udt_name.length(), udt_name.ptr()); } if (OB_SUCC(ret) && !OB_ISNULL(udt_info)) { if (OB_FAIL(udt.assign(*udt_info))) { LOG_WARN("assign udt info failed", K(ret), KPC(udt_info)); } else if (udt.is_object_type()) { udt.clear_property_flag(ObUDTTypeFlag::UDT_FLAG_OBJECT_TYPE_BODY); udt.set_object_ddl_type(ObUDTTypeFlag::UDT_FLAG_OBJECT_TYPE_SPEC); } if (OB_SUCC(ret) && OB_FAIL(ddl_service_.drop_udt(udt, schema_guard, &arg.ddl_stmt_str_))) { LOG_WARN("drop udt failed", K(ret), K(udt_name), K(*udt_info)); } } } else { bool exist = false; const ObUDTTypeInfo *udt_info = NULL; ObUDTTypeInfo udt; const ObUDTTypeCode type_code = ObUDTTypeCode::UDT_TYPE_OBJECT_BODY; if (OB_FAIL(schema_guard.check_udt_exist(tenant_id, db_schema->get_database_id(), OB_INVALID_ID, type_code, udt_name, exist))) { LOG_WARN("failed to check udt info exist", K(udt_name), K(ret)); } else if (exist) { if (OB_FAIL(schema_guard.get_udt_info(tenant_id, db_schema->get_database_id(), OB_INVALID_ID, udt_name, type_code, udt_info))) { LOG_WARN("get udt info failed", K(ret)); } } else if (!arg.if_exist_) { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_USER_ERROR(OB_ERR_SP_DOES_NOT_EXIST, "UDT", db_name.length(), db_name.ptr(), udt_name.length(), udt_name.ptr()); } if (OB_SUCC(ret) && exist && !OB_ISNULL(udt_info)) { if (OB_FAIL(udt.assign(*udt_info))) { LOG_WARN("assign udt info failed", K(ret), KPC(udt_info)); } else if (udt.is_object_type()) { udt.clear_property_flag(ObUDTTypeFlag::UDT_FLAG_OBJECT_TYPE_SPEC); udt.set_object_ddl_type(ObUDTTypeFlag::UDT_FLAG_OBJECT_TYPE_BODY); } if (OB_SUCC(ret) && OB_FAIL(ddl_service_.drop_udt(udt, schema_guard, &arg.ddl_stmt_str_))) { LOG_WARN("drop udt failed", K(ret), K(udt_name), K(*udt_info)); } } } } } return ret; } //----Functions for managing dblinks---- int ObRootService::create_dblink(const obrpc::ObCreateDbLinkArg &arg) { int ret = OB_SUCCESS; if (OB_FAIL(ddl_service_.create_dblink(arg, &arg.ddl_stmt_str_))) { LOG_WARN("create_dblink failed", K(arg.dblink_info_), K(ret)); } return ret; } int ObRootService::drop_dblink(const obrpc::ObDropDbLinkArg &arg) { int ret = OB_SUCCESS; if (OB_FAIL(ddl_service_.drop_dblink(arg, &arg.ddl_stmt_str_))) { LOG_WARN("drop_dblink failed", K(arg.tenant_id_), K(arg.dblink_name_), K(ret)); } return ret; } //----End of functions for managing dblinks---- //-----Functions for managing synonyms----- int ObRootService::create_synonym(const ObCreateSynonymArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSynonymInfo synonym_info = arg.synonym_info_; uint64_t tenant_id = synonym_info.get_tenant_id(); ObString database_name = arg.db_name_; ObString obj_database_name = arg.obj_db_name_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; const ObDatabaseSchema *obj_db_schema = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, database_name, db_schema))) { LOG_WARN("get database schema failed", K(database_name), K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, obj_database_name, obj_db_schema))) { LOG_WARN("get database schema failed", K(obj_database_name), K(ret)); } else if (OB_ISNULL(db_schema)) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); } else if (OB_ISNULL(obj_db_schema)) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, obj_database_name.length(), obj_database_name.ptr()); } else if (OB_UNLIKELY(db_schema->is_in_recyclebin()) || OB_UNLIKELY(obj_db_schema->is_in_recyclebin())) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("can't create synonym of db in recyclebin", K(arg), KPC(db_schema), KPC(obj_db_schema), K(ret)); } else if (OB_UNLIKELY(OB_INVALID_ID == db_schema->get_database_id()) || OB_UNLIKELY(OB_INVALID_ID == obj_db_schema->get_database_id())) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), KPC(db_schema), KPC(obj_db_schema), K(ret)); } else { synonym_info.set_database_id(db_schema->get_database_id()); synonym_info.set_object_database_id(obj_db_schema->get_database_id()); } bool is_update = false; if (OB_SUCC(ret)) { ObArray conflict_schema_types; if (OB_FAIL(schema_guard.check_oracle_object_exist(tenant_id, synonym_info.get_database_id(), synonym_info.get_synonym_name_str(), SYNONYM_SCHEMA, INVALID_ROUTINE_TYPE, arg.or_replace_, conflict_schema_types))) { LOG_WARN("fail to check oracle_object exist", K(ret), K(synonym_info)); } else if (conflict_schema_types.count() > 0) { ret = OB_ERR_EXIST_OBJECT; LOG_WARN("Name is already used by an existing object", K(ret), K(synonym_info), K(conflict_schema_types)); } } if (OB_SUCC(ret)) { // can not delete, it will update synonym_info between check_synonym_exist. if (OB_FAIL(ddl_service_.check_synonym_exist(synonym_info, arg.or_replace_, is_update))) { LOG_WARN("failed to check_synonym_exist", K(synonym_info), K(arg.or_replace_), K(is_update), K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(ddl_service_.create_synonym(synonym_info, arg.dependency_info_, &arg.ddl_stmt_str_, is_update, schema_guard))) { LOG_WARN("create_synonym failed", K(synonym_info), K(ret)); } } } return ret; } int ObRootService::drop_synonym(const obrpc::ObDropSynonymArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.drop_synonym(arg))) { LOG_WARN("ddl service failed to drop synonym", K(arg), K(ret)); } return ret; } //-----End of functions for managing synonyms----- int ObRootService::admin_sync_rewrite_rules(const obrpc::ObSyncRewriteRuleArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminSyncRewriteRules admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("dispatch sync rewrite rules failed", K(arg), K(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "admin_sync_rewrite_rules", K(ret), K(arg)); } } return ret; } int ObRootService::create_package(const obrpc::ObCreatePackageArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObPackageInfo new_package_info = arg.package_info_; const ObPackageInfo *old_package_info = NULL; uint64_t tenant_id = new_package_info.get_tenant_id(); ObString database_name = arg.db_name_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; const ObUserInfo *user_info = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, database_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create package of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } else { new_package_info.set_database_id(db_schema->get_database_id()); } if (OB_SUCC(ret) && database_name.case_compare(OB_SYS_DATABASE_NAME) != 0 && lib::is_oracle_mode()) { if (OB_FAIL(schema_guard.get_user_info( tenant_id, database_name, ObString(OB_DEFAULT_HOST_NAME), user_info))) { LOG_WARN("failed to get user info", K(ret), K(database_name)); } else if (OB_ISNULL(user_info)) { ret = OB_USER_NOT_EXIST; LOG_WARN("user is does not exist", K(ret), K(database_name)); } else if (OB_INVALID_ID == user_info->get_user_id()) { ret = OB_USER_NOT_EXIST; LOG_WARN("user id is invalid", K(ret), K(database_name)); } else { new_package_info.set_owner_id(user_info->get_user_id()); } } if (OB_SUCC(ret)) { ObArray conflict_schema_types; // package body 查重只比较有没有重复的 package body,package 查重需要比较除 package body 以外的对象 if (PACKAGE_TYPE == new_package_info.get_type() && OB_FAIL(schema_guard.check_oracle_object_exist(tenant_id, db_schema->get_database_id(), new_package_info.get_package_name(), PACKAGE_SCHEMA, INVALID_ROUTINE_TYPE, arg.is_replace_, conflict_schema_types))) { LOG_WARN("fail to check object exist", K(ret), K(new_package_info.get_package_name())); } else if (conflict_schema_types.count() > 0) { // 这里检查 oracle 模式下新对象的名字是否已经被其他对象占用了 ret = OB_ERR_EXIST_OBJECT; LOG_WARN("Name is already used by an existing object in oralce mode", K(ret), K(new_package_info.get_package_name()), K(conflict_schema_types)); } } if (OB_SUCC(ret)) { if (OB_FAIL(schema_guard.get_package_info(tenant_id, db_schema->get_database_id(), new_package_info.get_package_name(), new_package_info.get_type(), new_package_info.get_compatibility_mode(), old_package_info))) { LOG_WARN("failed to check package info exist", K(new_package_info), K(ret)); } else if (OB_ISNULL(old_package_info) || arg.is_replace_) { bool need_create = true; // 对于系统包, 为了避免多次重建, 比较下新的系统包与已经存在的系统包是否相同 if (OB_NOT_NULL(old_package_info) && OB_SYS_TENANT_ID == tenant_id) { if (old_package_info->get_source().length() == new_package_info.get_source().length() && (0 == MEMCMP(old_package_info->get_source().ptr(), new_package_info.get_source().ptr(), old_package_info->get_source().length())) && old_package_info->get_exec_env() == new_package_info.get_exec_env()) { need_create = false; LOG_INFO("do not recreate package with same source", K(ret), K(old_package_info->get_source()), K(new_package_info.get_source()), K(need_create)); } else { LOG_INFO("recreate package with diff source", K(ret), K(old_package_info->get_source()), K(new_package_info.get_source()), K(need_create)); } } if (need_create) { ObSArray &public_routine_infos = const_cast &>(arg.public_routine_infos_); ObErrorInfo error_info = arg.error_info_; ObSArray &dep_infos = const_cast &>(arg.dependency_infos_); if (OB_FAIL(ddl_service_.create_package(schema_guard, old_package_info, new_package_info, public_routine_infos, error_info, dep_infos, &arg.ddl_stmt_str_))) { LOG_WARN("create package failed", K(ret), K(new_package_info)); } } } else { ret = OB_ERR_PACKAGE_ALREADY_EXISTS; const char *type = (new_package_info.get_type() == PACKAGE_TYPE ? "PACKAGE" : "PACKAGE BODY"); LOG_USER_ERROR(OB_ERR_PACKAGE_ALREADY_EXISTS, type, database_name.length(), database_name.ptr(), new_package_info.get_package_name().length(), new_package_info.get_package_name().ptr()); } } } return ret; } int ObRootService::alter_package(const obrpc::ObAlterPackageArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { uint64_t tenant_id = arg.tenant_id_; const ObString &db_name = arg.db_name_; const ObString &package_name = arg.package_name_; ObPackageType package_type = arg.package_type_; int64_t compatible_mode = arg.compatible_mode_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, db_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(db_name), K(ret)); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create package of db in recyclebin", K(ret), K(arg), K(*db_schema)); } if (OB_SUCC(ret)) { bool exist = false; ObSArray &public_routine_infos = const_cast &>(arg.public_routine_infos_); if (OB_FAIL(schema_guard.check_package_exist(tenant_id, db_schema->get_database_id(), package_name, package_type, compatible_mode, exist))) { LOG_WARN("failed to check package info exist", K(package_name), K(ret)); } else if (exist) { const ObPackageInfo *package_info = NULL; if (OB_FAIL(schema_guard.get_package_info(tenant_id, db_schema->get_database_id(), package_name, package_type, compatible_mode, package_info))) { LOG_WARN("get package info failed", K(ret)); } else if (OB_ISNULL(package_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("package info is null", K(db_schema->get_database_id()), K(package_name), K(package_type), K(ret)); } else if (OB_FAIL(ddl_service_.alter_package(schema_guard, *package_info, public_routine_infos, const_cast(arg.error_info_), &arg.ddl_stmt_str_))) { LOG_WARN("drop package failed", K(ret), K(package_name)); } } else { ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST; const char *type = (package_type == PACKAGE_TYPE ? "PACKAGE" : "PACKAGE BODY"); LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST, type, db_schema->get_database_name_str().length(), db_schema->get_database_name(), package_name.length(), package_name.ptr()); } } } return ret; } int ObRootService::drop_package(const obrpc::ObDropPackageArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { uint64_t tenant_id = arg.tenant_id_; const ObString &db_name = arg.db_name_; const ObString &package_name = arg.package_name_; ObPackageType package_type = arg.package_type_; int64_t compatible_mode = arg.compatible_mode_; ObSchemaGetterGuard schema_guard; const ObDatabaseSchema *db_schema = NULL; if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, db_name, db_schema))) { LOG_WARN("get database schema failed", K(ret)); } else if (NULL == db_schema) { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, db_name.length(), db_name.ptr()); } else if (db_schema->is_in_recyclebin()) { ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT; LOG_WARN("Can't not create package of db in recyclebin", K(ret), K(arg), K(*db_schema)); } else if (OB_INVALID_ID == db_schema->get_database_id()) { ret = OB_ERR_BAD_DATABASE; LOG_WARN("database id is invalid", K(tenant_id), K(*db_schema), K(ret)); } if (OB_SUCC(ret)) { bool exist = false; if (OB_FAIL(schema_guard.check_package_exist(tenant_id, db_schema->get_database_id(), package_name, package_type, compatible_mode, exist))) { LOG_WARN("failed to check package info exist", K(package_name), K(ret)); } else if (exist) { const ObPackageInfo *package_info = NULL; ObErrorInfo error_info = arg.error_info_; if (OB_FAIL(schema_guard.get_package_info(tenant_id, db_schema->get_database_id(), package_name, package_type, compatible_mode, package_info))) { LOG_WARN("get package info failed", K(ret)); } else if (OB_FAIL(ddl_service_.drop_package(*package_info, error_info, &arg.ddl_stmt_str_))) { LOG_WARN("drop package failed", K(ret), K(package_name)); } } else { ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST; const char *type = (package_type == PACKAGE_TYPE ? "PACKAGE" : "PACKAGE BODY"); LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST, type, db_name.length(), db_name.ptr(), package_name.length(), package_name.ptr()); } } } return ret; } int ObRootService::create_trigger(const obrpc::ObCreateTriggerArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.create_trigger(arg))) { LOG_WARN("failed to create trigger", K(ret)); } return ret; } int ObRootService::alter_trigger(const obrpc::ObAlterTriggerArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.alter_trigger(arg))) { LOG_WARN("failed to alter trigger", K(ret)); } return ret; } int ObRootService::drop_trigger(const obrpc::ObDropTriggerArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.drop_trigger(arg))) { LOG_WARN("failed to drop trigger", K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // sequence //////////////////////////////////////////////////////////////// int ObRootService::do_sequence_ddl(const obrpc::ObSequenceDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.do_sequence_ddl(arg))) { LOG_WARN("do sequence ddl failed", K(arg), K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // context //////////////////////////////////////////////////////////////// int ObRootService::do_context_ddl(const obrpc::ObContextDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.do_context_ddl(arg))) { LOG_WARN("do context ddl failed", K(arg), K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // schema revise //////////////////////////////////////////////////////////////// int ObRootService::schema_revise(const obrpc::ObSchemaReviseArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.do_schema_revise(arg))) { LOG_WARN("schema revise failed", K(arg), K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // keystore //////////////////////////////////////////////////////////////// int ObRootService::do_keystore_ddl(const obrpc::ObKeystoreDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.do_keystore_ddl(arg))) { LOG_WARN("do sequence ddl failed", K(arg), K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // label security policy //////////////////////////////////////////////////////////////// int ObRootService::handle_label_se_policy_ddl(const obrpc::ObLabelSePolicyDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.handle_label_se_policy_ddl(arg))) { LOG_WARN("do label security policy ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::handle_label_se_component_ddl(const obrpc::ObLabelSeComponentDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.handle_label_se_component_ddl(arg))) { LOG_WARN("do label security policy ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::handle_label_se_label_ddl(const obrpc::ObLabelSeLabelDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.handle_label_se_label_ddl(arg))) { LOG_WARN("do label security policy ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::handle_label_se_user_level_ddl(const obrpc::ObLabelSeUserLevelDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.handle_label_se_user_level_ddl(arg))) { LOG_WARN("do label security policy ddl failed", K(arg), K(ret)); } return ret; } // tablespace //////////////////////////////////////////////////////////////// int ObRootService::do_tablespace_ddl(const obrpc::ObTablespaceDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.do_tablespace_ddl(arg))) { LOG_WARN("do sequence ddl failed", K(arg), K(ret)); } return ret; } //////////////////////////////////////////////////////////////// // server & zone management //////////////////////////////////////////////////////////////// int ObRootService::add_server_for_bootstrap_in_version_smaller_than_4_2_0( const common::ObAddr &server, const common::ObZone &zone) { return server_manager_.add_server(server, zone); } int ObRootService::add_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; ObTimeoutCtx ctx; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(inited_)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx)); } else {} if (OB_SUCC(ret)) { if (!ObHeartbeatService::is_service_enabled()) { // the old logic LOG_INFO("sys tenant data version < 4.2, add_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(old_add_server(arg))) { LOG_WARN("fail to add server by using old logic", KR(ret), K(arg)); } } else { // the new logic LOG_INFO("sys tenant data version >= 4.2, add_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_zone_op_service_.add_servers(arg.servers_, arg.zone_))) { LOG_WARN("fail to add servers", KR(ret), K(arg)); } int tmp_ret = OB_SUCCESS; if (OB_TMP_FAIL(load_server_manager())) { // ** FIXME (linqiucen.lqc): temp. solution. // ** This will be removed if we do not need whitelist in server_manager LOG_WARN("fail to load server_manager, please try 'ALTER SYSTEM RELOAD SERVER;'", KR(ret), KR(tmp_ret)); ret = OB_SUCC(ret) ? tmp_ret : ret; } } } FLOG_INFO("add server", KR(ret), K(arg)); return ret; } int ObRootService::old_add_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; uint64_t sys_data_version = 0; // argument if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(GET_MIN_DATA_VERSION(OB_SYS_TENANT_ID, sys_data_version))) { LOG_WARN("fail to get sys data version", KR(ret)); } else { LOG_INFO("add_server", K(arg), "timeout_ts", THIS_WORKER.get_timeout_ts()); ObCheckServerEmptyArg new_arg(ObCheckServerEmptyArg::ADD_SERVER, sys_data_version); ObCheckDeploymentModeArg dp_arg; dp_arg.single_zone_deployment_on_ = OB_FILE_SYSTEM_ROUTER.is_single_zone_deployment_on(); for (int64_t i = 0; OB_SUCC(ret) && i < arg.servers_.count(); ++i) { const ObAddr &addr = arg.servers_[i]; Bool is_empty(false); Bool is_deployment_mode_match(false); if (OB_FAIL(rpc_proxy_.to(addr).is_empty_server(new_arg, is_empty))) { LOG_WARN("fail to check is server empty", K(ret), K(addr)); } else if (!is_empty) { ret = OB_OP_NOT_ALLOW; LOG_WARN("add non-empty server not allowed", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "add non-empty server"); } else if (OB_FAIL([&](){ int ret = OB_SUCCESS; ret = rpc_proxy_.to(addr).check_deployment_mode_match( dp_arg, is_deployment_mode_match); return ret;}())) { LOG_WARN("fail to check deployment mode match", K(ret)); } else if (!is_deployment_mode_match) { ret = OB_OP_NOT_ALLOW; LOG_WARN("add server deployment mode mot match not allowed", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "add server deployment mode not match"); } if (OB_SUCC(ret)) { if (OB_FAIL(server_manager_.add_server(addr, arg.zone_))) { LOG_WARN("add_server failed", "server", addr, "zone", arg.zone_, K(ret)); } } } } ROOTSERVICE_EVENT_ADD("root_service", "add_server", K(ret), K(arg)); return ret; } int ObRootService::delete_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; ObTimeoutCtx ctx; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(inited_)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx)); } else {} if (OB_SUCC(ret)) { if (!ObHeartbeatService::is_service_enabled()) { // the old logic LOG_INFO("sys tenant data version < 4.2, delete_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(old_delete_server(arg))) { LOG_WARN("fail to delete server by using the old logic", KR(ret), K(arg)); } } else { // the new logic LOG_INFO("sys tenant data version >= 4.2, delete_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_zone_op_service_.delete_servers(arg.servers_, arg.zone_))) { LOG_WARN("fail to delete servers", KR(ret), K(arg)); } int tmp_ret = OB_SUCCESS; if (OB_TMP_FAIL(load_server_manager())) { // ** FIXME (linqiucen.lqc): temp. solution. // ** This will be removed if we do not need whitelist in server_manager LOG_WARN("fail to load server_manager, please try 'ALTER SYSTEM RELOAD SERVER;'", KR(ret), KR(tmp_ret)); ret = OB_SUCC(ret) ? tmp_ret : ret; } else { root_balancer_.wakeup(); empty_server_checker_.wakeup(); lost_replica_checker_.wakeup(); LOG_INFO("delete server and load server manager successfully", K(arg)); } } } FLOG_INFO("delete server", KR(ret), K(arg)); return ret; } int ObRootService::old_delete_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; bool has_enough = false; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(check_server_have_enough_resource_for_delete_server(arg.servers_, arg.zone_))) { LOG_WARN("not enough resource, cannot delete servers", K(ret), K(arg)); } else if (OB_FAIL(check_all_ls_has_leader("delete server"))) { LOG_WARN("fail to check all ls has leader", KR(ret), K(arg)); } else if (OB_FAIL(server_manager_.delete_server(arg.servers_, arg.zone_))) { LOG_WARN("delete_server failed", "servers", arg.servers_, "zone", arg.zone_, K(ret)); } else { root_balancer_.wakeup(); empty_server_checker_.wakeup(); lost_replica_checker_.wakeup(); } ROOTSERVICE_EVENT_ADD("root_service", "delete_server", K(ret), K(arg)); return ret; } int ObRootService::check_server_have_enough_resource_for_delete_server( const ObIArray &servers, const ObZone &zone) { int ret = OB_SUCCESS; common::ObZone tmp_zone; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { FOREACH_CNT_X(server, servers, OB_SUCC(ret)) { if (zone.is_empty()) { // still use server manager here, since this func. will be called only in version < 4.2 if (OB_FAIL(server_manager_.get_server_zone(*server, tmp_zone))) { LOG_WARN("fail to get server zone", K(ret)); } } else { if (OB_FAIL(server_manager_.get_server_zone(*server, tmp_zone))) { LOG_WARN("fail to get server zone", K(ret)); } else if (tmp_zone != zone) { ret = OB_SERVER_ZONE_NOT_MATCH; LOG_WARN("delete server not in zone", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(unit_manager_.check_enough_resource_for_delete_server( *server, tmp_zone))) { LOG_WARN("fail to check enouch resource", K(ret)); } } }//end for each } return ret; } int ObRootService::cancel_delete_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; ObTimeoutCtx ctx; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(inited_)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx)); } else {} if (OB_SUCC(ret)) { if (!ObHeartbeatService::is_service_enabled()) { // the old logic LOG_INFO("sys tenant data version < 4.2, cancel_delete_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(old_cancel_delete_server(arg))) { LOG_WARN("fail to cancel delete server by using the old logic", KR(ret), K(arg)); } } else { // the new logic LOG_INFO("sys tenant data version >= 4.2, cancel_delete_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_zone_op_service_.cancel_delete_servers(arg.servers_, arg.zone_))) { LOG_WARN("fail to cancel delete servers", KR(ret), K(arg)); } int tmp_ret = OB_SUCCESS; if (OB_TMP_FAIL(load_server_manager())) { // ** FIXME (linqiucen.lqc): temp. solution. // ** This will be removed if we do not need whitelist in server_manager LOG_WARN("fail to load server_manager, please try 'ALTER SYSTEM RELOAD SERVER;'", KR(ret), KR(tmp_ret)); ret = OB_SUCC(ret) ? tmp_ret : ret; } else { root_balancer_.wakeup(); } } } FLOG_INFO("cancel delete server", KR(ret), K(arg)); return ret; } int ObRootService::old_cancel_delete_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < arg.servers_.count(); ++i) { const bool commit = false; if (OB_FAIL(ret)) { } else if (OB_FAIL(server_manager_.end_delete_server(arg.servers_[i], arg.zone_, commit))) { LOG_WARN("delete_server failed", "server", arg.servers_[i], "zone", arg.zone_, K(commit), K(ret)); } else { // TODO: @wanhong.wwh NEED support cancel DR task root_balancer_.wakeup(); } } } ROOTSERVICE_EVENT_ADD("root_service", "cancel_delete_server", K(ret), K(arg)); return ret; } int ObRootService::start_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; ObTimeoutCtx ctx; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(inited_)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx)); } else {} if (OB_SUCC(ret)) { if (!ObHeartbeatService::is_service_enabled()) { // the old logic LOG_INFO("sys tenant data version < 4.2, start_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_manager_.start_server_list(arg.servers_, arg.zone_))) { LOG_WARN("fail to start server by using old logic", KR(ret), K(arg)); } } else { // the new logic LOG_INFO("sys tenant data version >= 4.2, start_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_zone_op_service_.start_servers(arg.servers_, arg.zone_))) { LOG_WARN("fail to start servers", KR(ret), K(arg)); } int tmp_ret = OB_SUCCESS; if (OB_TMP_FAIL(load_server_manager())) { // ** FIXME (linqiucen.lqc): temp. solution. // ** This will be removed if we do not need whitelist in server_manager LOG_WARN("fail to load server_manager, please try 'ALTER SYSTEM RELOAD SERVER;'", KR(ret), KR(tmp_ret)); ret = OB_SUCC(ret) ? tmp_ret : ret; } } } FLOG_INFO("start server", KR(ret), K(arg)); return ret; } int ObRootService::stop_server(const obrpc::ObAdminServerArg &arg) { int ret = OB_SUCCESS; ObTimeoutCtx ctx; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(inited_)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) { LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx)); } else { if (!ObHeartbeatService::is_service_enabled()) { // the old logic LOG_INFO("sys tenant data version < 4.2, stop_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_zone_op_service_.stop_server_precheck(arg.servers_, arg.op_))) { LOG_WARN("fail to precheck stop server", KR(ret), K(arg)); } else if (OB_FAIL(server_manager_.stop_server_list(arg.servers_, arg.zone_))) { LOG_WARN("stop server failed", "server", arg.servers_, "zone", arg.zone_, KR(ret)); } } else { LOG_INFO("sys tenant data version >= 4.2, stop_server", K(arg), "timeout_ts", ctx.get_timeout()); if (OB_FAIL(server_zone_op_service_.stop_servers(arg.servers_, arg.zone_, arg.op_))) { LOG_WARN("stop server failed", KR(ret), K(arg)); } int tmp_ret = OB_SUCCESS; if (OB_TMP_FAIL(load_server_manager())) { // ** FIXME (linqiucen.lqc): temp. solution. // ** This will be removed if we do not need whitelist in server_manager LOG_WARN("fail to load server_manager, please try 'ALTER SYSTEM RELOAD SERVER;'", KR(ret), KR(tmp_ret)); ret = OB_SUCC(ret) ? tmp_ret : ret; } if (OB_TMP_FAIL(try_notify_switch_leader(obrpc::ObNotifySwitchLeaderArg::STOP_SERVER))) { LOG_WARN("failed to notify switch leader", KR(ret), KR(tmp_ret)); } } } FLOG_INFO("stop server", KR(ret), K(arg)); return ret; } int ObRootService::add_zone(const obrpc::ObAdminZoneArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(zone_manager_.add_zone(arg.zone_, arg.region_, arg.idc_, arg.zone_type_))) { LOG_WARN("failed to add zone", K(ret), K(arg)); } else { LOG_INFO("add zone ok", K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "add_zone", K(ret), "sql_text", ObHexEscapeSqlStr(arg.sql_stmt_str_)); return ret; } int ObRootService::delete_zone(const obrpc::ObAdminZoneArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { // @note to avoid deadlock risk, put it beside ZoneManager::write_lock_. ObServerManager::add_server also call the interfaces of zone_mgr. // it does not matter while add server after check. int64_t alive_count = 0; int64_t not_alive_count = 0; ObArray servers_info; 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(ObServerTableOperator::get(*GCTX.sql_proxy_, servers_info))) { LOG_WARN("fail to get servers_info", KR(ret), KP(GCTX.sql_proxy_)); } else if (OB_FAIL(ObRootUtils::get_server_count(servers_info, arg.zone_, alive_count, not_alive_count))) { LOG_WARN("failed to get server count of the zone", KR(ret), K(arg.zone_), K(servers_info)); } else { LOG_INFO("current server count of zone", "zone", arg.zone_, K(alive_count), K(not_alive_count)); if (alive_count > 0 || not_alive_count > 0) { ret = OB_ERR_ZONE_NOT_EMPTY; LOG_USER_ERROR(OB_ERR_ZONE_NOT_EMPTY, alive_count, not_alive_count); } else if (OB_FAIL(zone_manager_.delete_zone(arg.zone_))) { LOG_WARN("delete zone failed", K(ret), K(arg)); } else { LOG_INFO("delete zone ok", K(arg)); } } } ROOTSERVICE_EVENT_ADD("root_service", "delete_zone", K(ret), "sql_text", ObHexEscapeSqlStr(arg.sql_stmt_str_)); return ret; } int ObRootService::start_zone(const obrpc::ObAdminZoneArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(zone_manager_.start_zone(arg.zone_))) { LOG_WARN("failed to start zone", K(ret), K(arg)); } else { LOG_INFO("start zone ok", K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "start_zone", K(ret), "sql_text", ObHexEscapeSqlStr(arg.sql_stmt_str_)); return ret; } //check whether has a object that all primary_zones were stopped after this time stop. //basic idea: //1. get the intersection tenant of to_stop_list and stopped_server_list. if tenant is only on stopp_list, it is no matter with this time stop. // therefor, only need to consider the intersection of two sets; //2. set the union of to_stop_list and stopped_list to zone_list. set the intersection tenant of to_stop_list and stopped_server_list to tenant_ids, // check whether the primary zone of every tenant in tenant_ids is the subset of zone_list. if it is the subset, then the leader of the object may switch // to non_primary_zone observer, this situation is not allowed; if it is not the subset, than still has replica in primary zone can be leader. int ObRootService::check_can_stop(const ObZone &zone, const ObIArray &servers, const bool is_stop_zone) { int ret = OB_SUCCESS; int64_t start_time = ObTimeUtility::current_time(); ObArray to_stop_list; ObArray stopped_zone_list; ObArray stopped_server_list; ObArray servers_info_in_table; if ((!is_stop_zone && (0 == servers.count() || zone.is_empty())) || (is_stop_zone && zone.is_empty())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(servers), K(zone)); } else if (OB_FAIL(ObRootUtils::get_stopped_zone_list(stopped_zone_list, stopped_server_list))) { LOG_WARN("fail to get stopped zone list", KR(ret)); } else if (0 >= stopped_server_list.count()) { //nothing todo } else { if (!is_stop_zone) { if (OB_FAIL(to_stop_list.assign(servers))) { LOG_WARN("fail to push back", KR(ret), K(servers)); } } 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 if (OB_FAIL(ObServerTableOperator::get(*GCTX.sql_proxy_, servers_info_in_table))) { LOG_WARN("fail to get servers_info_in_table", KR(ret), KP(GCTX.sql_proxy_)); } else if (OB_FAIL(ObRootUtils::get_servers_of_zone(servers_info_in_table, zone, to_stop_list))) { LOG_WARN("fail to get servers of zone", KR(ret), K(zone)); } ObArray tenant_ids; bool is_in = false; if (OB_FAIL(ret)) { } else if (OB_FAIL(ObRootUtils::get_tenant_intersection(unit_manager_, //get intersection tenant of to_stop_list and stopped_server_list to_stop_list, stopped_server_list, tenant_ids))) { LOG_WARN("fail to get tenant intersections", KR(ret)); } else if (!has_exist_in_array(stopped_zone_list, zone) && OB_FAIL(stopped_zone_list.push_back(zone))) { LOG_WARN("fail to push back", KR(ret), K(zone)); } else if (OB_FAIL(ObRootUtils::check_primary_region_in_zonelist(schema_service_, //check whether stop primary region of the tenant &ddl_service_, unit_manager_, zone_manager_, tenant_ids, stopped_zone_list, is_in))) { LOG_WARN("fail to check tenant stop primary region", KR(ret)); } else if (!is_in) { //nothing todo } else { ret = OB_OP_NOT_ALLOW; LOG_WARN("stop all primary region is not allowed", KR(ret), K(zone), K(servers)); } } int64_t cost = ObTimeUtility::current_time() - start_time; LOG_INFO("check can stop zone/server", KR(ret), K(zone), K(servers), K(cost)); return ret; } int ObRootService::stop_zone(const obrpc::ObAdminZoneArg &arg) { int ret = OB_SUCCESS; ObArray empty_server; HEAP_VAR(ObZoneInfo, zone_info) { bool zone_active = false; bool zone_exist = false; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(zone_manager_.check_zone_exist(arg.zone_, zone_exist))) { LOG_WARN("fail to check zone exist", K(ret)); } else if (!zone_exist) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("zone not exist"); LOG_USER_ERROR(OB_ENTRY_NOT_EXIST, "zone not exist"); } else if (OB_FAIL(zone_manager_.check_zone_active(arg.zone_, zone_active))) { LOG_WARN("fail to check zone active", KR(ret), K(arg.zone_)); } else if (!zone_active) { //nothing todo } else if (ObAdminZoneArg::ISOLATE == arg.op_) { if (OB_FAIL(check_can_stop(arg.zone_, empty_server, true/*is_stop_zone*/))) { LOG_WARN("fail to check zone can stop", KR(ret), K(arg)); if (OB_OP_NOT_ALLOW == ret) { LOG_USER_ERROR(OB_OP_NOT_ALLOW, "Stop all server in primary region is disabled"); } } } else { //stop zone/force stop zone if (ObRootUtils::have_other_stop_task(arg.zone_)) { ret = OB_STOP_SERVER_IN_MULTIPLE_ZONES; LOG_WARN("cannot stop zone when other stop task already exist", KR(ret), K(arg)); LOG_USER_ERROR(OB_STOP_SERVER_IN_MULTIPLE_ZONES, "cannot stop server or stop zone in multiple zones"); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(zone_manager_.get_zone(arg.zone_, zone_info))) { LOG_WARN("fail to get zone info", K(ret)); } else { common::ObZoneType zone_type = static_cast(zone_info.zone_type_.value_); if (ObAdminZoneArg::ISOLATE == arg.op_) { // isolate server no need to check count and status of replicas, it can not kill observer savely } else if (common::ZONE_TYPE_READONLY == zone_type) { // do not need to check anything for readonly zone } else if (common::ZONE_TYPE_READWRITE == zone_type || common::ZONE_TYPE_ENCRYPTION == zone_type) { ObArray server_list; ObArray servers_info; 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(ObServerTableOperator::get(*GCTX.sql_proxy_, servers_info))) { LOG_WARN("fail to get servers_info", KR(ret), KP(GCTX.sql_proxy_)); } else if (OB_FAIL(ObRootUtils::get_servers_of_zone(servers_info, arg.zone_, server_list))) { LOG_WARN("get servers of zone failed", KR(ret), K(arg.zone_), K(servers_info)); } else if (server_list.count() <= 0) { //do not need to check anyting while zone is empty } else if (OB_FAIL(check_majority_and_log_in_sync( server_list, arg.force_stop_,/*skip_log_sync_check*/ "stop zone"))) { LOG_WARN("fail to check majority and log in-sync", KR(ret), K(arg)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid zone type", K(ret), "zone", arg.zone_, K(zone_type)); } if (OB_SUCC(ret)) { if (OB_FAIL(zone_manager_.stop_zone(arg.zone_))) { LOG_WARN("stop zone failed", K(arg), K(ret)); } else { LOG_INFO("stop zone ok", K(arg)); int tmp_ret = OB_SUCCESS; if (OB_TMP_FAIL(try_notify_switch_leader(obrpc::ObNotifySwitchLeaderArg::STOP_ZONE))) { LOG_WARN("failed to notify switch leader", KR(ret), KR(tmp_ret)); } } } else { //set other error code to 4179 } } ROOTSERVICE_EVENT_ADD("root_service", "stop_zone", K(ret), "sql_text", ObHexEscapeSqlStr(arg.sql_stmt_str_)); } return ret; } int ObRootService::alter_zone(const obrpc::ObAdminZoneArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(zone_manager_.alter_zone(arg))) { LOG_WARN("failed to alter zone", K(ret), K(arg)); } else { LOG_INFO("alter zone ok", K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "alter_zone", K(ret), "sql_text", ObHexEscapeSqlStr(arg.sql_stmt_str_)); return ret; } int ObRootService::generate_stop_server_log_in_sync_dest_server_array( const common::ObIArray &alive_server_array, const common::ObIArray &excluded_server_array, common::ObIArray &dest_server_array) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { dest_server_array.reset(); for (int64_t i = 0; OB_SUCC(ret) && i < alive_server_array.count(); ++i) { const common::ObAddr &server = alive_server_array.at(i); if (has_exist_in_array(excluded_server_array, server)) { // in this excluded server array } else { if (OB_FAIL(dest_server_array.push_back(server))) { LOG_WARN("fail to push back", K(ret)); } } } } return ret; } int ObRootService::try_notify_switch_leader(const obrpc::ObNotifySwitchLeaderArg::SwitchLeaderComment &comment) { int ret = OB_SUCCESS; ObServerManager::ObServerArray server_list; ObZone zone; obrpc::ObNotifySwitchLeaderArg arg; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(SVR_TRACER.get_alive_servers(zone, server_list))) { LOG_WARN("failed to get server list", KR(ret), K(zone)); } else if (OB_FAIL(arg.init(OB_INVALID_TENANT_ID, ObLSID(), ObAddr(), comment))) { LOG_WARN("failed to init switch leader arg", KR(ret), K(comment)); } else if (OB_FAIL(ObRootUtils::notify_switch_leader(&rpc_proxy_, OB_SYS_TENANT_ID, arg, server_list))) { LOG_WARN("failed to notify switch leader", KR(ret), K(arg), K(server_list)); } return ret; } //////////////////////////////////////////////////////////////// // system admin command (alter system ...) //////////////////////////////////////////////////////////////// int ObRootService::init_sys_admin_ctx(ObSystemAdminCtx &ctx) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ctx.rs_status_ = &rs_status_; ctx.rpc_proxy_ = &rpc_proxy_; ctx.sql_proxy_ = &sql_proxy_; ctx.server_mgr_ = &server_manager_; ctx.zone_mgr_ = &zone_manager_; ctx.schema_service_ = schema_service_; ctx.ddl_service_ = &ddl_service_; ctx.config_mgr_ = config_mgr_; ctx.unit_mgr_ = &unit_manager_; ctx.root_inspection_ = &root_inspection_; ctx.root_service_ = this; ctx.root_balancer_ = &root_balancer_; ctx.upgrade_storage_format_executor_ = &upgrade_storage_format_executor_; ctx.create_inner_schema_executor_ = &create_inner_schema_executor_; ctx.inited_ = true; } return ret; } int ObRootService::admin_switch_replica_role(const obrpc::ObAdminSwitchReplicaRoleArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminSwitchReplicaRole admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute switch replica role failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_switch_replica_role", K(ret), K(arg)); return ret; } int ObRootService::admin_switch_rs_role(const obrpc::ObAdminSwitchRSRoleArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); return ret; } int ObRootService::admin_change_replica(const obrpc::ObAdminChangeReplicaArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); return ret; } int ObRootService::admin_drop_replica(const obrpc::ObAdminDropReplicaArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); return ret; } int ObRootService::admin_migrate_replica(const obrpc::ObAdminMigrateReplicaArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); return ret; } int ObRootService::admin_report_replica(const obrpc::ObAdminReportReplicaArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminReportReplica admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute report replica failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_report_replica", K(ret), K(arg)); return ret; } int ObRootService::admin_flush_cache(const obrpc::ObAdminFlushCacheArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminFlushCache admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("dispatch flush cache failed", K(arg), K(ret)); } ROOTSERVICE_EVENT_ADD("root_service", "admin_flush_cache", K(ret), K(arg)); } } return ret; } int ObRootService::admin_recycle_replica(const obrpc::ObAdminRecycleReplicaArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminRecycleReplica admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute recycle replica failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_recycle_replica", K(ret), K(arg)); return ret; } int ObRootService::admin_merge(const obrpc::ObAdminMergeArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminMerge admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute merge control failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_merge", K(ret), K(arg)); return ret; } int ObRootService::admin_recovery(const obrpc::ObAdminRecoveryArg &arg) { int ret = OB_NOT_SUPPORTED; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("ObRootService has not been inited", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(arg)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminZoneFastRecovery admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute merge control failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_recovery", K(ret), K(arg)); return ret; } int ObRootService::admin_clear_roottable(const obrpc::ObAdminClearRoottableArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminClearRoottable admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute clear root table failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_clear_roottable", K(ret), K(arg)); return ret; } int ObRootService::admin_refresh_schema(const obrpc::ObAdminRefreshSchemaArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminRefreshSchema admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute refresh schema failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_refresh_schema", K(ret), K(arg)); return ret; } int ObRootService::admin_set_config(obrpc::ObAdminSetConfigArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (arg.is_backup_config_) { if (OB_FAIL(admin_set_backup_config(arg))) { LOG_WARN("fail to set backup config", K(ret), K(arg)); } } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObLatchWGuard guard(set_config_lock_, ObLatchIds::CONFIG_LOCK); ObAdminSetConfig admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute set config failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_set_config", K(ret), K(arg)); return ret; } int ObRootService::admin_clear_location_cache( const obrpc::ObAdminClearLocationCacheArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminClearLocationCache admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute clear location cache failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_clear_location_cache", K(ret), K(arg)); return ret; } int ObRootService::admin_refresh_memory_stat(const ObAdminRefreshMemStatArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminRefreshMemStat admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute refresh memory stat failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_refresh_memory_stat", K(ret)); return ret; } int ObRootService::admin_wash_memory_fragmentation(const ObAdminWashMemFragmentationArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminWashMemFragmentation admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute refresh memory stat failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_wash_memory_fragmentation", K(ret)); return ret; } int ObRootService::admin_refresh_io_calibration(const obrpc::ObAdminRefreshIOCalibrationArg &arg) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminRefreshIOCalibration admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute refresh io calibration failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_refresh_io_calibration", K(ret)); return ret; } int ObRootService::admin_reload_unit() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminReloadUnit admin_util(ctx); if (OB_FAIL(admin_util.execute())) { LOG_WARN("execute reload unit failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_reload_unit", K(ret)); return ret; } int ObRootService::admin_reload_server() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminReloadServer admin_util(ctx); if (OB_FAIL(admin_util.execute())) { LOG_WARN("execute reload server failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_reload_server", K(ret)); return ret; } int ObRootService::admin_reload_zone() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminReloadZone admin_util(ctx); if (OB_FAIL(admin_util.execute())) { LOG_WARN("execute reload zone failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_reload_zone", K(ret)); return ret; } int ObRootService::admin_clear_merge_error(const obrpc::ObAdminMergeArg &arg) { int ret = OB_SUCCESS; LOG_INFO("admin receive clear_merge_error request"); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", KR(ret)); } else { ObAdminClearMergeError admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute clear merge error failed", KR(ret), K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "clear_merge_error", KR(ret), K(arg)); } } return ret; } int ObRootService::admin_migrate_unit(const obrpc::ObAdminMigrateUnitArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminMigrateUnit admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute migrate unit failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_migrate_unit", K(ret), K(arg)); return ret; } int ObRootService::admin_upgrade_virtual_schema() { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminUpgradeVirtualSchema admin_util(ctx); if (OB_FAIL(admin_util.execute())) { LOG_WARN("upgrade virtual schema failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_upgrade_virtual_schema", K(ret)); return ret; } int ObRootService::admin_upgrade_cmd(const obrpc::Bool &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminUpgradeCmd admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("begin upgrade failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_upgrade_cmd", K(ret), K(arg)); return ret; } int ObRootService::admin_rolling_upgrade_cmd(const obrpc::ObAdminRollingUpgradeArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminRollingUpgradeCmd admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("begin upgrade failed", K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_rolling_upgrade_cmd", K(ret), K(arg)); return ret; } int ObRootService::physical_restore_tenant(const obrpc::ObPhysicalRestoreTenantArg &arg, obrpc::Int64 &res_job_id) { int ret = OB_SUCCESS; bool has_standby_cluster = false; res_job_id = OB_INVALID_ID; int64_t current_timestamp = ObTimeUtility::current_time(); int64_t start_ts = ObTimeUtility::current_time(); int64_t job_id = OB_INVALID_ID; int64_t refreshed_schema_version = OB_INVALID_VERSION; ObSchemaGetterGuard schema_guard; int64_t restore_concurrency = 0; omt::ObTenantConfigGuard tenant_config(TENANT_CONF(MTL_ID())); if (tenant_config.is_valid()) { restore_concurrency = tenant_config->ha_high_thread_score; } if (0 == restore_concurrency) { restore_concurrency = OB_DEFAULT_RESTORE_CONCURRENCY; } if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (GCTX.is_standby_cluster() || GCONF.in_upgrade_mode()) { ret = OB_OP_NOT_ALLOW; LOG_WARN("restore tenant while in standby cluster or " "in upgrade mode is not allowed", KR(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "restore tenant while in standby cluster or in upgrade mode"); } else if (0 == restore_concurrency) { ret = OB_OP_NOT_ALLOW; LOG_WARN("restore tenant when restore_concurrency is 0 not allowed", KR(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "restore tenant when restore_concurrency is 0"); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table( OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("fail to get sys tenant's schema guard", KR(ret)); } else if (OB_FAIL(schema_guard.get_schema_version(OB_SYS_TENANT_ID, refreshed_schema_version))) { LOG_WARN("fail to get sys schema version", KR(ret)); } else { HEAP_VAR(ObPhysicalRestoreJob, job_info) { // just to check sys tenant's schema with latest schema version ObDDLSQLTransaction trans(schema_service_, false /*end_signal*/); if (OB_FAIL(trans.start(&sql_proxy_, OB_SYS_TENANT_ID, refreshed_schema_version))) { LOG_WARN("failed to start trans, ", K(ret)); } else if (OB_FAIL(RS_JOB_CREATE_EXT(job_id, RESTORE_TENANT, trans, "sql_text", ObHexEscapeSqlStr(arg.get_sql_stmt())))) { LOG_WARN("fail create rs job", K(ret), K(arg)); } else if (job_id < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid job_id", K(ret), K(job_id)); } else if (OB_FAIL(ObRestoreUtil::fill_physical_restore_job(job_id, arg, job_info))) { LOG_WARN("fail to fill physical restore job", K(ret), K(job_id), K(arg)); } else { job_info.set_restore_start_ts(start_ts); res_job_id = job_id; } if (FAILEDx(check_restore_tenant_valid(job_info, schema_guard))) { LOG_WARN("failed to check restore tenant vailid", KR(ret), K(job_info)); } if (FAILEDx(ObRestoreUtil::record_physical_restore_job(trans, job_info))) { LOG_WARN("fail to record physical restore job", K(ret), K(job_id), K(arg)); } else { //TODO wakeup restore scheduler } if (trans.is_started()) { int temp_ret = OB_SUCCESS; if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) { LOG_WARN("trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret)); ret = (OB_SUCC(ret)) ? temp_ret : ret; } } } } LOG_INFO("[RESTORE] physical restore tenant start", K(arg), K(ret)); ROOTSERVICE_EVENT_ADD("physical_restore", "restore_start", K(ret), "tenant_name", arg.tenant_name_); if (OB_SUCC(ret)) { const char *status_str = ObPhysicalRestoreTableOperator::get_restore_status_str( static_cast(PHYSICAL_RESTORE_CREATE_TENANT)); ROOTSERVICE_EVENT_ADD("physical_restore", "change_restore_status", "job_id", job_id, "tenant_name", arg.tenant_name_, "status", status_str); } return ret; } int ObRootService::check_restore_tenant_valid(const share::ObPhysicalRestoreJob &job_info, share::schema::ObSchemaGetterGuard &schema_guard) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!job_info.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(job_info)); } else { //check tenant if exist const ObTenantSchema *tenant_schema = NULL; const ObString &tenant_name = job_info.get_tenant_name(); if (OB_FAIL(schema_guard.get_tenant_info(tenant_name, tenant_schema))) { LOG_WARN("fail to get tenant schema", KR(ret), K(job_info)); } else if (OB_NOT_NULL(tenant_schema)) { ret = OB_OP_NOT_ALLOW; LOG_WARN("restore tenant with existed tenant name is not allowed", KR(ret), K(tenant_name)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "restore tenant with existed tenant name is"); } else { // check if resource pool contains any E zone ObSqlString pool_list_str; ObArray pool_list; ObArray pools; ObArray zones; if (OB_FAIL(pool_list_str.assign(job_info.get_pool_list()))) { LOG_WARN("failed to assign pool list", KR(ret), K(job_info)); } else if (OB_FAIL(ObRestoreService::assign_pool_list(pool_list_str.ptr(), pool_list))) { LOG_WARN("failed to assgin pool list", KR(ret), K(pool_list_str)); } else if (OB_FAIL(ObUnitManager::convert_pool_name_list(pool_list, pools))) { LOG_WARN("fail to convert pools", KR(ret), K(pool_list)); } else if (OB_FAIL(unit_manager_.get_zones_of_pools(pools, zones))) { LOG_WARN("fail to get zones of pools", KR(ret), K(pools)); } else { HEAP_VAR(ObZoneInfo, info) { for (int64_t i = 0; OB_SUCC(ret) && i < zones.count(); i++) { const ObZone &zone = zones.at(i); info.reset(); if (OB_FAIL(zone_manager_.get_zone(zone, info))) { LOG_WARN("fail to get zone info", KR(ret), K(zone)); } else if (static_cast(ObZoneType::ZONE_TYPE_ENCRYPTION) == info.zone_type_.value_) { ret = OB_NOT_SUPPORTED; LOG_WARN("restore tenant with encrypted zone is not supported", KR(ret), K(info)); } } } } } } //TODO check if need check R replica return ret; } int ObRootService::run_job(const obrpc::ObRunJobArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminRunJob admin_util(ctx); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("run job failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_run_job", K(ret), K(arg)); return ret; } int ObRootService::run_upgrade_job(const obrpc::ObUpgradeJobArg &arg) { int ret = OB_SUCCESS; int64_t version = arg.version_; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret), K(arg)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), KR(ret)); } else if (ObUpgradeJobArg::UPGRADE_POST_ACTION == arg.action_ && !ObUpgradeChecker::check_data_version_exist(version)) { ret = OB_NOT_SUPPORTED; LOG_WARN("unsupported version to run upgrade job", KR(ret), K(version)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "run upgrade job with such version is"); } else if (ObUpgradeJobArg::STOP_UPGRADE_JOB == arg.action_) { if (OB_FAIL(upgrade_executor_.stop())) { LOG_WARN("fail to stop upgrade task", KR(ret)); } else { upgrade_executor_.start(); } } else if (OB_FAIL(submit_upgrade_task(arg))) { LOG_WARN("fail to submit upgrade task", KR(ret), K(arg)); } ROOTSERVICE_EVENT_ADD("root_service", "admin_run_upgrade_job", KR(ret), K(arg)); return ret; } int ObRootService::upgrade_table_schema(const obrpc::ObUpgradeTableSchemaArg &arg) { int ret = OB_SUCCESS; const int64_t start = ObTimeUtility::current_time(); FLOG_INFO("[UPGRADE] start to upgrade table", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("arg is invalid", KR(ret), K(arg)); } else if (!arg.upgrade_virtual_schema()) { // upgrade single system table if (OB_FAIL(ddl_service_.upgrade_table_schema(arg))) { LOG_WARN("fail to upgrade table schema", KR(ret), K(arg)); } } else { // upgrade all virtual table/sys view ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminUpgradeVirtualSchema admin_util(ctx); int64_t upgrade_cnt = 0; if (OB_FAIL(admin_util.execute(arg.get_tenant_id(), upgrade_cnt))) { LOG_WARN("upgrade virtual schema failed", KR(ret), K(arg)); } } } FLOG_INFO("[UPGRADE] finish upgrade table", KR(ret), K(arg), "cost_us", ObTimeUtility::current_time() - start); return ret; } int ObRootService::broadcast_ds_action(const obrpc::ObDebugSyncActionArg &arg) { LOG_INFO("receive broadcast debug sync actions", K(arg)); int ret = OB_SUCCESS; ObArray server_list; const ObZone all_zone; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(SVR_TRACER.get_alive_servers(all_zone, server_list))) { LOG_WARN("get all alive servers failed", K(all_zone), K(ret)); } else { FOREACH_X(s, server_list, OB_SUCCESS == ret) { if (OB_FAIL(rpc_proxy_.to(*s).timeout(config_->rpc_timeout).set_debug_sync_action(arg))) { LOG_WARN("set server's global sync action failed", K(ret), "server", *s, K(arg)); } } } return ret; } int ObRootService::check_dangling_replica_finish(const obrpc::ObCheckDanglingReplicaFinishArg &arg) { UNUSED(arg); return OB_NOT_SUPPORTED; } int ObRootService::fetch_alive_server(const ObFetchAliveServerArg &arg, ObFetchAliveServerResult &result) { LOG_DEBUG("receive fetch alive server request"); ObZone empty_zone; // for all server int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } else if (!server_refreshed_) { ret = OB_SERVER_IS_INIT; LOG_WARN("RS is initializing, server not refreshed, can not process this request"); } else if (arg.cluster_id_ != config_->cluster_id) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cluster id mismatch", K(ret), K(arg), "cluster_id", static_cast(config_->cluster_id)); } else if (OB_FAIL(SVR_TRACER.get_servers_by_status(empty_zone, result.active_server_list_, result.inactive_server_list_))) { LOG_WARN("get alive servers failed", K(ret)); } return ret; } int ObRootService::refresh_server(const bool load_frozen_status, const bool need_retry) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!in_service()|| (server_refreshed_ && load_frozen_status)) { // no need to refresh again for fast recover } else { { ObTimeoutCtx ctx; if (load_frozen_status) { ctx.set_timeout(config_->rpc_timeout); } if (OB_FAIL(load_server_manager())) { LOG_WARN("build server manager failed", K(ret), K(load_frozen_status)); } else { LOG_INFO("build server manager succeed", K(load_frozen_status)); } if (FAILEDx(SVR_TRACER.refresh())) { LOG_WARN("fail to refresh all server tracer", KR(ret)); } } // request heartbeats from observers if (OB_SUCC(ret) && !ObHeartbeatService::is_service_enabled()) { int temp_ret = OB_SUCCESS; if (OB_SUCCESS != (temp_ret = request_heartbeats())) { LOG_WARN("request heartbeats failed", K(temp_ret)); } else { LOG_INFO("request heartbeats succeed"); } } if (OB_SUCC(ret)) { server_refreshed_ = true; LOG_INFO("refresh server success", K(load_frozen_status)); } else if (need_retry) { LOG_INFO("refresh server failed, retry", K(ret), K(load_frozen_status)); int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = schedule_refresh_server_timer_task( ObRefreshServerTask::REFRESH_SERVER_INTERVAL))) { if (OB_CANCELED != ret) { LOG_ERROR("schedule refresh server task failed", K(ret)); } else { LOG_WARN("schedule refresh server task failed, because the server is stopping", K(ret)); } } else { ObTaskController::get().allow_next_syslog(); LOG_INFO("schedule refresh server task again", KR(tmp_ret), KR(ret)); } } else {} // no more to do } return ret; } int ObRootService::refresh_schema(const bool load_frozen_status) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { ObTimeoutCtx ctx; int64_t schema_version = OB_INVALID_VERSION; if (load_frozen_status) { ctx.set_timeout(config_->rpc_timeout); } ObArray tenant_ids; //depend on sys schema while start RS if (OB_FAIL(tenant_ids.push_back(OB_SYS_TENANT_ID))) { LOG_WARN("fail to refresh sys schema", K(ret)); } else if (OB_FAIL(schema_service_->refresh_and_add_schema(tenant_ids))) { LOG_WARN("refresh schema failed", K(ret), K(load_frozen_status)); } else if (OB_FAIL(schema_service_->get_tenant_schema_version(OB_SYS_TENANT_ID, schema_version))) { LOG_WARN("fail to get max schema version", K(ret)); } else { LOG_INFO("refresh schema with new mode succeed", K(load_frozen_status), K(schema_version)); } if (OB_SUCC(ret)) { ObSchemaService *schema_service = schema_service_->get_schema_service(); if (NULL == schema_service) { ret = OB_ERR_SYS; LOG_WARN("schema_service can't be null", K(ret), K(schema_version)); } else { schema_service->set_refreshed_schema_version(schema_version); LOG_INFO("set schema version succeed", K(ret), K(schema_service), K(schema_version)); } } } return ret; } int ObRootService::set_cluster_version() { int ret = OB_SUCCESS; int64_t affected_rows = 0; char sql[1024] = {0}; ObMySQLProxy &sql_proxy = ddl_service_.get_sql_proxy(); snprintf(sql, sizeof(sql), "alter system set min_observer_version = '%s'", PACKAGE_VERSION); if (OB_FAIL(sql_proxy.write(OB_SYS_TENANT_ID, sql, affected_rows))) { LOG_WARN("execute sql failed", K(sql)); } return ret; } int ObRootService::admin_set_tracepoint(const obrpc::ObAdminSetTPArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else { ObSystemAdminCtx ctx; if (OB_FAIL(init_sys_admin_ctx(ctx))) { LOG_WARN("init_sys_admin_ctx failed", K(ret)); } else { ObAdminSetTP admin_util(ctx, arg); if (OB_FAIL(admin_util.execute(arg))) { LOG_WARN("execute report replica failed", K(arg), K(ret)); } } } ROOTSERVICE_EVENT_ADD("root_service", "admin_set_tracepoint", K(ret), K(arg)); return ret; } // RS may receive refresh time zone from observer with old binary during upgrade. // do notiong int ObRootService::refresh_time_zone_info(const obrpc::ObRefreshTimezoneArg &arg) { int ret = OB_SUCCESS; UNUSED(arg); ROOTSERVICE_EVENT_ADD("root_service", "refresh_time_zone_info", K(ret), K(arg)); return ret; } int ObRootService::request_time_zone_info(const ObRequestTZInfoArg &arg, ObRequestTZInfoResult &result) { UNUSED(arg); int ret = OB_SUCCESS; uint64_t tenant_id = OB_SYS_TENANT_ID; ObTZMapWrap tz_map_wrap; ObTimeZoneInfoManager *tz_info_mgr = NULL; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(OTTZ_MGR.get_tenant_timezone(tenant_id, tz_map_wrap, tz_info_mgr))) { LOG_WARN("get tenant timezone failed", K(ret)); } else if (OB_ISNULL(tz_info_mgr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get_tz_mgr failed", K(ret), K(tz_info_mgr)); } else if (OB_FAIL(tz_info_mgr->response_time_zone_info(result))) { LOG_WARN("fail to response tz_info", K(ret)); } else { LOG_INFO("rs success to response lastest tz_info to server", "server", arg.obs_addr_, "last_version", result.last_version_); } return ret; } bool ObRootService::check_config(const ObConfigItem &item, const char *&err_info) { bool bret = true; err_info = NULL; if (!inited_) { bret = false; LOG_WARN_RET(OB_NOT_INIT, "service not init"); } else if (0 == STRCMP(item.name(), MIN_OBSERVER_VERSION)) { if (OB_SUCCESS != ObClusterVersion::is_valid(item.str())) { LOG_WARN_RET(OB_INVALID_ERROR, "fail to parse min_observer_version value"); bret = false; } } else if (0 == STRCMP(item.name(), __BALANCE_CONTROLLER)) { ObString balance_troller_str(item.str()); ObRootBalanceHelp::BalanceController switch_info; int tmp_ret = ObRootBalanceHelp::parse_balance_info(balance_troller_str, switch_info); if (OB_SUCCESS != tmp_ret) { LOG_WARN_RET(tmp_ret, "fail to parse balance switch", K(balance_troller_str)); bret = false; } } return bret; } int ObRootService::report_replica() { int ret = OB_SUCCESS; ObArray server_list; ObZone null_zone; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(SVR_TRACER.get_alive_servers(null_zone, server_list))) { LOG_WARN("fail to get alive server", K(ret)); } else { FOREACH_CNT(server, server_list) { if (OB_ISNULL(server)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get invalid server", K(ret)); } else if (OB_FAIL(rpc_proxy_.to(*server).report_replica())) { LOG_WARN("fail to force observer report replica", K(ret), K(*server)); } ret = OB_SUCCESS; } } return ret; } int ObRootService::report_single_replica( const int64_t tenant_id, const ObLSID &ls_id) { int ret = OB_SUCCESS; ObArray server_list; ObZone null_zone; obrpc::ObReportSingleReplicaArg arg; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_FAIL(SVR_TRACER.get_alive_servers(null_zone, server_list))) { LOG_WARN("fail to get alive server", KR(ret)); } else if (OB_INVALID_TENANT_ID == tenant_id || !ls_id.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(ls_id)); } else { arg.tenant_id_ = tenant_id; arg.ls_id_ = ls_id; FOREACH_CNT(server, server_list) { if (OB_ISNULL(server)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get invalid server", KR(ret)); // } else if (OB_FAIL(rpc_proxy_.to(*server).report_single_replica(arg))) {//TODO(xiuming):delete it // LOG_WARN("fail to force observer report replica", KR(ret), K(server), K(arg)); } ret = OB_SUCCESS; } } return ret; } int ObRootService::update_all_server_config() { int ret = OB_SUCCESS; ObZone empty_zone; ObArray server_list; ObArray config_all_server_list; ObArray empty_excluded_server_list; bool need_update = true; HEAP_VAR(ObAdminSetConfigItem, all_server_config) { auto &value = all_server_config.value_; int64_t pos = 0; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!SVR_TRACER.has_build())) { need_update = false; } else if (OB_FAIL(SVR_TRACER.get_servers_of_zone(empty_zone, server_list))) { LOG_WARN("fail to get server", K(ret)); } else if (OB_UNLIKELY(0 == server_list.size())) { need_update = false; LOG_WARN("no servers in all_server_tracer"); } else if (OB_FAIL(all_server_config.name_.assign(config_->all_server_list.name()))) { LOG_WARN("fail to assign name", K(ret)); } else if (OB_FAIL(ObShareUtil::parse_all_server_list(empty_excluded_server_list, config_all_server_list))) { LOG_WARN("fail to parse all_server_list from GCONF", KR(ret)); } else if (ObRootUtils::is_subset(server_list, config_all_server_list) && ObRootUtils::is_subset(config_all_server_list, server_list)) { need_update = false; LOG_TRACE("server_list is the same as config_all_server_list, no need to update GCONF.all_server_list", K(server_list), K(config_all_server_list)); } else { LOG_INFO("GCONF.all_server_list should be updated", K(config_all_server_list), K(server_list)); char ip_port_buf[MAX_IP_PORT_LENGTH]; for (int64_t i = 0; i < server_list.count() - 1; i++) { if (OB_FAIL(server_list.at(i).ip_port_to_string(ip_port_buf, MAX_IP_PORT_LENGTH))) { LOG_WARN("fail to print ip port", K(ret), "server", server_list.at(i)); } else if (OB_FAIL(databuff_printf(value.ptr(), OB_MAX_CONFIG_VALUE_LEN, pos, "%s", ip_port_buf))) { LOG_WARN("fail to databuff_printf", K(ret), K(i), K(server_list)); } else if (OB_FAIL(databuff_printf(value.ptr(), OB_MAX_CONFIG_VALUE_LEN, pos, "%c", ','))) { LOG_WARN("fail to print char", K(ret), K(i), K(server_list)); } } if (OB_SUCC(ret) && 0 < server_list.count()) { if (OB_FAIL(server_list.at(server_list.count() - 1).ip_port_to_string(ip_port_buf, MAX_IP_PORT_LENGTH))) { LOG_WARN("fail to print ip port", K(ret), "server", server_list.at(server_list.count() - 1)); } else if (OB_FAIL(databuff_printf(value.ptr(), OB_MAX_CONFIG_VALUE_LEN, pos, "%s", ip_port_buf))) { LOG_WARN("fail to databuff_printf", K(ret), K(server_list), K(ip_port_buf)); } } } if (OB_SIZE_OVERFLOW == ret) { LOG_ERROR("can't print server addr to buffer, size overflow", K(ret), K(server_list)); } if (need_update && OB_SUCC(ret)) { ObAdminSetConfigArg arg; arg.is_inner_ = true; if (OB_FAIL(arg.items_.push_back(all_server_config))) { LOG_WARN("fail to push back", K(ret)); } else if (OB_FAIL(admin_set_config(arg))) { LOG_WARN("fail to set config", K(ret)); } else { LOG_INFO("update all server config success", K(arg)); } } } return ret; } ///////////////////////// ObRootService::ObReportCoreTableReplicaTask::ObReportCoreTableReplicaTask(ObRootService &root_service) : ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(INT64_MAX); //retry until success } int ObRootService::ObReportCoreTableReplicaTask::process() { int ret = OB_SUCCESS; const int64_t tenant_id = OB_SYS_TENANT_ID; if (OB_FAIL(root_service_.report_single_replica(tenant_id, SYS_LS))) { LOG_WARN("fail to report single replica", K(ret), K(tenant_id), K(SYS_LS)); } else { LOG_INFO("report all_core table succeed"); } return ret; } ObAsyncTask *ObRootService::ObReportCoreTableReplicaTask::deep_copy(char *buf, const int64_t buf_size) const { ObReportCoreTableReplicaTask *task = NULL; if (NULL == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size), KP(buf)); } else { task = new (buf) ObReportCoreTableReplicaTask(root_service_); } return task; } //////////////ObReloadUnitManagerTask ObRootService::ObReloadUnitManagerTask::ObReloadUnitManagerTask(ObRootService &root_service, ObUnitManager &unit_manager) : ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service), unit_manager_(unit_manager) { set_retry_times(INT64_MAX); // retry until success } int ObRootService::ObReloadUnitManagerTask::process() { int ret = OB_SUCCESS; if (OB_FAIL(unit_manager_.load())) { LOG_WARN("fail to reload unit_manager", K(ret)); } else { LOG_INFO("reload unit_manger succeed"); } return ret; } ObAsyncTask *ObRootService::ObReloadUnitManagerTask::deep_copy(char *buf, const int64_t buf_size) const { ObReloadUnitManagerTask *task = NULL; if (NULL == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size), KP(buf)); } else { task = new (buf) ObReloadUnitManagerTask(root_service_, unit_manager_); } return task; } ObRootService::ObLoadDDLTask::ObLoadDDLTask(ObRootService &root_service) : ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(INT64_MAX); } int ObRootService::ObLoadDDLTask::process() { int ret = OB_SUCCESS; ObDDLScheduler &ddl_scheduler = root_service_.get_ddl_scheduler(); if (OB_FAIL(ddl_scheduler.recover_task())) { LOG_WARN("load ddl task failed", K(ret)); } return ret; } ObAsyncTask *ObRootService::ObLoadDDLTask::deep_copy(char *buf, const int64_t buf_size) const { ObLoadDDLTask *task = nullptr; if (nullptr == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buf is not enough", K(buf_size), "request_size", sizeof(*this)); } else { task = new (buf) ObLoadDDLTask(root_service_); } return task; } ObRootService::ObRefreshIOCalibrationTask::ObRefreshIOCalibrationTask(ObRootService &root_service) : ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(INT64_MAX); } int ObRootService::ObRefreshIOCalibrationTask::process() { int ret = OB_SUCCESS; obrpc::ObAdminRefreshIOCalibrationArg arg; arg.only_refresh_ = true; if (OB_FAIL(root_service_.admin_refresh_io_calibration(arg))) { LOG_WARN("refresh io calibration failed", K(ret), K(arg)); } else { LOG_INFO("refresh io calibration succeeded"); } return ret; } ObAsyncTask *ObRootService::ObRefreshIOCalibrationTask::deep_copy(char *buf, const int64_t buf_size) const { ObRefreshIOCalibrationTask *task = nullptr; if (nullptr == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buf is not enough", K(buf_size), "request_size", sizeof(*this)); } else { task = new (buf) ObRefreshIOCalibrationTask(root_service_); } return task; } //////////////////// ObRootService::ObSelfCheckTask::ObSelfCheckTask(ObRootService &root_service) :ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(0); // don't retry when failed } int ObRootService::ObSelfCheckTask::process() { int ret = OB_SUCCESS; if (OB_FAIL(root_service_.self_check())) { LOG_WARN("fail to do root inspection check, please check it", K(ret)); } else { LOG_INFO("self check success!"); } return ret; } ObAsyncTask *ObRootService::ObSelfCheckTask::deep_copy(char *buf, const int64_t buf_size) const { ObSelfCheckTask *task = NULL; if (NULL == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size)); } else { task = new(buf) ObSelfCheckTask(root_service_); } return task; } ///////////////////////// ObRootService::ObUpdateAllServerConfigTask::ObUpdateAllServerConfigTask(ObRootService &root_service) : ObAsyncTimerTask(root_service.task_queue_), root_service_(root_service) { set_retry_times(INT64_MAX); // retry until success } int ObRootService::ObUpdateAllServerConfigTask::process() { int ret = OB_SUCCESS; if (OB_FAIL(root_service_.update_all_server_config())) { LOG_WARN("fail to update all server config", K(ret)); } else { LOG_INFO("update all server config success"); } return ret; } ObAsyncTask *ObRootService::ObUpdateAllServerConfigTask::deep_copy(char *buf, const int64_t buf_size) const { ObUpdateAllServerConfigTask *task = NULL; if (NULL == buf || buf_size < static_cast(sizeof(*this))) { LOG_WARN_RET(OB_BUF_NOT_ENOUGH, "buffer not large enough", K(buf_size), KP(buf)); } else { task = new (buf) ObUpdateAllServerConfigTask(root_service_); } return task; } ///////////////////////// int ObRootService::admin_clear_balance_task(const obrpc::ObAdminClearBalanceTaskArg &args) { // TODO: @wanhong.wwh NEED SUPPORT UNUSEDx(args); return 0; } status::ObRootServiceStatus ObRootService::get_status() const { return rs_status_.get_rs_status(); } int ObRootService::table_allow_ddl_operation(const obrpc::ObAlterTableArg &arg) { int ret = OB_SUCCESS; const ObTableSchema *schema = NULL; ObSchemaGetterGuard schema_guard; const AlterTableSchema &alter_table_schema = arg.alter_table_schema_; const uint64_t tenant_id = alter_table_schema.get_tenant_id(); const ObString &origin_database_name = alter_table_schema.get_origin_database_name(); const ObString &origin_table_name = alter_table_schema.get_origin_table_name(); schema_guard.set_session_id(arg.session_id_); if (arg.is_refresh_sess_active_time()) { //do nothing } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invali argument", K(ret), K(arg)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("get schema guard in inner table failed", K(ret)); } else if (OB_FAIL(schema_guard.get_table_schema(tenant_id, origin_database_name, origin_table_name, false, schema))) { LOG_WARN("fail to get table schema", K(ret), K(tenant_id), K(origin_database_name), K(origin_table_name)); } else if (OB_ISNULL(schema)) { ret = OB_TABLE_NOT_EXIST; LOG_WARN("invalid schema", K(ret)); LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(origin_database_name), to_cstring(origin_table_name)); } else if (schema->is_in_splitting()) { //TODO ddl must not execute on splitting table due to split not unstable ret = OB_OP_NOT_ALLOW; LOG_WARN("table is physical or logical split can not split", K(ret), K(schema)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "table is in physial or logical split, ddl operation"); } else if (schema->is_ctas_tmp_table()) { if (!alter_table_schema.alter_option_bitset_.has_member(ObAlterTableArg::SESSION_ID)) { //to prevet alter table after failed to create table, the table is invisible. ret = OB_OP_NOT_ALLOW; LOG_WARN("try to alter invisible table schema", K(schema->get_session_id()), K(arg)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "try to alter invisible table"); } } return ret; } // ask each server to update statistic int ObRootService::update_stat_cache(const obrpc::ObUpdateStatCacheArg &arg) { int ret = OB_SUCCESS; ObZone null_zone; ObSEArray server_list; bool evict_plan_failed = false; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(SVR_TRACER.get_alive_servers(null_zone, server_list))) { LOG_WARN("fail to get alive server", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < server_list.count(); i++) { if (OB_FAIL(rpc_proxy_.to(server_list.at(i)).update_local_stat_cache(arg))) { LOG_WARN("fail to update table statistic", K(ret), K(server_list.at(i))); // OB_SQL_PC_NOT_EXIST represent evict plan failed if (OB_SQL_PC_NOT_EXIST == ret) { ret = OB_SUCCESS; evict_plan_failed = true; } } else { /*do nothing*/} } } if (OB_SUCC(ret) && evict_plan_failed) { ret = OB_SQL_PC_NOT_EXIST; } return ret; } int ObRootService::check_weak_read_version_refresh_interval(int64_t refresh_interval, bool &valid) { int ret = OB_SUCCESS; ObSchemaGetterGuard sys_schema_guard; ObArray tenant_ids; valid = true; if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", KR(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, sys_schema_guard))) { LOG_WARN("get sys schema guard failed", KR(ret)); } else if (OB_FAIL(sys_schema_guard.get_tenant_ids(tenant_ids))) { LOG_WARN("get tenant ids failed", KR(ret)); } else { ObSchemaGetterGuard schema_guard; const ObSimpleTenantSchema *tenant_schema = NULL; const ObSysVarSchema *var_schema = NULL; ObObj obj; int64_t session_max_stale_time = 0; uint64_t tenant_id = OB_INVALID_TENANT_ID; for (int64_t i = 0; OB_SUCC(ret) && valid && i < tenant_ids.count(); i++) { tenant_id = tenant_ids[i]; if (OB_FAIL(sys_schema_guard.get_tenant_info(tenant_id, tenant_schema))) { LOG_WARN("fail to get tenant schema", KR(ret), K(tenant_id)); } else if (OB_ISNULL(tenant_schema)) { ret = OB_SUCCESS; LOG_WARN("tenant schema is null, skip and continue", KR(ret), K(tenant_id)); } else if (!tenant_schema->is_normal()) { ret = OB_SUCCESS; LOG_WARN("tenant schema is not normal, skip and continue", KR(ret), K(tenant_id)); } else if (OB_FAIL(GCTX.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(schema_guard.get_tenant_system_variable(tenant_id, OB_SV_MAX_READ_STALE_TIME, var_schema))) { LOG_WARN("get tenant system variable failed", KR(ret), K(tenant_id)); } else if (OB_ISNULL(var_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("var schema is null", KR(ret), K(tenant_id)); } else if (OB_FAIL(var_schema->get_value(NULL, NULL, obj))) { LOG_WARN("get value failed", KR(ret), K(tenant_id), K(obj)); } else if (OB_FAIL(obj.get_int(session_max_stale_time))) { LOG_WARN("get int failed", KR(ret), K(tenant_id), K(obj)); } else if (session_max_stale_time != share::ObSysVarFactory::INVALID_MAX_READ_STALE_TIME && refresh_interval > session_max_stale_time) { valid = false; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "weak_read_version_refresh_interval is larger than ob_max_read_stale_time"); } } } return ret; } int ObRootService::set_config_pre_hook(obrpc::ObAdminSetConfigArg &arg) { int ret = OB_SUCCESS; if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } FOREACH_X(item, arg.items_, OB_SUCCESS == ret) { bool valid = true; if (item->name_.is_empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("empty config name", "item", *item, K(ret)); } else if (0 == STRCMP(item->name_.ptr(), FREEZE_TRIGGER_PERCENTAGE)) { // check write throttle percentage for (int i = 0; i < item->tenant_ids_.count() && valid; i++) { valid = valid && ObConfigFreezeTriggerIntChecker::check(item->tenant_ids_.at(i), *item); if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "tenant freeze_trigger_percentage which should smaller than writing_throttling_trigger_percentage"); LOG_WARN("config invalid", "item", *item, K(ret), K(i), K(item->tenant_ids_.at(i))); } } } else if (0 == STRCMP(item->name_.ptr(), WRITING_THROTTLEIUNG_TRIGGER_PERCENTAGE)) { // check freeze trigger for (int i = 0; i < item->tenant_ids_.count() && valid; i++) { valid = valid && ObConfigWriteThrottleTriggerIntChecker::check(item->tenant_ids_.at(i), *item); if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "tenant writing_throttling_trigger_percentage which should greater than freeze_trigger_percentage"); LOG_WARN("config invalid", "item", *item, K(ret), K(i), K(item->tenant_ids_.at(i))); } } } else if (0 == STRCMP(item->name_.ptr(), WEAK_READ_VERSION_REFRESH_INTERVAL)) { int64_t refresh_interval = ObConfigTimeParser::get(item->value_.ptr(), valid); if (valid && OB_FAIL(check_weak_read_version_refresh_interval(refresh_interval, valid))) { LOG_WARN("check refresh interval failed ", KR(ret), K(*item)); } else if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_WARN("config invalid", KR(ret), K(*item)); } } else if (0 == STRCMP(item->name_.ptr(), PARTITION_BALANCE_SCHEDULE_INTERVAL)) { const int64_t DEFAULT_BALANCER_IDLE_TIME = 10 * 1000 * 1000L; // 10s for (int i = 0; i < item->tenant_ids_.count() && valid; i++) { const uint64_t tenant_id = item->tenant_ids_.at(i); omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id)); int64_t balancer_idle_time = tenant_config.is_valid() ? tenant_config->balancer_idle_time : DEFAULT_BALANCER_IDLE_TIME; int64_t interval = ObConfigTimeParser::get(item->value_.ptr(), valid); if (valid) { if (0 == interval) { valid = true; } else if (interval >= balancer_idle_time) { valid = true; } else { valid = false; char err_msg[DEFAULT_BUF_LENGTH]; (void)snprintf(err_msg, sizeof(err_msg), "partition_balance_schedule_interval of tenant %ld, " "it should not be less than balancer_idle_time", tenant_id); LOG_USER_ERROR(OB_INVALID_ARGUMENT, err_msg); } } if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_WARN("config invalid", KR(ret), K(*item), K(balancer_idle_time), K(tenant_id)); } } } else if (0 == STRCMP(item->name_.ptr(), BALANCER_IDLE_TIME)) { const int64_t DEFAULT_PARTITION_BALANCE_SCHEDULE_INTERVAL = 2 * 3600 * 1000 * 1000L; // 2h for (int i = 0; i < item->tenant_ids_.count() && valid; i++) { const uint64_t tenant_id = item->tenant_ids_.at(i); omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id)); int64_t interval = tenant_config.is_valid() ? tenant_config->partition_balance_schedule_interval : DEFAULT_PARTITION_BALANCE_SCHEDULE_INTERVAL; int64_t idle_time = ObConfigTimeParser::get(item->value_.ptr(), valid); if (valid && (idle_time > interval)) { valid = false; char err_msg[DEFAULT_BUF_LENGTH]; (void)snprintf(err_msg, sizeof(err_msg), "balancer_idle_time of tenant %ld, " "it should not be longer than partition_balance_schedule_interval", tenant_id); LOG_USER_ERROR(OB_INVALID_ARGUMENT, err_msg); } if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_WARN("config invalid", KR(ret), K(*item), K(interval), K(tenant_id)); } } } else if (0 == STRCMP(item->name_.ptr(), LOG_DISK_UTILIZATION_LIMIT_THRESHOLD)) { // check log_disk_utilization_limit_threshold for (int i = 0; i < item->tenant_ids_.count() && valid; i++) { valid = valid && ObConfigLogDiskLimitThresholdIntChecker::check(item->tenant_ids_.at(i), *item); if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "log_disk_utilization_limit_threshold should be greater than log_disk_throttling_percentage " "when log_disk_throttling_percentage is not equal to 100"); LOG_WARN("config invalid", "item", *item, K(ret), K(i), K(item->tenant_ids_.at(i))); } } } else if (0 == STRCMP(item->name_.ptr(), LOG_DISK_THROTTLING_PERCENTAGE)) { // check log_disk_throttling_percentage for (int i = 0; i < item->tenant_ids_.count() && valid; i++) { valid = valid && ObConfigLogDiskThrottlingPercentageIntChecker::check(item->tenant_ids_.at(i), *item); if (!valid) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "log_disk_throttling_percentage should be equal to 100 or smaller than log_disk_utilization_limit_threshold"); LOG_WARN("config invalid", "item", *item, K(ret), K(i), K(item->tenant_ids_.at(i))); } } } } return ret; } int ObRootService::set_config_post_hook(const obrpc::ObAdminSetConfigArg &arg) { int ret = OB_SUCCESS; if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(arg)); } FOREACH_X(item, arg.items_, OB_SUCCESS == ret) { if (item->name_.is_empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("empty config name", "item", *item, K(ret)); } else if (0 == STRCMP(item->name_.ptr(), ENABLE_REBALANCE) || 0 == STRCMP(item->name_.ptr(), ENABLE_REREPLICATION)) { // TODO: @wanhong.wwh SUPPORT clear DR task after disable rebalance and rereplication } else if (0 == STRCMP(item->name_.ptr(), MERGER_CHECK_INTERVAL)) { //daily_merge_scheduler_.wakeup(); } else if (0 == STRCMP(item->name_.ptr(), ENABLE_AUTO_LEADER_SWITCH)) { //wake_up leader_cooridnator } else if (0 == STRCMP(item->name_.ptr(), OBCONFIG_URL)) { int tmp_ret = OB_SUCCESS; bool force_update = true; if (OB_SUCCESS != (tmp_ret = submit_update_rslist_task(force_update))) { LOG_WARN("fail to submit update rs list task", KR(ret), K(tmp_ret)); } LOG_INFO("obconfig_url parameters updated, force submit update rslist task", KR(tmp_ret), KPC(item)); } else if (0 == STRCMP(item->name_.ptr(), SCHEMA_HISTORY_RECYCLE_INTERVAL)) { schema_history_recycler_.wakeup(); LOG_INFO("schema_history_recycle_interval parameters updated, wakeup schema_history_recycler", KPC(item)); } } return ret; } //ensure execute on DDL thread int ObRootService::force_create_sys_table(const obrpc::ObForceCreateSysTableArg &arg) { return OB_NOT_SUPPORTED; } // set tenant's locality // TODO // 1. set all locality of normal tenant to DEFAULT first. // 2. verify that replica distribution satifies the new locality int ObRootService::force_set_locality(const obrpc::ObForceSetLocalityArg &arg) { LOG_INFO("receive force set locality arg", K(arg)); int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; const ObTenantSchema *tenant_schema = NULL; const uint64_t tenant_id = arg.exec_tenant_id_; if (!inited_) { LOG_WARN("not init", KR(ret)); } else if (!arg.is_valid() || is_meta_tenant(tenant_id)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("fail to get schema guard with version in inner table", KR(ret)); } else if (OB_FAIL(schema_guard.get_tenant_info(tenant_id, tenant_schema))) { LOG_WARN("fail to get tenant schema", KR(ret), K(tenant_id)); } else if (OB_ISNULL(tenant_schema)) { ret = OB_TENANT_NOT_EXIST; LOG_WARN("tenant not exist", KR(ret)); } else { ObTenantSchema new_tenant; if (OB_FAIL(new_tenant.assign(*tenant_schema))) { LOG_WARN("fail to assgin tenant schema", KR(ret), KPC(tenant_schema)); } else if (OB_FAIL(new_tenant.set_locality(arg.locality_))) { LOG_WARN("fail to set locality", KR(ret), K(arg)); } else if (OB_FAIL(new_tenant.set_previous_locality(ObString("")))) { LOG_WARN("fail to reset previous locality", KR(ret), K(arg)); } else if (OB_FAIL(ddl_service_.force_set_locality(schema_guard, new_tenant))) { LOG_WARN("fail to force set locality", K(ret), K(new_tenant)); } } LOG_INFO("force set locality", K(arg)); return ret; } int ObRootService::clear_special_cluster_schema_status() { int ret = OB_SUCCESS; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", KR(ret)); } else { ObSchemaService *schema_service = schema_service_->get_schema_service(); if (OB_ISNULL(schema_service)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", K(ret)); } else { schema_service->set_cluster_schema_status( ObClusterSchemaStatus::NORMAL_STATUS); } } return ret; } int ObRootService::get_is_in_bootstrap(bool &is_bootstrap) const { int ret = OB_SUCCESS; is_bootstrap = false; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", KR(ret)); } else { ObSchemaService *schema_service = schema_service_->get_schema_service(); if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", KR(ret)); } else if (ObClusterSchemaStatus::BOOTSTRAP_STATUS == schema_service->get_cluster_schema_status()) { is_bootstrap = true; } } return ret; } int ObRootService::log_nop_operation(const obrpc::ObDDLNopOpreatorArg &arg) { int ret = OB_SUCCESS; LOG_INFO("start to log nop operation", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.log_nop_operation(arg))) { LOG_WARN("failed to log nop operation", K(ret), K(arg)); } return ret; } // if tenant_id = OB_INVALID_TENANT_ID, indicates refresh all tenants's schema; // otherwise, refresh specify tenant's schema. ensure schema_version not fallback by outer layer logic. int ObRootService::broadcast_schema(const obrpc::ObBroadcastSchemaArg &arg) { int ret = OB_SUCCESS; LOG_INFO("receieve broadcast_schema request", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_ISNULL(schema_service_) || OB_ISNULL(schema_service_->get_schema_service())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", K(ret), KP_(schema_service)); } else { ObRefreshSchemaInfo schema_info; ObSchemaService *schema_service = schema_service_->get_schema_service(); if (OB_INVALID_TENANT_ID != arg.tenant_id_) { // tenant_id is valid, just refresh specify tenant's schema. schema_info.set_tenant_id(arg.tenant_id_); schema_info.set_schema_version(arg.schema_version_); } else { // tenant_id = OB_INVALID_TENANT_ID, indicates refresh all tenants's schema; if (OB_FAIL(schema_service->inc_sequence_id())) { LOG_WARN("increase sequence_id failed", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(schema_service->inc_sequence_id())) { LOG_WARN("increase sequence_id failed", K(ret)); } else if (OB_FAIL(schema_service->set_refresh_schema_info(schema_info))) { LOG_WARN("fail to set refresh schema info", K(ret), K(schema_info)); } } LOG_INFO("end broadcast_schema request", K(ret), K(arg)); return ret; } /* * standby_cluster, will return local tenant's schema_version * primary_cluster, will return tenant's newest schema_version * - schema_version = OB_CORE_SCHEMA_VERSION, indicate the tenant is garbage. * - schema_version = OB_INVALID_VERSION, indicate that it is failed to get schame_version. * - schema_version > OB_CORE_SCHEMA_VERSION, indicate that the schema_version is valid. */ int ObRootService::get_tenant_schema_versions( const obrpc::ObGetSchemaArg &arg, obrpc::ObTenantSchemaVersions &tenant_schema_versions) { int ret = OB_SUCCESS; tenant_schema_versions.reset(); ObSchemaGetterGuard schema_guard; ObArray tenant_ids; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", K(ret)); } else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table( OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("fail to get schema guard", KR(ret)); } else if (OB_FAIL(schema_guard.get_tenant_ids(tenant_ids))) { LOG_WARN("fail to get tenant ids", KR(ret)); } else { int64_t tenant_id = OB_INVALID_TENANT_ID; int64_t schema_version = 0; for (int64_t i = 0; i < tenant_ids.count() && OB_SUCC(ret); i++) { ObSchemaGetterGuard tenant_schema_guard; tenant_id = tenant_ids.at(i); schema_version = 0; if (OB_SYS_TENANT_ID == tenant_id || STANDBY_CLUSTER == ObClusterInfoGetter::get_cluster_role_v2()) { // 对于备库,由于schema_status不在DDL线程推进,且能接受最终一致, // 故只需取本地schema版本即可 if (OB_FAIL(schema_service_->get_tenant_refreshed_schema_version( tenant_id, schema_version))) { LOG_WARN("fail to get tenant refreshed schema version", K(ret), K(tenant_id)); } } else { // for primary cluster, need to get newest schema_version from inner table. ObRefreshSchemaStatus schema_status; schema_status.tenant_id_ = tenant_id; int64_t version_in_inner_table = OB_INVALID_VERSION; bool is_restore = false; if (OB_FAIL(schema_service_->check_tenant_is_restore(&schema_guard, tenant_id, is_restore))) { LOG_WARN("fail to check tenant is restore", KR(ret), K(tenant_id)); } else if (is_restore) { ObSchemaStatusProxy *schema_status_proxy = GCTX.schema_status_proxy_; if (OB_ISNULL(schema_status_proxy)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_status_proxy is null", KR(ret)); } else if (OB_FAIL(schema_status_proxy->get_refresh_schema_status(tenant_id, schema_status))) { LOG_WARN("failed to get tenant refresh schema status", KR(ret), K(tenant_id)); } else if (OB_INVALID_VERSION != schema_status.readable_schema_version_) { ret = OB_EAGAIN; LOG_WARN("tenant's sys replicas are not restored yet, try later", KR(ret), K(tenant_id)); } } if (FAILEDx(schema_service_->get_schema_version_in_inner_table( sql_proxy_, schema_status, version_in_inner_table))) { // failed tenant creation, inner table is empty, return OB_CORE_SCHEMA_VERSION if (OB_EMPTY_RESULT == ret) { LOG_INFO("create tenant maybe failed", K(ret), K(tenant_id)); schema_version = OB_CORE_SCHEMA_VERSION; ret = OB_SUCCESS; } else { LOG_WARN("fail to get latest schema version in inner table", K(ret)); } } else if (OB_FAIL(schema_service_->get_tenant_refreshed_schema_version( tenant_id, schema_version))) { LOG_WARN("fail to get tenant refreshed schema version", K(ret), K(tenant_id)); } else if (schema_version < version_in_inner_table) { ObArray tenant_ids; if (OB_FAIL(tenant_ids.push_back(tenant_id))) { LOG_WARN("fail to push back tenant_id", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_service_->refresh_and_add_schema(tenant_ids))) { LOG_WARN("fail to refresh schema", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_service_->get_tenant_refreshed_schema_version( tenant_id, schema_version))) { LOG_WARN("fail to get tenant refreshed schema version", K(ret), K(tenant_id)); } else if (schema_version < version_in_inner_table) { ret = OB_ERR_UNEXPECTED; LOG_WARN("local version is still less than version in table", K(ret), K(tenant_id), K(schema_version), K(version_in_inner_table)); } else {} } else {} } if (OB_FAIL(ret)) { } else if (OB_FAIL(tenant_schema_versions.add(tenant_id, schema_version))) { LOG_WARN("fail to add tenant schema version", KR(ret), K(tenant_id), K(schema_version)); } if (OB_FAIL(ret) && arg.ignore_fail_ && OB_SYS_TENANT_ID != tenant_id) { int64_t invalid_schema_version = OB_INVALID_SCHEMA_VERSION; if (OB_FAIL(tenant_schema_versions.add(tenant_id, invalid_schema_version))) { LOG_WARN("fail to add tenant schema version", KR(ret), K(tenant_id), K(schema_version)); } } } // end for } return ret; } int ObRootService::generate_user(const ObClusterRole &cluster_role, const char* user_name, const char* user_passwd) { int ret = OB_SUCCESS; ObSqlString ddl_stmt_str; int64_t affected_row = 0; ObString passwd(user_passwd); ObString encry_passwd; char enc_buf[ENC_BUF_LEN] = {0}; if (OB_ISNULL(user_name) || OB_ISNULL(user_passwd)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(user_name), K(user_passwd)); } else if (PRIMARY_CLUSTER != cluster_role) { LOG_INFO("standby cluster, no need to create user", K(cluster_role)); } else if (OB_FAIL(sql::ObCreateUserExecutor::encrypt_passwd(passwd, encry_passwd, enc_buf, ENC_BUF_LEN))) { LOG_WARN("Encrypt passwd failed", K(ret)); } else if (OB_FAIL(ObDDLSqlGenerator::gen_create_user_sql(ObAccountArg(user_name, OB_SYS_HOST_NAME), encry_passwd, ddl_stmt_str))) { LOG_WARN("fail to gen create user sql", KR(ret)); } else if (OB_FAIL(sql_proxy_.write(ddl_stmt_str.ptr(), affected_row))) { LOG_WARN("execute sql failed", K(ret), K(ddl_stmt_str)); } else { LOG_INFO("create user success", K(user_name), K(affected_row)); } ddl_stmt_str.reset(); if (OB_FAIL(ret) || PRIMARY_CLUSTER != cluster_role) { //nothing todo } else if (OB_FAIL(ddl_stmt_str.assign_fmt("grant select on *.* to '%s'", user_name))) { LOG_WARN("fail to assign fmt", KR(ret)); } else if (OB_FAIL(sql_proxy_.write(ddl_stmt_str.ptr(), affected_row))) { LOG_WARN("fail to write", KR(ret), K(ddl_stmt_str)); } else { LOG_INFO("grant privilege success", K(ddl_stmt_str)); } return ret; } int ObRootService::get_recycle_schema_versions( const obrpc::ObGetRecycleSchemaVersionsArg &arg, obrpc::ObGetRecycleSchemaVersionsResult &result) { int ret = OB_SUCCESS; LOG_INFO("receive get recycle schema versions request", K(arg)); bool is_standby = GCTX.is_standby_cluster(); bool in_service = is_full_service(); if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("arg is invalid", K(ret), K(arg)); } else if (!is_standby || !in_service) { ret = OB_STATE_NOT_MATCH; LOG_WARN("should be standby cluster and rs in service", KR(ret), K(is_standby), K(in_service)); } else if (OB_FAIL(schema_history_recycler_.get_recycle_schema_versions(arg, result))) { LOG_WARN("fail to get recycle schema versions", KR(ret), K(arg)); } LOG_INFO("get recycle schema versions", KR(ret), K(arg), K(result)); return ret; } int ObRootService::do_profile_ddl(const obrpc::ObProfileDDLArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ddl_service_.handle_profile_ddl(arg))) { LOG_WARN("handle ddl failed", K(arg), K(ret)); } return ret; } int ObRootService::rebuild_index_in_restore( const obrpc::ObRebuildIndexInRestoreArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); return ret; } int ObRootService::handle_archive_log(const obrpc::ObArchiveLogArg &arg) { int ret = OB_SUCCESS; LOG_INFO("handle_archive_log", K(arg)); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ObBackupServiceProxy::handle_archive_log(arg))) { LOG_WARN("failed to handle archive log", K(ret)); } return ret; } int ObRootService::handle_backup_database(const obrpc::ObBackupDatabaseArg &in_arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ObBackupServiceProxy::handle_backup_database(in_arg))) { LOG_WARN("failed to handle backup database", K(ret), K(in_arg)); } FLOG_INFO("handle_backup_database", K(ret), K(in_arg)); return ret; } int ObRootService::handle_validate_database(const obrpc::ObBackupManageArg &arg) { int ret = OB_NOT_SUPPORTED; LOG_ERROR("not supported now", K(ret), K(arg)); return ret; } int ObRootService::handle_validate_backupset(const obrpc::ObBackupManageArg &arg) { int ret = OB_NOT_SUPPORTED; LOG_ERROR("not supported now", K(ret), K(arg)); return ret; } int ObRootService::handle_cancel_validate(const obrpc::ObBackupManageArg &arg) { int ret = OB_NOT_SUPPORTED; LOG_ERROR("not supported now", K(ret), K(arg)); return ret; } int ObRootService::disaster_recovery_task_reply( const obrpc::ObDRTaskReplyResult &arg) { int ret = OB_SUCCESS; DEBUG_SYNC(BEFORE_RS_DEAL_WITH_RPC); FLOG_INFO("[DRTASK_NOTICE] receive disaster recovery task reply", K(arg)); if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", KR(ret), K(arg)); } else if (OB_FAIL(disaster_recovery_task_mgr_.deal_with_task_reply(arg))) { LOG_WARN("fail to execute over", KR(ret), K(arg)); } return ret; } int ObRootService::handle_backup_manage(const obrpc::ObBackupManageArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else { switch (arg.type_) { case ObBackupManageArg::CANCEL_BACKUP: { if (OB_FAIL(handle_backup_database_cancel(arg))) { LOG_WARN("failed to handle backup database cancel", K(ret), K(arg)); } break; }; case ObBackupManageArg::VALIDATE_DATABASE: { if (OB_FAIL(handle_validate_database(arg))) { LOG_WARN("failed to handle validate database", K(ret), K(arg)); } break; }; case ObBackupManageArg::VALIDATE_BACKUPSET: { if (OB_FAIL(handle_validate_backupset(arg))) { LOG_WARN("failed to handle validate backupset", K(ret), K(arg)); } break; }; case ObBackupManageArg::CANCEL_VALIDATE: { if (OB_FAIL(handle_cancel_validate(arg))) { LOG_WARN("failed to handle cancel validate", K(ret), K(arg)); } break; }; case ObBackupManageArg::CANCEL_BACKUP_BACKUPSET: { if (OB_FAIL(handle_cancel_backup_backup(arg))) { LOG_WARN("failed to handle cancel backup backup", K(ret), K(arg)); } break; } case ObBackupManageArg::CANCEL_BACKUP_BACKUPPIECE: { if (OB_FAIL(handle_cancel_backup_backup(arg))) { LOG_WARN("failed to handle cancel backup backup", K(ret), K(arg)); } break; } case ObBackupManageArg::CANCEL_ALL_BACKUP_FORCE: { if (OB_FAIL(handle_cancel_all_backup_force(arg))) { LOG_WARN("failed to handle cancel all backup force", K(ret), K(arg)); } break; }; default: { ret = OB_INVALID_ARGUMENT; LOG_ERROR("invalid backup manage arg", K(ret), K(arg)); break; } } } FLOG_INFO("finish handle_backup_manage", K(ret), K(arg)); return ret; } int ObRootService::handle_backup_delete(const obrpc::ObBackupCleanArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ObBackupServiceProxy::handle_backup_delete(arg))) { LOG_WARN("failed to handle backup delete", K(ret), K(arg)); } return ret; } int ObRootService::handle_delete_policy(const obrpc::ObDeletePolicyArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(ObBackupServiceProxy::handle_delete_policy(arg))) { LOG_WARN("failed to handle delete policy", K(ret), K(arg)); } return ret; } int ObRootService::handle_backup_database_cancel( const obrpc::ObBackupManageArg &arg) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (ObBackupManageArg::CANCEL_BACKUP != arg.type_) { ret = OB_INVALID_ARGUMENT; LOG_WARN("handle backup database cancel get invalid argument", K(ret), K(arg)); } else if (OB_FAIL(ObBackupServiceProxy::handle_backup_database_cancel(arg))) { LOG_WARN("failed to start schedule backup cancel", K(ret), K(arg)); } return ret; } int ObRootService::check_backup_scheduler_working(Bool &is_working) { int ret = OB_NOT_SUPPORTED; is_working = true; FLOG_INFO("not support check backup scheduler working, should not use anymore", K(ret), K(is_working)); return ret; } ObRootService::ObTenantGlobalContextCleanTimerTask::ObTenantGlobalContextCleanTimerTask( ObRootService &root_service) : root_service_(root_service) { } int ObRootService::ObTenantGlobalContextCleanTimerTask::schedule(int tg_id) { return TG_SCHEDULE(tg_id, *this, SCHEDULE_PERIOD, true); } void ObRootService::ObTenantGlobalContextCleanTimerTask::runTimerTask() { int ret = OB_SUCCESS; if (OB_FAIL(root_service_.clean_global_context())) { LOG_WARN("failed to clean global context", K(ret)); } } int ObRootService::handle_cancel_backup_backup(const obrpc::ObBackupManageArg &arg) { int ret = OB_NOT_SUPPORTED; LOG_ERROR("not supported now", K(ret), K(arg)); return ret; } int ObRootService::handle_cancel_all_backup_force(const obrpc::ObBackupManageArg &arg) { int ret = OB_NOT_SUPPORTED; LOG_ERROR("not support now", K(ret), K(arg)); return ret; } void ObRootService::reset_fail_count() { ATOMIC_STORE(&fail_count_, 0); } void ObRootService::update_fail_count(int ret) { int64_t count = ATOMIC_AAF(&fail_count_, 1); if (count > OB_ROOT_SERVICE_START_FAIL_COUNT_UPPER_LIMIT && REACH_TIME_INTERVAL(60 * 1000 * 1000)) { LOG_ERROR("rs_monitor_check : fail to start root service", KR(ret), K(count)); } else { LOG_WARN("rs_monitor_check : fail to start root service", KR(ret), K(count)); } LOG_DBA_WARN(OB_ERR_ROOTSERVICE_START, "msg", "rootservice start()/do_restart() has failure", KR(ret), "fail_cnt", count); } int ObRootService::send_physical_restore_result(const obrpc::ObPhysicalRestoreResult &res) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!res.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(res)); } else { ret = OB_NOT_SUPPORTED; //TODO set physical restore result } LOG_INFO("get physical restore job's result", K(ret), K(res)); return ret; } int ObRootService::create_restore_point(const obrpc::ObCreateRestorePointArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); LOG_WARN("craete restpre point is not supported now", K(ret)); return ret; } int ObRootService::drop_restore_point(const obrpc::ObDropRestorePointArg &arg) { int ret = OB_NOT_SUPPORTED; UNUSED(arg); LOG_WARN("drop restpre point is not supported now", K(ret)); return ret; } int ObRootService::build_ddl_single_replica_response(const obrpc::ObDDLBuildSingleReplicaResponseArg &arg) { int ret = OB_SUCCESS; LOG_INFO("receive build ddl single replica response", K(arg)); ObDDLTaskInfo info; info.row_scanned_ = arg.row_scanned_; info.row_inserted_ = arg.row_inserted_; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not inited", K(ret)); } else if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(arg)); } else if (OB_FAIL(ddl_scheduler_.on_sstable_complement_job_reply( arg.tablet_id_/*source tablet id*/, ObDDLTaskKey(arg.tenant_id_, arg.dest_schema_id_, arg.schema_version_), arg.snapshot_version_, arg.execution_id_, arg.ret_code_, info))) { LOG_WARN("handle column checksum calc response failed", K(ret), K(arg)); } return ret; } int ObRootService::purge_recyclebin_objects(int64_t purge_each_time) { int ret = OB_SUCCESS; // always passed int64_t expire_timeval = GCONF.recyclebin_object_expire_time; ObSEArray tenant_ids; ObSchemaGetterGuard guard; if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_serviece_ is null", KR(ret)); } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) { LOG_WARN("fail to get sys schema guard", KR(ret)); } else if (OB_FAIL(guard.get_tenant_ids(tenant_ids))) { LOG_WARN("get all tenants failed", KR(ret)); } else { const int64_t current_time = ObTimeUtility::current_time(); obrpc::Int64 expire_time = current_time - expire_timeval; const int64_t SLEEP_INTERVAL = 100 * 1000; //100ms interval of send rpc const int64_t PURGE_EACH_RPC = 10; //delete count per rpc obrpc::Int64 affected_rows = 0; obrpc::ObPurgeRecycleBinArg arg; int64_t purge_sum = purge_each_time; const bool is_standby = PRIMARY_CLUSTER != ObClusterInfoGetter::get_cluster_role_v2(); const ObSimpleTenantSchema *simple_tenant = NULL; //ignore ret for (int i = 0; i < tenant_ids.count() && in_service() && purge_sum > 0; ++i) { int64_t purge_time = GCONF._recyclebin_object_purge_frequency; const uint64_t tenant_id = tenant_ids.at(i); if (purge_time <= 0) { break; } if (OB_SYS_TENANT_ID != tenant_id && is_standby) { // standby cluster won't purge recyclebin automacially. LOG_TRACE("user tenant won't purge recyclebin automacially in standby cluster", K(tenant_id)); continue; } else if (OB_FAIL(guard.get_tenant_info(tenant_id, simple_tenant))) { LOG_WARN("fail to get simple tenant schema", KR(ret), K(tenant_id)); } else if (OB_ISNULL(simple_tenant)) { ret = OB_TENANT_NOT_EXIST; LOG_WARN("simple tenant schema not exist", KR(ret), K(tenant_id)); } else if (!simple_tenant->is_normal()) { // only deal with normal tenant. LOG_TRACE("tenant which isn't normal won't purge recyclebin automacially", K(tenant_id)); continue; } // ignore error code of different tenant ret = OB_SUCCESS; affected_rows = 0; arg.tenant_id_ = tenant_id; arg.expire_time_ = expire_time; arg.auto_purge_ = true; arg.exec_tenant_id_ = tenant_id; LOG_INFO("start purge recycle objects of tenant", K(arg), K(purge_sum)); while (OB_SUCC(ret) && in_service() && purge_sum > 0) { int64_t start_time = ObTimeUtility::current_time(); arg.purge_num_ = purge_sum > PURGE_EACH_RPC ? PURGE_EACH_RPC : purge_sum; // replcace timeout from hardcode 9s to 10 * GCONF.rpc_timeout if (OB_FAIL(common_proxy_.timeout(10 * GCONF.rpc_timeout).purge_expire_recycle_objects(arg, affected_rows))) { LOG_WARN("purge reyclebin objects failed", KR(ret), K(current_time), K(expire_time), K(affected_rows), K(arg)); } else { purge_sum -= affected_rows; if (arg.purge_num_ != affected_rows) { int64_t cost_time = ObTimeUtility::current_time() - start_time; LOG_INFO("purge recycle objects", KR(ret), K(cost_time), K(expire_time), K(current_time), K(affected_rows)); if (OB_SUCC(ret) && in_service()) { ob_usleep(SLEEP_INTERVAL); } break; } } int64_t cost_time = ObTimeUtility::current_time() - start_time; LOG_INFO("purge recycle objects", KR(ret), K(cost_time), K(expire_time), K(current_time), K(affected_rows)); if (OB_SUCC(ret) && in_service()) { ob_usleep(SLEEP_INTERVAL); } } } } return ret; } int ObRootService::flush_opt_stat_monitoring_info(const obrpc::ObFlushOptStatArg &arg) { int ret = OB_SUCCESS; ObZone empty_zone; ObSEArray server_list; if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (OB_FAIL(SVR_TRACER.get_alive_servers(empty_zone, server_list))) { LOG_WARN("fail to get alive server", KR(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < server_list.count(); ++i) { if (OB_FAIL(rpc_proxy_.to(server_list.at(i)).flush_local_opt_stat_monitoring_info(arg))) { LOG_WARN("fail to update table statistic", K(ret), K(server_list.at(i))); } else { /*do nothing*/} } } return ret; } int ObRootService::clean_global_context() { int ret = OB_SUCCESS; ObArray tenant_ids; ObSchemaGetterGuard schema_guard; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not inited", KR(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is null", KR(ret)); } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("get schema guard failed", KR(ret)); } else if (OB_FAIL(schema_guard.get_tenant_ids(tenant_ids))) { LOG_WARN("failed to get all tenant ids", KR(ret), K(tenant_ids)); } else { ObGlobalContextOperator ctx_operator; if (OB_FAIL(ctx_operator.clean_global_context(tenant_ids, sql_proxy_, *schema_service_))) { LOG_WARN("failed to clean global context", K(ret)); } } return ret; } int ObRootService::admin_set_backup_config(const obrpc::ObAdminSetConfigArg &arg) { int ret = OB_SUCCESS; if (!arg.is_valid()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid backup config arg", K(ret)); } else if (!arg.is_backup_config_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("admin set config type not backup config", K(ret), K(arg)); } share::BackupConfigItemPair config_item; share::ObBackupConfigParserMgr config_parser_mgr; ARRAY_FOREACH_X(arg.items_, i , cnt, OB_SUCC(ret)) { const ObAdminSetConfigItem &item = arg.items_.at(i); uint64_t exec_tenant_id = OB_INVALID_TENANT_ID; ObMySQLTransaction trans; config_parser_mgr.reset(); if ((common::is_sys_tenant(item.exec_tenant_id_) && item.tenant_name_.is_empty()) || (common::is_user_tenant(item.exec_tenant_id_) && !item.tenant_name_.is_empty()) || common::is_meta_tenant(item.exec_tenant_id_)) { ret = OB_NOT_SUPPORTED; LOG_WARN("backup config only support user tenant", K(ret)); } else if (!item.tenant_name_.is_empty()) { schema::ObSchemaGetterGuard guard; if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service must not be null", K(ret)); } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) { LOG_WARN("fail to get tenant schema guard", K(ret)); } else if (OB_FAIL(guard.get_tenant_id(ObString(item.tenant_name_.ptr()), exec_tenant_id))) { LOG_WARN("fail to get tenant id", K(ret)); } } else { exec_tenant_id = item.exec_tenant_id_; } if (OB_FAIL(ret)) { } else if (OB_FAIL(trans.start(&sql_proxy_, gen_meta_tenant_id(exec_tenant_id)))) { LOG_WARN("fail to start trans", K(ret)); } else { common::ObSqlString name; common::ObSqlString value; if (OB_FAIL(name.assign(item.name_.ptr()))) { LOG_WARN("fail to assign name", K(ret)); } else if (OB_FAIL(value.assign(item.value_.ptr()))) { LOG_WARN("fail to assign value", K(ret)); } else if (OB_FAIL(config_parser_mgr.init(name, value, exec_tenant_id))) { LOG_WARN("fail to init backup config parser mgr", K(ret), K(item)); } else if (OB_FAIL(config_parser_mgr.update_inner_config_table(rpc_proxy_, trans))) { LOG_WARN("fail to update inner config table", K(ret)); } if (OB_SUCC(ret)) { if (OB_FAIL(trans.end(true))) { LOG_WARN("fail to commit trans", K(ret)); } } else { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = trans.end(false))) { LOG_WARN("fail to rollback trans", K(tmp_ret)); } } } } return ret; } int ObRootService::cancel_ddl_task(const ObCancelDDLTaskArg &arg) { int ret = OB_SUCCESS; LOG_INFO("receive cancel ddl task", K(arg)); if (OB_UNLIKELY(!arg.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(arg)); } else if (OB_FAIL(SYS_TASK_STATUS_MGR.cancel_task(arg.get_task_id()))) { LOG_WARN("cancel task failed", K(ret)); } else { LOG_INFO("succeed to cancel ddl task", K(arg)); } return ret; } int ObRootService::check_majority_and_log_in_sync( const ObIArray &to_stop_servers, const bool skip_log_sync_check, const char *print_str) { int ret = OB_SUCCESS; ObLSStatusOperator ls_status_op; bool need_retry = false; const int64_t CHECK_RETRY_INTERVAL = 100 * 1000; // 100ms const int64_t RESERVED_TIME = 500 * 1000; // 500ms int64_t start_time = ObTimeUtility::current_time(); int64_t abs_timeout_us = OB_INVALID_TIMESTAMP; ObTimeoutCtx ctx; const int64_t DEFAULT_RETRY_TIMEOUT = GCONF.internal_sql_execute_timeout; LOG_INFO("check majority and log in sync start", K(to_stop_servers), K(skip_log_sync_check), K(DEFAULT_RETRY_TIMEOUT)); if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_ISNULL(schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", KR(ret)); } else if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, DEFAULT_RETRY_TIMEOUT))) { LOG_WARN("failed to set default timeout ctx", KR(ret), K(DEFAULT_RETRY_TIMEOUT)); } else { abs_timeout_us = ctx.get_abs_timeout() - RESERVED_TIME; if (OB_FAIL(ctx.set_abs_timeout(abs_timeout_us))) { LOG_WARN("fail to set abs timeout", KR(ret), K(abs_timeout_us)); } else { do { if (need_retry) { ob_usleep(CHECK_RETRY_INTERVAL); } if (OB_FAIL(ls_status_op.check_all_ls_has_majority_and_log_sync( to_stop_servers, skip_log_sync_check, print_str, *schema_service_, sql_proxy_, need_retry))) { LOG_WARN("fail to get and check all ls_paxos_info", KR(ret), K(to_stop_servers), K(skip_log_sync_check)); } } while ((OB_OP_NOT_ALLOW == ret) && need_retry); } } LOG_INFO("check majority and log in sync finish", K(to_stop_servers), K(skip_log_sync_check), "cost_time", ObTimeUtility::current_time() - start_time); return ret; } int ObRootService::check_all_ls_has_leader(const char *print_str) { int ret = OB_SUCCESS; ObLSStatusOperator ls_status_op; const int64_t CHECK_RETRY_INTERVAL = 100 * 1000; // 100ms const int64_t RESERVED_TIME = 500 * 1000; // 500ms int64_t start_time = ObTimeUtility::current_time(); int64_t abs_timeout_us = OB_INVALID_TIMESTAMP; bool has_ls_without_leader = false; ObTimeoutCtx ctx; const int64_t DEFAULT_RETRY_TIMEOUT = GCONF.internal_sql_execute_timeout; ObSqlString last_error_msg; if (OB_UNLIKELY(!inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", KR(ret)); } else if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, DEFAULT_RETRY_TIMEOUT))) { LOG_WARN("failed to set default timeout ctx", KR(ret), K(DEFAULT_RETRY_TIMEOUT)); } else { abs_timeout_us = ctx.get_abs_timeout() - RESERVED_TIME; if (OB_FAIL(ctx.set_abs_timeout(abs_timeout_us))) { LOG_WARN("fail to set abs timeout", KR(ret), K(abs_timeout_us)); } else { do { if (has_ls_without_leader) { ob_usleep(CHECK_RETRY_INTERVAL); } if (OB_FAIL(ls_status_op.check_all_ls_has_leader( sql_proxy_, print_str, has_ls_without_leader, last_error_msg))) { LOG_WARN("fail to check all ls has leader", KR(ret), K(print_str)); } } while (OB_OP_NOT_ALLOW == ret && has_ls_without_leader); } } if (OB_TIMEOUT == ret) { ret = OB_OP_NOT_ALLOW; if (!last_error_msg.empty()) { LOG_USER_ERROR(OB_OP_NOT_ALLOW, last_error_msg.ptr()); } else { LOG_WARN("fail to check all ls has leader because inner sql timeout", KR(ret), K(print_str)); char err_msg[OB_TMP_BUF_SIZE_256]; (void)snprintf(err_msg, sizeof(err_msg), "check leader for all LS timeout, %s", print_str); LOG_USER_ERROR(OB_OP_NOT_ALLOW, err_msg); } } LOG_INFO("check all ls has leader finish", KR(ret), K(abs_timeout_us), K(start_time), "cost_time", ObTimeUtility::current_time() - start_time); return ret; } void ObRootService::update_cpu_quota_concurrency_in_memory_() { { omt::ObTenantConfigGuard tenant_config(TENANT_CONF(OB_SYS_TENANT_ID)); tenant_config->cpu_quota_concurrency = MAX(10, tenant_config->cpu_quota_concurrency); } } int ObRootService::set_cpu_quota_concurrency_config_() { int64_t affected_rows = 0; int ret = OB_SUCCESS; if (OB_FAIL(sql_proxy_.write("ALTER SYSTEM SET cpu_quota_concurrency = 10;", affected_rows))) { LOG_WARN("update cpu_quota_concurrency failed", K(ret)); } else if (OB_FAIL(check_config_result("cpu_quota_concurrency", "10"))) { LOG_WARN("failed to check config same", K(ret)); } return ret; } int ObRootService::recompile_all_views_batch(const obrpc::ObRecompileAllViewsBatchArg &arg) { int ret = OB_SUCCESS; int64_t start_time = ObTimeUtility::current_time(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.recompile_all_views_batch(arg.tenant_id_, arg.view_ids_))) { LOG_WARN("failed to recompile all views", K(ret), K(arg.tenant_id_)); } LOG_INFO("recompile all views batch finish", KR(ret), K(start_time), "cost_time", ObTimeUtility::current_time() - start_time); return ret; } int ObRootService::try_add_dep_infos_for_synonym_batch(const obrpc::ObTryAddDepInofsForSynonymBatchArg &arg) { int ret = OB_SUCCESS; int64_t start_time = ObTimeUtility::current_time(); if (!inited_) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); } else if (OB_FAIL(ddl_service_.try_add_dep_info_for_all_synonyms_batch(arg.tenant_id_, arg.synonym_ids_))) { LOG_WARN("failed to add synonym dep info", K(ret), K(arg.tenant_id_)); } LOG_INFO("add dep infos for synonym batch finish", KR(ret), K(start_time), "cost_time", ObTimeUtility::current_time() - start_time); return ret; } } // end namespace rootserver } // end namespace oceanbase