oceanbase
11941 строка · 487.5 Кб
1/**
2* Copyright (c) 2021 OceanBase
3* OceanBase CE is licensed under Mulan PubL v2.
4* You can use this software according to the terms and conditions of the Mulan PubL v2.
5* You may obtain a copy of Mulan PubL v2 at:
6* http://license.coscl.org.cn/MulanPubL-2.0
7* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10* See the Mulan PubL v2 for more details.
11*/
12
13#define USING_LOG_PREFIX RS
14
15#include "ob_unit_manager.h"
16
17#include <cmath>
18#include <float.h>
19
20#include "lib/string/ob_sql_string.h"
21#include "lib/allocator/ob_mod_define.h"
22#include "lib/time/ob_time_utility.h"
23#include "lib/container/ob_array_iterator.h"
24#include "lib/mysqlclient/ob_mysql_proxy.h"
25#include "lib/mysqlclient/ob_mysql_transaction.h"
26#include "lib/utility/ob_tracepoint.h"
27#include "share/ob_unit_getter.h"
28#include "share/ob_unit_stat.h"
29#include "share/ob_debug_sync.h"
30#include "share/ob_srv_rpc_proxy.h"
31#include "share/config/ob_server_config.h"
32#include "share/ob_schema_status_proxy.h"
33#include "share/ob_dml_sql_splicer.h"
34#include "share/ob_max_id_fetcher.h"
35#include "share/inner_table/ob_inner_table_schema.h"
36#include "share/ob_tenant_memstore_info_operator.h"
37#include "share/ob_rpc_struct.h"
38#include "storage/ob_file_system_router.h"
39#include "observer/ob_server_struct.h"
40#include "observer/omt/ob_tenant_node_balancer.h"
41#include "rootserver/ob_balance_info.h"
42#include "rootserver/ob_zone_manager.h"
43#include "rootserver/ob_rs_event_history_table_operator.h"
44#include "rootserver/ob_unit_placement_strategy.h"
45#include "rootserver/ob_rs_job_table_operator.h"
46#include "rootserver/ob_root_service.h"
47#include "rootserver/ob_root_balancer.h"
48#include "rootserver/ob_server_manager.h"
49#include "storage/ob_file_system_router.h"
50#include "share/ob_all_server_tracer.h"
51#include "rootserver/ob_heartbeat_service.h"
52
53namespace oceanbase
54{
55using namespace common;
56using namespace common::sqlclient;
57using namespace common::hash;
58using namespace share;
59using namespace share::schema;
60namespace rootserver
61{
62
63int ObUnitManager::ZoneUnitPtr::assign(const ZoneUnitPtr &other)
64{
65int ret = OB_SUCCESS;
66zone_ = other.zone_;
67if (OB_FAIL(copy_assign(unit_ptrs_, other.unit_ptrs_))) {
68LOG_WARN("fail to assign unit_ptrs", K(ret));
69}
70return ret;
71}
72
73int ObUnitManager::ZoneUnitPtr::sort_by_unit_id_desc()
74{
75UnitGroupIdCmp cmp;
76std::sort(unit_ptrs_.begin(), unit_ptrs_.end(), cmp);
77return cmp.get_ret();
78}
79
80int ObUnitManager::ZoneUnit::assign(const ZoneUnit &other)
81{
82int ret = OB_SUCCESS;
83zone_ = other.zone_;
84if (OB_FAIL(copy_assign(unit_infos_, other.unit_infos_))) {
85LOG_WARN("failed to assign unit_infos_", K(ret));
86}
87return ret;
88}
89////////////////////////////////////////////////////////////////
90double ObUnitManager::ObUnitLoad::get_demand(ObResourceType resource_type) const
91{
92double ret = -1;
93switch (resource_type) {
94case RES_CPU:
95ret = unit_config_->min_cpu();
96break;
97case RES_MEM:
98ret = static_cast<double>(unit_config_->memory_size());
99break;
100case RES_LOG_DISK:
101ret = static_cast<double>(unit_config_->log_disk_size());
102break;
103default:
104ret = -1;
105break;
106}
107return ret;
108}
109
110const char *ObUnitManager::end_migrate_op_type_to_str(const ObUnitManager::EndMigrateOp &t)
111{
112const char* str = "UNKNOWN";
113if (EndMigrateOp::COMMIT == t) {
114str = "COMMIT";
115} else if (EndMigrateOp::ABORT == t) {
116str = "ABORT";
117} else if (EndMigrateOp::REVERSE == t) {
118str = "REVERSE";
119} else {
120str = "NONE";
121}
122return str;
123}
124////////////////////////////////////////////////////////////////
125ObUnitManager::ObUnitManager(ObServerManager &server_mgr, ObZoneManager &zone_mgr)
126: inited_(false), loaded_(false), proxy_(NULL), server_config_(NULL),
127srv_rpc_proxy_(NULL), server_mgr_(server_mgr),
128zone_mgr_(zone_mgr), ut_operator_(), id_config_map_(),
129name_config_map_(), config_ref_count_map_(), config_pools_map_(),
130config_pools_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
131config_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
132id_pool_map_(), name_pool_map_(),
133pool_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
134pool_unit_map_(),
135pool_unit_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
136id_unit_map_(),
137allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
138server_loads_(),
139load_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
140tenant_pools_map_(),
141tenant_pools_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
142server_migrate_units_map_(),
143migrate_units_allocator_(OB_MALLOC_NORMAL_BLOCK_SIZE, ObMalloc(ObModIds::OB_RS_UNIT_MANAGER)),
144lock_(ObLatchIds::UNIT_MANAGER_LOCK),
145schema_service_(NULL), root_balance_(NULL)
146{
147}
148
149ObUnitManager::~ObUnitManager()
150{
151ObHashMap<uint64_t, ObArray<share::ObResourcePool *> *>::iterator iter1;
152for (iter1 = config_pools_map_.begin(); iter1 != config_pools_map_.end(); ++iter1) {
153ObArray<share::ObResourcePool *> *ptr = iter1->second;
154if (NULL != ptr) {
155ptr->reset();
156ptr = NULL;
157}
158}
159ObHashMap<uint64_t, ObArray<ObUnit *> *>::iterator iter2;
160for (iter2 = pool_unit_map_.begin(); iter2 != pool_unit_map_.end(); ++iter2) {
161ObArray<share::ObUnit *> *ptr = iter2->second;
162if (NULL != ptr) {
163ptr->reset();
164ptr = NULL;
165}
166}
167ObHashMap<ObAddr, ObArray<ObUnitLoad> *>::iterator iter3;
168for (iter3 = server_loads_.begin(); iter3 != server_loads_.end(); ++iter3) {
169ObArray<ObUnitLoad> *ptr = iter3->second;
170if (NULL != ptr) {
171ptr->reset();
172ptr = NULL;
173}
174}
175TenantPoolsMap::iterator iter4;
176for (iter4 = tenant_pools_map_.begin(); iter4 != tenant_pools_map_.end(); ++iter4) {
177common::ObArray<share::ObResourcePool *> *ptr = iter4->second;
178if (NULL != ptr) {
179ptr->reset();
180ptr = NULL;
181}
182}
183ObHashMap<ObAddr, ObArray<uint64_t> *>::iterator iter5;
184for (iter5 = server_migrate_units_map_.begin();
185iter5 != server_migrate_units_map_.end();
186++iter5) {
187common::ObArray<uint64_t> *ptr = iter5->second;
188if (NULL != ptr) {
189ptr->reset();
190ptr = NULL;
191}
192}
193}
194
195int ObUnitManager::init(ObMySQLProxy &proxy,
196ObServerConfig &server_config,
197obrpc::ObSrvRpcProxy &srv_rpc_proxy,
198share::schema::ObMultiVersionSchemaService &schema_service,
199ObRootBalancer &root_balance,
200ObRootService &root_service)
201{
202int ret = OB_SUCCESS;
203if (inited_) {
204ret = OB_INIT_TWICE;
205LOG_WARN("init twice", K(ret));
206} else if (OB_FAIL(ut_operator_.init(proxy))) {
207LOG_WARN("init unit table operator failed", K(ret));
208} else if (OB_FAIL(pool_unit_map_.create(
209POOL_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_POOL_UNIT_MAP))) {
210LOG_WARN("pool_unit_map_ create failed", LITERAL_K(POOL_MAP_BUCKET_NUM), K(ret));
211} else if (OB_FAIL(id_unit_map_.create(
212UNIT_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_ID_UNIT_MAP))) {
213LOG_WARN("id_unit_map_ create failed",
214LITERAL_K(UNIT_MAP_BUCKET_NUM), K(ret));
215} else if (OB_FAIL(id_config_map_.create(
216CONFIG_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_ID_CONFIG_MAP))) {
217LOG_WARN("id_config_map_ create failed",
218LITERAL_K(CONFIG_MAP_BUCKET_NUM), K(ret));
219} else if (OB_FAIL(name_config_map_.create(
220CONFIG_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_NAME_CONFIG_MAP))) {
221LOG_WARN("name_config_map_ create failed",
222LITERAL_K(CONFIG_MAP_BUCKET_NUM), K(ret));
223} else if (OB_FAIL(config_ref_count_map_.create(
224CONFIG_REF_COUNT_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_CONFIG_REF_COUNT_MAP))) {
225LOG_WARN("config_ref_count_map_ create failed",
226LITERAL_K(CONFIG_REF_COUNT_MAP_BUCKET_NUM), K(ret));
227} else if (OB_FAIL(config_pools_map_.create(CONFIG_POOLS_MAP_BUCKET_NUM,
228ObModIds::OB_HASH_BUCKET_CONFIG_POOLS_MAP))) {
229LOG_WARN("create config_pools_map failed",
230LITERAL_K(CONFIG_POOLS_MAP_BUCKET_NUM), K(ret));
231} else if (OB_FAIL(id_pool_map_.create(
232POOL_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_ID_POOL_MAP))) {
233LOG_WARN("id_pool_map_ create failed",
234LITERAL_K(POOL_MAP_BUCKET_NUM), K(ret));
235} else if (OB_FAIL(name_pool_map_.create(
236POOL_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_NAME_POOL_MAP))) {
237LOG_WARN("name_pool_map_ create failed",
238LITERAL_K(POOL_MAP_BUCKET_NUM), K(ret));
239} else if (OB_FAIL(server_loads_.create(
240UNITLOAD_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_SERVER_UNITLOAD_MAP))) {
241LOG_WARN("server_loads_ create failed",
242LITERAL_K(UNITLOAD_MAP_BUCKET_NUM), K(ret));
243} else if (OB_FAIL(tenant_pools_map_.create(
244TENANT_POOLS_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_TENANT_POOLS_MAP))) {
245LOG_WARN("tenant_pools_map_ create failed",
246LITERAL_K(TENANT_POOLS_MAP_BUCKET_NUM), K(ret));
247} else if (OB_FAIL(server_migrate_units_map_.create(
248SERVER_MIGRATE_UNITS_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_SERVER_MIGRATE_UNIT_MAP))) {
249LOG_WARN("server_migrate_units_map_ create failed",
250LITERAL_K(SERVER_MIGRATE_UNITS_MAP_BUCKET_NUM), K(ret));
251} else {
252proxy_ = &proxy;
253server_config_ = &server_config;
254srv_rpc_proxy_ = &srv_rpc_proxy;
255root_service_ = &root_service;
256schema_service_ = &schema_service;
257root_balance_ = &root_balance;
258loaded_ = false;
259inited_ = true;
260}
261return ret;
262}
263
264int ObUnitManager::load()
265{
266DEBUG_SYNC(BEFORE_RELOAD_UNIT);
267int ret = OB_SUCCESS;
268SpinWLockGuard guard(lock_);
269if (!inited_) {
270ret = OB_NOT_INIT;
271LOG_WARN("not init", K(ret));
272} else {
273loaded_ = false;
274ObHashMap<uint64_t, ObArray<share::ObResourcePool *> *>::iterator iter1;
275for (iter1 = config_pools_map_.begin(); iter1 != config_pools_map_.end(); ++iter1) {
276ObArray<share::ObResourcePool *> *ptr = iter1->second;
277if (NULL != ptr) {
278ptr->reset();
279ptr = NULL;
280}
281}
282ObHashMap<uint64_t, ObArray<ObUnit *> *>::iterator iter2;
283for (iter2 = pool_unit_map_.begin(); iter2 != pool_unit_map_.end(); ++iter2) {
284ObArray<share::ObUnit *> *ptr = iter2->second;
285if (NULL != ptr) {
286ptr->reset();
287ptr = NULL;
288}
289}
290ObHashMap<ObAddr, ObArray<ObUnitLoad> *>::iterator iter3;
291for (iter3 = server_loads_.begin(); iter3 != server_loads_.end(); ++iter3) {
292ObArray<ObUnitLoad> *ptr = iter3->second;
293if (NULL != ptr) {
294ptr->reset();
295ptr = NULL;
296}
297}
298TenantPoolsMap::iterator iter4;
299for (iter4 = tenant_pools_map_.begin(); iter4 != tenant_pools_map_.end(); ++iter4) {
300common::ObArray<share::ObResourcePool *> *ptr = iter4->second;
301if (NULL != ptr) {
302ptr->reset();
303ptr = NULL;
304}
305}
306ObHashMap<ObAddr, ObArray<uint64_t> *>::iterator iter5;
307for (iter5 = server_migrate_units_map_.begin();
308iter5 != server_migrate_units_map_.end();
309++iter5) {
310common::ObArray<uint64_t> *ptr = iter5->second;
311if (NULL != ptr) {
312ptr->reset();
313ptr = NULL;
314}
315}
316if (OB_FAIL(id_config_map_.clear())) {
317LOG_WARN("id_config_map_ clear failed", K(ret));
318} else if (OB_FAIL(name_config_map_.clear())) {
319LOG_WARN("name_pool_map_ clear failed", K(ret));
320} else if (OB_FAIL(config_ref_count_map_.clear())) {
321LOG_WARN("config_ref_count_map_ clear failed", K(ret));
322} else if (OB_FAIL(config_pools_map_.clear())) {
323LOG_WARN("config_pools_map_ clear failed", K(ret));
324} else if (OB_FAIL(id_pool_map_.clear())) {
325LOG_WARN("id_pool_map_ clear failed", K(ret));
326} else if (OB_FAIL(name_pool_map_.clear())) {
327LOG_WARN("name_pool_map_ clear failed", K(ret));
328} else if (OB_FAIL(pool_unit_map_.clear())) {
329LOG_WARN("pool_unit_map_ clear failed", K(ret));
330} else if (OB_FAIL(id_unit_map_.clear())) {
331LOG_WARN("id_unit_map_ clear failed", K(ret));
332} else if (OB_FAIL(server_loads_.clear())) {
333LOG_WARN("server_loads_ clear failed", K(ret));
334} else if (OB_FAIL(tenant_pools_map_.clear())) {
335LOG_WARN("tenant_pools_map_ clear failed", K(ret));
336} else if (OB_FAIL(server_migrate_units_map_.clear())) {
337LOG_WARN("server_migrate_units_map_ clear failed", K(ret));
338}
339
340// free all memory
341if (OB_SUCC(ret)) {
342config_allocator_.reset();
343config_pools_allocator_.reset();
344pool_allocator_.reset();
345pool_unit_allocator_.reset();
346allocator_.reset();
347load_allocator_.reset();
348tenant_pools_allocator_.reset();
349migrate_units_allocator_.reset();
350}
351
352// load unit config
353ObArray<ObUnitConfig> configs;
354if (OB_SUCC(ret)) {
355if (OB_FAIL(ut_operator_.get_unit_configs(configs))) {
356LOG_WARN("get_unit_configs failed", K(ret));
357} else if (OB_FAIL(build_config_map(configs))) {
358LOG_WARN("build_config_map failed", K(ret));
359}
360}
361
362// load resource pool
363ObArray<share::ObResourcePool> pools;
364if (OB_SUCC(ret)) {
365if (OB_FAIL(ut_operator_.get_resource_pools(pools))) {
366LOG_WARN("get_resource_pools failed", K(ret));
367} else if (OB_FAIL(build_pool_map(pools))) {
368LOG_WARN("build_pool_map failed", K(ret));
369}
370}
371
372// load unit
373ObArray<ObUnit> units;
374if (OB_SUCC(ret)) {
375if (OB_FAIL(ut_operator_.get_units(units))) {
376LOG_WARN("get_units failed", K(ret));
377} else if (OB_FAIL(build_unit_map(units))) {
378LOG_WARN("build_unit_map failed", K(ret));
379}
380}
381
382// build tenant pools
383if (OB_SUCC(ret)) {
384for (ObHashMap<uint64_t, share::ObResourcePool *>::iterator it = id_pool_map_.begin();
385OB_SUCCESS == ret && it != id_pool_map_.end(); ++it) {
386// pool not grant to tenant don't add to tenant_pools_map
387if (NULL == it->second) {
388ret = OB_ERR_UNEXPECTED;
389LOG_WARN("it->second is null", KP(it->second), K(ret));
390} else if (it->second->is_granted_to_tenant()) {
391if (OB_FAIL(insert_tenant_pool(it->second->tenant_id_, it->second))) {
392LOG_WARN("insert_tenant_pool failed", "tenant_id", it->second->tenant_id_,
393"pool", *(it->second), K(ret));
394}
395}
396}
397}
398
399// build server migrate units
400if (OB_SUCC(ret)) {
401FOREACH_CNT_X(unit, units, OB_SUCCESS == ret) {
402if (unit->migrate_from_server_.is_valid()) {
403if (OB_FAIL(insert_migrate_unit(unit->migrate_from_server_, unit->unit_id_))) {
404LOG_WARN("insert_migrate_unit failed", "server", unit->migrate_from_server_,
405"unit_id", unit->unit_id_, K(ret));
406}
407}
408}
409}
410
411if (OB_SUCC(ret)) {
412loaded_ = true;
413}
414}
415LOG_INFO("unit manager load finish", K(ret));
416return ret;
417}
418
419int ObUnitManager::create_unit_config(const ObUnitConfig &unit_config, const bool if_not_exist)
420{
421int ret = OB_SUCCESS;
422SpinWLockGuard guard(lock_);
423if (OB_FAIL(inner_create_unit_config_(unit_config, if_not_exist))) {
424LOG_WARN("fail to create unit config", KR(ret), K(unit_config), K(if_not_exist));
425}
426return ret;
427}
428
429int ObUnitManager::inner_create_unit_config_(const ObUnitConfig &unit_config, const bool if_not_exist)
430{
431int ret = OB_SUCCESS;
432ObUnitConfig *temp_config = NULL;
433ObUnitConfig *new_config = NULL;
434uint64_t unit_config_id = unit_config.unit_config_id();
435const ObUnitConfigName &name = unit_config.name();
436const ObUnitResource &rpc_ur = unit_config.unit_resource();
437ObUnitResource ur = rpc_ur;
438
439LOG_INFO("start create unit config", K(name), K(rpc_ur), K(if_not_exist));
440
441if (!check_inner_stat()) {
442ret = OB_INNER_STAT_ERROR;
443LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
444} else if (name.is_empty()) {
445ret = OB_MISS_ARGUMENT;
446LOG_WARN("miss 'name' argument", KR(ret), K(name));
447LOG_USER_ERROR(OB_MISS_ARGUMENT, "resource unit name");
448} else if (OB_FAIL(ur.init_and_check_valid_for_unit(rpc_ur))) {
449LOG_WARN("init from user specified unit resource and check valid fail", KR(ret), K(rpc_ur));
450} else if (OB_SUCCESS == (ret = get_unit_config_by_name(name, temp_config))) {
451if (NULL == temp_config) {
452ret = OB_ERR_UNEXPECTED;
453LOG_WARN("temp_config is null", KP(temp_config), K(ret));
454} else if (if_not_exist) {
455LOG_USER_NOTE(OB_RESOURCE_UNIT_EXIST, to_cstring(name));
456LOG_INFO("unit config already exist", K(name));
457} else {
458ret = OB_RESOURCE_UNIT_EXIST;
459LOG_USER_ERROR(OB_RESOURCE_UNIT_EXIST, to_cstring(name));
460LOG_WARN("unit config already exist", K(name), KR(ret));
461}
462} else if (OB_ENTRY_NOT_EXIST != ret) {
463LOG_WARN("get_unit_config_by_name failed", "config_name", name, KR(ret));
464}
465// allocate new unit config id
466else if (OB_INVALID_ID == unit_config_id && OB_FAIL(fetch_new_unit_config_id(unit_config_id))) {
467LOG_WARN("fetch_new_unit_config_id failed", KR(ret), K(unit_config));
468} else {
469if (OB_ISNULL(new_config = config_allocator_.alloc())) {
470ret = OB_ALLOCATE_MEMORY_FAILED;
471LOG_ERROR("alloc memory failed", KR(ret));
472} else if (OB_FAIL(new_config->init(unit_config_id, name, ur))) {
473LOG_WARN("init unit config fail", KR(ret), K(unit_config_id), K(name), K(ur));
474} else if (OB_FAIL(ut_operator_.update_unit_config(*proxy_, *new_config))) {
475LOG_WARN("update_unit_config failed", "unit config", *new_config, K(ret));
476} else if (OB_FAIL(insert_unit_config(new_config))) {
477LOG_WARN("insert_unit_config failed", "unit config", *new_config, K(ret));
478}
479
480// avoid memory leak
481if (OB_FAIL(ret) && NULL != new_config) {
482config_allocator_.free(new_config);
483new_config = NULL;
484}
485}
486LOG_INFO("finish create unit config", KR(ret), K(name), K(rpc_ur), K(if_not_exist), KPC(new_config));
487return ret;
488}
489
490int ObUnitManager::alter_unit_config(const ObUnitConfig &unit_config)
491{
492int ret = OB_SUCCESS;
493ObUnitConfig *old_config = NULL;
494ObArray<share::ObResourcePool *> *pools = NULL;
495SpinWLockGuard guard(lock_);
496const ObUnitConfigName &name = unit_config.name();
497const ObUnitResource &rpc_ur = unit_config.unit_resource();
498
499if (!check_inner_stat()) {
500ret = OB_INNER_STAT_ERROR;
501LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
502} else if (name.is_empty()) {
503ret = OB_MISS_ARGUMENT;
504LOG_WARN("miss 'name' argument", KR(ret));
505LOG_USER_ERROR(OB_MISS_ARGUMENT, "resource unit name");
506} else if (OB_FAIL(get_unit_config_by_name(name, old_config))) {
507if (OB_ENTRY_NOT_EXIST != ret) {
508LOG_WARN("get_unit_config_by_name failed", K(name), K(ret));
509} else {
510// overwrite ret on purpose
511ret = OB_RESOURCE_UNIT_NOT_EXIST;
512LOG_WARN("config does not exist", K(name), KR(ret));
513LOG_USER_ERROR(OB_RESOURCE_UNIT_NOT_EXIST, to_cstring(name));
514}
515} else if (OB_ISNULL(old_config)) {
516ret = OB_ERR_UNEXPECTED;
517LOG_WARN("old_config is null", KP(old_config), KR(ret));
518} else {
519// copy unit resource
520ObUnitResource new_ur = old_config->unit_resource();
521const ObUnitResource old_ur = old_config->unit_resource();
522
523// update based on user specified
524if (OB_FAIL(new_ur.update_and_check_valid_for_unit(rpc_ur))) {
525LOG_WARN("update and check valid for unit fail", KR(ret), K(new_ur), K(rpc_ur));
526} else {
527if (OB_FAIL(get_pools_by_config(old_config->unit_config_id(), pools))) {
528if (OB_ENTRY_NOT_EXIST != ret) {
529LOG_WARN("get_pools_by_config failed", "config_id", old_config->unit_config_id(), KR(ret));
530} else {
531ret = OB_SUCCESS;
532// this unit config is not used by any resource pools
533// update the config directly
534}
535} else if (NULL == pools) {
536ret = OB_ERR_UNEXPECTED;
537LOG_WARN("pools is null", KP(pools), K(ret));
538} else {
539if (OB_FAIL(check_expand_resource_("ALTER_RESOURCE_UNIT", *pools, old_ur, new_ur))) {
540LOG_WARN("check expand config failed", K(old_ur), K(new_ur), KR(ret));
541} else if (OB_FAIL(check_shrink_resource_(*pools, old_ur, new_ur))) {
542LOG_WARN("check shrink config failed", K(old_ur), K(new_ur), KR(ret));
543} else if (OB_FAIL(check_full_resource_pool_memory_condition(*pools, new_ur.memory_size()))) {
544LOG_WARN("fail to check full resource pool memory condition", K(ret), K(new_ur), KPC(pools));
545}
546}
547}
548
549if (OB_SUCC(ret)) {
550ObUnitConfig new_config;
551if (OB_FAIL(new_config.init(old_config->unit_config_id(), old_config->name(), new_ur))) {
552LOG_WARN("init new unit config fail", KR(ret), KPC(old_config), K(new_ur));
553} else if (OB_FAIL(ut_operator_.update_unit_config(*proxy_, new_config))) {
554LOG_WARN("update_unit_config failed", K(new_config), KR(ret));
555} else if (OB_FAIL(old_config->update_unit_resource(new_ur))) {
556LOG_WARN("update unit resource of unit config fail", KR(ret), KPC(old_config), K(new_ur));
557}
558}
559
560if (OB_SUCC(ret)) {
561ROOTSERVICE_EVENT_ADD("unit", "alter_resource_unit",
562"name", old_config->name(),
563"unit_config_id", old_config->unit_config_id(),
564"old_resource", old_ur,
565"new_resource", new_ur);
566}
567}
568return ret;
569}
570
571int ObUnitManager::check_unit_config_exist(const share::ObUnitConfigName &unit_config_name,
572bool &is_exist)
573{
574int ret = OB_SUCCESS;
575SpinRLockGuard guard(lock_);
576ObUnitConfig *config = NULL;
577is_exist = false;
578
579if (!check_inner_stat()) {
580ret = OB_INNER_STAT_ERROR;
581LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
582} else if (unit_config_name.is_empty()) {
583ret = OB_INVALID_ARGUMENT;
584LOG_WARN("invalid argument", KR(ret), K(unit_config_name));
585} else if (OB_FAIL(get_unit_config_by_name(unit_config_name, config))) {
586if (OB_ENTRY_NOT_EXIST != ret) {
587LOG_WARN("get_unit_config_by_name failed", KR(ret), K(unit_config_name));
588} else {
589ret = OB_SUCCESS;
590// is_exist = false
591}
592} else if (OB_ISNULL(config)) {
593ret = OB_ERR_UNEXPECTED;
594LOG_WARN("unexpected null", KR(ret), KP(config), K(unit_config_name));
595} else {
596is_exist = true;
597}
598
599return ret;
600}
601
602int ObUnitManager::drop_unit_config(const ObUnitConfigName &name, const bool if_exist)
603{
604int ret = OB_SUCCESS;
605LOG_INFO("start drop unit config", K(name));
606SpinWLockGuard guard(lock_);
607ObUnitConfig *config = NULL;
608int64_t ref_count = 0;
609if (!check_inner_stat()) {
610ret = OB_INNER_STAT_ERROR;
611LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
612} else if (name.is_empty()) {
613ret = OB_INVALID_ARGUMENT;
614LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource unit name");
615LOG_WARN("invalid argument", K(name), K(ret));
616} else if (OB_FAIL(get_unit_config_by_name(name, config))) {
617if (OB_ENTRY_NOT_EXIST != ret) {
618LOG_WARN("get_unit_config_by_name failed", K(name), K(ret));
619} else {
620if (if_exist) {
621ret = OB_SUCCESS;
622LOG_USER_NOTE(OB_RESOURCE_UNIT_NOT_EXIST, to_cstring(name));
623LOG_INFO("unit config not exist, no need to delete it", K(name));
624} else {
625ret = OB_RESOURCE_UNIT_NOT_EXIST;
626LOG_USER_ERROR(OB_RESOURCE_UNIT_NOT_EXIST, to_cstring(name));
627LOG_WARN("unit config not exist", K(name), K(ret));
628}
629}
630} else if (NULL == config) {
631ret = OB_ERR_UNEXPECTED;
632LOG_WARN("config is null", KP(config), K(ret));
633} else if (OB_FAIL(get_config_ref_count(config->unit_config_id(), ref_count))) {
634LOG_WARN("get_config_ref_count failed", "config_id", config->unit_config_id(), K(ret));
635} else if (0 != ref_count) {
636ret = OB_RESOURCE_UNIT_IS_REFERENCED;
637LOG_USER_ERROR(OB_RESOURCE_UNIT_IS_REFERENCED, to_cstring(name));
638LOG_WARN("some resource pool is using this unit config, can not delete it",
639K(ref_count), K(ret));
640} else if (OB_FAIL(ut_operator_.remove_unit_config(*proxy_, config->unit_config_id()))) {
641LOG_WARN("remove_unit_config failed", "config_id", config->unit_config_id(), K(ret));
642} else if (OB_FAIL(delete_unit_config(config->unit_config_id(), config->name()))) {
643LOG_WARN("delete_unit_config failed", "config id", config->unit_config_id(),
644"name", config->name(), K(ret));
645} else {
646ROOTSERVICE_EVENT_ADD("unit", "drop_resource_unit",
647"name", config->name());
648// free memory
649config_allocator_.free(config);
650config = NULL;
651}
652LOG_INFO("finish drop unit config", K(name), K(ret));
653return ret;
654}
655
656int ObUnitManager::check_tenant_pools_in_shrinking(
657const uint64_t tenant_id,
658bool &is_shrinking)
659{
660int ret = OB_SUCCESS;
661common::ObArray<share::ObResourcePool *> *pools = NULL;
662SpinRLockGuard guard(lock_);
663if (!check_inner_stat()) {
664ret = OB_INNER_STAT_ERROR;
665LOG_WARN("check inner stat failed", K(ret), K(inited_), K(loaded_));
666} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
667ret = OB_INVALID_ARGUMENT;
668LOG_WARN("invalid argument", K(ret));
669} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
670LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
671} else if (OB_UNLIKELY(NULL == pools)) {
672ret = OB_ERR_UNEXPECTED;
673LOG_WARN("pools ptr is null", K(ret), KP(pools));
674} else {
675is_shrinking = false;
676for (int64_t i = 0; !is_shrinking && OB_SUCC(ret) && i < pools->count(); ++i) {
677common::ObArray<share::ObUnit *> *units = NULL;
678const share::ObResourcePool *pool = pools->at(i);
679if (NULL == pool) {
680ret = OB_ERR_UNEXPECTED;
681LOG_WARN("pool ptr is null", K(ret), KP(pool));
682} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
683LOG_WARN("fail to get units by pool", K(ret), "pool_id", pool->resource_pool_id_);
684} else if (NULL == units) {
685ret = OB_ERR_UNEXPECTED;
686LOG_WARN("units ptrs is null", K(ret), KP(units));
687} else {
688is_shrinking = false;
689for (int64_t j = 0; !is_shrinking && OB_SUCC(ret) && j < units->count(); ++j) {
690const ObUnit *unit = units->at(j);
691if (OB_UNLIKELY(NULL == unit)) {
692ret = OB_ERR_UNEXPECTED;
693LOG_WARN("unit ptr si null", K(ret));
694} else if (ObUnit::UNIT_STATUS_DELETING == unit->status_) {
695is_shrinking = true;
696} else if (ObUnit::UNIT_STATUS_ACTIVE == unit->status_) {
697// a normal unit, go on and check next
698} else {
699ret = OB_ERR_UNEXPECTED;
700LOG_WARN("unit status unexpected", K(ret), "unit_status", unit->status_);
701}
702}
703}
704}
705}
706return ret;
707}
708
709int ObUnitManager::check_pool_in_shrinking(
710const uint64_t pool_id,
711bool &is_shrinking)
712{
713int ret = OB_SUCCESS;
714SpinRLockGuard guard(lock_);
715if (OB_FAIL(inner_check_pool_in_shrinking_(pool_id, is_shrinking))) {
716LOG_WARN("inner check pool in shrinking failed", KR(ret), K(pool_id), K(is_shrinking));
717}
718return ret;
719}
720
721int ObUnitManager::inner_check_pool_in_shrinking_(
722const uint64_t pool_id,
723bool &is_shrinking)
724{
725int ret = OB_SUCCESS;
726if (!check_inner_stat()) {
727ret = OB_INNER_STAT_ERROR;
728LOG_WARN("check inner stat failed", K(ret), K(inited_), K(loaded_));
729} else if (OB_UNLIKELY(OB_INVALID_ID == pool_id)) {
730ret = OB_INVALID_ARGUMENT;
731LOG_WARN("invalid argument", K(ret), K(pool_id));
732} else {
733common::ObArray<share::ObUnit *> *units = NULL;
734if (OB_FAIL(get_units_by_pool(pool_id, units))) {
735LOG_WARN("fail to get units by pool", K(ret), K(pool_id));
736} else if (NULL == units) {
737ret = OB_ERR_UNEXPECTED;
738LOG_WARN("units ptr is null", K(ret), KP(units));
739} else {
740is_shrinking = false;
741for (int64_t i = 0; !is_shrinking && OB_SUCC(ret) && i < units->count(); ++i) {
742const ObUnit *unit = units->at(i);
743if (OB_UNLIKELY(NULL == unit)) {
744ret = OB_ERR_UNEXPECTED;
745LOG_WARN("unit ptr is null", K(ret));
746} else if (ObUnit::UNIT_STATUS_DELETING == unit->status_) {
747is_shrinking = true;
748} else if (ObUnit::UNIT_STATUS_ACTIVE == unit->status_) {
749// a normal unit, go on and check next
750} else {
751ret = OB_ERR_UNEXPECTED;
752LOG_WARN("unit status unexpected", K(ret), "unit_status", unit->status_);
753}
754}
755}
756}
757return ret;
758}
759
760int ObUnitManager::construct_resource_pool_to_clone_(
761const uint64_t source_tenant_id,
762share::ObResourcePool &pool_to_clone)
763{
764int ret = OB_SUCCESS;
765int64_t unit_num = 0;
766share::schema::ObSchemaGetterGuard schema_guard;
767const share::schema::ObTenantSchema *tenant_schema = NULL;
768common::ObSEArray<common::ObZone, DEFAULT_ZONE_COUNT> zone_list;
769if (OB_UNLIKELY(OB_INVALID_TENANT_ID == source_tenant_id)) {
770ret = OB_INVALID_ARGUMENT;
771LOG_WARN("invalid argument", KR(ret), K(source_tenant_id));
772} else if (OB_FAIL(construct_source_tenant_unit_num_(source_tenant_id, unit_num))) {
773LOG_WARN("fail to construct source tenant unit_num", KR(ret), K(source_tenant_id), K(unit_num));
774} else if (OB_ISNULL(schema_service_)) {
775ret = OB_NOT_INIT;
776LOG_WARN("schema service is null", K(schema_service_), KR(ret));
777} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
778LOG_WARN("fail to get tenant schema guard", KR(ret));
779} else if (OB_FAIL(schema_guard.get_tenant_info(source_tenant_id, tenant_schema))) {
780LOG_WARN("fail to get tenant info", KR(ret), K(source_tenant_id));
781} else if (OB_ISNULL(tenant_schema)) {
782ret = OB_ERR_UNEXPECTED;
783LOG_WARN("tenant schema is null", KR(ret), KP(tenant_schema));
784// just get units in locality is ok
785} else if (OB_FAIL(tenant_schema->get_zone_list(zone_list))) {
786LOG_WARN("fail to get zone list", KR(ret));
787} else if (0 >= zone_list.count()) {
788ret = OB_INVALID_ARGUMENT;
789LOG_WARN("source tenant zone list should have at least zone zone", KR(ret), K(source_tenant_id), K(zone_list));
790} else if (OB_FAIL(pool_to_clone.zone_list_.assign(zone_list))) {
791LOG_WARN("fail to assign zone_list", KR(ret), K(source_tenant_id), K(pool_to_clone), K(zone_list));
792} else {
793// pool_to_clone.name_ is already setted before
794pool_to_clone.unit_count_ = unit_num;
795pool_to_clone.replica_type_ = REPLICA_TYPE_FULL;
796// parameters below will be setted later:
797// pool_to_clone.resource_pool_id_ will be setted when inner_create_resource_pool
798// pool_to_clone.unit_config_id_ will be setted when inner_create_resource_pool
799// pool_to_clone.tenant_id_ will be setted when granted this pool to tenant
800}
801return ret;
802}
803
804int ObUnitManager::construct_source_tenant_unit_num_(
805const uint64_t source_tenant_id,
806int64_t &unit_num)
807{
808int ret = OB_SUCCESS;
809unit_num = 0;
810ObArray<uint64_t> pool_ids;
811share::ObResourcePool *pool;
812if (OB_UNLIKELY(OB_INVALID_TENANT_ID == source_tenant_id)) {
813ret = OB_INVALID_ARGUMENT;
814LOG_WARN("invalid argument", KR(ret), K(source_tenant_id));
815} else if (OB_FAIL(inner_get_pool_ids_of_tenant(source_tenant_id, pool_ids))) {
816LOG_WARN("fail to get resource pool ids of source tenant", KR(ret), K(source_tenant_id));
817} else if (OB_UNLIKELY(0 >= pool_ids.count())) {
818ret = OB_ERR_UNEXPECTED;
819LOG_WARN("source tenant should have at least one pool", KR(ret), K(pool_ids));
820} else if (OB_FAIL(get_resource_pool_by_id(pool_ids.at(0), pool))) {
821LOG_WARN("fail to get first resource pool", KR(ret), K(pool_ids));
822} else if (OB_ISNULL(pool)) {
823ret = OB_ERR_UNEXPECTED;
824LOG_WARN("pool is null", KR(ret), KP(pool));
825} else if (OB_UNLIKELY(0 >= pool->unit_count_)) {
826ret = OB_ERR_UNEXPECTED;
827LOG_WARN("source tenant should have at least one unit", KR(ret), K(source_tenant_id), KPC(pool));
828} else {
829// tenant's resource pools should have same unit_num
830// so it is ok for us to pick unit_num of first pool
831unit_num = pool->unit_count_;
832}
833return ret;
834}
835
836int ObUnitManager::clone_resource_pool(
837share::ObResourcePool &resource_pool,
838const share::ObUnitConfigName &unit_config_name,
839const uint64_t source_tenant_id)
840{
841int ret = OB_SUCCESS;
842LOG_INFO("start clone_resource_pool", K(resource_pool), K(unit_config_name), K(source_tenant_id));
843SpinWLockGuard guard(lock_);
844bool if_not_exist = false;
845common::ObArray<share::ObUnitInfo> source_units;
846if (OB_UNLIKELY(OB_INVALID_TENANT_ID == source_tenant_id)) {
847ret = OB_INVALID_ARGUMENT;
848LOG_WARN("invalid argument", KR(ret), K(resource_pool), K(unit_config_name), K(source_tenant_id));
849} else if (OB_FAIL(construct_resource_pool_to_clone_(source_tenant_id, resource_pool))) {
850LOG_WARN("fail to construct resource pool to clone", KR(ret), K(source_tenant_id), K(resource_pool));
851} else if (OB_FAIL(inner_get_all_unit_infos_by_tenant_(source_tenant_id, source_units))) {
852LOG_WARN("fail to get units by source tenant", KR(ret), K(source_tenant_id));
853} else if (OB_FAIL(inner_create_resource_pool_(
854resource_pool,
855unit_config_name,
856if_not_exist,
857source_tenant_id,
858source_units))) {
859LOG_WARN("fail to inner create resource pool for clone tenant", KR(ret), K(resource_pool),
860K(unit_config_name), K(if_not_exist), K(source_tenant_id), K(source_units));
861}
862LOG_INFO("finish clone_resource_pool", KR(ret), K(resource_pool), K(unit_config_name), K(source_tenant_id));
863return ret;
864}
865
866int ObUnitManager::create_resource_pool(
867share::ObResourcePool &resource_pool,
868const ObUnitConfigName &config_name,
869const bool if_not_exist)
870{
871int ret = OB_SUCCESS;
872SpinWLockGuard guard(lock_);
873common::ObArray<share::ObUnitInfo> source_units; // not used
874if (OB_FAIL(inner_create_resource_pool_(resource_pool, config_name, if_not_exist, OB_INVALID_TENANT_ID/*source_tenant_id*/, source_units))) {
875LOG_WARN("fail to inner create resource pool", KR(ret), K(resource_pool), K(config_name), K(if_not_exist));
876}
877return ret;
878}
879
880int ObUnitManager::inner_create_resource_pool_(
881share::ObResourcePool &resource_pool,
882const ObUnitConfigName &config_name,
883const bool if_not_exist,
884const uint64_t source_tenant_id,
885const common::ObIArray<share::ObUnitInfo> &source_units)
886{
887int ret = OB_SUCCESS;
888LOG_INFO("start inner create resource pool", K(resource_pool), K(config_name),
889K(if_not_exist), K(source_tenant_id), K(source_units));
890ObUnitConfig *config = NULL;
891share::ObResourcePool *pool = NULL;
892bool is_bootstrap_pool = (ObUnitConfig::SYS_UNIT_CONFIG_ID == resource_pool.unit_config_id_);
893// source_tenant_id is used to recognize whether this resource pool is for clone tenant
894// if OB_INVALID_TENANT_ID == source_tenant_id means this is clone resource pool for clone tenant
895// if OB_INVALID_TENANT_ID != source_tenant_id means this is create resource pool for normal/restore tenant
896// so please DO NOT check whether source_tenant_id is valid or not
897bool is_clone_tenant = OB_INVALID_TENANT_ID != source_tenant_id;
898const char *module = is_clone_tenant ? "CLONE_RESOURCE_POOL" : "CREATE_RESOURCE_POOL";
899
900if (!check_inner_stat()) {
901ret = OB_INNER_STAT_ERROR;
902LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
903} else if (is_bootstrap_pool && OB_FAIL(check_bootstrap_pool(resource_pool))) {
904LOG_WARN("check bootstrap pool failed", K(resource_pool), K(ret));
905} else if (!is_bootstrap_pool && OB_FAIL(check_resource_pool(resource_pool, is_clone_tenant))) {
906LOG_WARN("check_resource_pool failed", K(resource_pool), K(is_clone_tenant), K(ret));
907} else if (config_name.is_empty()) {
908ret = OB_INVALID_ARGUMENT;
909LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource unit name");
910LOG_WARN("invalid config_name", K(config_name), K(ret));
911} else if (OB_FAIL(get_unit_config_by_name(config_name, config))) {
912if (OB_ENTRY_NOT_EXIST != ret) {
913LOG_WARN("get_unit_config_by_name failed", K(config_name), K(ret));
914} else {
915ret = OB_RESOURCE_UNIT_NOT_EXIST;
916LOG_USER_ERROR(OB_RESOURCE_UNIT_NOT_EXIST, to_cstring(config_name));
917LOG_WARN("config not exist", K(config_name), K(ret));
918}
919} else if (NULL == config) {
920ret = OB_ERR_UNEXPECTED;
921LOG_WARN("config is null", KP(config), K(ret));
922} else if (OB_SUCCESS == (ret = inner_get_resource_pool_by_name(resource_pool.name_, pool))) {
923if (NULL == pool) {
924ret = OB_ERR_UNEXPECTED;
925LOG_WARN("pool is null", K_(resource_pool.name), KP(pool), K(ret));
926} else if (if_not_exist) {
927LOG_USER_NOTE(OB_RESOURCE_POOL_EXIST, to_cstring(resource_pool.name_));
928LOG_INFO("resource_pool already exist, no need to create", K(resource_pool.name_));
929} else {
930ret = OB_RESOURCE_POOL_EXIST;
931LOG_USER_ERROR(OB_RESOURCE_POOL_EXIST, to_cstring(resource_pool.name_));
932LOG_WARN("resource_pool already exist", "name", resource_pool.name_, K(ret));
933}
934} else if (OB_ENTRY_NOT_EXIST != ret) {
935LOG_WARN("get resource pool by name failed", "name", resource_pool.name_, K(ret));
936} else {
937ret = OB_SUCCESS;
938common::ObMySQLTransaction trans;
939share::ObResourcePool *new_pool = NULL;
940const int64_t min_full_resource_pool_memory = GCONF.__min_full_resource_pool_memory;
941if (NULL == (new_pool = pool_allocator_.alloc())) {
942ret = OB_ALLOCATE_MEMORY_FAILED;
943LOG_ERROR("alloc memory failed", K(ret));
944} else if (REPLICA_TYPE_FULL == resource_pool.replica_type_
945&& config->memory_size() < min_full_resource_pool_memory) {
946ret = OB_NOT_SUPPORTED;
947LOG_WARN("full resource pool min memory illegal", KR(ret), K(config->memory_size()),
948K(min_full_resource_pool_memory));
949LOG_USER_ERROR(OB_NOT_SUPPORTED, "unit MEMORY_SIZE less than __min_full_resource_pool_memory");
950} else {
951if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
952LOG_WARN("start transaction failed", K(ret));
953} else {
954if (OB_FAIL(new_pool->assign(resource_pool))) {
955LOG_WARN("failed to assign new_pool", K(ret));
956} else {
957new_pool->unit_config_id_ = config->unit_config_id();
958if (OB_INVALID_ID == new_pool->resource_pool_id_) {
959if (OB_FAIL(fetch_new_resource_pool_id(new_pool->resource_pool_id_))) {
960LOG_WARN("fetch_new_resource_pool_id failed", K(ret));
961}
962} else {
963// sys resource pool with pool_id set
964}
965}
966if (OB_FAIL(ret)) {
967} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, *new_pool, false/*need_check_conflict_with_clone*/))) {
968LOG_WARN("update_resource_pool failed", "resource_pool", *new_pool, K(ret));
969} else if (OB_FAIL(update_pool_map(new_pool))) {
970LOG_WARN("update pool map failed", "resource_pool", *new_pool, K(ret));
971}
972
973if (OB_SUCCESS == ret && !is_bootstrap_resource_pool(new_pool->resource_pool_id_)) {
974if (is_clone_tenant) {
975if (OB_FAIL(check_new_pool_units_for_clone_tenant_(trans, *new_pool, source_units))) {
976LOG_WARN("fail to check new pool units for clone tenant", KR(ret),
977K(source_tenant_id), K(source_units), "resource_pool", *new_pool);
978}
979} else if (OB_FAIL(allocate_new_pool_units_(trans, *new_pool, module))) {
980LOG_WARN("arrange pool units failed", K(module), KR(ret), "resource_pool", *new_pool);
981}
982}
983}
984
985if (trans.is_started()) {
986const bool commit = (OB_SUCC(ret));
987int temp_ret = OB_SUCCESS;
988if (OB_SUCCESS != (temp_ret = trans.end(commit))) {
989LOG_WARN("trans end failed", K(commit), K(temp_ret));
990ret = (OB_SUCCESS == ret) ? temp_ret : ret;
991}
992}
993if (OB_SUCC(ret)) {
994ret = OB_E(EventTable::EN_UNIT_MANAGER) OB_SUCCESS;
995DEBUG_SYNC(UNIT_MANAGER_WAIT_FOR_TIMEOUT);
996}
997
998if (OB_FAIL(ret)) {
999if (OB_INVALID_ID == new_pool->resource_pool_id_) {
1000// do nothing, fetch new resource pool id failed
1001} else {
1002int temp_ret = OB_SUCCESS; // avoid ret overwritten
1003// some error occur during doing the transaction, rollback change occur in memory
1004ObArray<ObUnit *> *units = NULL;
1005if (OB_SUCCESS == (temp_ret = get_units_by_pool(new_pool->resource_pool_id_, units))) {
1006if (NULL == units) {
1007temp_ret = OB_ERR_UNEXPECTED;
1008LOG_WARN("units is null", KP(units), K(temp_ret));
1009} else if (OB_SUCCESS != (temp_ret = delete_units_of_pool(
1010new_pool->resource_pool_id_))) {
1011LOG_WARN("delete_units_of_pool failed", "resource_pool_id",
1012new_pool->resource_pool_id_, K(temp_ret));
1013}
1014} else if (OB_ENTRY_NOT_EXIST != temp_ret) {
1015LOG_WARN("get_units_by_pool failed",
1016"resource_pool_id", new_pool->resource_pool_id_, K(temp_ret));
1017} else {
1018temp_ret = OB_SUCCESS;
1019}
1020
1021share::ObResourcePool *temp_pool = NULL;
1022if (OB_SUCCESS != temp_ret) {
1023} else if (OB_SUCCESS != (temp_ret = get_resource_pool_by_id(
1024new_pool->resource_pool_id_, temp_pool))) {
1025if (OB_ENTRY_NOT_EXIST != temp_ret) {
1026LOG_WARN("get_resource_pool_by_id failed", "pool_id", new_pool->resource_pool_id_,
1027K(temp_ret));
1028} else {
1029temp_ret = OB_SUCCESS;
1030// do nothing, no need to delete from id_map and name_map
1031}
1032} else if (NULL == temp_pool) {
1033temp_ret = OB_ERR_UNEXPECTED;
1034LOG_WARN("temp_pool is null", KP(temp_pool), K(temp_ret));
1035} else if (OB_SUCCESS != (temp_ret = delete_resource_pool(
1036new_pool->resource_pool_id_, new_pool->name_))) {
1037LOG_WARN("delete_resource_pool failed", "new pool", *new_pool, K(temp_ret));
1038}
1039}
1040// avoid memory leak
1041pool_allocator_.free(new_pool);
1042new_pool = NULL;
1043} else {
1044// inc unit config ref count at last
1045if (OB_FAIL(inc_config_ref_count(config->unit_config_id()))) {
1046LOG_WARN("inc_config_ref_count failed", "config id", config->unit_config_id(), K(ret));
1047} else if (OB_FAIL(insert_config_pool(config->unit_config_id(), new_pool))) {
1048LOG_WARN("insert config pool failed", "config id", config->unit_config_id(), K(ret));
1049} else {
1050ROOTSERVICE_EVENT_ADD("unit", is_clone_tenant ? "clone_resource_pool" : "create_resource_pool",
1051"name", new_pool->name_,
1052"unit", config_name,
1053"zone_list", new_pool->zone_list_,
1054"source_tenant_id", source_tenant_id);
1055}
1056}
1057}
1058}
1059LOG_INFO("finish inner create resource pool", K(resource_pool), K(config_name),
1060K(source_tenant_id), K(source_units), K(ret));
1061return ret;
1062}
1063
1064int ObUnitManager::check_new_pool_units_for_clone_tenant_(
1065ObISQLClient &client,
1066const share::ObResourcePool &pool,
1067const common::ObIArray<share::ObUnitInfo> &source_units)
1068{
1069int ret = OB_SUCCESS;
1070ObUnitConfig *config = NULL;
1071ObArray<ObServerInfoInTable> servers_info_of_source_units;
1072ObArray<ObUnitPlacementStrategy::ObServerResource> server_resources;
1073std::string resource_not_enough_reason;
1074
1075if (!check_inner_stat()) {
1076ret = OB_INNER_STAT_ERROR;
1077LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
1078} else if (OB_UNLIKELY(!pool.is_valid())
1079|| OB_UNLIKELY(pool.zone_list_.count() <= 0)
1080|| OB_UNLIKELY(source_units.count() <= 0)) {
1081ret = OB_INVALID_ARGUMENT;
1082LOG_WARN("invalid pool", KR(ret), K(pool), K(source_units));
1083} else if (OB_ISNULL(srv_rpc_proxy_)) {
1084ret = OB_ERR_UNEXPECTED;
1085LOG_WARN("srv_rpc_proxy_ is null", KR(ret), KP(srv_rpc_proxy_));
1086} else if (OB_FAIL(get_unit_config_by_id(pool.unit_config_id_, config))) {
1087LOG_WARN("get_unit_config_by_id failed", KR(ret), "unit_config_id", pool.unit_config_id_);
1088} else if (OB_ISNULL(config)) {
1089ret = OB_ERR_UNEXPECTED;
1090LOG_WARN("config is null", KR(ret), KP(config));
1091} else {
1092ObNotifyTenantServerResourceProxy notify_proxy(
1093*srv_rpc_proxy_,
1094&obrpc::ObSrvRpcProxy::notify_tenant_server_unit_resource);
1095for (int64_t i = 0; OB_SUCC(ret) && i < pool.zone_list_.count(); i++) {
1096// for each zone, check servers have enough resources
1097// ATTENTION:
1098// The locations of clone tenant's units are certain according to source tenant's units
1099// So there is no need to allocate servers for these units, but we have to check whether
1100// these servers have enough resources.
1101// We regard server inactive as a common case, let check success but log WARN in log file.
1102// We can ignore server inactive because majority of snapshot restored successfully is enough,
1103// it is ok currently to let it passed, just let log stream creation to handle this situation.
1104const ObZone &zone = pool.zone_list_.at(i);
1105servers_info_of_source_units.reuse();
1106server_resources.reuse();
1107
1108if (OB_FAIL(construct_server_resources_info_(
1109zone,
1110source_units,
1111servers_info_of_source_units,
1112server_resources))) {
1113LOG_WARN("fail to construct server resource infos", KR(ret), K(zone), K(source_units));
1114} else if (OB_FAIL(check_server_resources_and_persist_unit_info_(
1115client,
1116notify_proxy,
1117zone,
1118pool,
1119servers_info_of_source_units,
1120server_resources,
1121config->unit_resource()))) {
1122LOG_WARN("fail to check and persist unit info", KR(ret), K(zone), K(pool),
1123K(servers_info_of_source_units), K(server_resources), KPC(config));
1124}
1125}
1126}
1127return ret;
1128}
1129
1130int ObUnitManager::construct_server_resources_info_(
1131const ObZone &zone,
1132const ObIArray<share::ObUnitInfo> &source_units,
1133ObIArray<share::ObServerInfoInTable> &server_infos,
1134ObIArray<ObUnitPlacementStrategy::ObServerResource> &server_resources)
1135{
1136int ret = OB_SUCCESS;
1137server_infos.reset();
1138server_resources.reset();
1139if (!check_inner_stat()) {
1140ret = OB_INNER_STAT_ERROR;
1141LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
1142} else if (OB_UNLIKELY(zone.is_empty())
1143|| OB_UNLIKELY(0 >= source_units.count())) {
1144ret = OB_INVALID_ARGUMENT;
1145LOG_WARN("invalid argument", KR(ret), K(zone), K(source_units));
1146} else {
1147ObArray<obrpc::ObGetServerResourceInfoResult> active_servers_resource_info_result;
1148for (int64_t i = 0; OB_SUCC(ret) && i < source_units.count(); i++) {
1149const share::ObUnit &unit = source_units.at(i).unit_;
1150if (zone == unit.zone_) {
1151const common::ObAddr &source_unit_server = unit.server_;
1152bool server_is_active = false;
1153if (OB_FAIL(SVR_TRACER.check_server_active(source_unit_server, server_is_active))) {
1154LOG_WARN("fail to check server active", KR(ret), K(zone), K(unit),
1155K(source_unit_server), K(server_is_active));
1156} else if (server_is_active) {
1157ObServerInfoInTable server_info;
1158if (OB_FAIL(SVR_TRACER.get_server_info(source_unit_server, server_info))) {
1159LOG_WARN("fail to get server info", KR(ret), K(source_unit_server), K(server_info));
1160} else if (OB_FAIL(server_infos.push_back(server_info))) {
1161LOG_WARN("fail to add active server info into array", KR(ret), K(server_info));
1162}
1163} else {
1164// TODO@jingyu.cr:
1165// If server not alive, we can not get correct cpu/mem/log_disk capacity, so just ignore them
1166// Later, we can handle this case by ignoring zone with inactive server or find another valid
1167// server to put unit on, just let other majority replicas successfully restored is ok.
1168LOG_WARN("[CLONE_TENANT_UNIT] server is inactive, create clone tenant resource pool may failed",
1169K(zone), K(source_unit_server), K(server_is_active));
1170}
1171}
1172}
1173if (OB_FAIL(ret)) {
1174} else if (0 >= server_infos.count()) {
1175// just ignore, let snapshot creation decide whether to raise error
1176LOG_INFO("[CLONE_TENANT_UNIT] zone may have no valid servers to hold unit", K(zone), K(source_units));
1177} else if (OB_FAIL(get_servers_resource_info_via_rpc(server_infos, active_servers_resource_info_result))) {
1178LOG_WARN("fail to get server resource info via rpc", KR(ret), K(server_infos));
1179} else if (OB_FAIL(build_server_resources_(active_servers_resource_info_result, server_resources))) {
1180LOG_WARN("fail to build server resources", KR(ret), K(active_servers_resource_info_result));
1181}
1182}
1183return ret;
1184}
1185
1186int ObUnitManager::check_server_resources_and_persist_unit_info_(
1187ObISQLClient &client,
1188ObNotifyTenantServerResourceProxy ¬ify_proxy,
1189const ObZone &zone,
1190const share::ObResourcePool &pool,
1191const ObIArray<share::ObServerInfoInTable> &server_infos,
1192const ObIArray<ObUnitPlacementStrategy::ObServerResource> &server_resources,
1193const share::ObUnitResource &config)
1194{
1195int ret = OB_SUCCESS;
1196bool is_server_valid = false;
1197bool is_resource_enough = false;
1198uint64_t new_unit_id = OB_INVALID_ID;
1199ObArray<ObAddr> new_servers; // not used
1200ObArray<ObUnit> units;
1201const char* module = "clone_resource_pool";
1202bool for_clone_tenant = true;
1203int64_t not_excluded_server_count = 0;
1204std::string resource_not_enough_reason;
1205ObArray<ObAddr> excluded_servers; // not used
1206ObArray<ObUnitPlacementStrategy::ObServerResource> valid_server_resources;
1207if (!check_inner_stat()) {
1208ret = OB_INNER_STAT_ERROR;
1209LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
1210} else if (server_infos.count() != server_resources.count()) {
1211ret = OB_INVALID_ARGUMENT;
1212LOG_WARN("invalid servers_info and server_resources array", KR(ret), K(server_infos), K(server_resources));
1213} else if (OB_FAIL(construct_valid_servers_resource_(
1214zone,
1215config,
1216excluded_servers,
1217server_infos,
1218server_resources,
1219module,
1220for_clone_tenant,
1221not_excluded_server_count,
1222resource_not_enough_reason,
1223valid_server_resources))) {
1224LOG_WARN("fail to construct valid servers resource", KR(ret), K(zone), K(config),
1225K(excluded_servers), K(server_infos), K(module), K(for_clone_tenant));
1226} else {
1227for (int64_t i = 0; OB_SUCC(ret) && i < valid_server_resources.count(); i++) {
1228const ObUnitPlacementStrategy::ObServerResource &server_resource = valid_server_resources.at(i);
1229if (OB_FAIL(try_persist_unit_info_(
1230notify_proxy,
1231client,
1232zone,
1233pool,
1234lib::Worker::CompatMode::INVALID/*compat_mode*/,
12350/*unit_group_id*/,
1236server_resource.addr_,
1237new_servers,
1238units))) {
1239LOG_WARN("[CLONE_TENANT_UNIT] fail to persist unit info", KR(ret), K(zone), K(pool), K(server_resource));
1240}
1241}
1242int tmp_ret = OB_SUCCESS;
1243if (OB_TMP_FAIL(notify_proxy.wait())) {
1244LOG_WARN("fail to wait notify resource", KR(ret), K(tmp_ret));
1245ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
1246}
1247if (OB_FAIL(ret)) {
1248LOG_WARN("start to rollback unit persistence", KR(ret), K(units), K(pool));
1249if(OB_TMP_FAIL(rollback_persistent_units_(
1250units,
1251pool,
1252notify_proxy))) {
1253LOG_WARN("[CLONE_TENANT_UNIT] fail to rollback unit persistence",
1254KR(ret), KR(tmp_ret), K(units), K(pool));
1255}
1256}
1257}
1258return ret;
1259}
1260
1261int ObUnitManager::convert_pool_name_list(
1262const common::ObIArray<common::ObString> &split_pool_list,
1263common::ObIArray<share::ObResourcePoolName> &split_pool_name_list)
1264{
1265int ret = OB_SUCCESS;
1266split_pool_name_list.reset();
1267for (int64_t i = 0; OB_SUCC(ret) && i < split_pool_list.count(); ++i) {
1268share::ObResourcePoolName pool_name;
1269if (OB_FAIL(pool_name.assign(split_pool_list.at(i).ptr()))) {
1270LOG_WARN("fail to assign pool name", K(ret));
1271} else if (OB_FAIL(split_pool_name_list.push_back(pool_name))) {
1272LOG_WARN("fail to push back", K(ret));
1273}
1274}
1275return ret;
1276}
1277
1278int ObUnitManager::check_split_pool_name_condition(
1279const common::ObIArray<share::ObResourcePoolName> &split_pool_name_list)
1280{
1281int ret = OB_SUCCESS;
1282// Check whether the pool name already exists,
1283// and check whether the pool name is duplicate
1284const int64_t POOL_NAME_SET_BUCKET_NUM = 16;
1285ObHashSet<share::ObResourcePoolName> pool_name_set;
1286if (OB_FAIL(pool_name_set.create(POOL_NAME_SET_BUCKET_NUM))) {
1287LOG_WARN("fail to create hash set", K(ret));
1288} else {
1289for (int64_t i = 0; OB_SUCC(ret) && i < split_pool_name_list.count(); ++i) {
1290const share::ObResourcePoolName &pool_name = split_pool_name_list.at(i);
1291share::ObResourcePool *pool = NULL;
1292int tmp_ret = inner_get_resource_pool_by_name(pool_name, pool);
1293if (OB_ENTRY_NOT_EXIST == tmp_ret) {
1294// good, go on next, this pool name not exist
1295} else if (OB_SUCCESS == tmp_ret) {
1296if (NULL == pool) {
1297ret = OB_ERR_UNEXPECTED;
1298LOG_WARN("pool is null", K(ret), KP(pool), K(pool_name));
1299} else {
1300ret = OB_RESOURCE_POOL_EXIST;
1301LOG_WARN("resource pool already exist", K(ret), K(pool_name));
1302LOG_USER_ERROR(OB_RESOURCE_POOL_EXIST, to_cstring(pool_name));
1303}
1304} else {
1305ret = OB_ERR_UNEXPECTED;
1306LOG_WARN("unexpected error when get pool by name", K(ret), K(pool_name));
1307}
1308if (OB_SUCC(ret)) {
1309int tmp_ret = pool_name_set.exist_refactored(pool_name);
1310if (OB_HASH_NOT_EXIST == tmp_ret) {
1311if (OB_FAIL(pool_name_set.set_refactored(pool_name))) {
1312LOG_WARN("fail to set", K(ret), K(pool_name));
1313}
1314} else if (OB_HASH_EXIST == tmp_ret) {
1315ret = OB_INVALID_ARGUMENT;
1316LOG_WARN("invalid argument to split resource pool with duplicated name");
1317LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool name");
1318} else {
1319ret = OB_ERR_UNEXPECTED;
1320LOG_WARN("unexpected error when set hashset", K(ret));
1321}
1322}
1323}
1324}
1325return ret;
1326}
1327
1328int ObUnitManager::check_split_pool_zone_condition(
1329const common::ObIArray<common::ObZone> &split_zone_list,
1330const share::ObResourcePool &pool)
1331{
1332int ret = OB_SUCCESS;
1333const common::ObIArray<common::ObZone> &pool_zone_list = pool.zone_list_;
1334// Check whether the zone is included in the pool zone list,
1335// and check whether the zone is duplicated
1336const int64_t ZONE_SET_BUCKET_NUM = 16;
1337ObHashSet<common::ObZone> zone_set;
1338if (pool_zone_list.count() != split_zone_list.count()) {
1339ret = OB_INVALID_ARGUMENT;
1340LOG_WARN("invalid argument to split zone list", K(ret));
1341LOG_USER_ERROR(OB_INVALID_ARGUMENT, "corresponding zone vector");
1342} else if (OB_FAIL(zone_set.create(ZONE_SET_BUCKET_NUM))) {
1343LOG_WARN("fail to create hash set", K(ret));
1344} else {
1345for (int64_t i = 0; OB_SUCC(ret) && i < split_zone_list.count(); ++i) {
1346const common::ObZone &this_zone = split_zone_list.at(i);
1347if (!has_exist_in_array(pool_zone_list, this_zone)) {
1348ret = OB_INVALID_ARGUMENT;
1349LOG_WARN("invalid argument to non-exist zone in splitting zone vector", K(ret));
1350LOG_USER_ERROR(OB_INVALID_ARGUMENT, "non-exist zone in corresponding zone vector");
1351} else {
1352int tmp_ret = zone_set.exist_refactored(this_zone);
1353if (OB_HASH_NOT_EXIST == tmp_ret) {
1354if (OB_FAIL(zone_set.set_refactored(this_zone))) {
1355LOG_WARN("fail to set", K(ret), K(this_zone));
1356}
1357} else if (OB_HASH_EXIST == tmp_ret) {
1358ret = OB_INVALID_ARGUMENT;
1359LOG_WARN("invalid argument to duplicate zones in splitting zone vector", K(ret));
1360LOG_USER_ERROR(OB_INVALID_ARGUMENT, "duplidate zones in corresponding zone vector");
1361} else {
1362ret = OB_ERR_UNEXPECTED;
1363LOG_WARN("unexpected error when set hashset", K(ret));
1364}
1365}
1366}
1367}
1368return ret;
1369}
1370
1371int ObUnitManager::split_resource_pool(
1372const share::ObResourcePoolName &pool_name,
1373const common::ObIArray<common::ObString> &split_pool_list,
1374const common::ObIArray<common::ObZone> &split_zone_list)
1375{
1376int ret = OB_SUCCESS;
1377LOG_INFO("start split resource pool", K(pool_name), K(split_pool_list), K(split_zone_list));
1378SpinWLockGuard guard(lock_);
1379share::ObResourcePool *pool = NULL;
1380common::ObArray<share::ObResourcePoolName> split_pool_name_list;
1381if (!check_inner_stat()) {
1382ret = OB_INNER_STAT_ERROR;
1383LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1384} else if (pool_name.is_empty()
1385|| split_pool_list.count() <= 0
1386|| split_zone_list.count() <= 0) {
1387ret = OB_INVALID_ARGUMENT;
1388LOG_WARN("resource pool name is empty", K(ret), K(split_zone_list), K(split_pool_list));
1389LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool");
1390} else if (OB_FAIL(inner_get_resource_pool_by_name(pool_name, pool))) {
1391if (OB_ENTRY_NOT_EXIST != ret) {
1392LOG_WARN("get resource pool by name failed", K(ret), K(pool_name));
1393} else {
1394ret = OB_RESOURCE_POOL_NOT_EXIST;
1395LOG_WARN("resource pool not exist", K(ret), K(pool_name));
1396LOG_USER_ERROR(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(pool_name));
1397}
1398} else if (OB_UNLIKELY(NULL == pool)) {
1399ret = OB_ERR_UNEXPECTED;
1400LOG_WARN("pool ptr is null", K(ret));
1401} else if (OB_FAIL(convert_pool_name_list(split_pool_list, split_pool_name_list))) {
1402LOG_WARN("fail to convert pool name list", K(ret));
1403} else if (OB_FAIL(check_split_pool_name_condition(split_pool_name_list))) {
1404LOG_WARN("fail to check pool list name duplicate", K(ret));
1405} else if (split_pool_name_list.count() != split_zone_list.count()) {
1406ret = OB_INVALID_ARGUMENT;
1407LOG_WARN("invalid argument to split pool and zone count", K(ret));
1408LOG_USER_ERROR(OB_INVALID_ARGUMENT, "split pool and zone count");
1409} else if (OB_FAIL(check_split_pool_zone_condition(split_zone_list, *pool))) {
1410LOG_WARN("fail to check split pool zone condition", K(ret));
1411} else if (OB_FAIL(do_split_resource_pool(
1412pool, split_pool_name_list, split_zone_list))) {
1413LOG_WARN("fail to do split resource pool", K(ret));
1414} else {
1415LOG_INFO("succeed to split resource pool", K(pool_name),
1416"new_pool_name", split_pool_list,
1417"corresponding_zone", split_zone_list);
1418}
1419return ret;
1420}
1421
1422int ObUnitManager::do_split_pool_persistent_info(
1423share::ObResourcePool *pool,
1424const common::ObIArray<share::ObResourcePoolName> &split_pool_name_list,
1425const common::ObIArray<common::ObZone> &split_zone_list,
1426common::ObIArray<share::ObResourcePool *> &allocate_pool_ptrs)
1427{
1428int ret = OB_SUCCESS;
1429common::ObMySQLTransaction trans;
1430if (!check_inner_stat()) {
1431ret = OB_INNER_STAT_ERROR;
1432LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1433} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
1434LOG_WARN("fail to start transaction", K(ret));
1435} else if (OB_UNLIKELY(split_zone_list.count() != split_pool_name_list.count()
1436|| NULL == pool)) {
1437ret = OB_INVALID_ARGUMENT;
1438LOG_WARN("invalid argument", K(ret));
1439} else {
1440// Write down the resource pool allocated during execution
1441allocate_pool_ptrs.reset();
1442for (int64_t i = 0; OB_SUCC(ret) && i < split_pool_name_list.count(); ++i) {
1443const share::ObResourcePoolName &new_pool_name = split_pool_name_list.at(i);
1444const common::ObZone &zone = split_zone_list.at(i);
1445share::ObResourcePool *new_pool = NULL;
1446if (NULL == (new_pool = pool_allocator_.alloc())) {
1447ret = OB_ALLOCATE_MEMORY_FAILED;
1448LOG_ERROR("fail to alloc memory", K(ret));
1449} else if (OB_FAIL(allocate_pool_ptrs.push_back(new_pool))) {
1450LOG_WARN("fail to push back", K(ret));
1451} else if (OB_FAIL(fill_splitting_pool_basic_info(new_pool_name, new_pool, zone, pool))) {
1452LOG_WARN("fail to fill splitting pool basic info", K(ret));
1453}
1454}
1455for (int64_t i = 0; OB_SUCC(ret) && i < allocate_pool_ptrs.count(); ++i) {
1456share::ObResourcePool *new_pool = allocate_pool_ptrs.at(i);
1457if (OB_UNLIKELY(NULL == new_pool)) {
1458ret = OB_ERR_UNEXPECTED;
1459LOG_WARN("pool ptr is null", K(ret));
1460} else if (new_pool->zone_list_.count() != 1) {
1461ret = OB_ERR_UNEXPECTED;
1462LOG_WARN("zone list count unexpected", K(ret), "zone_list", new_pool->zone_list_);
1463} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, *new_pool, false/*need_check_conflict_with_clone*/))) {
1464LOG_WARN("fail to update resource pool", K(ret));
1465} else if (OB_FAIL(split_pool_unit_persistent_info(
1466trans, new_pool->zone_list_.at(0), new_pool, pool))) {
1467LOG_WARN("fail to split pool unit persistent info", K(ret));
1468}
1469}
1470if (OB_FAIL(ret)) {
1471} else if (ut_operator_.remove_resource_pool(trans, pool->resource_pool_id_)) {
1472LOG_WARN("fail to remove resource pool persistent info", K(ret),
1473"pool_id", pool->resource_pool_id_);
1474} else {} // all persistent infos update finished
1475const bool commit = (OB_SUCCESS == ret);
1476int tmp_ret = OB_SUCCESS;
1477if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
1478LOG_WARN("fail to end trans", K(tmp_ret), K(commit));
1479ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
1480}
1481if (OB_FAIL(ret)) {
1482// 1. The transaction did fail to commit.
1483// the internal table and the memory state remain the same,
1484// as long as the memory of allocate_pool_ptrs is released.
1485//
1486// 2. The transaction submission timed out, but the final submission was successful.
1487// The internal table and memory state are inconsistent,
1488// and the outer layer will call the reload unit manager.
1489// Still need to release the memory of allocate_pool_ptrs
1490for (int64_t i = 0; i < allocate_pool_ptrs.count(); ++i) {
1491share::ObResourcePool *new_pool = allocate_pool_ptrs.at(i);
1492if (NULL != new_pool) {
1493pool_allocator_.free(new_pool);
1494new_pool = NULL;
1495}
1496}
1497}
1498}
1499return ret;
1500}
1501
1502int ObUnitManager::do_split_pool_inmemory_info(
1503share::ObResourcePool *pool,
1504common::ObIArray<share::ObResourcePool *> &allocate_pool_ptrs)
1505{
1506int ret = OB_SUCCESS;
1507if (!check_inner_stat()) {
1508ret = OB_INNER_STAT_ERROR;
1509LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1510} else if (NULL == pool) {
1511ret = OB_INVALID_ARGUMENT;
1512LOG_WARN("invalid argument", K(ret));
1513} else {
1514for (int64_t i = 0; OB_SUCC(ret) && i < allocate_pool_ptrs.count(); ++i) {
1515share::ObResourcePool *new_pool = allocate_pool_ptrs.at(i);
1516if (OB_UNLIKELY(NULL == new_pool)) {
1517ret = OB_ERR_UNEXPECTED;
1518LOG_WARN("pool ptr is null", K(ret));
1519} else if (new_pool->zone_list_.count() != 1) {
1520ret = OB_ERR_UNEXPECTED;
1521LOG_WARN("zone list count unexpected", K(ret), "zone_list", new_pool->zone_list_);
1522} else if (OB_FAIL(inc_config_ref_count(new_pool->unit_config_id_))) {
1523LOG_WARN("fail to inc config ref count", K(ret),
1524"unit_config_id", new_pool->unit_config_id_);
1525} else if (OB_FAIL(insert_config_pool(new_pool->unit_config_id_, new_pool))) {
1526LOG_WARN("fail to insert config pool", K(ret),
1527"unit_config_id", new_pool->unit_config_id_);
1528} else if (OB_FAIL(update_pool_map(new_pool))) {
1529LOG_WARN("fail to update pool map", K(ret),
1530"resource_pool_id", new_pool->resource_pool_id_);
1531} else if (!new_pool->is_granted_to_tenant()) {
1532// bypass
1533} else if (OB_FAIL(insert_tenant_pool(new_pool->tenant_id_, new_pool))) {
1534LOG_WARN("fail to insert tenant pool", K(ret), "tenant_id", new_pool->tenant_id_);
1535}
1536if (OB_FAIL(ret)) {
1537// failed
1538} else if (OB_FAIL(split_pool_unit_inmemory_info(
1539new_pool->zone_list_.at(0), new_pool, pool))) {
1540LOG_WARN("fail to split pool unit inmemory info", K(ret));
1541} else {} // no more
1542}
1543common::ObArray<share::ObUnit *> *pool_units = NULL;
1544if (OB_FAIL(ret)) {
1545} else if (OB_FAIL(dec_config_ref_count(pool->unit_config_id_))) {
1546LOG_WARN("fail to dec config ref count", K(ret));
1547} else if (OB_FAIL(delete_config_pool(pool->unit_config_id_, pool))) {
1548LOG_WARN("fail to delete config pool", K(ret));
1549} else if (OB_FAIL(delete_resource_pool(pool->resource_pool_id_, pool->name_))) {
1550LOG_WARN("fail to delete resource pool", K(ret));
1551} else if (!pool->is_granted_to_tenant()) {
1552// bypass
1553} else if (OB_FAIL(delete_tenant_pool(pool->tenant_id_, pool))) {
1554LOG_WARN("fail to delete tenant pool", K(ret), "tenant_id", pool->tenant_id_);
1555}
1556if (OB_FAIL(ret)) {
1557} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, pool_units))) {
1558LOG_WARN("fail to get units by pool", K(ret), "pool_id", pool->resource_pool_id_);
1559} else if (OB_UNLIKELY(NULL == pool_units)) {
1560ret = OB_ERR_UNEXPECTED;
1561LOG_WARN("pool units ptr is null", K(ret));
1562} else if (OB_FAIL(pool_unit_map_.erase_refactored(pool->resource_pool_id_))) {
1563LOG_WARN("fail to erase map", K(ret), "pool_id", pool->resource_pool_id_);
1564} else {
1565pool_unit_allocator_.free(pool_units);
1566pool_units = NULL;
1567pool_allocator_.free(pool);
1568pool = NULL;
1569}
1570if (OB_FAIL(ret)) {
1571// reload
1572rootserver::ObRootService *root_service = NULL;
1573if (OB_UNLIKELY(NULL == (root_service = GCTX.root_service_))) {
1574ret = OB_ERR_UNEXPECTED;
1575LOG_WARN("rootservice is null", K(ret));
1576} else {
1577int tmp_ret = root_service->submit_reload_unit_manager_task();
1578if (OB_SUCCESS != tmp_ret) {
1579LOG_ERROR("fail to reload unit manager", K(tmp_ret));
1580}
1581}
1582}
1583}
1584return ret;
1585}
1586
1587int ObUnitManager::do_split_resource_pool(
1588share::ObResourcePool *pool,
1589const common::ObIArray<share::ObResourcePoolName> &split_pool_name_list,
1590const common::ObIArray<common::ObZone> &split_zone_list)
1591{
1592int ret = OB_SUCCESS;
1593common::ObArray<share::ObResourcePool *> allocate_pool_ptrs;
1594if (!check_inner_stat()) {
1595ret = OB_INNER_STAT_ERROR;
1596LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1597} else if (OB_UNLIKELY(NULL == pool)) {
1598ret = OB_INVALID_ARGUMENT;
1599LOG_WARN("invalid argument", K(ret));
1600} else if (split_pool_name_list.count() != split_zone_list.count()) {
1601ret = OB_ERR_UNEXPECTED;
1602LOG_WARN("split pool name and zone count not match",
1603K(ret), K(split_pool_name_list), K(split_zone_list));
1604} else if (OB_FAIL(do_split_pool_persistent_info(
1605pool, split_pool_name_list, split_zone_list, allocate_pool_ptrs))) {
1606LOG_WARN("fail to do split pool persistent info", K(ret));
1607} else if (OB_FAIL(do_split_pool_inmemory_info(pool, allocate_pool_ptrs))) {
1608LOG_WARN("fail to do split pool inmemory info", K(ret));
1609} else {} // no more
1610return ret;
1611}
1612
1613int ObUnitManager::fill_splitting_pool_basic_info(
1614const share::ObResourcePoolName &new_pool_name,
1615share::ObResourcePool *new_pool,
1616const common::ObZone &zone,
1617share::ObResourcePool *orig_pool)
1618{
1619int ret = OB_SUCCESS;
1620if (!check_inner_stat()) {
1621ret = OB_INNER_STAT_ERROR;
1622LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1623} else if (OB_UNLIKELY(new_pool_name.is_empty() || NULL == new_pool
1624|| zone.is_empty() || NULL == orig_pool)) {
1625ret = OB_INVALID_ARGUMENT;
1626LOG_WARN("invalid argument", K(ret), K(new_pool_name), KP(new_pool), K(zone), K(orig_pool));
1627} else {
1628new_pool->name_ = new_pool_name;
1629new_pool->unit_count_ = orig_pool->unit_count_;
1630new_pool->unit_config_id_ = orig_pool->unit_config_id_;
1631new_pool->tenant_id_ = orig_pool->tenant_id_;
1632new_pool->replica_type_ = orig_pool->replica_type_;
1633if (OB_FAIL(new_pool->zone_list_.push_back(zone))) {
1634LOG_WARN("fail to push back to zone list", K(ret));
1635} else if (OB_FAIL(fetch_new_resource_pool_id(new_pool->resource_pool_id_))) {
1636LOG_WARN("fail to fetch new resource pool id", K(ret));
1637} else {} // finish fill splitting pool basic info
1638}
1639return ret;
1640}
1641
1642int ObUnitManager::split_pool_unit_inmemory_info(
1643const common::ObZone &zone,
1644share::ObResourcePool *new_pool,
1645share::ObResourcePool *orig_pool)
1646{
1647int ret = OB_SUCCESS;
1648common::ObArray<share::ObUnit *> *new_units = NULL;
1649common::ObArray<share::ObUnit *> *orig_units = NULL;
1650if (!check_inner_stat()) {
1651ret = OB_INNER_STAT_ERROR;
1652LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1653} else if (OB_UNLIKELY(NULL == new_pool || NULL == orig_pool || zone.is_empty())) {
1654ret = OB_INVALID_ARGUMENT;
1655LOG_WARN("invalid argument", K(ret), KP(new_pool), K(orig_pool), K(zone));
1656} else if (OB_FAIL(get_units_by_pool(orig_pool->resource_pool_id_, orig_units))) {
1657LOG_WARN("fail to get units by pool", K(ret));
1658} else if (OB_UNLIKELY(NULL == orig_units)) {
1659ret = OB_ERR_UNEXPECTED;
1660LOG_WARN("units ptr is null", K(ret));
1661} else {
1662ret = get_units_by_pool(new_pool->resource_pool_id_, new_units);
1663if (OB_SUCCESS == ret) {
1664// got new units
1665} else if (OB_ENTRY_NOT_EXIST != ret) {
1666LOG_WARN("fail to get units by pool", K(ret));
1667} else {
1668if (NULL == (new_units = pool_unit_allocator_.alloc())) {
1669ret = OB_ALLOCATE_MEMORY_FAILED;
1670LOG_ERROR("fail to alloc memory", K(ret));
1671} else if (OB_FAIL(pool_unit_map_.set_refactored(new_pool->resource_pool_id_, new_units))) {
1672LOG_WARN("fail to set refactored", K(ret), "pool_id", new_pool->resource_pool_id_);
1673}
1674}
1675for (int64_t i = 0; OB_SUCC(ret) && i < orig_units->count(); ++i) {
1676share::ObUnit *unit = orig_units->at(i);
1677if (OB_UNLIKELY(NULL == unit)) {
1678ret = OB_ERR_UNEXPECTED;
1679LOG_WARN("unit ptr is null", K(ret));
1680} else if (zone != unit->zone_) {
1681// bypass
1682} else if (NULL == new_units) {
1683ret = OB_ERR_UNEXPECTED;
1684LOG_WARN("new units ptr is null", K(ret));
1685} else {
1686unit->resource_pool_id_ = new_pool->resource_pool_id_;
1687if (OB_FAIL(new_units->push_back(unit))) {
1688LOG_WARN("fail to push back", K(ret));
1689} else if (OB_FAIL(update_unit_load(unit, new_pool))) {
1690LOG_WARN("fail to update unit load", K(ret));
1691}
1692}
1693}
1694}
1695return ret;
1696}
1697
1698int ObUnitManager::split_pool_unit_persistent_info(
1699common::ObMySQLTransaction &trans,
1700const common::ObZone &zone,
1701share::ObResourcePool *new_pool,
1702share::ObResourcePool *orig_pool)
1703{
1704int ret = OB_SUCCESS;
1705common::ObArray<share::ObUnit *> *units = NULL;
1706if (!check_inner_stat()) {
1707ret = OB_INNER_STAT_ERROR;
1708LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
1709} else if (OB_UNLIKELY(NULL == new_pool || NULL == orig_pool || zone.is_empty())) {
1710ret = OB_INVALID_ARGUMENT;
1711LOG_WARN("invalid argument", K(ret), KP(new_pool), KP(orig_pool), K(zone));
1712} else if (OB_FAIL(get_units_by_pool(orig_pool->resource_pool_id_, units))) {
1713LOG_WARN("fail to get units by pool", K(ret));
1714} else if (OB_UNLIKELY(NULL == units)) {
1715ret = OB_ERR_UNEXPECTED;
1716LOG_WARN("units ptr is null", K(ret));
1717} else {
1718for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
1719const share::ObUnit *unit = units->at(i);
1720if (OB_UNLIKELY(NULL == unit)) {
1721ret = OB_ERR_UNEXPECTED;
1722LOG_WARN("unit ptr is null", K(ret));
1723} else if (unit->zone_ != zone) {
1724// bypass
1725} else {
1726share::ObUnit new_unit = *unit;
1727new_unit.resource_pool_id_ = new_pool->resource_pool_id_;
1728if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, false/*need_check_conflict_with_clone*/))) {
1729LOG_WARN("fail to update unit", K(ret), K(new_unit));
1730} else {
1731ROOTSERVICE_EVENT_ADD("unit", "split_pool",
1732"unit_id", unit->unit_id_,
1733"server", unit->server_,
1734"prev_pool_id", orig_pool->resource_pool_id_,
1735"curr_pool_id", new_pool->resource_pool_id_);
1736}
1737}
1738}
1739}
1740return ret;
1741}
1742
1743/* current_unit_num_per_zone: pool->unit_count_
1744* complete_unit_num_per_zone: pool->unit_count_ + unit_num_in_deleting
1745* has_unit_num_modification: when some unit in deleting this is true, else false
1746*/
1747int ObUnitManager::get_tenant_pools_complete_unit_num_and_status(
1748const uint64_t tenant_id,
1749const common::ObIArray<share::ObResourcePool *> &pools,
1750int64_t &complete_unit_num_per_zone,
1751int64_t ¤t_unit_num_per_zone,
1752bool &has_unit_num_modification)
1753{
1754int ret = OB_SUCCESS;
1755if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
1756ret = OB_INVALID_ARGUMENT;
1757LOG_WARN("invalid argument", KR(ret), K(tenant_id));
1758} else if (OB_UNLIKELY(pools.count() <= 0)) {
1759ret = OB_INVALID_ARGUMENT;
1760LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(pools));
1761} else {
1762complete_unit_num_per_zone = -1;
1763current_unit_num_per_zone = -1;
1764has_unit_num_modification = false;
1765for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
1766int64_t my_complete_unit_num_per_zone = 0;
1767int64_t my_current_unit_num_per_zone = 0;
1768bool my_unit_num_modification = false;
1769const share::ObResourcePool *pool = pools.at(i);
1770if (OB_UNLIKELY(nullptr == pool)) {
1771ret = OB_ERR_UNEXPECTED;
1772LOG_WARN("pool ptr is null", KR(ret), KP(pool), K(tenant_id));
1773} else if (tenant_id != pool->tenant_id_) {
1774ret = OB_ERR_UNEXPECTED;
1775LOG_WARN("tenant id not match");
1776} else if (OB_FAIL(get_pool_complete_unit_num_and_status(
1777pool, my_complete_unit_num_per_zone,
1778my_current_unit_num_per_zone, my_unit_num_modification))) {
1779LOG_WARN("fail to get pool complete unit num and status", KR(ret));
1780} else if (-1 == complete_unit_num_per_zone) {
1781complete_unit_num_per_zone = my_complete_unit_num_per_zone;
1782current_unit_num_per_zone = my_current_unit_num_per_zone;
1783has_unit_num_modification = my_unit_num_modification;
1784} else if (complete_unit_num_per_zone != my_complete_unit_num_per_zone
1785|| current_unit_num_per_zone != my_current_unit_num_per_zone
1786|| has_unit_num_modification != my_unit_num_modification) {
1787ret = OB_ERR_UNEXPECTED;
1788LOG_WARN("tenant pools unit status unexpected", KR(ret), K(tenant_id));
1789}
1790}
1791}
1792return ret;
1793}
1794
1795int ObUnitManager::determine_alter_resource_tenant_unit_num_type(
1796const uint64_t tenant_id,
1797const common::ObIArray<share::ObResourcePool *> &pools,
1798const int64_t new_unit_num,
1799int64_t &old_unit_num,
1800AlterUnitNumType &alter_unit_num_type)
1801{
1802int ret = OB_SUCCESS;
1803int64_t complete_unit_num_per_zone = 0;
1804old_unit_num = 0;
1805bool has_unit_num_modification = true;
1806
1807if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || new_unit_num <= 0)) {
1808ret = OB_INVALID_ARGUMENT;
1809LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(new_unit_num));
1810} else if (OB_FAIL(get_tenant_pools_complete_unit_num_and_status(
1811tenant_id, pools, complete_unit_num_per_zone,
1812old_unit_num, has_unit_num_modification))) {
1813LOG_WARN("fail to get tenant pools complete unit num and status", KR(ret), K(tenant_id));
1814} else if (OB_UNLIKELY(complete_unit_num_per_zone <= 0 || old_unit_num <= 0)) {
1815ret = OB_ERR_UNEXPECTED;
1816LOG_WARN("unexpected complete unit num", KR(ret),
1817K(complete_unit_num_per_zone), K(old_unit_num));
1818} else if (old_unit_num == new_unit_num) {
1819// when the new unit num is equal to the current unit num, do nothing and return
1820alter_unit_num_type = AUN_NOP;
1821} else {
1822if (has_unit_num_modification) { // a unit num change is taking place
1823if (new_unit_num == complete_unit_num_per_zone) {
1824// alter unit num to previous, it is a unit num rollback operation
1825alter_unit_num_type = AUN_ROLLBACK_SHRINK;
1826} else {
1827// alter unit num to a value not equal to the previous, an illegal operation
1828alter_unit_num_type = AUN_MAX;
1829}
1830} else { // no unit num change
1831if (new_unit_num > old_unit_num) {
1832alter_unit_num_type = AUN_EXPAND;
1833} else {
1834alter_unit_num_type = AUN_SHRINK;
1835}
1836}
1837}
1838return ret;
1839}
1840
1841int ObUnitManager::register_alter_resource_tenant_unit_num_rs_job(
1842const uint64_t tenant_id,
1843const int64_t new_unit_num,
1844const int64_t old_unit_num,
1845const AlterUnitNumType alter_unit_num_type,
1846const common::ObString &sql_text,
1847common::ObMySQLTransaction &trans)
1848{
1849int ret = OB_SUCCESS;
1850uint64_t tenant_data_version = 0;
1851if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id)
1852|| !(AUN_SHRINK == alter_unit_num_type || AUN_EXPAND == alter_unit_num_type))) {
1853ret = OB_INVALID_ARGUMENT;
1854LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(alter_unit_num_type));
1855} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
1856LOG_WARN("fail to get min data version", KR(ret), K(tenant_id));
1857} else if (tenant_data_version < DATA_VERSION_4_2_1_0) {
1858if (AUN_EXPAND == alter_unit_num_type) {
1859// skip, no rs job for expand task in version 4.1
1860// we do not need to rollback rs job, since in 4.1, there is no inprogress rs job at this step
1861} else if (OB_FAIL(register_shrink_tenant_pool_unit_num_rs_job(tenant_id,
1862new_unit_num, old_unit_num, sql_text, trans))) {
1863LOG_WARN("fail to execute register_shrink_tenant_pool_unit_num_rs_job", KR(ret),
1864K(tenant_id), K(new_unit_num));
1865}
1866} else { // tenant_data_version >= DATA_VERSION_4_2_1_0
1867// step 1: cancel rs job if exists
1868int64_t job_id = 0;
1869if (!ObShareUtil::is_tenant_enable_rebalance(tenant_id)) {
1870ret = OB_OP_NOT_ALLOW;
1871LOG_WARN("enable_rebalance is disabled, modify tenant unit num not allowed", KR(ret), K(tenant_id));
1872(void) print_user_error_(tenant_id);
1873} else if(OB_FAIL(cancel_alter_resource_tenant_unit_num_rs_job(tenant_id, trans))) {
1874LOG_WARN("fail to execute cancel_alter_resource_tenant_unit_num_rs_job",
1875KR(ret), K(tenant_id), K(sql_text));
1876} else {
1877ret = create_alter_resource_tenant_unit_num_rs_job(tenant_id,
1878new_unit_num, old_unit_num, job_id, sql_text, trans);
1879FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] create a new rs job", "type",
1880AUN_EXPAND == alter_unit_num_type ? "EXPAND UNIT_NUM" : "SHRINK UNIT_NUM",
1881KR(ret), K(tenant_id), K(job_id), K(alter_unit_num_type));
1882}
1883}
1884return ret;
1885}
1886
1887int ObUnitManager::find_alter_resource_tenant_unit_num_rs_job(
1888const uint64_t tenant_id,
1889int64_t &job_id,
1890common::ObISQLClient &sql_proxy)
1891{
1892int ret = OB_SUCCESS;
1893ret = RS_JOB_FIND(
1894ALTER_RESOURCE_TENANT_UNIT_NUM,
1895job_id,
1896sql_proxy,
1897"tenant_id", tenant_id);
1898if (OB_ENTRY_NOT_EXIST == ret) {
1899ret = RS_JOB_FIND(
1900SHRINK_RESOURCE_TENANT_UNIT_NUM, // only created in version < 4.2
1901job_id,
1902sql_proxy,
1903"tenant_id", tenant_id);
1904}
1905return ret;
1906}
1907int ObUnitManager::register_shrink_tenant_pool_unit_num_rs_job(
1908const uint64_t tenant_id,
1909const int64_t new_unit_num,
1910const int64_t old_unit_num,
1911const common::ObString &sql_text,
1912common::ObMySQLTransaction &trans)
1913{
1914int ret = OB_SUCCESS;
1915int64_t pos = 0;
1916int64_t job_id = 0;
1917if (!ObShareUtil::is_tenant_enable_rebalance(tenant_id)) {
1918ret = OB_OP_NOT_ALLOW;
1919LOG_WARN("enable_rebalance is disabled, modify tenant unit num not allowed", KR(ret), K(tenant_id));
1920(void) print_user_error_(tenant_id);
1921} else {
1922ret = create_alter_resource_tenant_unit_num_rs_job(
1923tenant_id,
1924new_unit_num,
1925old_unit_num,
1926job_id,
1927sql_text,
1928trans,
1929JOB_TYPE_SHRINK_RESOURCE_TENANT_UNIT_NUM);
1930FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] create a new rs job in Version < 4.2",
1931KR(ret), K(tenant_id), K(job_id), K(sql_text));
1932}
1933return ret ;
1934}
1935
1936void ObUnitManager::print_user_error_(const uint64_t tenant_id)
1937{
1938const int64_t ERR_MSG_LEN = 256;
1939char err_msg[ERR_MSG_LEN] = {'\0'};
1940int ret = OB_SUCCESS;
1941int64_t pos = 0;
1942if (OB_FAIL(databuff_printf(err_msg, ERR_MSG_LEN, pos,
1943"Tenant (%lu) 'enable_rebalance' is disabled, alter tenant unit num", tenant_id))) {
1944if (OB_SIZE_OVERFLOW == ret) {
1945LOG_WARN("format to buff size overflow", KR(ret));
1946} else {
1947LOG_WARN("format new unit num failed", KR(ret));
1948}
1949} else {
1950LOG_USER_ERROR(OB_OP_NOT_ALLOW, err_msg);
1951}
1952}
1953
1954int ObUnitManager::cancel_alter_resource_tenant_unit_num_rs_job(
1955const uint64_t tenant_id,
1956common::ObMySQLTransaction &trans)
1957{
1958int ret = OB_SUCCESS;
1959int64_t job_id = 0;
1960if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
1961ret = OB_INVALID_ARGUMENT;
1962LOG_WARN("invalid tenant_id", KR(ret), K(tenant_id));
1963} else if (OB_FAIL(find_alter_resource_tenant_unit_num_rs_job(tenant_id, job_id, trans))) {
1964if (OB_ENTRY_NOT_EXIST == ret) {
1965ret = OB_SUCCESS;
1966FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] there is no rs job in table",KR(ret), K(tenant_id));
1967} else {
1968LOG_WARN("fail to execute find_alter_resource_tenant_unit_num_rs_job", KR(ret), K(tenant_id));
1969}
1970} else {
1971ret = RS_JOB_COMPLETE(job_id, OB_CANCELED, trans);
1972FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] cancel an inprogress rs job", KR(ret),
1973K(tenant_id), K(job_id));
1974}
1975return ret;
1976}
1977
1978int ObUnitManager::create_alter_resource_tenant_unit_num_rs_job(
1979const uint64_t tenant_id,
1980const int64_t new_unit_num,
1981const int64_t old_unit_num,
1982int64_t &job_id,
1983const common::ObString &sql_text,
1984common::ObMySQLTransaction &trans,
1985ObRsJobType job_type)
1986{
1987int ret = OB_SUCCESS;
1988job_id = 0;
1989const int64_t extra_info_len = common::MAX_ROOTSERVICE_EVENT_EXTRA_INFO_LENGTH;
1990HEAP_VAR(char[extra_info_len], extra_info) {
1991memset(extra_info, 0, extra_info_len);
1992int64_t pos = 0;
1993share::schema::ObSchemaGetterGuard schema_guard;
1994const ObSimpleTenantSchema *tenant_schema;
1995if (OB_FAIL(databuff_printf(extra_info, extra_info_len, pos,
1996"FROM: '%ld', TO: '%ld'", old_unit_num, new_unit_num))) {
1997if (OB_SIZE_OVERFLOW == ret) {
1998LOG_WARN("format to buff size overflow", K(ret));
1999} else {
2000LOG_WARN("format new unit num failed", K(ret));
2001}
2002} else if (OB_ISNULL(schema_service_)) {
2003ret = OB_NOT_INIT;
2004LOG_WARN("schema service is null", KR(ret), KP(schema_service_));
2005} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
2006LOG_WARN("fail to get tenant schema guard", KR(ret), K(tenant_id));
2007} else if (OB_FAIL(schema_guard.get_tenant_info(tenant_id, tenant_schema))) {
2008LOG_WARN("fail to get tenant info", K(ret), K(tenant_id));
2009} else if (OB_ISNULL(tenant_schema)) {
2010ret = OB_ERR_UNEXPECTED;
2011LOG_WARN("tenant schema is null", KR(ret), KP(tenant_schema));
2012} else if (OB_FAIL(RS_JOB_CREATE_WITH_RET(
2013job_id,
2014job_type,
2015trans,
2016"tenant_id", tenant_id,
2017"tenant_name", tenant_schema->get_tenant_name(),
2018"sql_text", ObHexEscapeSqlStr(sql_text),
2019"extra_info", ObHexEscapeSqlStr(extra_info)))) {
2020LOG_WARN("fail to create rs job", KR(ret), K(tenant_id), K(job_type));
2021}
2022}
2023return ret;
2024}
2025
2026int ObUnitManager::rollback_alter_resource_tenant_unit_num_rs_job(
2027const uint64_t tenant_id,
2028const int64_t new_unit_num,
2029const int64_t old_unit_num,
2030const common::ObString &sql_text,
2031common::ObMySQLTransaction &trans)
2032{
2033int ret = OB_SUCCESS;
2034int64_t job_id = 0;
2035uint64_t tenant_data_version = 0;
2036if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
2037LOG_WARN("fail to get min data version", KR(ret), K(tenant_id));
2038} else if (tenant_data_version < DATA_VERSION_4_2_1_0) {
2039// in v4.1, it's allowed, since this will not track the number of logstreams
2040if (OB_FAIL(cancel_alter_resource_tenant_unit_num_rs_job(tenant_id, trans))) {
2041LOG_WARN("fail to execute cancel_alter_resource_tenant_unit_num_rs_job in v4.1", KR(ret), K(tenant_id));
2042}
2043} else if (!ObShareUtil::is_tenant_enable_rebalance(tenant_id)) {
2044ret = OB_OP_NOT_ALLOW;
2045LOG_WARN("enable_rebalance is disabled, modify tenant unit num not allowed", KR(ret), K(tenant_id));
2046(void) print_user_error_(tenant_id);
2047} else if (OB_FAIL(cancel_alter_resource_tenant_unit_num_rs_job(tenant_id, trans))) {
2048LOG_WARN("fail to execute cancel_alter_resource_tenant_unit_num_rs_job", KR(ret), K(tenant_id));
2049} else if (OB_FAIL(create_alter_resource_tenant_unit_num_rs_job(tenant_id,
2050new_unit_num, old_unit_num, job_id, sql_text, trans))) {
2051LOG_WARN("fail to execute create_alter_resource_tenant_unit_num_rs_job", KR(ret),
2052K(tenant_id), K(new_unit_num), K(old_unit_num), K(sql_text));
2053}
2054FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] rollback a SHRINK UNIT_NUM rs job",
2055KR(ret), K(tenant_id), K(job_id), K(new_unit_num));
2056return ret;
2057}
2058
2059int ObUnitManager::try_complete_shrink_tenant_pool_unit_num_rs_job(
2060const uint64_t tenant_id,
2061common::ObMySQLTransaction &trans)
2062{
2063int ret = OB_SUCCESS;
2064// this function is called by ObDDLService::drop_resource_pool_pre
2065const int check_ret = OB_SUCCESS; // no need to check ls status
2066int64_t job_id = 0;
2067if (OB_FAIL(find_alter_resource_tenant_unit_num_rs_job(tenant_id, job_id, trans))) {
2068if (OB_ENTRY_NOT_EXIST == ret) {
2069ret = OB_SUCCESS;
2070} else {
2071LOG_WARN("fail to execute find_alter_resource_tenant_unit_num_rs_job", KR(ret), K(tenant_id));
2072}
2073} else {
2074ret = complete_shrink_tenant_pool_unit_num_rs_job_(
2075tenant_id, job_id, check_ret, trans);
2076FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] complete an inprogress rs job DROP_TENANT_FORCE",
2077KR(ret), K(tenant_id), K(job_id));
2078}
2079return ret;
2080}
2081
2082int ObUnitManager::complete_shrink_tenant_pool_unit_num_rs_job_(
2083const uint64_t tenant_id,
2084const int64_t job_id,
2085const int check_ret,
2086common::ObMySQLTransaction &trans)
2087{
2088int ret = OB_SUCCESS;
2089if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id)) || job_id < 0) {
2090ret = OB_INVALID_ARGUMENT;
2091LOG_WARN("invalid tenant_id", KR(ret), K(tenant_id), K(job_id));
2092} else if (OB_SUCC(RS_JOB_COMPLETE(job_id, check_ret, trans))) {
2093FLOG_INFO("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] complete an inprogressing rs job SHRINK UNIT_NUM",
2094KR(ret), K(tenant_id), K(job_id), K(check_ret));
2095} else {
2096LOG_WARN("fail to complete rs job", KR(ret), K(tenant_id), K(job_id), K(check_ret));
2097if (OB_EAGAIN == ret) {
2098int64_t curr_job_id = 0;
2099if (OB_FAIL(find_alter_resource_tenant_unit_num_rs_job(tenant_id, curr_job_id, trans))) {
2100LOG_WARN("fail to find rs job", KR(ret), K(tenant_id), K(job_id), K(check_ret));
2101if (OB_ENTRY_NOT_EXIST == ret) {
2102FLOG_WARN("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] the specified rs job SHRINK UNIT_NUM might has "
2103"been already deleted in table manually",
2104KR(ret), K(tenant_id), K(job_id), K(check_ret));
2105ret = OB_SUCCESS;
2106}
2107} else {
2108ret = OB_EAGAIN;
2109FLOG_WARN("[ALTER_RESOURCE_TENANT_UNIT_NUM NOTICE] a non-checked rs job SHRINK UNIT_NUM cannot be committed",
2110KR(ret), K(job_id), K(curr_job_id));
2111}
2112}
2113}
2114return ret ;
2115}
2116
2117/* generate new unit group id for pools, we hold the assumption that
2118* each pool of pools comes from the same tenant and has the same unit num
2119*/
2120int ObUnitManager::generate_new_unit_group_id_array(
2121const uint64_t tenant_id,
2122const common::ObIArray<share::ObResourcePool *> &pools,
2123const int64_t new_unit_num,
2124common::ObIArray<uint64_t> &unit_group_id_array)
2125{
2126int ret = OB_SUCCESS;
2127if (OB_UNLIKELY(pools.count() <= 0 || new_unit_num <= 0)) {
2128ret = OB_INVALID_ARGUMENT;
2129LOG_WARN("invalid argument", KR(ret), K(pools), K(new_unit_num));
2130} else {
2131{ // defense check
2132int64_t sample_unit_num = -1;
2133for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2134const share::ObResourcePool *pool = pools.at(i);
2135if (OB_UNLIKELY(nullptr == pool)) {
2136ret = OB_ERR_UNEXPECTED;
2137LOG_WARN("pool ptr is null", KR(ret), K(tenant_id));
2138} else if (-1 == sample_unit_num) {
2139sample_unit_num = pool->unit_count_;
2140} else if (sample_unit_num != pool->unit_count_) {
2141ret = OB_ERR_UNEXPECTED;
2142LOG_WARN("unit num not match", KR(ret), K(tenant_id), KPC(pool), K(sample_unit_num));
2143}
2144}
2145}
2146const share::ObResourcePool *pool = pools.at(0);
2147int64_t unit_group_id_num = 0;
2148if (OB_FAIL(ret)) {
2149// failed, bypass
2150} else if (OB_UNLIKELY(nullptr == pool)) {
2151ret = OB_ERR_UNEXPECTED;
2152LOG_WARN("pool ptr is null", KR(ret));
2153} else if ((unit_group_id_num = new_unit_num - pool->unit_count_) <= 0) {
2154ret = OB_ERR_UNEXPECTED;
2155LOG_WARN("unit_group_id_num unexpected", KR(ret), K(unit_group_id_num), K(new_unit_num));
2156} else {
2157unit_group_id_array.reset();
2158for (int64_t i = 0; OB_SUCC(ret) && i < unit_group_id_num; ++i) {
2159uint64_t unit_group_id = OB_INVALID_ID;
2160if (OB_FAIL(fetch_new_unit_group_id(unit_group_id))) {
2161LOG_WARN("fail to fetch new unit group id", KR(ret));
2162} else if (OB_FAIL(unit_group_id_array.push_back(unit_group_id))) {
2163LOG_WARN("fail to push back", KR(ret));
2164}
2165}
2166}
2167}
2168return ret;
2169}
2170
2171/* when alter resource tenant and the new unit num is greater than the current unit num,
2172* this func is invoked.
2173*/
2174int ObUnitManager::expand_tenant_pools_unit_num_(
2175const uint64_t tenant_id,
2176common::ObIArray<share::ObResourcePool *> &pools,
2177const int64_t new_unit_num,
2178const int64_t old_unit_num,
2179const char *module,
2180const common::ObString &sql_text)
2181{
2182int ret = OB_SUCCESS;
2183common::ObMySQLTransaction trans;
2184common::ObArray<uint64_t> new_unit_group_id_array;
2185ObArray<ObAddr> new_servers;
2186if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || new_unit_num <= 0)) {
2187ret = OB_INVALID_ARGUMENT;
2188LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(new_unit_num));
2189} else if (OB_FAIL(generate_new_unit_group_id_array(
2190tenant_id, pools, new_unit_num, new_unit_group_id_array))) {
2191LOG_WARN("fail to generate new unit group id array", KR(ret), K(pools), K(new_unit_num));
2192} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
2193LOG_WARN("fail to start transaction", KR(ret));
2194} else if (OB_FAIL(register_alter_resource_tenant_unit_num_rs_job(tenant_id,
2195new_unit_num, old_unit_num, AUN_EXPAND, sql_text, trans))) {
2196LOG_WARN("fail to register shrink tenant pool unit num rs job", KR(ret),
2197K(tenant_id), K(sql_text), K(old_unit_num), K(new_unit_num));
2198} else {
2199share::ObResourcePool new_pool;
2200for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2201const bool new_allocate_pool = false;
2202const share::ObResourcePool *pool = pools.at(i);
2203new_pool.reset();
2204if (OB_UNLIKELY(nullptr == pool)) {
2205ret = OB_ERR_UNEXPECTED;
2206LOG_WARN("unexpected pool", KR(ret), K(tenant_id));
2207} else if (pool->tenant_id_ != tenant_id) {
2208ret = OB_ERR_UNEXPECTED;
2209LOG_WARN("tenant id not match", KR(ret),
2210K(tenant_id), "pool_tenant_id", pool->tenant_id_);
2211} else if (OB_FAIL(allocate_pool_units_(
2212trans, *pool, pool->zone_list_, &new_unit_group_id_array, new_allocate_pool,
2213new_unit_num - pool->unit_count_, module, new_servers))) {
2214LOG_WARN("fail to allocate pool units", K(module), KR(ret), K(new_unit_num), KPC(pool));
2215} else if (OB_FAIL(new_pool.assign(*pool))) {
2216LOG_WARN("fail to assign new pool", KR(ret));
2217} else if (FALSE_IT(new_pool.unit_count_ = new_unit_num)) {
2218// false it, shall never be here
2219} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, true/*need_check_conflict_with_clone*/))) {
2220LOG_WARN("fail to update resource pool", KR(ret), K(tenant_id));
2221}
2222}
2223const bool commit = (OB_SUCCESS == ret);
2224int tmp_ret = OB_SUCCESS;
2225if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
2226LOG_WARN("fail to trans end", KR(tmp_ret), K(commit));
2227ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
2228}
2229for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2230share::ObResourcePool *pool = pools.at(i);
2231if (OB_UNLIKELY(nullptr == pool)) {
2232ret = OB_ERR_UNEXPECTED;
2233LOG_WARN("unexpected pool", KR(ret), K(tenant_id));
2234} else {
2235pool->unit_count_ = new_unit_num;
2236}
2237}
2238}
2239return ret;
2240}
2241
2242int ObUnitManager::get_to_be_deleted_unit_group(
2243const uint64_t tenant_id,
2244const common::ObIArray<share::ObResourcePool *> &pools,
2245const int64_t new_unit_num,
2246const common::ObIArray<uint64_t> &deleted_unit_group_id_array,
2247common::ObIArray<uint64_t> &to_be_deleted_unit_group)
2248{
2249int ret = OB_SUCCESS;
2250if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || pools.count() <= 0)) {
2251ret = OB_INVALID_ARGUMENT;
2252LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(pools));
2253} else {
2254common::ObArray<uint64_t> all_unit_group_id_array;
2255const share::ObResourcePool *pool = pools.at(0);
2256const bool is_active = false;
2257int64_t to_be_deleted_num = 0;
2258if (OB_UNLIKELY(nullptr == pool)) {
2259ret = OB_ERR_UNEXPECTED;
2260LOG_WARN("pool ptr is null", KR(ret), KP(pool));
2261} else if ((to_be_deleted_num = pool->unit_count_ - new_unit_num) <= 0) {
2262ret = OB_ERR_UNEXPECTED;
2263LOG_WARN("unit num unexpected", KR(ret), KPC(pool), K(tenant_id), K(new_unit_num));
2264} else if (OB_FAIL(inner_get_all_unit_group_id(tenant_id, is_active, all_unit_group_id_array))) {
2265LOG_WARN("fail to get all unit group id", KR(ret), K(tenant_id));
2266} else if (to_be_deleted_num > all_unit_group_id_array.count()) {
2267ret = OB_ERR_UNEXPECTED;
2268LOG_WARN("unit num to match", KR(ret), K(tenant_id), K(new_unit_num),
2269"old_unit_num", pool->unit_count_,
2270"tenant_unit_group_num", all_unit_group_id_array.count());
2271} else if (deleted_unit_group_id_array.count() <= 0) {
2272// deleted unit groups not specified by the client, we choose for automatically
2273// If some servers are inactive, the related unit_group should take priority to be deleted.
2274ObArray<uint64_t> sorted_unit_group_id_array;
2275// inactive unit_group_id first
2276ObArray<ObUnitInfo> pool_unit_infos;
2277for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2278if (OB_UNLIKELY(nullptr == pools.at(i))) {
2279ret = OB_ERR_UNEXPECTED;
2280LOG_WARN("pool ptr is null", KR(ret), KP(pools.at(i)));
2281} else if (OB_FAIL(inner_get_unit_infos_of_pool_(pools.at(i)->resource_pool_id_, pool_unit_infos))) {
2282LOG_WARN("inner_get_unit_infos_of_pool failed", KR(ret), "resource_pool_id", pools.at(i)->resource_pool_id_);
2283} else if (pool_unit_infos.count() <= 0) {
2284ret = OB_ERR_UNEXPECTED;
2285LOG_WARN("pool_unit_infos is empty", KR(ret), "pool_id", pools.at(i)->resource_pool_id_);
2286} else {
2287ObServerInfoInTable server_info;
2288for (int64_t j = 0; OB_SUCC(ret) && j < pool_unit_infos.count(); ++j) {
2289ObUnit &unit = pool_unit_infos.at(j).unit_;
2290if (has_exist_in_array(sorted_unit_group_id_array, unit.unit_group_id_)) {
2291// skip, this unit_group_id has already been added
2292} else if (OB_FAIL(SVR_TRACER.get_server_info(unit.server_, server_info))) {
2293LOG_WARN("fail to get_server_info", KR(ret), K(unit));
2294} else if (!server_info.is_active()) {
2295if (OB_FAIL(sorted_unit_group_id_array.push_back(unit.unit_group_id_))) {
2296LOG_WARN("fail to push_back", KR(ret), K(unit));
2297}
2298} else {/*active server*/}
2299}
2300}
2301}
2302std::sort(sorted_unit_group_id_array.begin(), sorted_unit_group_id_array.end());
2303// then other active unit group id
2304for (int64_t i = 0; OB_SUCC(ret) && i < all_unit_group_id_array.count(); ++i) {
2305uint64_t ug_id = all_unit_group_id_array.at(i);
2306if (has_exist_in_array(sorted_unit_group_id_array, ug_id)) {
2307// skip, offline unit_group_id is already pushed
2308} else if (OB_FAIL(sorted_unit_group_id_array.push_back(ug_id))) {
2309LOG_WARN("fail to push back", KR(ret), K(ug_id));
2310}
2311}
2312for (int64_t i = 0; OB_SUCC(ret) && i < to_be_deleted_num; ++i) {
2313if (OB_FAIL(to_be_deleted_unit_group.push_back(sorted_unit_group_id_array.at(i)))) {
2314LOG_WARN("fail to push back", KR(ret));
2315}
2316}
2317LOG_INFO("Automatically determined on unit_group to delete for shrinking tenant unit num.",
2318KR(ret), K(tenant_id), K(new_unit_num),
2319K(to_be_deleted_unit_group), K(sorted_unit_group_id_array));
2320} else if (deleted_unit_group_id_array.count() == to_be_deleted_num) {
2321// the deleted unit groups are specified by the client
2322for (int64_t i = 0; OB_SUCC(ret) && i < deleted_unit_group_id_array.count(); ++i) {
2323const uint64_t unit_group_id = deleted_unit_group_id_array.at(i);
2324if (has_exist_in_array(all_unit_group_id_array, unit_group_id)) {
2325if (OB_FAIL(to_be_deleted_unit_group.push_back(unit_group_id))) {
2326LOG_WARN("fail to push back", KR(ret));
2327}
2328} else {
2329ret = OB_OP_NOT_ALLOW;
2330LOG_USER_ERROR(OB_OP_NOT_ALLOW, "delete unit group which does not belong to this tenant");
2331}
2332}
2333} else {
2334// deleted unit groups num is not match to the specified num.
2335ret = OB_OP_NOT_ALLOW;
2336LOG_USER_ERROR(OB_OP_NOT_ALLOW, "to be deleted unit num not match");
2337}
2338}
2339return ret;
2340}
2341
2342int ObUnitManager::check_shrink_tenant_pools_allowed(
2343const uint64_t tenant_id,
2344common::ObIArray<share::ObResourcePool *> &pools,
2345const int64_t unit_num,
2346bool &is_allowed)
2347{
2348int ret = OB_SUCCESS;
2349if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || pools.count() <= 0)) {
2350ret = OB_INVALID_ARGUMENT;
2351LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(pools));
2352} else {
2353is_allowed = true;
2354for (int64_t i = 0; is_allowed && OB_SUCC(ret) && i < pools.count(); ++i) {
2355share::ObResourcePool *pool = pools.at(i);
2356bool my_is_allowed = true;
2357if (OB_UNLIKELY(nullptr == pool)) {
2358ret = OB_ERR_UNEXPECTED;
2359LOG_WARN("pool ptr is null", KR(ret), KP(pool));
2360} else if (tenant_id != pool->tenant_id_) {
2361ret = OB_ERR_UNEXPECTED;
2362LOG_WARN("tenant_id not match", KR(ret), K(tenant_id), "pool_tenant_id", pool->tenant_id_);
2363} else if (OB_FAIL(check_shrink_granted_pool_allowed(pool, unit_num, my_is_allowed))) {
2364LOG_WARN("fail to check shrink granted pool allowed", KR(ret));
2365} else {
2366is_allowed = my_is_allowed;
2367}
2368}
2369}
2370return ret;
2371}
2372
2373// There are two situations to consider in the shrinkage of the resource pool:
2374// 1. There is no resource pool granted to tenants
2375// the specified number of units can be directly deleted when the resource pool shrinks.
2376// 2. Resource pool that has been granted to tenants
2377// It is necessary to select the specified units from the resource pool,
2378// mark these units as the deleting state,
2379// and wait for all the replicas to be moved from such units before the whole process can be considered complete.
2380// The unit num of the pool that has been granted to the tenant needs to be scaled down.
2381// Preconditions:
2382// 2.1 The reduced unit num cannot be less than the number of replicas of locality in the corresponding zone
2383// 2.2 At present, the shrinking operation is performed when the unit is in a steady state,
2384// the shrinking is allowed when all units are not migrated.
2385// We avoid the unit being in both the migration and the deleting state, thereby reducing the complexity
2386int ObUnitManager::shrink_tenant_pools_unit_num(
2387const uint64_t tenant_id,
2388common::ObIArray<share::ObResourcePool *> &pools,
2389const int64_t new_unit_num,
2390const int64_t old_unit_num,
2391const common::ObIArray<uint64_t> &delete_unit_group_id_array,
2392const common::ObString &sql_text)
2393{
2394int ret = OB_SUCCESS;
2395common::ObMySQLTransaction trans;
2396bool is_allowed = false;
2397common::ObArray<uint64_t> to_be_deleted_unit_group;
2398
2399if (OB_FAIL(check_shrink_tenant_pools_allowed(
2400tenant_id, pools, new_unit_num, is_allowed))) {
2401LOG_WARN("fail to check shrink tenant pools allowed", KR(ret), K(tenant_id));
2402} else if (!is_allowed) {
2403ret = OB_OP_NOT_ALLOW;
2404LOG_WARN("cannot shrink tenant pools unit num", KR(ret), K(tenant_id));
2405} else if (OB_FAIL(get_to_be_deleted_unit_group(
2406tenant_id, pools, new_unit_num,
2407delete_unit_group_id_array, to_be_deleted_unit_group))) {
2408LOG_WARN("fail to get to be deleted unit group", KR(ret), K(tenant_id));
2409} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
2410LOG_WARN("fail to start transaction", KR(ret));
2411} else {
2412if (OB_FAIL(register_alter_resource_tenant_unit_num_rs_job(tenant_id,
2413new_unit_num, old_unit_num, AUN_SHRINK, sql_text, trans))) {
2414LOG_WARN("fail to register shrink tenant pool unit num rs job", KR(ret),
2415K(tenant_id), K(new_unit_num), K(sql_text), K(old_unit_num));
2416} else {
2417share::ObResourcePool new_pool;
2418for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2419share::ObResourcePool *pool = pools.at(i);
2420common::ObArray<share::ObUnit *> *units = nullptr;
2421new_pool.reset();
2422if (OB_UNLIKELY(nullptr == pool || tenant_id != pool->tenant_id_)) {
2423ret = OB_ERR_UNEXPECTED;
2424LOG_WARN("pool info unexpected", KR(ret), K(tenant_id), KPC(pool));
2425} else if (OB_FAIL(new_pool.assign(*pool))) {
2426LOG_WARN("fail to assign new pool", KR(ret), K(tenant_id), KPC(pool));
2427} else if (FALSE_IT(new_pool.unit_count_ = new_unit_num)) {
2428// shall never be here
2429} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, true/*need_check_conflict_with_clone*/))) {
2430LOG_WARN("fail to update resource pool", KR(ret), K(tenant_id), K(new_pool));
2431} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
2432LOG_WARN("fail to get units by pool", KR(ret), KPC(pool), K(tenant_id));
2433} else if (OB_UNLIKELY(nullptr == units)) {
2434ret = OB_ERR_UNEXPECTED;
2435LOG_WARN("units ptr is null", KR(ret), K(tenant_id), KPC(pool));
2436} else {
2437ObUnit new_unit;
2438for (int64_t j = 0; OB_SUCC(ret) && j < units->count(); ++j) {
2439new_unit.reset();
2440const ObUnit *unit = units->at(j);
2441if (OB_UNLIKELY(nullptr == unit)) {
2442ret = OB_ERR_UNEXPECTED;
2443LOG_WARN("unit ptr is null", KR(ret));
2444} else if (!has_exist_in_array(to_be_deleted_unit_group, unit->unit_group_id_)) {
2445// bypass
2446} else if (FALSE_IT(new_unit = *unit)) {
2447// shall never be here
2448} else if (FALSE_IT(new_unit.status_ = ObUnit::UNIT_STATUS_DELETING)) {
2449// shall never be here
2450} else if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, true/*need_check_conflict_with_clone*/))) {
2451LOG_WARN("fail to update unit", KR(ret), K(new_unit));
2452}
2453}
2454}
2455}
2456}
2457// however, we need to end this transaction
2458if (trans.is_started()) {
2459const bool commit = (OB_SUCCESS == ret);
2460int tmp_ret = OB_SUCCESS;
2461if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
2462LOG_WARN("trans end failed", K(tmp_ret), K(commit));
2463ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
2464}
2465}
2466// modify in memory pool/unit info
2467for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2468share::ObResourcePool *pool = pools.at(i);
2469common::ObArray<share::ObUnit *> *units = nullptr;
2470if (OB_UNLIKELY(nullptr == pool || tenant_id != pool->tenant_id_)) {
2471ret = OB_ERR_UNEXPECTED;
2472LOG_WARN("pool info unexpected", KR(ret), K(tenant_id), KPC(pool));
2473} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
2474LOG_WARN("fail to get units by pool", KR(ret), KPC(pool), K(tenant_id));
2475} else if (OB_UNLIKELY(nullptr == units)) {
2476ret = OB_ERR_UNEXPECTED;
2477LOG_WARN("units ptr is null", KR(ret), K(tenant_id), KPC(pool));
2478} else {
2479pool->unit_count_ = new_unit_num;
2480for (int64_t j = 0; OB_SUCC(ret) && j < units->count(); ++j) {
2481ObUnit *unit = units->at(j);
2482if (OB_UNLIKELY(nullptr == unit)) {
2483ret = OB_ERR_UNEXPECTED;
2484LOG_WARN("unit ptr is null", KR(ret));
2485} else if (!has_exist_in_array(to_be_deleted_unit_group, unit->unit_group_id_)) {
2486// bypass
2487} else {
2488unit->status_ = ObUnit::UNIT_STATUS_DELETING;
2489}
2490}
2491}
2492}
2493}
2494return ret;
2495}
2496
2497int ObUnitManager::rollback_tenant_shrink_pools_unit_num(
2498const uint64_t tenant_id,
2499common::ObIArray<share::ObResourcePool *> &pools,
2500const int64_t new_unit_num,
2501const int64_t old_unit_num,
2502const common::ObString &sql_text)
2503{
2504int ret = OB_SUCCESS;
2505common::ObMySQLTransaction trans;
2506if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || new_unit_num <= 0)) {
2507ret = OB_INVALID_ARGUMENT;
2508LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(new_unit_num));
2509} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
2510LOG_WARN("start transaction failed", K(ret));
2511} else {
2512if (OB_FAIL(rollback_alter_resource_tenant_unit_num_rs_job(tenant_id, new_unit_num,
2513old_unit_num, sql_text, trans))) {
2514LOG_WARN("rollback rs_job failed ", KR(ret), K(new_unit_num), K(old_unit_num), K(sql_text));
2515} else {
2516share::ObResourcePool new_pool;
2517for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2518common::ObArray<share::ObUnit *> *units = nullptr;
2519const share::ObResourcePool *pool = pools.at(i);
2520new_pool.reset();
2521if (OB_UNLIKELY(nullptr == pool)) {
2522ret = OB_ERR_UNEXPECTED;
2523LOG_WARN("pool ptr is null", KR(ret), K(tenant_id));
2524} else if (OB_FAIL(new_pool.assign(*pool))) {
2525LOG_WARN("fail to assign new pool", KR(ret), KPC(pool));
2526} else if (FALSE_IT(new_pool.unit_count_ = new_unit_num)) {
2527// shall never be here
2528} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, false/*need_check_conflict_with_clone*/))) {
2529LOG_WARN("fail to update resource pool", KR(ret), K(new_pool));
2530} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
2531LOG_WARN("fail to get units by pool", KR(ret), "pool_id", pool->resource_pool_id_);
2532} else if (OB_UNLIKELY(nullptr == units)) {
2533ret = OB_ERR_UNEXPECTED;
2534LOG_WARN("units is null", KR(ret), K(tenant_id), "pool_id", pool->resource_pool_id_);
2535} else {
2536for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
2537const ObUnit *this_unit = units->at(i);
2538if (OB_UNLIKELY(NULL == this_unit)) {
2539ret = OB_ERR_UNEXPECTED;
2540LOG_WARN("unit ptr is null", K(ret));
2541} else if (ObUnit::UNIT_STATUS_ACTIVE == this_unit->status_) {
2542// go and process the unit in deleting
2543} else if (ObUnit::UNIT_STATUS_DELETING == this_unit->status_) {
2544ObUnit new_unit = *this_unit;
2545new_unit.status_ = ObUnit::UNIT_STATUS_ACTIVE;
2546if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, true/*need_check_conflict_with_clone*/))) {
2547LOG_WARN("fail to update unit", K(ret), K(new_unit), "cur_unit", *this_unit);
2548}
2549} else {
2550ret = OB_ERR_UNEXPECTED;
2551LOG_WARN("unexpected unit status", K(ret), "unit", *this_unit);
2552}
2553}
2554}
2555}
2556}
2557const bool commit = (OB_SUCCESS == ret);
2558int tmp_ret = OB_SUCCESS;
2559if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
2560LOG_WARN("fail to trans end", KR(tmp_ret), K(commit));
2561ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
2562}
2563}
2564if (OB_SUCC(ret)) {
2565for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
2566common::ObArray<share::ObUnit *> *units = nullptr;
2567share::ObResourcePool *pool = pools.at(i);
2568if (OB_UNLIKELY(nullptr == pool)) {
2569ret = OB_ERR_UNEXPECTED;
2570LOG_WARN("pool ptr is null", KR(ret), K(tenant_id));
2571} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
2572LOG_WARN("fail to get units by pool", KR(ret), "pool_id", pool->resource_pool_id_);
2573} else if (OB_UNLIKELY(nullptr == units)) {
2574ret = OB_ERR_UNEXPECTED;
2575LOG_WARN("units is null", KR(ret), K(tenant_id), "pool_id", pool->resource_pool_id_);
2576} else {
2577pool->unit_count_ = new_unit_num;
2578for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
2579ObUnit *this_unit = units->at(i);
2580if (OB_UNLIKELY(NULL == this_unit)) {
2581ret = OB_ERR_UNEXPECTED;
2582LOG_WARN("unit ptr is null", K(ret));
2583} else if (ObUnit::UNIT_STATUS_ACTIVE == this_unit->status_) {
2584// go and process the unit in deleting
2585} else if (ObUnit::UNIT_STATUS_DELETING == this_unit->status_) {
2586this_unit->status_ = ObUnit::UNIT_STATUS_ACTIVE;
2587} else {
2588ret = OB_ERR_UNEXPECTED;
2589LOG_WARN("unexpected unit status", K(ret), "unit", *this_unit);
2590}
2591}
2592}
2593}
2594}
2595return ret;
2596}
2597
2598int ObUnitManager::alter_resource_tenant(
2599const uint64_t tenant_id,
2600const int64_t new_unit_num,
2601const common::ObIArray<uint64_t> &delete_unit_group_id_array,
2602const common::ObString &sql_text)
2603{
2604int ret = OB_SUCCESS;
2605LOG_INFO("start to alter resource tenant", K(tenant_id));
2606SpinWLockGuard guard(lock_);
2607// related variables
2608common::ObArray<share::ObResourcePool *> *pools = nullptr;
2609const char *module = "ALTER_RESOURCE_TENANT";
2610AlterUnitNumType alter_unit_num_type = AUN_MAX;
2611int64_t old_unit_num = 0;
2612
2613if (OB_UNLIKELY(!check_inner_stat())) {
2614ret = OB_INNER_STAT_ERROR;
2615LOG_WARN("fail to check inner stat", KR(ret), K(inited_), K(loaded_));
2616} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || new_unit_num <= 0)) {
2617ret = OB_INVALID_ARGUMENT;
2618LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(new_unit_num));
2619} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
2620LOG_WARN("fail to get pools by tenant", KR(ret), K(tenant_id));
2621} else if (OB_UNLIKELY(nullptr == pools)) {
2622ret = OB_ERR_UNEXPECTED;
2623LOG_WARN("pools ptr is null", KR(ret), K(tenant_id));
2624} else if (OB_FAIL(determine_alter_resource_tenant_unit_num_type(
2625tenant_id, *pools, new_unit_num, old_unit_num, alter_unit_num_type))) {
2626LOG_WARN("fail to do determine alter resource tenant unit num type", KR(ret));
2627} else if (AUN_NOP == alter_unit_num_type) {
2628if (delete_unit_group_id_array.count() > 0) {
2629ret = OB_NOT_SUPPORTED;
2630LOG_USER_ERROR(OB_NOT_SUPPORTED, "delete unit group without unit num change");
2631} else {} // good, nothing to do with unit group
2632} else if (AUN_ROLLBACK_SHRINK == alter_unit_num_type) {
2633if (delete_unit_group_id_array.count() > 0) {
2634ret = OB_NOT_SUPPORTED;
2635LOG_USER_ERROR(OB_NOT_SUPPORTED, "rollback shrink pool unit num combined with deleting unit");
2636} else if (OB_FAIL(rollback_tenant_shrink_pools_unit_num(
2637tenant_id, *pools, new_unit_num, old_unit_num, sql_text))) {
2638LOG_WARN("fail to rollback shrink pool unit num", K(ret),
2639K(new_unit_num), K(sql_text), K(old_unit_num));
2640}
2641} else if (AUN_EXPAND == alter_unit_num_type) {
2642// in 4.1, if enable_rebalance is false, this op can be executed successfully
2643// in 4.2, it will return OB_OP_NOT_ALLOW
2644if (delete_unit_group_id_array.count() > 0) {
2645ret = OB_NOT_SUPPORTED;
2646LOG_USER_ERROR(OB_NOT_SUPPORTED, "expand pool unit num combined with deleting unit");
2647} else if (OB_FAIL(expand_tenant_pools_unit_num_(
2648tenant_id, *pools, new_unit_num, old_unit_num, module, sql_text))) {
2649LOG_WARN("fail to expend pool unit num", K(module), KR(ret), K(new_unit_num), K(tenant_id),
2650KPC(pools), K(sql_text), K(old_unit_num));
2651}
2652} else if (AUN_SHRINK == alter_unit_num_type) {
2653// both 4.1 and 4.2 do not allow this op when enable_rebalance is false.
2654if (OB_FAIL(shrink_tenant_pools_unit_num(tenant_id, *pools, new_unit_num,
2655old_unit_num, delete_unit_group_id_array, sql_text))) {
2656LOG_WARN("fail to shrink pool unit num", K(ret), K(new_unit_num), K(sql_text), K(old_unit_num));
2657}
2658} else if (AUN_MAX == alter_unit_num_type) {
2659ret = OB_OP_NOT_ALLOW;
2660LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter unit group num while the previous operation is in progress");
2661} else {
2662ret = OB_ERR_UNEXPECTED;
2663LOG_WARN("unexpected alter unit group num type", KR(ret), K(alter_unit_num_type));
2664}
2665return ret;
2666}
2667
2668int ObUnitManager::merge_resource_pool(
2669const common::ObIArray<common::ObString> &old_pool_list,
2670const common::ObIArray<common::ObString> &new_pool_list)
2671{
2672int ret = OB_SUCCESS;
2673LOG_INFO("start merge resource pool", K(old_pool_list), K(new_pool_list));
2674SpinWLockGuard guard(lock_);
2675common::ObArray<share::ObResourcePoolName> old_pool_name_list;
2676share::ObResourcePoolName merge_pool_name;
2677common::ObArray<share::ObResourcePool *> old_pool;//Pool to be merged
2678common::ObArray<common::ObZone> merge_zone_list;//zone list to be merged
2679if (!check_inner_stat()) {
2680ret = OB_INNER_STAT_ERROR;
2681LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
2682} else if (new_pool_list.count() <= 0
2683|| old_pool_list.count() <= 0
2684|| old_pool_list.count() < 2
2685//Preventing only one pool from being merged is meaningless
2686|| new_pool_list.count() > 1) {
2687//Can only be merged into one resource pool
2688ret = OB_INVALID_ARGUMENT;
2689LOG_WARN("resource pool zone list is illeagle", K(old_pool_list), K(new_pool_list));
2690LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool");
2691} else if (OB_FAIL(convert_pool_name_list(old_pool_list, old_pool_name_list,
2692new_pool_list, merge_pool_name))) {//1.parse pool name
2693LOG_WARN("fail to convert pool name list", K(ret));
2694} else if (OB_FAIL(check_old_pool_name_condition(
2695old_pool_name_list, merge_zone_list, old_pool))) {
2696//2. check the pool that in old_pool_list is whether valid
2697LOG_WARN("fail to check old pool name condition", K(ret));
2698} else if (OB_FAIL(check_merge_pool_name_condition(merge_pool_name))) {
2699//3. check the merge_pool_name is whether the new pool
2700LOG_WARN("fail to check merge pool name condition", K(ret));
2701} else if (OB_FAIL(do_merge_resource_pool(merge_pool_name, merge_zone_list, old_pool))) {
2702LOG_WARN("fail to do merge resource pool", K(ret));
2703} else {
2704LOG_INFO("success to merge resource pool", K(merge_pool_name),
2705"old_pool_name", old_pool_list);
2706}
2707return ret;
2708}
2709
2710int ObUnitManager::convert_pool_name_list(
2711const common::ObIArray<common::ObString> &old_pool_list,
2712common::ObIArray<share::ObResourcePoolName> &old_pool_name_list,
2713const common::ObIArray<common::ObString> &new_pool_list,
2714share::ObResourcePoolName &merge_pool_name)
2715{
2716int ret = OB_SUCCESS;
2717old_pool_name_list.reset();
2718for (int64_t i = 0; OB_SUCC(ret) && i < old_pool_list.count(); ++i) {
2719share::ObResourcePoolName pool_name;
2720if (OB_FAIL(pool_name.assign(old_pool_list.at(i).ptr()))) {
2721LOG_WARN("fail to assign pool name", K(ret));
2722} else if (has_exist_in_array(old_pool_name_list, pool_name)) {//Check for duplication
2723ret = OB_OP_NOT_ALLOW;
2724LOG_WARN("not allow merge resource pool repeat", K(ret));
2725LOG_USER_ERROR(OB_OP_NOT_ALLOW, "merge resource pool repeat");
2726} else if (OB_FAIL(old_pool_name_list.push_back(pool_name))) {
2727LOG_WARN("fail to push back", K(ret));
2728}
2729}
2730if (OB_SUCC(ret)) {
2731if (OB_FAIL(merge_pool_name.assign(new_pool_list.at(0).ptr()))) {
2732LOG_WARN("fail to assign pool name", K(ret));
2733}
2734}
2735return ret;
2736}
2737
2738int ObUnitManager::check_merge_pool_name_condition(
2739const share::ObResourcePoolName &merge_pool_name)
2740{
2741int ret = OB_SUCCESS;
2742// check the pool name is whether exist,
2743// and check the pool name is whether duplication.
2744share::ObResourcePool *pool = NULL;
2745int tmp_ret = inner_get_resource_pool_by_name(merge_pool_name, pool);
2746if (OB_ENTRY_NOT_EXIST == tmp_ret) {
2747// good, go on next, this pool name not exist
2748} else if (OB_SUCCESS == tmp_ret) {
2749if (NULL == pool) {
2750ret = OB_ERR_UNEXPECTED;
2751LOG_WARN("pool is null", K(ret), KP(pool), K(merge_pool_name));
2752} else {
2753ret = OB_RESOURCE_POOL_EXIST;
2754LOG_WARN("resource pool already exist", K(ret), K(merge_pool_name));
2755LOG_USER_ERROR(OB_RESOURCE_POOL_EXIST, to_cstring(merge_pool_name));
2756}
2757} else {
2758ret = OB_ERR_UNEXPECTED;
2759LOG_WARN("unexpected error when get pool by name", K(ret), K(merge_pool_name));
2760}
2761return ret;
2762}
2763
2764int ObUnitManager::check_old_pool_name_condition(
2765common::ObIArray<share::ObResourcePoolName> &old_pool_name_list,
2766common::ObIArray<common::ObZone> &merge_zone_list,
2767common::ObIArray<share::ObResourcePool*> &old_pool)
2768{
2769int ret = OB_SUCCESS;
2770common::ObReplicaType replica_type = REPLICA_TYPE_MAX;
2771uint64_t tenant_id = OB_INVALID_ID;
2772share::ObUnitConfig *unit_config = NULL;
2773int64_t unit_count = 0;
2774const int64_t POOL_NAME_SET_BUCKET_NUM = 16;
2775ObHashSet<share::ObResourcePoolName> pool_name_set;
2776if (OB_FAIL(pool_name_set.create(POOL_NAME_SET_BUCKET_NUM))) {
2777LOG_WARN("fail to create hash set", K(ret));
2778} else {
2779for (int64_t i = 0; OB_SUCC(ret) && i < old_pool_name_list.count(); ++i) {
2780const share::ObResourcePoolName &pool_name = old_pool_name_list.at(i);
2781share::ObUnitConfig *this_unit_config = NULL;
2782share::ObResourcePool *pool = NULL;
2783if (OB_FAIL(inner_get_resource_pool_by_name(pool_name, pool))) {
2784LOG_WARN("fail to get resource pool by name", K(ret));
2785} else if (OB_ISNULL(pool)) {
2786ret = OB_ERR_UNEXPECTED;
2787LOG_WARN("pool is null", K(ret), K(pool), K(pool_name));
2788} else {
2789if (0 == i) {
2790replica_type = pool->replica_type_;
2791tenant_id = pool->tenant_id_;
2792unit_count = pool->unit_count_;
2793if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, unit_config))) {
2794if (OB_ENTRY_NOT_EXIST == ret) {
2795ret = OB_RESOURCE_UNIT_NOT_EXIST;
2796}
2797LOG_WARN("can not find config for unit",
2798"unit_config_id", pool->unit_config_id_,
2799K(ret));
2800} else if (NULL == unit_config) {
2801ret = OB_ERR_UNEXPECTED;
2802LOG_WARN("config is null", K(*unit_config), K(ret));
2803} else {} //no more
2804} else {
2805if (replica_type != pool->replica_type_) {
2806// Determine whether the replica_type is the same
2807ret = OB_OP_NOT_ALLOW;
2808LOG_WARN("not allow pool replica type different",
2809K(ret), K(replica_type), K(pool->replica_type_));
2810LOG_USER_ERROR(OB_OP_NOT_ALLOW, "pool replica type different");
2811} else if (tenant_id != pool->tenant_id_) {
2812// Determine whether the tenant_id is the same
2813ret = OB_OP_NOT_ALLOW;
2814LOG_WARN("not allow pool tenant id different",
2815K(ret), K(tenant_id), K(pool->tenant_id_));
2816LOG_USER_ERROR(OB_OP_NOT_ALLOW, "pool tenant id different");
2817} else if (unit_count != pool->unit_count_) {
2818// Determine whether the unit_count is the same
2819ret = OB_OP_NOT_ALLOW;
2820LOG_WARN("not allow pool unit count different",
2821K(ret), K(unit_count), K(pool->unit_count_));
2822LOG_USER_ERROR(OB_OP_NOT_ALLOW, "pool unit count different");
2823} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, this_unit_config))) {
2824if (OB_ENTRY_NOT_EXIST == ret) {
2825ret = OB_RESOURCE_UNIT_NOT_EXIST;
2826}
2827LOG_WARN("can not find config for unit",
2828"unit_config_id", pool->unit_config_id_,
2829K(ret));
2830} else if (NULL == this_unit_config) {
2831ret = OB_ERR_UNEXPECTED;
2832LOG_WARN("config is null", KP(this_unit_config), K(ret));
2833} else {//Determine whether the unit config is the same
2834if (unit_config->unit_config_id() == this_unit_config->unit_config_id()) {//nothing todo
2835} else {
2836ret = OB_OP_NOT_ALLOW;
2837LOG_WARN("not allow pool unit config different",
2838K(ret), K(*this_unit_config), K(*unit_config));
2839LOG_USER_ERROR(OB_OP_NOT_ALLOW, "pool unit config different");
2840}
2841}
2842}
2843if (OB_SUCC(ret)) {
2844int tmp_ret = pool_name_set.exist_refactored(pool_name);
2845if (OB_HASH_NOT_EXIST == tmp_ret) {
2846if (OB_FAIL(pool_name_set.set_refactored(pool_name))) {
2847LOG_WARN("fail to set", K(ret), K(pool_name));
2848}
2849} else if (OB_HASH_EXIST == tmp_ret) {
2850ret = OB_INVALID_ARGUMENT;
2851LOG_WARN("invalid argument to merge resource pool duplicate");
2852LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool name duplicate");
2853} else {
2854ret = OB_ERR_UNEXPECTED;
2855LOG_WARN("unexpected error when set hashset", K(ret));
2856}
2857}
2858if (OB_SUCC(ret)) {
2859// Judge whether the zone has crossover,
2860// it is implicitly judged whether the pool_name is repeated, no need to repeat the judgment
2861for (int64_t j = 0; OB_SUCC(ret) && j < pool->zone_list_.count(); ++j) {
2862const common::ObZone &this_zone = pool->zone_list_.at(j);
2863if (has_exist_in_array(merge_zone_list, this_zone)) {
2864ret = OB_OP_NOT_ALLOW;
2865LOG_WARN("not allow to merge resource pool with duplicated zone");
2866LOG_USER_ERROR(OB_OP_NOT_ALLOW, "resource pool with duplicated zone");
2867} else if (OB_FAIL(merge_zone_list.push_back(this_zone))) {
2868LOG_WARN("fail to push back", K(ret));
2869}
2870}
2871}
2872if (OB_SUCC(ret)) {
2873ObArray<ObUnit *> *units = nullptr;
2874if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
2875LOG_WARN("fail to get units by pool", KR(ret), KPC(pool));
2876} else if (OB_UNLIKELY(nullptr == units)) {
2877ret = OB_ERR_UNEXPECTED;
2878LOG_WARN("units ptr is null", KR(ret), KPC(pool));
2879} else {
2880for (int64_t j = 0; OB_SUCC(ret) && j < units->count(); ++j) {
2881ObUnit *unit = units->at(j);
2882if (OB_UNLIKELY(nullptr == unit)) {
2883ret = OB_ERR_UNEXPECTED;
2884LOG_WARN("unit ptr is null", KR(ret));
2885} else if (unit->status_ != ObUnit::UNIT_STATUS_ACTIVE) {
2886ret = OB_OP_NOT_ALLOW;
2887LOG_WARN("merging pools when any pool in shrinking not allowed", KR(ret), KPC(pool));
2888LOG_USER_ERROR(OB_OP_NOT_ALLOW, "merging pools when any pool in shrinking");
2889}
2890}
2891}
2892}
2893if (OB_SUCC(ret)) {
2894if (OB_FAIL(old_pool.push_back(pool))) {
2895LOG_WARN("fail to push back", K(ret));
2896}
2897}
2898}
2899}
2900}
2901return ret;
2902}
2903
2904
2905int ObUnitManager::do_merge_resource_pool(
2906const share::ObResourcePoolName &merge_pool_name,
2907const common::ObIArray<common::ObZone> &merge_zone_list,
2908common::ObIArray<share::ObResourcePool*> &old_pool)
2909{
2910int ret = OB_SUCCESS;
2911share::ObResourcePool *allocate_pool_ptr = nullptr;
2912if (!check_inner_stat()) {
2913ret = OB_INNER_STAT_ERROR;
2914LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
2915} else if (OB_FAIL(do_merge_pool_persistent_info(
2916allocate_pool_ptr, merge_pool_name,
2917merge_zone_list, old_pool))) {
2918LOG_WARN("fail to do merge pool persistent info", K(ret));
2919} else if (OB_FAIL(do_merge_pool_inmemory_info(allocate_pool_ptr, old_pool))) {
2920LOG_WARN("fail to do merge pool inmemory info", K(ret));
2921} else {} //no more
2922return ret;
2923}
2924
2925int ObUnitManager::do_merge_pool_persistent_info(
2926share::ObResourcePool *&allocate_pool_ptr,
2927const share::ObResourcePoolName &merge_pool_name,
2928const common::ObIArray<common::ObZone> &merge_zone_list,
2929const common::ObIArray<share::ObResourcePool*> &old_pool)
2930{
2931int ret = OB_SUCCESS;
2932common::ObMySQLTransaction trans;
2933if (!check_inner_stat()) {
2934ret = OB_INNER_STAT_ERROR;
2935LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
2936} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
2937LOG_WARN("fail to start transaction", K(ret));
2938} else {
2939if (NULL == (allocate_pool_ptr = pool_allocator_.alloc())) {
2940ret = OB_ALLOCATE_MEMORY_FAILED;
2941LOG_ERROR("fail to alloc memory", K(ret));
2942} else if (OB_FAIL(fill_merging_pool_basic_info(allocate_pool_ptr, merge_pool_name,
2943merge_zone_list, old_pool))) {
2944// The specifications of the pools to be merged are the same, so select the first pool here
2945LOG_WARN("fail to fill merging pool basic info", K(ret));
2946} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, *allocate_pool_ptr, false/*need_check_conflict_with_clone*/))) {
2947LOG_WARN("fail to update resource pool", K(ret));
2948} else {
2949for (int64_t i = 0; OB_SUCC(ret) && i < old_pool.count(); ++i) {
2950if (OB_FAIL(merge_pool_unit_persistent_info(
2951trans, allocate_pool_ptr, old_pool.at(i)))) {
2952LOG_WARN("fail to split pool unit persistent info", K(ret));
2953}
2954}
2955}
2956if (OB_SUCC(ret)) {
2957for (int64_t i = 0; i < old_pool.count() && OB_SUCC(ret); ++i) {
2958if (OB_FAIL(ut_operator_.remove_resource_pool(trans, old_pool.at(i)->resource_pool_id_))) {
2959LOG_WARN("fail to remove resource pool persistent info", K(ret),
2960"pool_id", old_pool.at(i)->resource_pool_id_);
2961} else {} // all persistent infos update finished
2962}
2963}
2964const bool commit = (OB_SUCCESS == ret);
2965int tmp_ret = OB_SUCCESS;
2966if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
2967LOG_WARN("fail to end trans", K(tmp_ret), K(commit));
2968ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
2969}
2970if (OB_FAIL(ret)) {
2971// 1. The transaction did fail to commit.
2972// the internal table and the memory state remain the same,
2973// as long as the memory of allocate_pool_ptrs is released.
2974//
2975// 2. The transaction submission timed out, but the final submission was successful.
2976// The internal table and memory state are inconsistent,
2977// and the outer layer will call the reload unit manager.
2978// Still need to release the memory of allocate_pool_ptrs
2979if (NULL != allocate_pool_ptr) {
2980pool_allocator_.free(allocate_pool_ptr);
2981allocate_pool_ptr = NULL;
2982}
2983}
2984}
2985return ret;
2986}
2987
2988int ObUnitManager::fill_merging_pool_basic_info(
2989share::ObResourcePool *&allocate_pool_ptr,
2990const share::ObResourcePoolName &merge_pool_name,
2991const common::ObIArray<common::ObZone> &merge_zone_list,
2992const common::ObIArray<share::ObResourcePool*> &old_pool)
2993{
2994int ret = OB_SUCCESS;
2995if (!check_inner_stat()) {
2996ret = OB_INNER_STAT_ERROR;
2997LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
2998} else if (OB_UNLIKELY(old_pool.count() <= 1)) {
2999//It doesn't make sense to merge only one pool
3000ret = OB_INVALID_ARGUMENT;
3001LOG_WARN("invalid argument", K(ret));
3002}
3003if (OB_SUCC(ret)) {
3004share::ObResourcePool *orig_pool = old_pool.at(0);
3005if (OB_UNLIKELY(merge_pool_name.is_empty() || NULL == allocate_pool_ptr
3006|| NULL == orig_pool)) {
3007ret = OB_INVALID_ARGUMENT;
3008LOG_WARN("invalid argument", K(ret), K(merge_pool_name), KP(allocate_pool_ptr), K(orig_pool));
3009} else {
3010allocate_pool_ptr->name_ = merge_pool_name;
3011allocate_pool_ptr->unit_count_ = orig_pool->unit_count_;
3012allocate_pool_ptr->unit_config_id_ = orig_pool->unit_config_id_;
3013allocate_pool_ptr->tenant_id_ = orig_pool->tenant_id_;
3014allocate_pool_ptr->replica_type_ = orig_pool->replica_type_;
3015if (OB_FAIL(fetch_new_resource_pool_id(allocate_pool_ptr->resource_pool_id_))) {
3016LOG_WARN("fail to fetch new resource pool id", K(ret));
3017} else {
3018for (int64_t i = 0; i < merge_zone_list.count() && OB_SUCC(ret); ++i) {
3019if (OB_UNLIKELY(merge_zone_list.at(i).is_empty())) {
3020ret = OB_INVALID_ARGUMENT;
3021LOG_WARN("invalid argument", K(ret), K(merge_zone_list.at(i)));
3022} else if (OB_FAIL(allocate_pool_ptr->zone_list_.push_back(merge_zone_list.at(i)))) {
3023LOG_WARN("fail to push back to zone list", K(ret));
3024}
3025}
3026} // finish fill splitting pool basic info
3027}
3028}
3029return ret;
3030}
3031
3032int ObUnitManager::merge_pool_unit_persistent_info(
3033common::ObMySQLTransaction &trans,
3034share::ObResourcePool *new_pool,
3035share::ObResourcePool *orig_pool)
3036{
3037int ret = OB_SUCCESS;
3038common::ObArray<share::ObUnit *> *units = NULL;
3039if (!check_inner_stat()) {
3040ret = OB_INNER_STAT_ERROR;
3041LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
3042} else if (OB_UNLIKELY(NULL == new_pool || NULL == orig_pool)) {
3043ret = OB_INVALID_ARGUMENT;
3044LOG_WARN("invalid argument", K(ret), KP(new_pool), KP(orig_pool));
3045} else if (OB_FAIL(get_units_by_pool(orig_pool->resource_pool_id_, units))) {
3046LOG_WARN("fail to get units by pool", K(ret));
3047} else if (OB_UNLIKELY(NULL == units)) {
3048ret = OB_ERR_UNEXPECTED;
3049LOG_WARN("units ptr is null", K(ret));
3050} else {
3051for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
3052const share::ObUnit *unit = units->at(i);
3053if (OB_UNLIKELY(NULL == unit)) {
3054ret = OB_ERR_UNEXPECTED;
3055LOG_WARN("unit ptr is null", K(ret));
3056} else {
3057share::ObUnit new_unit = *unit;
3058new_unit.resource_pool_id_ = new_pool->resource_pool_id_;
3059if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, false/*need_check_conflict_with_clone*/))) {
3060LOG_WARN("fail to update unit", K(ret), K(new_unit));
3061}
3062ROOTSERVICE_EVENT_ADD("unit", "merge_pool",
3063"unit_id", unit->unit_id_,
3064"server", unit->server_,
3065"prev_pool_id", orig_pool->resource_pool_id_,
3066"curr_pool_id", new_pool->resource_pool_id_,K(ret));
3067}
3068}
3069}
3070return ret;
3071}
3072
3073int ObUnitManager::do_merge_pool_inmemory_info(
3074share::ObResourcePool *new_pool/*allocate_pool_ptr*/,
3075common::ObIArray<share::ObResourcePool*> &old_pool)
3076{
3077int ret = OB_SUCCESS;
3078if (!check_inner_stat()) {
3079ret = OB_INNER_STAT_ERROR;
3080LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
3081} else if (NULL == new_pool) {
3082ret = OB_INVALID_ARGUMENT;
3083LOG_WARN("invalid argument", K(ret));
3084} else {
3085if (OB_FAIL(inc_config_ref_count(new_pool->unit_config_id_))) {
3086LOG_WARN("fail to inc config ref count", K(ret),
3087"unit_config_id", new_pool->unit_config_id_);
3088} else if (OB_FAIL(insert_config_pool(new_pool->unit_config_id_, new_pool))) {
3089LOG_WARN("fail to insert config pool", K(ret),
3090"unit_config_id", new_pool->unit_config_id_);
3091} else if (OB_FAIL(update_pool_map(new_pool))) {
3092LOG_WARN("fail to update pool map", K(ret),
3093"resource_pool_id", new_pool->resource_pool_id_);
3094} else if (!new_pool->is_granted_to_tenant()) {
3095// bypass
3096} else if (OB_FAIL(insert_tenant_pool(new_pool->tenant_id_, new_pool))) {
3097LOG_WARN("fail to insert tenant pool", K(ret), "tenant_id", new_pool->tenant_id_);
3098}
3099if (OB_FAIL(ret)) {
3100// failed
3101} else if (OB_FAIL(merge_pool_unit_inmemory_info(new_pool, old_pool))) {
3102LOG_WARN("fail to split pool unit inmemory info", K(ret));
3103} else {} // no more
3104for (int64_t i = 0 ; i < old_pool.count() && OB_SUCC(ret); ++i) {
3105common::ObArray<share::ObUnit *> *pool_units = NULL;
3106if (OB_FAIL(ret)) {
3107} else if (OB_FAIL(dec_config_ref_count(old_pool.at(i)->unit_config_id_))) {
3108LOG_WARN("fail to dec config ref count", K(ret));
3109} else if (OB_FAIL(delete_config_pool(old_pool.at(i)->unit_config_id_, old_pool.at(i)))) {
3110LOG_WARN("fail to delete config pool", K(ret));
3111} else if (OB_FAIL(delete_resource_pool(old_pool.at(i)->resource_pool_id_,
3112old_pool.at(i)->name_))) {
3113LOG_WARN("fail to delete resource pool", K(ret));
3114} else if (OB_INVALID_ID == old_pool.at(i)->tenant_id_) {
3115// bypass
3116} else if (OB_FAIL(delete_tenant_pool(old_pool.at(i)->tenant_id_, old_pool.at(i)))) {
3117LOG_WARN("fail to delete tenant pool", K(ret), "tenant_id", old_pool.at(i)->tenant_id_);
3118}
3119if (OB_FAIL(ret)) {
3120} else if (OB_FAIL(get_units_by_pool(old_pool.at(i)->resource_pool_id_, pool_units))) {
3121LOG_WARN("fail to get units by pool", K(ret), "pool_id", old_pool.at(i)->resource_pool_id_);
3122} else if (OB_UNLIKELY(NULL == pool_units)) {
3123ret = OB_ERR_UNEXPECTED;
3124LOG_WARN("pool units ptr is null", K(ret));
3125} else if (OB_FAIL(pool_unit_map_.erase_refactored(old_pool.at(i)->resource_pool_id_))) {
3126LOG_WARN("fail to erase map", K(ret), "pool_id", old_pool.at(i)->resource_pool_id_);
3127} else {
3128pool_unit_allocator_.free(pool_units);
3129pool_units = NULL;
3130pool_allocator_.free(old_pool.at(i));
3131old_pool.at(i) = NULL;
3132}
3133}
3134if (OB_FAIL(ret)) {
3135// reload
3136rootserver::ObRootService *root_service = NULL;
3137if (OB_UNLIKELY(NULL == (root_service = GCTX.root_service_))) {
3138ret = OB_ERR_UNEXPECTED;
3139LOG_WARN("rootservice is null", K(ret));
3140} else {
3141int tmp_ret = root_service->submit_reload_unit_manager_task();
3142if (OB_SUCCESS != tmp_ret) {
3143LOG_ERROR("fail to reload unit manager", K(tmp_ret));
3144}
3145}
3146}
3147}
3148return ret;
3149}
3150
3151int ObUnitManager::merge_pool_unit_inmemory_info(
3152share::ObResourcePool *new_pool/*allocate_pool_ptr*/,
3153common::ObIArray<share::ObResourcePool*> &old_pool)
3154{
3155int ret = OB_SUCCESS;
3156common::ObArray<share::ObUnit *> *new_units = NULL;
3157if (!check_inner_stat()) {
3158ret = OB_INNER_STAT_ERROR;
3159LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
3160} else if (OB_UNLIKELY(NULL == new_pool)) {
3161ret = OB_INVALID_ARGUMENT;
3162LOG_WARN("invalid argument", K(ret), KP(new_pool));
3163} else {
3164ret = get_units_by_pool(new_pool->resource_pool_id_, new_units);
3165if (OB_SUCCESS == ret) {
3166// got new units
3167} else if (OB_ENTRY_NOT_EXIST != ret) {
3168LOG_WARN("fail to get units by pool", K(ret));
3169} else {
3170if (NULL == (new_units = pool_unit_allocator_.alloc())) {
3171ret = OB_ALLOCATE_MEMORY_FAILED;
3172LOG_ERROR("fail to alloc memory", K(ret));
3173} else if (OB_FAIL(pool_unit_map_.set_refactored(new_pool->resource_pool_id_, new_units))) {
3174LOG_WARN("fail to set refactored", K(ret), "pool_id", new_pool->resource_pool_id_);
3175}
3176}
3177for (int64_t i = 0; i < old_pool.count() && OB_SUCC(ret); ++i) {
3178common::ObArray<share::ObUnit *> *orig_units = NULL;
3179if (OB_ISNULL(old_pool.at(i))) {
3180ret = OB_INVALID_ARGUMENT;
3181LOG_WARN("invalid argument", K(ret), KP(old_pool.at(i)));
3182} else if (OB_FAIL(get_units_by_pool(old_pool.at(i)->resource_pool_id_, orig_units))) {
3183LOG_WARN("fail to get units by pool", K(ret));
3184} else if (OB_UNLIKELY(NULL == orig_units)) {
3185ret = OB_ERR_UNEXPECTED;
3186LOG_WARN("units ptr is null", K(ret));
3187} else {
3188for (int64_t i = 0; OB_SUCC(ret) && i < orig_units->count(); ++i) {
3189share::ObUnit *unit = orig_units->at(i);
3190if (OB_UNLIKELY(NULL == unit)) {
3191ret = OB_ERR_UNEXPECTED;
3192LOG_WARN("unit ptr is null", K(ret));
3193} else if (NULL == new_units) {
3194ret = OB_ERR_UNEXPECTED;
3195LOG_WARN("new units ptr is null", K(ret));
3196} else {
3197unit->resource_pool_id_ = new_pool->resource_pool_id_;
3198if (OB_FAIL(new_units->push_back(unit))) {
3199LOG_WARN("fail to push back", K(ret));
3200} else if (OB_FAIL(update_unit_load(unit, new_pool))) {
3201LOG_WARN("fail to update unit load", K(ret));
3202}
3203}
3204}
3205}
3206}
3207}
3208return ret;
3209}
3210
3211int ObUnitManager::alter_resource_pool(const share::ObResourcePool &alter_pool,
3212const ObUnitConfigName &config_name,
3213const common::ObIArray<uint64_t> &delete_unit_id_array)
3214{
3215int ret = OB_SUCCESS;
3216LOG_INFO("start alter resource pool", K(alter_pool), K(config_name));
3217SpinWLockGuard guard(lock_);
3218share::ObResourcePool *pool = NULL;
3219share::ObResourcePool pool_bak;
3220// don't invoke alter_pool.is_valid() here, alter_pool.unit_count may be 0
3221if (!check_inner_stat()) {
3222ret = OB_INNER_STAT_ERROR;
3223LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3224} else if (alter_pool.name_.is_empty()) {
3225ret = OB_INVALID_ARGUMENT;
3226LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool name");
3227LOG_WARN("resource pool name is empty", "resource pool name", alter_pool.name_, K(ret));
3228} else if (alter_pool.unit_count_ < 0) {
3229ret = OB_INVALID_ARGUMENT;
3230LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource unit num");
3231LOG_WARN("invalid resource pool unit num", "unit num", alter_pool.unit_count_, K(ret));
3232} else if (OB_FAIL(inner_get_resource_pool_by_name(alter_pool.name_, pool))) {
3233if (OB_ENTRY_NOT_EXIST != ret) {
3234LOG_WARN("get resource pool by name failed", "resource_pool name", alter_pool.name_, K(ret));
3235} else {
3236ret = OB_RESOURCE_POOL_NOT_EXIST;
3237LOG_USER_ERROR(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(alter_pool.name_));
3238LOG_WARN("resource pool not exist", "resource pool name", alter_pool.name_, K(ret));
3239}
3240} else if (NULL == pool) {
3241ret = OB_ERR_UNEXPECTED;
3242LOG_WARN("pool is null", KP(pool), K(ret));
3243} else if (REPLICA_TYPE_LOGONLY == pool->replica_type_
3244&& alter_pool.unit_count_ > 1) {
3245ret = OB_NOT_SUPPORTED;
3246LOG_WARN("logonly resource pool should only have one unit on one zone", K(ret), K(alter_pool));
3247} else {
3248int64_t alter_count = 0;
3249if (!config_name.is_empty()) {
3250++alter_count;
3251}
3252if (0 != alter_pool.unit_count_) {
3253++alter_count;
3254}
3255if (alter_pool.zone_list_.count() > 0) {
3256++alter_count;
3257}
3258if (alter_count > 1) {
3259ret = OB_NOT_SUPPORTED;
3260LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter unit_num, resource_unit, zone_list in one cmd");
3261LOG_WARN("only support alter one item one time", K(alter_pool), K(config_name), K(ret));
3262}
3263
3264if (OB_FAIL(ret)) {
3265} else if (OB_FAIL(pool_bak.assign(*pool))) {
3266LOG_WARN("failed to assign pool_bak", K(ret));
3267}
3268
3269//TODO: modiry replica_type not support;
3270// alter unit config
3271if (OB_FAIL(ret)) {
3272} else if (config_name.is_empty()) {
3273// config not change
3274} else if (OB_FAIL(alter_pool_unit_config(pool, config_name))) {
3275LOG_WARN("alter_pool_unit_config failed", "pool", *pool, K(config_name), K(ret));
3276}
3277
3278// alter unit num
3279if (OB_FAIL(ret)) {
3280} else if (0 == alter_pool.unit_count_) {
3281// unit num not change
3282} else if (OB_FAIL(alter_pool_unit_num(pool, alter_pool.unit_count_, delete_unit_id_array))) {
3283LOG_WARN("alter_pool_unit_num failed", "pool", *pool,
3284"unit_num", alter_pool.unit_count_, K(ret));
3285}
3286
3287// alter zone list
3288if (OB_FAIL(ret)) {
3289} else if (alter_pool.zone_list_.count() <=0) {
3290// zone list not change
3291} else if (OB_FAIL(alter_pool_zone_list(pool, alter_pool.zone_list_))) {
3292LOG_WARN("alter_pool_zone_list failed", "pool", *pool,
3293"zone_list", alter_pool.zone_list_, K(ret));
3294}
3295}
3296if (OB_SUCC(ret)) {
3297ROOTSERVICE_EVENT_ADD("unit", "alter_resource_pool",
3298"name", pool_bak.name_);
3299}
3300LOG_INFO("finish alter resource pool", K(alter_pool), K(config_name), K(ret));
3301return ret;
3302}
3303
3304int ObUnitManager::drop_resource_pool(const uint64_t pool_id, const bool if_exist)
3305{
3306int ret = OB_SUCCESS;
3307LOG_INFO("start drop resource pool", K(pool_id));
3308SpinWLockGuard guard(lock_);
3309share::ObResourcePool *pool = NULL;
3310if (!check_inner_stat()) {
3311ret = OB_INNER_STAT_ERROR;
3312LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3313} else if (OB_INVALID_ID == pool_id) {
3314ret = OB_INVALID_ARGUMENT;
3315LOG_WARN("invalid argument", K(pool_id), K(ret));
3316} else if (OB_FAIL(get_resource_pool_by_id(pool_id, pool))) {
3317if (OB_ENTRY_NOT_EXIST != ret) {
3318LOG_WARN("get resource pool by id failed", K(pool_id), K(ret));
3319} else {
3320if (if_exist) {
3321ret = OB_SUCCESS;
3322LOG_USER_NOTE(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(pool_id));
3323LOG_INFO("resource_pool not exist, but no need drop it", K(pool_id));
3324} else {
3325ret = OB_RESOURCE_POOL_NOT_EXIST;
3326LOG_USER_ERROR(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(pool_id));
3327LOG_WARN("resource_pool not exist", K(pool_id), K(ret));
3328}
3329}
3330} else if (OB_FAIL(inner_drop_resource_pool(pool))) {
3331LOG_WARN("fail to inner drop resource pool", KR(ret), K(pool_id));
3332}
3333LOG_INFO("finish drop resource pool", K(pool_id), K(ret));
3334return ret;
3335}
3336
3337int ObUnitManager::drop_resource_pool(const ObResourcePoolName &name, const bool if_exist)
3338{
3339int ret = OB_SUCCESS;
3340LOG_INFO("start drop resource pool", K(name));
3341SpinWLockGuard guard(lock_);
3342share::ObResourcePool *pool = NULL;
3343if (!check_inner_stat()) {
3344ret = OB_INNER_STAT_ERROR;
3345LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3346} else if (name.is_empty()) {
3347ret = OB_INVALID_ARGUMENT;
3348LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool name");
3349LOG_WARN("invalid argument", K(name), K(ret));
3350} else if (OB_FAIL(inner_get_resource_pool_by_name(name, pool))) {
3351if (OB_ENTRY_NOT_EXIST != ret) {
3352LOG_WARN("get resource pool by name failed", K(name), K(ret));
3353} else {
3354if (if_exist) {
3355ret = OB_SUCCESS;
3356LOG_USER_NOTE(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(name));
3357LOG_INFO("resource_pool not exist, but no need drop it", K(name));
3358} else {
3359ret = OB_RESOURCE_POOL_NOT_EXIST;
3360LOG_USER_ERROR(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(name));
3361LOG_WARN("resource_pool not exist", K(name), K(ret));
3362}
3363}
3364} else if (OB_FAIL(inner_drop_resource_pool(pool))) {
3365LOG_WARN("fail to inner drop resource pool", KR(ret), K(name));
3366}
3367LOG_INFO("finish drop resource pool", K(name), K(ret));
3368return ret;
3369}
3370
3371int ObUnitManager::remove_resource_pool_unit_in_trans(const int64_t resource_pool_id,
3372ObMySQLTransaction &trans)
3373{
3374int ret = OB_SUCCESS;
3375int migrate_unit_ret = OB_CANCELED;
3376if (OB_INVALID_ID == resource_pool_id
3377|| !trans.is_started()) {
3378ret = OB_INVALID_ARGUMENT;
3379LOG_WARN("invalid argument", K(ret), K(resource_pool_id),
3380"is_started", trans.is_started());
3381} else if (!check_inner_stat()) {
3382ret = OB_INNER_STAT_ERROR;
3383LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3384} else if (OB_FAIL(ut_operator_.remove_units(trans, resource_pool_id))) {
3385LOG_WARN("remove_units failed", K(ret), K(resource_pool_id));
3386} else if (OB_FAIL(ut_operator_.remove_resource_pool(trans, resource_pool_id))) {
3387LOG_WARN("remove_resource_pool failed", K(ret), K(resource_pool_id));
3388} else if (OB_FAIL(complete_migrate_unit_rs_job_in_pool(resource_pool_id,
3389migrate_unit_ret,
3390trans))) {
3391LOG_WARN("failed to complete migrate unit in pool", K(ret), K(resource_pool_id));
3392}
3393return ret;
3394}
3395// site lock at the call
3396int ObUnitManager::delete_resource_pool_unit(share::ObResourcePool *pool)
3397{
3398int ret = OB_SUCCESS;
3399if (OB_ISNULL(pool)) {
3400ret = OB_INVALID_ARGUMENT;
3401LOG_WARN("pool is null or invalid", K(ret), K(pool));
3402} else if (!check_inner_stat()) {
3403ret = OB_INNER_STAT_ERROR;
3404LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3405} else {
3406if (OB_FAIL(delete_units_of_pool(pool->resource_pool_id_))) {
3407LOG_WARN("delete_units_of_pool failed", "pool id", pool->resource_pool_id_, K(ret));
3408} else if (OB_FAIL(delete_resource_pool(pool->resource_pool_id_, pool->name_))) {
3409LOG_WARN("delete_resource_pool failed", "pool", *pool, K(ret));
3410} else {
3411const uint64_t config_id = pool->unit_config_id_;
3412if (OB_FAIL(dec_config_ref_count(config_id))) {
3413LOG_WARN("dec_config_ref_count failed", K(config_id), K(ret));
3414} else if (OB_FAIL(delete_config_pool(config_id, pool))) {
3415LOG_WARN("delete config pool failed", K(config_id), "pool", *pool, K(ret));
3416} else {
3417ROOTSERVICE_EVENT_ADD("unit", "drop_resource_pool",
3418"name", pool->name_);
3419}
3420pool_allocator_.free(pool);
3421pool = NULL;
3422}
3423}
3424return ret;
3425}
3426
3427//After the 14x version,
3428//the same tenant is allowed to have multiple unit specifications in a zone,
3429//but it is necessary to ensure that these units can be scattered on each server in the zone,
3430//and multiple units of the same tenant cannot be located on the same machine;
3431int ObUnitManager::check_server_enough(const uint64_t tenant_id,
3432const ObIArray<ObResourcePoolName> &pool_names,
3433bool &enough)
3434{
3435int ret = OB_SUCCESS;
3436enough = true;
3437share::ObResourcePool *pool = NULL;
3438ObArray<ObUnitInfo> unit_infos;
3439ObArray<ObUnitInfo> total_unit_infos;
3440common::ObArray<share::ObResourcePool *> *pools = NULL;;
3441if (!check_inner_stat()) {
3442ret = OB_INNER_STAT_ERROR;
3443LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3444} else if (pool_names.count() <= 0 || !is_valid_tenant_id(tenant_id)) {
3445ret = OB_INVALID_ARGUMENT;
3446LOG_WARN("invalid argument", K(pool_names), K(tenant_id), K(ret));
3447} else {
3448//Count the number of newly added units
3449for (int64_t i = 0; i < pool_names.count() && OB_SUCC(ret); i++) {
3450unit_infos.reset();
3451if (OB_FAIL(inner_get_resource_pool_by_name(pool_names.at(i), pool))) {
3452LOG_WARN("fail to get resource pool by name", K(ret), "pool_name", pool_names.at(i));
3453} else if (OB_ISNULL(pool)) {
3454ret = OB_ERR_UNEXPECTED;
3455LOG_WARN("get invalid pool", K(ret), K(pool));
3456} else if (OB_FAIL(inner_get_unit_infos_of_pool_(pool->resource_pool_id_, unit_infos))) {
3457LOG_WARN("fail to get unit infos", K(ret), K(*pool));
3458} else {
3459for (int64_t j = 0; j < unit_infos.count() && OB_SUCC(ret); j++) {
3460if (OB_FAIL(total_unit_infos.push_back(unit_infos.at(j)))) {
3461LOG_WARN("fail to push back unit", K(ret), K(total_unit_infos), K(j), K(unit_infos));
3462} else {
3463LOG_DEBUG("add unit infos", K(ret), K(total_unit_infos), K(unit_infos));
3464}
3465}
3466} //end else
3467} // end for
3468}
3469//Count the number of existing units
3470if (FAILEDx(get_pools_by_tenant_(tenant_id, pools))) {
3471if (OB_ENTRY_NOT_EXIST == ret) {
3472// a new tenant, without resource pool already granted
3473ret = OB_SUCCESS;
3474} else {
3475LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
3476}
3477} else if (OB_UNLIKELY(NULL == pools)) {
3478ret = OB_ERR_UNEXPECTED;
3479LOG_WARN("pools is null", K(ret), KP(pools));
3480} else {
3481for (int64_t i = 0; i < pools->count() && OB_SUCC(ret); i++) {
3482unit_infos.reset();
3483const share::ObResourcePool *pool = pools->at(i);
3484if (OB_UNLIKELY(NULL == pool)) {
3485ret = OB_ERR_UNEXPECTED;
3486LOG_WARN("pool ptr is null", K(ret), KP(pool));
3487} else if (OB_FAIL(inner_get_unit_infos_of_pool_(pool->resource_pool_id_, unit_infos))) {
3488LOG_WARN("fail to get unit infos", K(ret), K(*pool));
3489} else {
3490for (int64_t j = 0; j < unit_infos.count() && OB_SUCC(ret); j++) {
3491if (OB_FAIL(total_unit_infos.push_back(unit_infos.at(j)))) {
3492LOG_WARN("fail to push back unit", K(ret), K(total_unit_infos), K(j), K(unit_infos));
3493} else {
3494LOG_WARN("add unit infos", K(ret), K(total_unit_infos), K(unit_infos));
3495}
3496}
3497}
3498}
3499}
3500ObArray<ObZoneInfo> zone_infos;
3501if (FAILEDx(zone_mgr_.get_zone(zone_infos))) {
3502LOG_WARN("fail to get zone infos", K(ret));
3503} else {
3504//Count the number of units in zone
3505for (int64_t i = 0; i < zone_infos.count() && OB_SUCC(ret) && enough; i++) {
3506const ObZone &zone = zone_infos.at(i).zone_;
3507int64_t unit_count = 0;
3508int64_t alive_server_count = 0;
3509for (int64_t j = 0; j < total_unit_infos.count() && OB_SUCC(ret); j++) {
3510if (total_unit_infos.at(j).unit_.zone_ == zone) {
3511unit_count ++;
3512}
3513}
3514if (unit_count > 0) {
3515if (OB_FAIL(SVR_TRACER.get_alive_servers_count(zone, alive_server_count))) {
3516LOG_WARN("fail to get alive server count", KR(ret), K(zone));
3517} else if (alive_server_count < unit_count) {
3518//ret = OB_UNIT_NUM_OVER_SERVER_COUNT;
3519enough = false;
3520LOG_WARN("resource pool unit num over zone server count", K(ret), K(unit_count), K(alive_server_count),
3521K(total_unit_infos));
3522}
3523}
3524}
3525}
3526return ret;
3527}
3528
3529//The F/L scheme has new restrictions.
3530//If the logonly replica exists in the locality before adding the Logonly pool, the change is not allowed
3531int ObUnitManager::check_locality_for_logonly_unit(const share::schema::ObTenantSchema &tenant_schema,
3532const ObIArray<ObResourcePoolName> &pool_names,
3533bool &is_permitted)
3534{
3535int ret = OB_SUCCESS;
3536is_permitted = true;
3537ObArray<ObZone> zone_with_logonly_unit;
3538ObArray<share::ObZoneReplicaNumSet> zone_locality;
3539if (!check_inner_stat()) {
3540ret = OB_INNER_STAT_ERROR;
3541LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3542} else if (pool_names.count() <= 0) {
3543ret = OB_INVALID_ARGUMENT;
3544LOG_WARN("invalid argument", K(pool_names), K(ret));
3545} else {
3546FOREACH_CNT_X(pool_name, pool_names, OB_SUCCESS == ret) {
3547share::ObResourcePool *pool = NULL;
3548if (OB_FAIL(inner_get_resource_pool_by_name(*pool_name, pool))) {
3549LOG_WARN("get resource pool by name failed", "pool_name", *pool_name, K(ret));
3550} else if (NULL == pool) {
3551ret = OB_ERR_UNEXPECTED;
3552LOG_WARN("pool is null", KP(pool), K(ret));
3553} else if (REPLICA_TYPE_LOGONLY != pool->replica_type_) {
3554//nothing todo
3555} else {
3556for (int64_t i = 0; i < pool->zone_list_.count() && OB_SUCC(ret); i++) {
3557if (OB_FAIL(zone_with_logonly_unit.push_back(pool->zone_list_.at(i)))) {
3558LOG_WARN("fail to push back", K(ret));
3559}
3560}
3561}
3562}
3563}
3564if (OB_FAIL(ret)) {
3565} else if (OB_FAIL(tenant_schema.get_zone_replica_attr_array(zone_locality))) {
3566LOG_WARN("fail to get zone replica attr array", K(ret));
3567} else {
3568for (int64_t i = 0; i < zone_locality.count() && OB_SUCC(ret); i++) {
3569if ((zone_locality.at(i).replica_attr_set_.get_logonly_replica_num() == 1
3570|| zone_locality.at(i).replica_attr_set_.get_encryption_logonly_replica_num() == 1)
3571&& has_exist_in_array(zone_with_logonly_unit, zone_locality.at(i).zone_)) {
3572is_permitted = false;
3573ret = OB_NOT_SUPPORTED;
3574LOG_WARN("logonly replica already exist before logonly pool create", K(ret), K(zone_locality),
3575K(zone_with_logonly_unit));
3576}
3577}
3578}
3579return ret;
3580}
3581
3582/* when expand zone resource for tenant this func is invoked,
3583* we need to check whether the tenant units are in deleting.
3584* if any tenant unit is in deleting,
3585* @is_allowed returns false
3586*/
3587int ObUnitManager::check_expand_zone_resource_allowed_by_old_unit_stat_(
3588const uint64_t tenant_id,
3589bool &is_allowed)
3590{
3591int ret = OB_SUCCESS;
3592ObArray<share::ObResourcePool *> *cur_pool_array = nullptr;
3593if (OB_UNLIKELY(!check_inner_stat())) {
3594ret = OB_INNER_STAT_ERROR;
3595LOG_WARN("fail to check inner stat", KR(ret));
3596} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
3597ret = OB_INVALID_ARGUMENT;
3598LOG_WARN("invalid argument", KR(ret), K(tenant_id));
3599} else {
3600int tmp_ret = get_pools_by_tenant_(tenant_id, cur_pool_array);
3601if (OB_ENTRY_NOT_EXIST == tmp_ret) {
3602is_allowed = true;
3603} else if (OB_UNLIKELY(nullptr == cur_pool_array)) {
3604ret = OB_ERR_UNEXPECTED;
3605LOG_WARN("cur_pool is null", KR(ret), K(tenant_id));
3606} else {
3607is_allowed = true;
3608for (int64_t i = 0; is_allowed && OB_SUCC(ret) && i < cur_pool_array->count(); ++i) {
3609share::ObResourcePool *cur_pool = cur_pool_array->at(i);
3610ObArray<share::ObUnit *> *units = nullptr;
3611if (OB_UNLIKELY(nullptr == cur_pool)) {
3612ret = OB_ERR_UNEXPECTED;
3613LOG_WARN("cur pool is null", KR(ret));
3614} else if (OB_FAIL(get_units_by_pool(cur_pool->resource_pool_id_, units))) {
3615LOG_WARN("fail to get units by pool", KR(ret),
3616"pool_id", cur_pool->resource_pool_id_);
3617} else if (OB_UNLIKELY(nullptr == units)) {
3618ret = OB_ERR_UNEXPECTED;
3619LOG_WARN("units ptrs is null", KR(ret), K(tenant_id), KPC(cur_pool));
3620} else {
3621for (int64_t j = 0; is_allowed && OB_SUCC(ret) && j < units->count(); ++j) {
3622if (OB_UNLIKELY(nullptr == units->at(j))) {
3623ret = OB_ERR_UNEXPECTED;
3624LOG_WARN("units ptrs is null", KR(ret), K(tenant_id), KPC(cur_pool));
3625} else {
3626is_allowed = ObUnit::UNIT_STATUS_ACTIVE == units->at(j)->status_;
3627}
3628}
3629}
3630}
3631}
3632}
3633return ret;
3634}
3635
3636int ObUnitManager::check_expand_zone_resource_allowed_by_new_unit_stat_(
3637const common::ObIArray<share::ObResourcePoolName> &pool_names)
3638{
3639int ret = OB_SUCCESS;
3640for (int64_t i = 0; OB_SUCC(ret) && i < pool_names.count(); ++i) {
3641share::ObResourcePool *pool = NULL;
3642ObArray<ObUnit *> *units = nullptr;
3643if (OB_FAIL(inner_get_resource_pool_by_name(pool_names.at(i), pool))) {
3644LOG_WARN("get resource pool by name failed", "pool_name", pool_names.at(i), K(ret));
3645} else if (NULL == pool) {
3646ret = OB_ERR_UNEXPECTED;
3647LOG_WARN("pool is null", KP(pool), K(ret));
3648} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
3649LOG_WARN("fail to get units by pool", K(ret));
3650} else if (OB_UNLIKELY(nullptr == units)) {
3651ret = OB_ERR_UNEXPECTED;
3652LOG_WARN("units ptr is null", K(ret));
3653} else {
3654for (int64_t j = 0; OB_SUCC(ret) && j < units->count(); ++j) {
3655ObUnit *unit = units->at(j);
3656if (OB_UNLIKELY(nullptr == unit)) {
3657ret = OB_ERR_UNEXPECTED;
3658LOG_WARN("unit ptr is null", KR(ret), KPC(pool));
3659} else if (unit->status_ != ObUnit::UNIT_STATUS_ACTIVE) {
3660ret = OB_ERR_UNEXPECTED;
3661LOG_WARN("unexpected unit status", KR(ret), KPC(pool), KPC(unit));
3662} else {/* good */}
3663}
3664}
3665}
3666return ret;
3667}
3668
3669/* 1 when this is a tenant being created:
3670* check the input pools, each input pool unit num shall be equal, otherwise illegal
3671* 2 when this is a tenant which exists:
3672* check the input pools, each input pool unit num shall be equal to the pools already granted to the tenant.
3673*/
3674int ObUnitManager::check_tenant_pools_unit_num_legal_(
3675const uint64_t tenant_id,
3676const common::ObIArray<share::ObResourcePoolName> &input_pool_names,
3677bool &unit_num_legal,
3678int64_t &sample_unit_num)
3679{
3680int ret = OB_SUCCESS;
3681ObArray<share::ObResourcePool *> *cur_pool_array = nullptr;
3682if (OB_UNLIKELY(!check_inner_stat())) {
3683ret = OB_INNER_STAT_ERROR;
3684LOG_WARN("fail to check inner stat", KR(ret));
3685} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id)
3686|| input_pool_names.count() <= 0)) {
3687ret = OB_INVALID_ARGUMENT;
3688LOG_WARN("invalid argument", KR(ret));
3689} else {
3690unit_num_legal = true;
3691sample_unit_num = -1;
3692int tmp_ret = get_pools_by_tenant_(tenant_id, cur_pool_array);
3693if (OB_ENTRY_NOT_EXIST == tmp_ret) {
3694// when create tenant pools belong to this tenant is empty
3695} else if (OB_UNLIKELY(nullptr == cur_pool_array)) {
3696ret = OB_ERR_UNEXPECTED;
3697LOG_WARN("cur_pool is null", KR(ret), K(tenant_id));
3698} else if (OB_UNLIKELY(cur_pool_array->count() <= 0)) {
3699ret = OB_ERR_UNEXPECTED;
3700LOG_WARN("pool_array", KR(ret));
3701} else if (OB_UNLIKELY(nullptr == cur_pool_array->at(0))) {
3702ret = OB_ERR_UNEXPECTED;
3703LOG_WARN("pool ptr is null", KR(ret));
3704} else {
3705sample_unit_num = cur_pool_array->at(0)->unit_count_;
3706}
3707for (int64_t i = 0; OB_SUCC(ret) && unit_num_legal && i < input_pool_names.count(); ++i) {
3708share::ObResourcePool *pool = NULL;
3709if (OB_FAIL(inner_get_resource_pool_by_name(input_pool_names.at(i), pool))) {
3710LOG_WARN("fail to get pool by name", KR(ret), "pool_name", input_pool_names.at(i));
3711} else if (OB_UNLIKELY(nullptr == pool)) {
3712ret = OB_ERR_UNEXPECTED;
3713LOG_WARN("pool ptr is null", KR(ret), "pool_name", input_pool_names.at(i));
3714} else if (-1 == sample_unit_num) {
3715sample_unit_num = pool->unit_count_;
3716} else if (sample_unit_num == pool->unit_count_) {
3717// this is good, unit num matched
3718} else {
3719unit_num_legal = false;
3720}
3721}
3722}
3723return ret;
3724}
3725
3726int ObUnitManager::get_pool_unit_group_id_(
3727const share::ObResourcePool &pool,
3728common::ObIArray<uint64_t> &new_unit_group_id_array)
3729{
3730int ret = OB_SUCCESS;
3731if (!pool.is_granted_to_tenant()) {
3732for (int64_t i = 0; OB_SUCC(ret) && i < pool.unit_count_; ++i) {
3733if (OB_FAIL(new_unit_group_id_array.push_back(0/*not granted to tenant*/))) {
3734LOG_WARN("fail to push back", KR(ret));
3735}
3736}
3737} else {
3738const bool is_active = false;
3739if (OB_FAIL(inner_get_all_unit_group_id(pool.tenant_id_, is_active, new_unit_group_id_array))) {
3740LOG_WARN("fail to get all unit group id", KR(ret), K(pool));
3741}
3742}
3743return ret;
3744}
3745
3746/* get unit group id for a tenant
3747* 1 when bootstrap:
3748* generate unit group id for sys unit group, assign 0 directly
3749* 2 when revoke pools for tenant:
3750* after revokes pools, unit group id shall be set to 0 which representing these units
3751* is not belong to any unit group
3752* 3 when grant pools for tenant:
3753* 3.1 when this is a tenant being created: fetch unit group id from inner table
3754* 3.2 when this is a tenant which exists: get unit group id from units granted to this tenant
3755*/
3756int ObUnitManager::get_tenant_pool_unit_group_id_(
3757const bool is_bootstrap,
3758const bool grant,
3759const uint64_t tenant_id,
3760const int64_t unit_group_num,
3761common::ObIArray<uint64_t> &new_unit_group_id_array)
3762{
3763int ret = OB_SUCCESS;
3764if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || unit_group_num <= 0)) {
3765ret = OB_INVALID_ARGUMENT;
3766LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(unit_group_num));
3767} else if (is_bootstrap) {
3768if (OB_FAIL(new_unit_group_id_array.push_back(OB_SYS_UNIT_GROUP_ID))) {
3769LOG_WARN("fail to push back", KR(ret));
3770}
3771} else {
3772if (!grant) {
3773// when revoke pools, unit_group_id in units shall be modified to 0
3774for (int64_t i = 0; OB_SUCC(ret) && i < unit_group_num; ++i) {
3775if (OB_FAIL(new_unit_group_id_array.push_back(
37760/* 0 means this unit doesn't belong to any unit group*/))) {
3777LOG_WARN("fail to push back", KR(ret));
3778}
3779}
3780} else {
3781// when grant pools, an unit group id greater than 0 is needed for every unit
3782ObArray<share::ObResourcePool *> *tenant_pool_array = nullptr;
3783int tmp_ret = get_pools_by_tenant_(tenant_id, tenant_pool_array);
3784if (OB_ENTRY_NOT_EXIST == tmp_ret) {
3785// need to fetch unit group from inner table, since this is invoked by create tenant
3786for (int64_t i = 0; OB_SUCC(ret) && i < unit_group_num; ++i) {
3787uint64_t unit_group_id = OB_INVALID_ID;
3788if (OB_FAIL(fetch_new_unit_group_id(unit_group_id))) {
3789LOG_WARN("fail to fetch new unit group id", KR(ret));
3790} else if (OB_FAIL(new_unit_group_id_array.push_back(unit_group_id))) {
3791LOG_WARN("fail to push back", KR(ret));
3792}
3793}
3794} else {
3795const bool is_active = false;
3796if (OB_FAIL(inner_get_all_unit_group_id(tenant_id, is_active, new_unit_group_id_array))) {
3797LOG_WARN("fail to get all unit group id array", KR(ret), K(tenant_id));
3798}
3799}
3800}
3801}
3802return ret;
3803}
3804
3805int ObUnitManager::inner_get_all_unit_group_id(
3806const uint64_t tenant_id,
3807const bool is_active,
3808common::ObIArray<uint64_t> &unit_group_array)
3809{
3810int ret = OB_SUCCESS;
3811if (OB_UNLIKELY(!check_inner_stat())) {
3812ret = OB_INNER_STAT_ERROR;
3813LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3814} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
3815ret = OB_INVALID_ARGUMENT;
3816LOG_WARN("invalid argument", KR(ret), K(tenant_id));
3817} else {
3818ObArray<share::ObResourcePool *> *cur_pool_array = nullptr;
3819if (OB_FAIL(get_pools_by_tenant_(tenant_id, cur_pool_array))) {
3820if (OB_ENTRY_NOT_EXIST == ret) {
3821// bypass
3822ret = OB_SUCCESS;
3823} else {
3824LOG_WARN("fail to get pools by tenant", KR(ret), K(tenant_id));
3825}
3826} else if (OB_ISNULL(cur_pool_array)) {
3827ret = OB_ERR_UNEXPECTED;
3828LOG_WARN("cur pool array ptr is null", KR(ret), K(tenant_id));
3829} else if (cur_pool_array->count() <= 0) {
3830ret = OB_ERR_UNEXPECTED;
3831LOG_WARN("cur_pool_array is empty", KR(ret), K(tenant_id));
3832} else {
3833share::ObResourcePool *cur_pool = cur_pool_array->at(0);
3834common::ObArray<ObUnit *> zone_sorted_unit_array;
3835if (OB_ISNULL(cur_pool)) {
3836ret = OB_ERR_UNEXPECTED;
3837LOG_WARN("cur_pool ptr is null", KR(ret), KP(cur_pool));
3838} else if (OB_FAIL(build_zone_sorted_unit_array_(cur_pool, zone_sorted_unit_array))) {
3839LOG_WARN("fail to build zone_sorted_unit_array", KR(ret), K(cur_pool));
3840} else {
3841for (int64_t j = 0; OB_SUCC(ret) && j < zone_sorted_unit_array.count(); ++j) {
3842ObUnit *unit = zone_sorted_unit_array.at(j);
3843if (OB_ISNULL(unit)) {
3844ret = OB_ERR_UNEXPECTED;
3845LOG_WARN("unit ptr is null", KR(ret), K(tenant_id), KPC(cur_pool), K(j));
3846} else if (has_exist_in_array(unit_group_array, unit->unit_group_id_)) {
3847//unit_count_ is small than unit group count while some unit is in deleting
3848break;
3849} else if (is_active && ObUnit::UNIT_STATUS_ACTIVE != unit->status_) {
3850//need active unit group
3851continue;
3852} else if (OB_FAIL(unit_group_array.push_back(unit->unit_group_id_))) {
3853LOG_WARN("fail to push back", KR(ret), K(unit));
3854}
3855}
3856if (OB_SUCC(ret) && OB_UNLIKELY(unit_group_array.count() < cur_pool->unit_count_)) {
3857ret = OB_ERR_UNEXPECTED;
3858LOG_WARN("pool unit count unexpected", KR(ret), KPC(cur_pool),
3859K(unit_group_array));
3860}
3861}
3862}
3863}
3864return ret;
3865}
3866
3867int ObUnitManager::get_unit_in_group(
3868const uint64_t tenant_id,
3869const uint64_t unit_group_id,
3870const common::ObZone &zone,
3871share::ObUnitInfo &unit_info)
3872{
3873int ret = OB_SUCCESS;
3874common::ObArray<share::ObUnitInfo> unit_info_array;
3875if (OB_UNLIKELY(zone.is_empty())) {
3876ret = OB_INVALID_ARGUMENT;
3877LOG_WARN("invalid argument", KR(ret));
3878} else if (OB_FAIL(get_unit_group(
3879tenant_id,
3880unit_group_id,
3881unit_info_array))) {
3882LOG_WARN("fail to get unit group", KR(ret), K(tenant_id), K(unit_group_id));
3883} else {
3884bool found = false;
3885for (int64_t i = 0; !found && OB_SUCC(ret) && i < unit_info_array.count(); ++i) {
3886const share::ObUnitInfo &this_unit_info = unit_info_array.at(i);
3887if (this_unit_info.unit_.zone_ != zone) {
3888// bypass
3889} else if (OB_FAIL(unit_info.assign(this_unit_info))) {
3890LOG_WARN("fail to assign unit info", KR(ret));
3891} else {
3892found = true;
3893}
3894}
3895if (OB_FAIL(ret)) {
3896// failed
3897} else if (!found) {
3898ret = OB_ENTRY_NOT_EXIST;
3899} else {} // good
3900}
3901return ret;
3902}
3903
3904int ObUnitManager::get_unit_group(
3905const uint64_t tenant_id,
3906const uint64_t unit_group_id,
3907common::ObIArray<share::ObUnitInfo> &unit_info_array)
3908{
3909int ret = OB_SUCCESS;
3910SpinWLockGuard guard(lock_);
3911if (OB_UNLIKELY(!check_inner_stat())) {
3912ret = OB_INNER_STAT_ERROR;
3913LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
3914} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id)
3915|| 0 == unit_group_id
3916|| OB_INVALID_ID == unit_group_id)) {
3917ret = OB_INVALID_ARGUMENT;
3918LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(unit_group_id));
3919} else {
3920ObArray<share::ObResourcePool *> *cur_pool_array = nullptr;
3921ret = get_pools_by_tenant_(tenant_id, cur_pool_array);
3922if (OB_ENTRY_NOT_EXIST == ret) {
3923// bypass
3924} else if (OB_SUCCESS != ret) {
3925LOG_WARN("fail to get unit group", KR(ret), K(tenant_id), K(unit_group_id));
3926} else if (OB_UNLIKELY(nullptr == cur_pool_array)) {
3927ret = OB_ERR_UNEXPECTED;
3928LOG_WARN("cur pool array ptr is null", KR(ret), K(tenant_id), K(unit_group_id));
3929} else {
3930ObUnitInfo unit_info;
3931for (int64_t i = 0; OB_SUCC(ret) && i < cur_pool_array->count(); ++i) {
3932share::ObResourcePool *cur_pool = cur_pool_array->at(i);
3933ObArray<share::ObUnit *> *units = nullptr;
3934ObUnitConfig *config = nullptr;
3935if (OB_UNLIKELY(nullptr == cur_pool)) {
3936ret = OB_ERR_UNEXPECTED;
3937LOG_WARN("cur pool is null", KR(ret));
3938} else if (OB_FAIL(get_unit_config_by_id(cur_pool->unit_config_id_, config))) {
3939LOG_WARN("fail to get pool unit config", KR(ret), K(tenant_id), KPC(cur_pool));
3940} else if (OB_FAIL(get_units_by_pool(cur_pool->resource_pool_id_, units))) {
3941LOG_WARN("fail to get units by pool", KR(ret),
3942"pool_id", cur_pool->resource_pool_id_);
3943} else if (OB_UNLIKELY(nullptr == units)) {
3944ret = OB_ERR_UNEXPECTED;
3945LOG_WARN("units ptrs is null", KR(ret), K(tenant_id), KPC(cur_pool));
3946} else {
3947for (int64_t j = 0; OB_SUCC(ret) && j < units->count(); ++j) {
3948if (OB_UNLIKELY(nullptr == units->at(j))) {
3949ret = OB_ERR_UNEXPECTED;
3950LOG_WARN("units ptrs is null", KR(ret), K(tenant_id), KPC(cur_pool));
3951} else if (units->at(j)->unit_group_id_ != unit_group_id) {
3952// unit group id not match
3953} else {
3954unit_info.reset();
3955unit_info.config_ = *config;
3956unit_info.unit_ = *(units->at(j));
3957if (OB_FAIL(unit_info.pool_.assign(*cur_pool))) {
3958LOG_WARN("fail to assign", KR(ret), KPC(cur_pool));
3959} else if (OB_FAIL(unit_info_array.push_back(unit_info))) {
3960LOG_WARN("fail to push back", K(unit_info));
3961}
3962}
3963}
3964}
3965}
3966if (OB_SUCC(ret)) {
3967if (unit_info_array.count() <= 0) {
3968ret = OB_ENTRY_NOT_EXIST;
3969}
3970}
3971}
3972}
3973return ret;
3974}
3975
3976// TODO(cangming.zl): need a new function to abstract the process of getting pools by pool_names
3977// TODO: disable resource pools intersect for one tenant
3978// NEED to disable logics to handle resource pool intersect in server_balancer
3979int ObUnitManager::grant_pools(common::ObMySQLTransaction &trans,
3980common::ObIArray<uint64_t> &new_unit_group_id_array,
3981const lib::Worker::CompatMode compat_mode,
3982const ObIArray<ObResourcePoolName> &pool_names,
3983const uint64_t tenant_id,
3984const bool is_bootstrap,
3985const uint64_t source_tenant_id,
3986/*arg "const bool skip_offline_server" is no longer supported*/
3987const bool check_data_version)
3988{
3989int ret = OB_SUCCESS;
3990SpinWLockGuard guard(lock_);
3991const bool grant = true;
3992bool intersect = false;
3993bool server_enough = true;
3994bool is_grant_pool_allowed = false;
3995bool unit_num_legal = false;
3996int64_t legal_unit_num = -1;
3997if (!check_inner_stat()) {
3998ret = OB_INNER_STAT_ERROR;
3999LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), KR(ret));
4000} else if (pool_names.count() <= 0 || !is_valid_tenant_id(tenant_id)) {
4001ret = OB_INVALID_ARGUMENT;
4002LOG_WARN("invalid argument", K(pool_names), K(tenant_id), K(ret));
4003} else if (OB_FAIL(check_pool_ownership_(tenant_id, pool_names, true/*is_grant*/))) {
4004LOG_WARN("check pool ownership failed", KR(ret), K(pool_names));
4005} else if (OB_FAIL(check_pool_intersect_(tenant_id, pool_names, intersect))) {
4006LOG_WARN("check pool intersect failed", K(pool_names), KR(ret));
4007} else if (intersect) {
4008ret = OB_POOL_SERVER_INTERSECT;
4009LOG_USER_ERROR(OB_POOL_SERVER_INTERSECT, to_cstring(pool_names));
4010LOG_WARN("resource pool unit server intersect", K(pool_names), KR(ret));
4011} else if (!is_bootstrap
4012&& OB_FAIL(check_server_enough(tenant_id, pool_names, server_enough))) {
4013LOG_WARN("fail to check server enough", KR(ret), K(tenant_id), K(pool_names));
4014} else if (!server_enough) {
4015ret = OB_UNIT_NUM_OVER_SERVER_COUNT;
4016LOG_WARN("resource pool unit num over zone server count", K(ret), K(pool_names), K(tenant_id));
4017} else if (OB_FAIL(check_expand_zone_resource_allowed_by_old_unit_stat_(
4018tenant_id, is_grant_pool_allowed))) {
4019LOG_WARN("fail to check grant pools allowed by unit stat", KR(ret), K(tenant_id));
4020} else if (!is_grant_pool_allowed) {
4021ret = OB_OP_NOT_ALLOW;
4022LOG_USER_ERROR(OB_OP_NOT_ALLOW, "grant pool when pools in shrinking");
4023} else if (OB_FAIL(check_expand_zone_resource_allowed_by_new_unit_stat_(pool_names))) {
4024LOG_WARN("fail to check grant pools allowed by unit stat", KR(ret));
4025} else if (OB_FAIL(check_tenant_pools_unit_num_legal_(
4026tenant_id, pool_names, unit_num_legal, legal_unit_num))) {
4027LOG_WARN("fail to check pools unit num legal", KR(ret), K(tenant_id), K(pool_names));
4028} else if (!unit_num_legal) {
4029ret = OB_OP_NOT_ALLOW;
4030LOG_WARN("pools belong to one tenant with different unit num are not allowed",
4031KR(ret), K(tenant_id), K(pool_names));
4032LOG_USER_ERROR(OB_OP_NOT_ALLOW, "pools belong to one tenant with different unit num are");
4033} else if (OB_FAIL(get_tenant_pool_unit_group_id_(
4034is_bootstrap, grant, tenant_id, legal_unit_num, new_unit_group_id_array))) {
4035LOG_WARN("fail to generate new unit group id", KR(ret), K(tenant_id), K(legal_unit_num));
4036} else if (OB_FAIL(do_grant_pools_(
4037trans, new_unit_group_id_array, compat_mode,
4038pool_names, tenant_id, is_bootstrap,
4039source_tenant_id, check_data_version))) {
4040LOG_WARN("do grant pools failed", KR(ret), K(grant), K(pool_names), K(tenant_id),
4041K(compat_mode), K(is_bootstrap), K(source_tenant_id));
4042}
4043LOG_INFO("grant resource pools to tenant", KR(ret), K(pool_names), K(tenant_id), K(is_bootstrap));
4044return ret;
4045}
4046
4047int ObUnitManager::revoke_pools(common::ObMySQLTransaction &trans,
4048common::ObIArray<uint64_t> &new_unit_group_id_array,
4049const ObIArray<ObResourcePoolName> &pool_names,
4050const uint64_t tenant_id)
4051{
4052int ret = OB_SUCCESS;
4053SpinWLockGuard guard(lock_);
4054const bool grant = false;
4055bool unit_num_legal = false;
4056int64_t legal_unit_num = -1;
4057if (!check_inner_stat()) {
4058ret = OB_INNER_STAT_ERROR;
4059LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4060} else if (pool_names.count() <= 0 || !is_valid_tenant_id(tenant_id)) {
4061ret = OB_INVALID_ARGUMENT;
4062LOG_WARN("invalid argument", K(pool_names), K(tenant_id), K(ret));
4063} else if (OB_FAIL(check_pool_ownership_(tenant_id, pool_names, false/*is_grant*/))) {
4064LOG_WARN("check pool ownership failed", KR(ret), K(pool_names));
4065} else if (OB_FAIL(check_tenant_pools_unit_num_legal_(
4066tenant_id, pool_names, unit_num_legal, legal_unit_num))) {
4067LOG_WARN("fail to check pools unit num legal", KR(ret), K(tenant_id), K(pool_names));
4068} else if (!unit_num_legal) {
4069ret = OB_OP_NOT_ALLOW;
4070LOG_WARN("pools belong to one tenant with different unit num are not allowed",
4071KR(ret), K(tenant_id), K(pool_names));
4072} else if (OB_FAIL(get_tenant_pool_unit_group_id_(
4073false /* is_bootstrap */, grant, tenant_id,
4074legal_unit_num, new_unit_group_id_array))) {
4075LOG_WARN("fail to generate new unit group id", KR(ret), K(tenant_id), K(legal_unit_num));
4076} else if (OB_FAIL(do_revoke_pools_(trans, new_unit_group_id_array, pool_names, tenant_id))) {
4077LOG_WARN("do revoke pools failed", KR(ret), K(grant), K(pool_names), K(tenant_id));
4078}
4079LOG_INFO("revoke resource pools from tenant", K(pool_names), K(ret));
4080return ret;
4081}
4082
4083int ObUnitManager::inner_get_pool_ids_of_tenant(const uint64_t tenant_id,
4084ObIArray<uint64_t> &pool_ids) const
4085{
4086int ret = OB_SUCCESS;
4087if (!check_inner_stat()) {
4088ret = OB_INNER_STAT_ERROR;
4089LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4090} else if (!is_valid_tenant_id(tenant_id)) {
4091ret = OB_INVALID_ARGUMENT;
4092LOG_WARN("invalid argument", K(tenant_id), K(ret));
4093} else {
4094pool_ids.reuse();
4095ObArray<share::ObResourcePool *> *pools = NULL;
4096if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
4097if (OB_ENTRY_NOT_EXIST != ret) {
4098LOG_DEBUG("get_pools_by_tenant failed", K(tenant_id), K(ret));
4099} else {
4100// just return empty pool_ids
4101if (OB_GTS_TENANT_ID != tenant_id) {
4102LOG_INFO("tenant doesn't own any pool", K(tenant_id), KR(ret));
4103}
4104ret = OB_SUCCESS;
4105}
4106} else if (NULL == pools) {
4107ret = OB_ERR_UNEXPECTED;
4108LOG_WARN("pools is null", KP(pools), K(ret));
4109} else {
4110for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
4111if (NULL == pools->at(i)) {
4112ret = OB_ERR_UNEXPECTED;
4113LOG_WARN("pool is null", "pool", OB_P(pools->at(i)), K(ret));
4114} else if (OB_FAIL(pool_ids.push_back(pools->at(i)->resource_pool_id_))) {
4115LOG_WARN("push_back failed", K(ret));
4116}
4117}
4118}
4119}
4120return ret;
4121}
4122
4123int ObUnitManager::get_tenant_alive_servers_non_block(const uint64_t tenant_id,
4124common::ObIArray<ObAddr> &servers)
4125{
4126int ret = OB_SUCCESS;
4127if (!check_inner_stat()) {
4128ret = OB_INNER_STAT_ERROR;
4129LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
4130} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
4131ret = OB_INVALID_ARGUMENT;
4132LOG_WARN("invalid argument", KR(ret), K(tenant_id));
4133} else {
4134ObArray<ObUnit> tenant_units;
4135uint64_t valid_tnt_id = is_meta_tenant(tenant_id) ? gen_user_tenant_id(tenant_id) : tenant_id;
4136// Try lock and get units from inmemory data. If lock failed, get from inner table.
4137if (lock_.try_rdlock()) {
4138// Get from inmemory data
4139ObArray<share::ObResourcePool *> *pools = nullptr;
4140if (OB_FAIL(get_pools_by_tenant_(valid_tnt_id, pools))) {
4141LOG_WARN("failed to get pools by tenant", KR(ret), K(valid_tnt_id));
4142} else if (OB_ISNULL(pools)) {
4143ret = OB_ERR_UNEXPECTED;
4144LOG_WARN("pools is nullptr", KR(ret), KP(pools));
4145} else {
4146for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
4147const share::ObResourcePool *pool = pools->at(i);
4148ObArray<ObUnit *> *pool_units;
4149if (OB_ISNULL(pool)) {
4150ret = OB_ERR_UNEXPECTED;
4151LOG_WARN("pool is nullptr", KR(ret), KP(pool));
4152} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, pool_units))) {
4153LOG_WARN("fail to get_units_by_pool", KR(ret),
4154"pool_id", pool->resource_pool_id_);
4155} else if (OB_ISNULL(pool_units)) {
4156ret = OB_ERR_UNEXPECTED;
4157LOG_WARN("pool_units is nullptr", KR(ret), KP(pool_units));
4158} else {
4159ARRAY_FOREACH_X(*pool_units, idx, cnt, OB_SUCC(ret)) {
4160const ObUnit *unit = pool_units->at(idx);
4161if (OB_ISNULL(unit)) {
4162ret = OB_ERR_UNEXPECTED;
4163LOG_WARN("unit is nullptr", KR(ret), KP(unit));
4164} else if (OB_FAIL(tenant_units.push_back(*unit))) {
4165LOG_WARN("failed to push_back unit", KR(ret), KPC(unit));
4166}
4167}
4168}
4169}
4170}
4171lock_.unlock();
4172} else {
4173// Get from inner_table
4174tenant_units.reuse();
4175if (OB_FAIL(ut_operator_.get_units_by_tenant(valid_tnt_id, tenant_units))) {
4176LOG_WARN("fail to get_units_by_tenant from inner_table",
4177KR(ret), K(tenant_id), K(valid_tnt_id));
4178}
4179}
4180
4181// Filter alive servers
4182if (OB_SUCC(ret)) {
4183servers.reuse();
4184FOREACH_X(unit, tenant_units, OB_SUCC(ret)) {
4185bool is_alive = false;
4186if (OB_FAIL(SVR_TRACER.check_server_alive(unit->server_, is_alive))) {
4187LOG_WARN("check_server_alive failed", KR(ret), K(unit->server_));
4188} else if (is_alive) {
4189if (has_exist_in_array(servers, unit->server_)) {
4190// server exist
4191} else if (OB_FAIL(servers.push_back(unit->server_))) {
4192LOG_WARN("push_back failed", KR(ret), K(unit->server_));
4193}
4194}
4195if (OB_FAIL(ret) || !unit->migrate_from_server_.is_valid()) {
4196// skip
4197} else if (OB_FAIL(SVR_TRACER.check_server_alive(unit->migrate_from_server_, is_alive))) {
4198LOG_WARN("check_server_alive failed", KR(ret), K(unit->migrate_from_server_));
4199} else if (is_alive) {
4200if (has_exist_in_array(servers, unit->migrate_from_server_)) {
4201// server exist
4202} else if (OB_FAIL(servers.push_back(unit->migrate_from_server_))) {
4203LOG_WARN("push_back failed", KR(ret), K(unit->migrate_from_server_));
4204}
4205}
4206}
4207}
4208}
4209return ret;
4210}
4211
4212int ObUnitManager::get_pool_ids_of_tenant(const uint64_t tenant_id,
4213ObIArray<uint64_t> &pool_ids) const
4214{
4215int ret = OB_SUCCESS;
4216SpinRLockGuard guard(lock_);
4217if (!check_inner_stat()) {
4218ret = OB_INNER_STAT_ERROR;
4219LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4220} else if (!is_valid_tenant_id(tenant_id)) {
4221ret = OB_INVALID_ARGUMENT;
4222LOG_WARN("invalid argument", K(tenant_id), K(ret));
4223} else if (OB_FAIL(inner_get_pool_ids_of_tenant(tenant_id, pool_ids))) {
4224LOG_WARN("fail to inner get pool ids of tenant", K(ret));
4225}
4226return ret;
4227}
4228
4229int ObUnitManager::get_pool_names_of_tenant(const uint64_t tenant_id,
4230ObIArray<ObResourcePoolName> &pool_names) const
4231{
4232int ret = OB_SUCCESS;
4233SpinRLockGuard guard(lock_);
4234if (!check_inner_stat()) {
4235ret = OB_INNER_STAT_ERROR;
4236LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4237} else if (!is_valid_tenant_id(tenant_id)) {
4238ret = OB_INVALID_ARGUMENT;
4239LOG_WARN("invalid argument", K(tenant_id), K(ret));
4240} else {
4241ObArray<share::ObResourcePool *> *pools = NULL;
4242if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
4243if (OB_ENTRY_NOT_EXIST != ret) {
4244LOG_WARN("get_pools_by_tenant failed", K(tenant_id), K(ret));
4245} else {
4246// just return empty pool_ids
4247ret = OB_SUCCESS;
4248LOG_WARN("tenant doesn't own any pool", K(tenant_id), K(ret));
4249}
4250} else if (NULL == pools) {
4251ret = OB_ERR_UNEXPECTED;
4252LOG_WARN("pools is null", KP(pools), K(ret));
4253} else {
4254pool_names.reuse();
4255for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
4256if (NULL == pools->at(i)) {
4257ret = OB_ERR_UNEXPECTED;
4258LOG_WARN("pool is null", "pool", OB_P(pools->at(i)), K(ret));
4259} else if (OB_FAIL(pool_names.push_back(pools->at(i)->name_))) {
4260LOG_WARN("push_back failed", K(ret));
4261}
4262}
4263}
4264}
4265return ret;
4266}
4267
4268
4269int ObUnitManager::get_unit_config_by_pool_name(
4270const ObString &pool_name,
4271share::ObUnitConfig &unit_config) const
4272{
4273int ret = OB_SUCCESS;
4274share::ObResourcePool *pool = NULL;
4275ObUnitConfig *config = NULL;
4276SpinRLockGuard guard(lock_);
4277if (!check_inner_stat()) {
4278ret = OB_INNER_STAT_ERROR;
4279LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4280} else if (OB_FAIL(inner_get_resource_pool_by_name(pool_name, pool))) {
4281if (OB_ENTRY_NOT_EXIST != ret) {
4282LOG_WARN("get resource pool by name failed", K(pool_name), K(ret));
4283} else {
4284ret = OB_RESOURCE_POOL_NOT_EXIST;
4285LOG_WARN("pool not exist", K(ret), K(pool_name));
4286}
4287} else if (NULL == pool) {
4288ret = OB_INVALID_ARGUMENT;
4289LOG_WARN("pool is null", KP(pool), K(ret));
4290} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, config))) {
4291if (OB_ENTRY_NOT_EXIST == ret) {
4292ret = OB_RESOURCE_UNIT_NOT_EXIST;
4293}
4294LOG_WARN("can not find config for unit",
4295"unit_config_id", pool->unit_config_id_,
4296K(ret));
4297} else if (NULL == config) {
4298ret = OB_ERR_UNEXPECTED;
4299LOG_WARN("config is null", KP(config), K(ret));
4300} else {
4301unit_config = *config;
4302}
4303return ret;
4304}
4305
4306
4307int ObUnitManager::get_zones_of_pools(const ObIArray<ObResourcePoolName> &pool_names,
4308ObIArray<ObZone> &zones) const
4309{
4310int ret = OB_SUCCESS;
4311SpinRLockGuard guard(lock_);
4312if (!check_inner_stat()) {
4313ret = OB_INNER_STAT_ERROR;
4314LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4315} else if (pool_names.count() <= 0) {
4316ret = OB_INVALID_ARGUMENT;
4317LOG_WARN("pool_names is empty", K(pool_names), K(ret));
4318} else {
4319for (int64_t i = 0; OB_SUCC(ret) && i < pool_names.count(); ++i) {
4320share::ObResourcePool *pool = NULL;
4321if (pool_names.at(i).is_empty()) {
4322ret = OB_INVALID_ARGUMENT;
4323LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool name");
4324LOG_WARN("invalid pool name", "pool name", pool_names.at(i), K(ret));
4325} else if (OB_FAIL(inner_get_resource_pool_by_name(pool_names.at(i), pool))) {
4326if (OB_ENTRY_NOT_EXIST != ret) {
4327LOG_WARN("get resource pool by name failed", "name", pool_names.at(i), K(ret));
4328} else {
4329ret = OB_RESOURCE_POOL_NOT_EXIST;
4330LOG_USER_ERROR(OB_RESOURCE_POOL_NOT_EXIST, to_cstring(pool_names.at(i)));
4331LOG_WARN("pool not exist", "pool_name", pool_names.at(i), K(ret));
4332}
4333} else if (NULL == pool) {
4334ret = OB_ERR_UNEXPECTED;
4335LOG_WARN("pool is null", KP(pool), K(ret));
4336} else if (OB_FAIL(append(zones, pool->zone_list_))) {
4337LOG_WARN("append failed", "zone_list", pool->zone_list_, K(ret));
4338}
4339}
4340}
4341return ret;
4342}
4343
4344int ObUnitManager::get_pools(common::ObIArray<share::ObResourcePool> &pools) const
4345{
4346int ret = OB_SUCCESS;
4347SpinWLockGuard guard(lock_);
4348if (!check_inner_stat()) {
4349ret = OB_INNER_STAT_ERROR;
4350LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4351} else {
4352ObHashMap<uint64_t, share::ObResourcePool *>::const_iterator iter = id_pool_map_.begin();
4353for ( ; OB_SUCC(ret) && iter != id_pool_map_.end(); ++iter) {
4354if (NULL == iter->second) {
4355ret = OB_ERR_UNEXPECTED;
4356LOG_WARN("iter->second is null", KP(iter->second), K(ret));
4357} else if (OB_FAIL(pools.push_back(*(iter->second)))) {
4358LOG_WARN("push_back failed", K(ret));
4359}
4360}
4361}
4362return ret;
4363}
4364
4365int ObUnitManager::create_sys_units(const ObIArray<ObUnit> &sys_units)
4366{
4367int ret = OB_SUCCESS;
4368SpinWLockGuard guard(lock_);
4369if (!check_inner_stat()) {
4370ret = OB_INNER_STAT_ERROR;
4371LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4372} else if (sys_units.count() <= 0) {
4373ret = OB_INVALID_ARGUMENT;
4374LOG_WARN("sys_units is empty", K(sys_units), K(ret));
4375} else {
4376for (int64_t i = 0; OB_SUCC(ret) && i < sys_units.count(); ++i) {
4377if (OB_FAIL(add_unit(*proxy_, sys_units.at(i)))) {
4378LOG_WARN("add_unit failed", "unit", sys_units.at(i), K(ret));
4379}
4380}
4381}
4382return ret;
4383}
4384
4385int ObUnitManager::inner_get_tenant_pool_zone_list(
4386const uint64_t tenant_id,
4387common::ObIArray<common::ObZone> &zone_list) const
4388{
4389int ret = OB_SUCCESS;
4390ObArray<share::ObResourcePool *> *pools = NULL;
4391if (!check_inner_stat()) {
4392ret = OB_INNER_STAT_ERROR;
4393LOG_WARN("check inner stat failed", K(ret), K(inited_), K(loaded_));
4394} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
4395ret = OB_INVALID_ARGUMENT;
4396LOG_WARN("invalid argument", K(ret), K(tenant_id));
4397} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
4398LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
4399} else if (OB_UNLIKELY(NULL == pools)) {
4400ret = OB_ERR_UNEXPECTED;
4401LOG_WARN("pools ptr is null", K(ret), K(tenant_id));
4402} else if (pools->count() <= 0) {
4403ret = OB_ERR_UNEXPECTED;
4404LOG_WARN("pools array is empty", K(ret), K(*pools));
4405} else {
4406zone_list.reset();
4407for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
4408const share::ObResourcePool *pool = pools->at(i);
4409if (NULL == pool) {
4410ret = OB_ERR_UNEXPECTED;
4411LOG_WARN("pool is null", K(ret), KP(pool));
4412} else if (OB_FAIL(append(zone_list, pool->zone_list_))) {
4413LOG_WARN("fail to append", K(ret));
4414} else {} // no more to do
4415}
4416}
4417return ret;
4418}
4419
4420int ObUnitManager::get_tenant_pool_zone_list(
4421const uint64_t tenant_id,
4422common::ObIArray<common::ObZone> &zone_list) const
4423{
4424int ret = OB_SUCCESS;
4425SpinRLockGuard guard(lock_);
4426if (OB_FAIL(inner_get_tenant_pool_zone_list(tenant_id, zone_list))) {
4427LOG_WARN("fail to inner get tenant pool zone list", K(ret));
4428}
4429return ret;
4430}
4431
4432// cancel migrate units on server to other servers
4433int ObUnitManager::cancel_migrate_out_units(const ObAddr &server)
4434{
4435int ret = OB_SUCCESS;
4436SpinWLockGuard guard(lock_);
4437ObArray<uint64_t> migrate_units;
4438if (!check_inner_stat()) {
4439ret = OB_INNER_STAT_ERROR;
4440LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
4441} else if (!server.is_valid()) {
4442ret = OB_INVALID_ARGUMENT;
4443LOG_WARN("invalid argument", K(server), K(ret));
4444} else if (OB_FAIL(get_migrate_units_by_server(server, migrate_units))) {
4445LOG_WARN("get_migrate_units_by_server failed", K(server), K(ret));
4446} else {
4447const EndMigrateOp op = REVERSE;
4448for (int64_t i = 0; OB_SUCC(ret) && i < migrate_units.count(); ++i) {
4449if (OB_FAIL(end_migrate_unit(migrate_units.at(i), op))) {
4450LOG_WARN("end_migrate_unit failed", "unit_id", migrate_units.at(i), K(op), K(ret));
4451}
4452}
4453}
4454LOG_INFO("cancel migrate out units", K(server), K(ret));
4455return ret;
4456}
4457
4458int ObUnitManager::check_server_empty(const ObAddr &server, bool &empty) const
4459{
4460int ret = OB_SUCCESS;
4461SpinRLockGuard guard(lock_);
4462ObArray<ObUnitLoad> *loads = NULL;
4463empty = false;
4464if (!check_inner_stat()) {
4465ret = OB_INNER_STAT_ERROR;
4466LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
4467} else if (!server.is_valid()) {
4468ret = OB_INVALID_ARGUMENT;
4469LOG_WARN("invalid server", K(server), K(ret));
4470} else if (OB_FAIL(get_loads_by_server(server, loads))) {
4471if (OB_ENTRY_NOT_EXIST != ret) {
4472LOG_WARN("get_loads_by_server failed", K(server), K(ret));
4473} else {
4474ret = OB_SUCCESS;
4475empty = true;
4476}
4477} else if (NULL == loads) {
4478ret = OB_ERR_UNEXPECTED;
4479LOG_WARN("loads is null", KP(loads), K(ret));
4480} else {
4481empty = false;
4482}
4483return ret;
4484}
4485
4486int ObUnitManager::finish_migrate_unit_not_in_tenant(
4487share::ObResourcePool *pool)
4488{
4489int ret = OB_SUCCESS;
4490SpinWLockGuard guard(lock_);
4491//Not in tenant unit
4492//Using pool, take the unit corresponding to the pool whose tenant_id is -1
4493if (-1 != pool->tenant_id_) {
4494//in tenant
4495//ignore in tenant unit
4496} else {
4497ObArray<ObUnitInfo> unit_infos;
4498if (OB_FAIL(inner_get_unit_infos_of_pool_(pool->resource_pool_id_, unit_infos))) {
4499LOG_WARN("fail to get units by pool", K(ret));
4500} else {
4501FOREACH_CNT_X(unit_info, unit_infos, OB_SUCC(ret)) {
4502if ((*unit_info).unit_.migrate_from_server_.is_valid()) {
4503if (OB_INVALID_ID == (*unit_info).unit_.unit_id_) {
4504ret = OB_INVALID_ARGUMENT;
4505LOG_WARN("invalid argument", K((*unit_info).unit_.unit_id_), K(ret));
4506} else {
4507const EndMigrateOp op = COMMIT;
4508if (OB_FAIL(end_migrate_unit((*unit_info).unit_.unit_id_, op))) {
4509LOG_WARN("end migrate unit failed", K(ret), K((*unit_info).unit_.unit_id_), K(op));
4510} else {
4511LOG_INFO("finish migrate unit not in tenant", K(ret),
4512"unit_id", (*unit_info).unit_.unit_id_);
4513}
4514}
4515} else {}//ignore not in migrate unit
4516}
4517}
4518}
4519return ret;
4520}
4521
4522int ObUnitManager::finish_migrate_unit_not_in_locality(
4523uint64_t tenant_id,
4524share::schema::ObSchemaGetterGuard *schema_guard,
4525ObArray<common::ObZone> zone_list)
4526{
4527int ret = OB_SUCCESS;
4528SpinWLockGuard guard(lock_);
4529const ObTenantSchema *tenant_schema = NULL;
4530ObArray<ObUnitInfo> unit_infos;
4531ObArray<common::ObZone> zone_locality_list;
4532if (OB_FAIL((*schema_guard).get_tenant_info(tenant_id, tenant_schema))) {
4533LOG_WARN("fail to get tenant schema", K(ret), K(tenant_id));
4534} else if (OB_ISNULL(tenant_schema)) {
4535ret = OB_ERR_UNEXPECTED;
4536LOG_WARN("tenant schema is null", K(ret));
4537} else if (OB_FAIL(tenant_schema->get_zone_list(zone_locality_list))) {
4538LOG_WARN("fail to get zone replica attr array", K(ret));
4539} else {
4540for (int64_t i = 0; i < zone_list.count() && OB_SUCC(ret); i++) {
4541if (!has_exist_in_array(zone_locality_list, zone_list.at(i))) {
4542//Get the unit that is in the zone locality but not in the zone_list,
4543//the zone that is not in the locality
4544if (OB_FAIL(inner_get_zone_alive_unit_infos_by_tenant(
4545tenant_id, zone_list.at(i), unit_infos))) {
4546LOG_WARN("fail to get zone alive unit infos by tenant", K(ret));
4547} else {
4548FOREACH_CNT_X(unit_info, unit_infos, OB_SUCC(ret)) {
4549if ((*unit_info).unit_.migrate_from_server_.is_valid()) {
4550if (OB_INVALID_ID == (*unit_info).unit_.unit_id_) {
4551ret = OB_INVALID_ARGUMENT;
4552LOG_WARN("invalid argument", K((*unit_info).unit_.unit_id_), K(ret));
4553} else {
4554const EndMigrateOp op = COMMIT;
4555if (OB_FAIL(end_migrate_unit((*unit_info).unit_.unit_id_, op))) {
4556LOG_WARN("end migrate unit failed", K(ret),
4557K((*unit_info).unit_.unit_id_), K(op));
4558} else {
4559LOG_INFO("finish migrate unit not in locality", K(ret),
4560"unit_id", (*unit_info).unit_.unit_id_);
4561}
4562}
4563} else {} //ignore not in migrate unit
4564} //end FOREACH
4565}
4566} else {} //ignore in locality unit
4567} //end for
4568}
4569return ret;
4570}
4571
4572int ObUnitManager::finish_migrate_unit(const uint64_t unit_id)
4573{
4574int ret = OB_SUCCESS;
4575SpinWLockGuard guard(lock_);
4576if (!check_inner_stat()) {
4577ret = OB_INNER_STAT_ERROR;
4578LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4579} else if (OB_INVALID_ID == unit_id) {
4580ret = OB_INVALID_ARGUMENT;
4581LOG_WARN("invalid argument", K(unit_id), K(ret));
4582} else {
4583const EndMigrateOp op = COMMIT;
4584if (OB_FAIL(end_migrate_unit(unit_id, op))) {
4585LOG_WARN("end_migrate_unit failed", K(unit_id), K(op), K(ret));
4586}
4587}
4588LOG_INFO("finish migrate unit", K(unit_id), K(ret));
4589return ret;
4590}
4591
4592int ObUnitManager::inner_get_zone_alive_unit_infos_by_tenant(
4593const uint64_t tenant_id,
4594const common::ObZone &zone,
4595common::ObIArray<share::ObUnitInfo> &unit_infos) const
4596{
4597int ret = OB_SUCCESS;
4598ObArray<uint64_t> rs_pool;
4599ObArray<ObUnitInfo> unit_array;
4600unit_infos.reset();
4601if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))
4602|| OB_UNLIKELY(zone.is_empty())) {
4603ret = OB_INVALID_ARGUMENT;
4604LOG_WARN("invalid argument", K(ret), K(tenant_id), K(zone));
4605} else if (OB_FAIL(inner_get_pool_ids_of_tenant(tenant_id, rs_pool))) {
4606LOG_WARN("fail to get pool ids by tennat", K(ret), K(tenant_id));
4607} else {
4608FOREACH_X(pool, rs_pool, OB_SUCCESS == ret) {
4609unit_array.reuse();
4610if (!check_inner_stat()) {
4611ret = OB_INNER_STAT_ERROR;
4612LOG_WARN("check inner stat failed", K(ret), K(inited_), K(loaded_));
4613} else if (OB_UNLIKELY(NULL == pool)) {
4614ret = OB_ERR_UNEXPECTED;
4615LOG_WARN("pool is null", K(ret));
4616} else if (OB_FAIL(inner_get_unit_infos_of_pool_(*pool, unit_array))) {
4617LOG_WARN("fail to get unit infos of pool", K(ret));
4618} else if (unit_array.count() > 0) {
4619FOREACH_X(u, unit_array, OB_SUCCESS == ret) {
4620bool is_alive = false;
4621bool is_in_service = false;
4622if (OB_UNLIKELY(NULL == u)) {
4623ret = OB_ERR_UNEXPECTED;
4624LOG_WARN("unit is empty", K(ret));
4625} else if (zone != u->unit_.zone_) {
4626// do not belong to this zone
4627} else if (OB_FAIL(SVR_TRACER.check_server_alive(u->unit_.server_, is_alive))) {
4628LOG_WARN("check_server_alive failed", "server", u->unit_.server_, K(ret));
4629} else if (OB_FAIL(SVR_TRACER.check_in_service(u->unit_.server_, is_in_service))) {
4630LOG_WARN("check server in service failed", "server", u->unit_.server_, K(ret));
4631} else if (!is_alive || !is_in_service) {
4632// ignore unit on not-alive server
4633} else if (ObUnit::UNIT_STATUS_ACTIVE != u->unit_.status_) {
4634// ignore the unit which is in deleting status
4635} else if (OB_FAIL(unit_infos.push_back(*u))) {
4636LOG_WARN("fail to push back", K(ret));
4637} else {} // no more to do
4638}
4639} else {} // empty array
4640}
4641}
4642return ret;
4643}
4644
4645int ObUnitManager::get_all_unit_infos_by_tenant(const uint64_t tenant_id,
4646ObIArray<ObUnitInfo> &unit_infos)
4647{
4648int ret = OB_SUCCESS;
4649SpinRLockGuard guard(lock_);
4650unit_infos.reset();
4651if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id)) {
4652LOG_WARN("invalid argument", KR(ret), K(tenant_id));
4653} else if (OB_FAIL(inner_get_all_unit_infos_by_tenant_(tenant_id, unit_infos))) {
4654LOG_WARN("fail to inner get unit infos of tenant", KR(ret), K(tenant_id));
4655}
4656return ret;
4657}
4658
4659int ObUnitManager::inner_get_all_unit_infos_by_tenant_(const uint64_t tenant_id,
4660ObIArray<ObUnitInfo> &unit_infos)
4661{
4662int ret = OB_SUCCESS;
4663share::schema::ObSchemaGetterGuard schema_guard;
4664const share::schema::ObTenantSchema *tenant_schema = NULL;
4665unit_infos.reset();
4666common::ObArray<common::ObZone> tenant_zone_list;
4667ObArray<uint64_t> rs_pool;
4668ObArray<ObUnitInfo> unit_array;
4669
4670if (!is_valid_tenant_id(tenant_id)) {
4671ret = OB_INVALID_ARGUMENT;
4672LOG_WARN("invalid argument", K(ret), K(tenant_id));
4673} else if (OB_ISNULL(schema_service_)) {
4674ret = OB_NOT_INIT;
4675LOG_WARN("schema service is null", K(schema_service_), KR(ret));
4676} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
4677LOG_WARN("fail to get tenant schema guard", KR(ret), K(tenant_id));
4678} else if (OB_FAIL(schema_guard.get_tenant_info(tenant_id, tenant_schema))) {
4679LOG_WARN("fail to get tenant info", K(ret), K(tenant_id));
4680} else if (OB_UNLIKELY(NULL == tenant_schema)) {
4681ret = OB_ERR_UNEXPECTED;
4682LOG_WARN("tenant schema is null", K(ret), KP(tenant_schema));
4683} else if (OB_FAIL(tenant_schema->get_zone_list(tenant_zone_list))) {
4684LOG_WARN("fail to get zone list", K(ret));
4685} else if (OB_FAIL(inner_get_pool_ids_of_tenant(tenant_id, rs_pool))) {
4686LOG_WARN("fail to get pool ids of tenant", K(ret), K(tenant_id));
4687} else {
4688FOREACH_X(pool, rs_pool, OB_SUCCESS == ret) {
4689unit_array.reuse();
4690if (!check_inner_stat()) {
4691ret = OB_INNER_STAT_ERROR;
4692LOG_WARN("check inner stat failed", K(ret), K(inited_), K(loaded_));
4693} else if (OB_UNLIKELY(NULL == pool)) {
4694ret = OB_ERR_UNEXPECTED;
4695LOG_WARN("pool is null", K(ret));
4696} else if (OB_UNLIKELY(OB_INVALID_ID == *pool)) {
4697ret = OB_INVALID_ARGUMENT;
4698LOG_WARN("invalid argument", KR(ret));
4699} else if (OB_FAIL(inner_get_unit_infos_of_pool_(*pool, unit_array))) {
4700LOG_WARN("fail to get unit infos of pool", K(ret));
4701} else if (unit_array.count() > 0) {
4702FOREACH_X(u, unit_array, OB_SUCCESS == ret) {
4703if (OB_UNLIKELY(NULL == u)) {
4704ret = OB_ERR_UNEXPECTED;
4705LOG_WARN("empty is null", K(ret));
4706} else if (!has_exist_in_array(tenant_zone_list, u->unit_.zone_)) {
4707// this unit do not in tenant zone list, ignore
4708} else if (OB_FAIL(unit_infos.push_back(*u))) {
4709LOG_WARN("fail to push back", K(ret));
4710} else {} // no more to do
4711}
4712} else {} // do nothing
4713}
4714}
4715return ret;
4716}
4717
4718int ObUnitManager::commit_shrink_tenant_resource_pool(const uint64_t tenant_id)
4719{
4720int ret = OB_SUCCESS;
4721SpinWLockGuard guard(lock_);
4722common::ObMySQLTransaction trans;
4723common::ObArray<share::ObResourcePool *> *pools = nullptr;
4724common::ObArray<common::ObArray<uint64_t>> resource_units;
4725
4726if (!check_inner_stat()) {
4727ret = OB_INNER_STAT_ERROR;
4728LOG_WARN("check_inner_stat failed", KR(ret), K(loaded_), K(inited_));
4729} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
4730ret = OB_INVALID_ARGUMENT;
4731LOG_WARN("invalid argument", KR(ret), K(tenant_id));
4732} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
4733LOG_WARN("failed to get pool by tenant", KR(ret), K(tenant_id));
4734} else if (OB_UNLIKELY(NULL == pools)) {
4735ret = OB_ERR_UNEXPECTED;
4736LOG_WARN("pool ptr is null", KR(ret), KP(pools));
4737} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
4738LOG_WARN("start transaction failed", KR(ret));
4739} else if (OB_FAIL(commit_shrink_resource_pool_in_trans_(*pools, trans, resource_units))) {
4740LOG_WARN("failed to shrink in trans", KR(ret), KPC(pools));
4741}
4742const bool commit = (OB_SUCCESS == ret);
4743int tmp_ret = OB_SUCCESS;
4744if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
4745LOG_WARN("trans end failed", K(tmp_ret), K(commit));
4746ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
4747}
4748if (OB_SUCC(ret)) {
4749if (OB_UNLIKELY(pools->count() != resource_units.count())) {
4750ret = OB_ERR_UNEXPECTED;
4751LOG_WARN("pools count must equal to unit count", KR(ret), KPC(pools), K(resource_units));
4752}
4753for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
4754share::ObResourcePool *pool = pools->at(i);
4755if (OB_ISNULL(pool)) {
4756ret = OB_ERR_UNEXPECTED;
4757LOG_WARN("pool is null", KR(ret), K(i), KPC(pools));
4758} else if (OB_FAIL(delete_inmemory_units(pool->resource_pool_id_, resource_units.at(i)))) {
4759LOG_WARN("failed to delete inmemory units", KR(ret), KPC(pool), K(i), K(resource_units));
4760}
4761}
4762}
4763return ret;
4764}
4765
4766int ObUnitManager::commit_shrink_resource_pool_in_trans_(
4767const common::ObIArray<share::ObResourcePool *> &pools,
4768common::ObMySQLTransaction &trans,
4769common::ObIArray<common::ObArray<uint64_t>> &resource_units)
4770{
4771int ret = OB_SUCCESS;
4772ObArray<ObUnit *> *units = NULL;
4773if (!check_inner_stat()) {
4774ret = OB_INNER_STAT_ERROR;
4775LOG_WARN("check_inner_stat failed", KR(ret), K(loaded_), K(inited_));
4776} else if (OB_UNLIKELY(0 == pools.count())) {
4777ret = OB_INVALID_ARGUMENT;
4778LOG_WARN("pool ptr is null", KR(ret), K(pools));
4779} else {
4780for (int64_t index = 0; OB_SUCC(ret) && index < pools.count(); ++index) {
4781// Commit shrink resource pool only needs to change the state of the unit,
4782// the state of the resource pool itself has been changed before,
4783// and there is no need to adjust it again.
4784units = NULL;
4785share::ObResourcePool *pool = pools.at(index);
4786if (OB_ISNULL(pool)) {
4787ret = OB_ERR_UNEXPECTED;
4788LOG_WARN("pool is null", KR(ret), K(index), K(pools));
4789} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
4790LOG_WARN("failed to get pool unit", KR(ret), KPC(pool));
4791} else if (OB_ISNULL(units)) {
4792ret = OB_ERR_UNEXPECTED;
4793LOG_WARN("units is null of the pool", KR(ret), KPC(pool));
4794} else {
4795common::ObArray<uint64_t> unit_ids;
4796const int64_t unit_count = pool->unit_count_;
4797if (unit_count <= 0) {
4798ret = OB_ERR_UNEXPECTED;
4799LOG_WARN("unit count unexpected", KR(ret), K(unit_count));
4800} else if (units->count() <= 0) {
4801ret = OB_ERR_UNEXPECTED;
4802LOG_WARN("zone unit ptrs has no element", KR(ret), "unit_cnt",
4803units->count());
4804} else {
4805for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
4806const ObUnit *unit = units->at(i);
4807if (OB_ISNULL(unit)) {
4808ret = OB_ERR_UNEXPECTED;
4809LOG_WARN("unit ptr is null", KR(ret), KP(unit), K(i), KPC(units));
4810} else if (ObUnit::UNIT_STATUS_DELETING == unit->status_) {
4811if (OB_FAIL(ut_operator_.remove_unit(trans, *unit))) {
4812LOG_WARN("fail to remove unit", KR(ret), "unit", *unit);
4813} else if (OB_FAIL(unit_ids.push_back(unit->unit_id_))) {
4814LOG_WARN("fail to push back", KR(ret), KPC(unit));
4815} else {} // no more to do
4816} else {} // active unit, do nothing
4817}// end for each unit
4818if (FAILEDx(resource_units.push_back(unit_ids))) {
4819LOG_WARN("failed to push back units", KR(ret), K(unit_ids));
4820}
4821}
4822}
4823}//end for each pool
4824}
4825return ret;
4826}
4827
4828int ObUnitManager::get_deleting_units_of_pool(
4829const uint64_t resource_pool_id,
4830ObIArray<share::ObUnit> &units) const
4831{
4832int ret = OB_SUCCESS;
4833SpinRLockGuard guard(lock_);
4834ObArray<ObUnit *> *inner_units = NULL;
4835if (!check_inner_stat()) {
4836ret = OB_INNER_STAT_ERROR;
4837LOG_WARN("check_inner_stat failed", K(ret), K(loaded_), K(inited_));
4838} else if (OB_UNLIKELY(OB_INVALID_ID == resource_pool_id)) {
4839ret = OB_INVALID_ARGUMENT;
4840LOG_WARN("invalid argument", K(ret), K(resource_pool_id));
4841} else if (OB_FAIL(get_units_by_pool(resource_pool_id, inner_units))) {
4842LOG_WARN("fail to get units by pool", K(ret), K(resource_pool_id));
4843} else if (NULL == inner_units) {
4844ret = OB_ERR_UNEXPECTED;
4845LOG_WARN("inner_units ptr is null", K(ret), KP(inner_units));
4846} else {
4847units.reset();
4848for (int64_t i = 0; OB_SUCC(ret) && i < inner_units->count(); ++i) {
4849const share::ObUnit *this_unit = inner_units->at(i);
4850if (NULL == this_unit) {
4851ret = OB_ERR_UNEXPECTED;
4852LOG_WARN("unit ptr is null", K(ret), KP(this_unit));
4853} else if (ObUnit::UNIT_STATUS_DELETING == this_unit->status_) {
4854if (OB_FAIL(units.push_back(*this_unit))) {
4855LOG_WARN("fail to push back", K(ret));
4856} else {} // no more to do
4857} else if (ObUnit::UNIT_STATUS_ACTIVE == this_unit->status_) {
4858// a normal unit, ignore
4859} else {
4860ret = OB_ERR_UNEXPECTED;
4861LOG_WARN("unexpected unit status", K(ret), "unit_status", this_unit->status_);
4862}
4863}
4864LOG_INFO("get deleting units of pool", K(ret), K(resource_pool_id), K(units));
4865}
4866return ret;
4867}
4868
4869int ObUnitManager::get_unit_infos_of_pool(const uint64_t resource_pool_id,
4870ObIArray<ObUnitInfo> &unit_infos) const
4871{
4872int ret = OB_SUCCESS;
4873SpinRLockGuard guard(lock_);
4874if (!check_inner_stat()) {
4875ret = OB_INNER_STAT_ERROR;
4876LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4877} else if (OB_INVALID_ID == resource_pool_id) {
4878ret = OB_INVALID_ARGUMENT;
4879LOG_WARN("invalid argument", K(resource_pool_id), K(ret));
4880} else if (OB_FAIL(inner_get_unit_infos_of_pool_(resource_pool_id, unit_infos))) {
4881LOG_WARN("inner_get_unit_infos_of_pool failed", K(resource_pool_id), K(ret));
4882}
4883return ret;
4884}
4885
4886int ObUnitManager::inner_get_unit_infos_of_pool_(const uint64_t resource_pool_id,
4887ObIArray<ObUnitInfo> &unit_infos) const
4888{
4889int ret = OB_SUCCESS;
4890if (!check_inner_stat()) {
4891ret = OB_INNER_STAT_ERROR;
4892LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4893} else if (OB_INVALID_ID == resource_pool_id) {
4894ret = OB_INVALID_ARGUMENT;
4895LOG_WARN("invalid argument", K(resource_pool_id), K(ret));
4896} else {
4897unit_infos.reuse();
4898ObUnitInfo unit_info;
4899share::ObResourcePool *pool = NULL;
4900ObUnitConfig *config = NULL;
4901if (OB_FAIL(get_resource_pool_by_id(resource_pool_id, pool))) {
4902if (OB_ENTRY_NOT_EXIST == ret) {
4903ret = OB_RESOURCE_POOL_NOT_EXIST;
4904}
4905LOG_WARN("get_resource_pool_by_id failed", K(resource_pool_id), K(ret));
4906} else if (NULL == pool) {
4907ret = OB_ERR_UNEXPECTED;
4908LOG_WARN("pool is null", KP(pool), K(ret));
4909} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, config))) {
4910if (OB_ENTRY_NOT_EXIST == ret) {
4911ret = OB_RESOURCE_UNIT_NOT_EXIST;
4912}
4913LOG_WARN("get_unit_config_by_id failed", "unit config id", pool->unit_config_id_, K(ret));
4914} else if (NULL == config) {
4915ret = OB_ERR_UNEXPECTED;
4916LOG_WARN("config is null", KP(config), K(ret));
4917} else {
4918unit_info.reset();
4919if (OB_FAIL(unit_info.pool_.assign(*pool))) {
4920LOG_WARN("failed to assign unit_info.pool_", K(ret));
4921} else {
4922unit_info.config_ = *config;
4923ObArray<ObUnit *> *units = NULL;
4924if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
4925LOG_WARN("get_units_by_pool failed", K(resource_pool_id), K(ret));
4926} else if (NULL == units) {
4927ret = OB_ERR_UNEXPECTED;
4928LOG_WARN("units is null", KP(units), K(ret));
4929} else if (units->count() <= 0) {
4930ret = OB_ENTRY_NOT_EXIST;
4931LOG_WARN("units of resource pool not exist", K(resource_pool_id), K(ret));
4932} else if (OB_FAIL(unit_infos.reserve(units->count()))) {
4933LOG_WARN("failed to reserve for unit_infos", KR(ret));
4934} else {
4935for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
4936if (NULL == units->at(i)) {
4937ret = OB_ERR_UNEXPECTED;
4938LOG_WARN("unit is null", "unit", OB_P(units->at(i)), K(ret));
4939} else {
4940unit_info.unit_ = *units->at(i);
4941if (OB_FAIL(unit_infos.push_back(unit_info))) {
4942LOG_WARN("push_back failed", K(ret));
4943}
4944}
4945}
4946}
4947}
4948}
4949}
4950return ret;
4951}
4952
4953int ObUnitManager::inner_get_unit_info_by_id(const uint64_t unit_id, ObUnitInfo &unit_info) const
4954{
4955int ret = OB_SUCCESS;
4956if (!check_inner_stat()) {
4957ret = OB_INNER_STAT_ERROR;
4958LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
4959} else if (OB_INVALID_ID == unit_id) {
4960ret = OB_INVALID_ARGUMENT;
4961LOG_WARN("invalid argument", K(unit_id), K(ret));
4962} else {
4963ObUnit *unit = NULL;
4964ObUnitConfig *config = NULL;
4965share::ObResourcePool *pool = NULL;
4966if (OB_FAIL(get_unit_by_id(unit_id, unit))) {
4967LOG_WARN("get_unit_by_id failed", K(unit_id), K(ret));
4968} else if (NULL == unit) {
4969ret = OB_ERR_UNEXPECTED;
4970LOG_WARN("unit is null", KP(unit), K(ret));
4971} else if (OB_FAIL(get_resource_pool_by_id(unit->resource_pool_id_, pool))) {
4972if (OB_ENTRY_NOT_EXIST == ret) {
4973ret = OB_RESOURCE_POOL_NOT_EXIST;
4974}
4975LOG_WARN("get_resource_pool_by_id failed", "pool id", unit->resource_pool_id_, K(ret));
4976} else if (NULL == pool) {
4977ret = OB_ERR_UNEXPECTED;
4978LOG_WARN("pool is null", KP(pool), K(ret));
4979} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, config))) {
4980if (OB_ENTRY_NOT_EXIST == ret) {
4981ret = OB_RESOURCE_UNIT_NOT_EXIST;
4982}
4983LOG_WARN("get_unit_config_by_id failed", "unit config id", pool->unit_config_id_, K(ret));
4984} else if (NULL == config) {
4985ret = OB_ERR_UNEXPECTED;
4986LOG_WARN("config is null", KP(config), K(ret));
4987} else {
4988if (OB_FAIL(unit_info.pool_.assign(*pool))) {
4989LOG_WARN("failed to assign unit_info.pool_", K(ret));
4990} else {
4991unit_info.unit_ = *unit;
4992unit_info.config_ = *config;
4993}
4994}
4995}
4996return ret;
4997}
4998
4999int ObUnitManager::extract_unit_ids(
5000const common::ObIArray<share::ObUnit *> &units,
5001common::ObIArray<uint64_t> &unit_ids)
5002{
5003int ret = OB_SUCCESS;
5004unit_ids.reset();
5005for (int64_t i = 0; OB_SUCC(ret) && i < units.count(); ++i) {
5006if (OB_UNLIKELY(NULL == units.at(i))) {
5007ret = OB_ERR_UNEXPECTED;
5008LOG_WARN("unit ptr is null", K(ret));
5009} else if (OB_FAIL(unit_ids.push_back(units.at(i)->unit_id_))) {
5010LOG_WARN("fail to push back", K(ret));
5011} else {} // no more to do
5012}
5013return ret;
5014}
5015
5016int ObUnitManager::inner_get_unit_ids(ObIArray<uint64_t> &unit_ids) const
5017{
5018int ret = OB_SUCCESS;
5019if (!check_inner_stat()) {
5020ret = OB_INNER_STAT_ERROR;
5021LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5022}
5023for (ObHashMap<uint64_t, ObArray<ObUnit *> *>::const_iterator it = pool_unit_map_.begin();
5024OB_SUCCESS == ret && it != pool_unit_map_.end(); ++it) {
5025if (NULL == it->second) {
5026ret = OB_ERR_UNEXPECTED;
5027LOG_ERROR("pointer of ObArray<ObUnit *> is null", "pool_id", it->first, K(ret));
5028} else if (it->second->count() <= 0) {
5029ret = OB_ERR_UNEXPECTED;
5030LOG_ERROR("array of unit is empty", "pool_id", it->first, K(ret));
5031} else {
5032const ObArray<ObUnit *> units = *it->second;
5033for (int64_t i = 0; OB_SUCC(ret) && i < units.count(); ++i) {
5034uint64_t unit_id = units.at(i)->unit_id_;
5035if (OB_FAIL(unit_ids.push_back(unit_id))) {
5036LOG_WARN("fail push back it", K(unit_id), K(ret));
5037}
5038}
5039}
5040}
5041return ret;
5042}
5043
5044int ObUnitManager::get_unit_ids(ObIArray<uint64_t> &unit_ids) const
5045{
5046int ret = OB_SUCCESS;
5047SpinRLockGuard guard(lock_);
5048if (OB_FAIL(inner_get_unit_ids(unit_ids))) {
5049LOG_WARN("fail to inner get unit ids", K(ret));
5050}
5051return ret;
5052}
5053
5054int ObUnitManager::calc_sum_load(const ObArray<ObUnitLoad> *unit_loads,
5055ObUnitConfig &sum_load)
5056{
5057int ret = OB_SUCCESS;
5058sum_load.reset();
5059if (NULL == unit_loads) {
5060// all be zero
5061} else {
5062for (int64_t i = 0; OB_SUCC(ret) && i < unit_loads->count(); ++i) {
5063if (!unit_loads->at(i).is_valid()) {
5064ret = OB_INVALID_ARGUMENT;
5065LOG_WARN("invalid unit_load", "unit_load", unit_loads->at(i), K(ret));
5066} else {
5067sum_load += *unit_loads->at(i).unit_config_;
5068}
5069}
5070}
5071return ret;
5072}
5073
5074int ObUnitManager::check_resource_pool(
5075share::ObResourcePool &resource_pool,
5076const bool is_clone_tenant) const
5077{
5078int ret = OB_SUCCESS;
5079if (!check_inner_stat()) {
5080ret = OB_INNER_STAT_ERROR;
5081LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5082} else if (resource_pool.name_.is_empty()) {
5083ret = OB_INVALID_ARGUMENT;
5084LOG_USER_ERROR(OB_INVALID_ARGUMENT, "resource pool name");
5085LOG_WARN("invalid resource pool name", "resource pool name", resource_pool.name_, K(ret));
5086} else if (resource_pool.unit_count_ <= 0) {
5087ret = OB_INVALID_ARGUMENT;
5088LOG_USER_ERROR(OB_INVALID_ARGUMENT, "unit num");
5089LOG_WARN("invalid resource unit num", "unit num", resource_pool.unit_count_, K(ret));
5090} else {
5091// check zones in zone_list not intersected
5092for (int64_t i = 0; OB_SUCC(ret) && i < resource_pool.zone_list_.count(); ++i) {
5093for (int64_t j = i + 1; OB_SUCC(ret) && j < resource_pool.zone_list_.count(); ++j) {
5094if (resource_pool.zone_list_[i] == resource_pool.zone_list_[j]) {
5095ret = OB_ZONE_DUPLICATED;
5096LOG_USER_ERROR(OB_ZONE_DUPLICATED, to_cstring(resource_pool.zone_list_[i]),
5097to_cstring(resource_pool.zone_list_));
5098LOG_WARN("duplicate zone in zone list", "zone_list", resource_pool.zone_list_, K(ret));
5099}
5100}
5101}
5102// check zones in zone_list all existed
5103if (OB_SUCC(ret)) {
5104FOREACH_CNT_X(zone, resource_pool.zone_list_, OB_SUCCESS == ret) {
5105bool zone_exist = false;
5106if (OB_FAIL(zone_mgr_.check_zone_exist(*zone, zone_exist))) {
5107LOG_WARN("check_zone_exist failed", KPC(zone), K(ret));
5108} else if (!zone_exist) {
5109ret = OB_ZONE_INFO_NOT_EXIST;
5110LOG_USER_ERROR(OB_ZONE_INFO_NOT_EXIST, to_cstring(*zone));
5111LOG_WARN("zone not exist", "zone", *zone, K(ret));
5112}
5113}
5114}
5115// construct all zone as zone_list if zone_list is null
5116if (OB_SUCCESS == ret && 0 == resource_pool.zone_list_.count()) {
5117ObArray<ObZoneInfo> zone_infos;
5118if (OB_FAIL(zone_mgr_.get_zone(zone_infos))) {
5119LOG_WARN("get_zone failed", K(ret));
5120} else {
5121FOREACH_CNT_X(zone_info, zone_infos, OB_SUCCESS == ret) {
5122if (OB_FAIL(resource_pool.zone_list_.push_back(zone_info->zone_))) {
5123LOG_WARN("push_back failed", K(ret));
5124}
5125}
5126if (OB_SUCCESS == ret && resource_pool.zone_list_.count() <= 0) {
5127ret = OB_ERR_UNEXPECTED;
5128LOG_WARN("not active zone found", K(ret));
5129}
5130}
5131}
5132// check zones in zone_list has enough alive servers to support unit_num
5133// ATTENTION:
5134// There is a limit that we have to persist all unit config successfully before create tenant.
5135// For clone tenant, the locations of units to create is certain.
5136// If majority of servers is down, clone tenant will fail, and this case can be detected before persist unit.
5137// So for clone tenant, just skip this check, just make sure majority of teannt snapshot can restored is ok.
5138if (!is_clone_tenant) {
5139FOREACH_CNT_X(zone, resource_pool.zone_list_, OB_SUCCESS == ret) {
5140int64_t alive_server_count = 0;
5141if (OB_FAIL(SVR_TRACER.get_alive_servers_count(*zone, alive_server_count))) {
5142LOG_WARN("get_alive_servers failed", KR(ret), KPC(zone));
5143} else if (alive_server_count < resource_pool.unit_count_) {
5144ret = OB_UNIT_NUM_OVER_SERVER_COUNT;
5145LOG_WARN("resource pool unit num over zone server count", "unit_count",
5146resource_pool.unit_count_, K(alive_server_count), K(ret), "zone", *zone);
5147}
5148}
5149}
5150}
5151return ret;
5152}
5153
5154int ObUnitManager::allocate_new_pool_units_(
5155ObISQLClient &client,
5156const share::ObResourcePool &pool,
5157const char *module)
5158{
5159int ret = OB_SUCCESS;
5160if (!check_inner_stat()) {
5161ret = OB_INNER_STAT_ERROR;
5162LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5163} else if (!pool.is_valid() || pool.zone_list_.count() <= 0) {
5164ret = OB_INVALID_ARGUMENT;
5165LOG_WARN("invalid pool", K(pool), K(ret));
5166} else {
5167const bool new_allocate_pool = true;
5168const int64_t delta_unit_num = pool.unit_count_;
5169ObArray<ObAddr> new_servers;
5170if (OB_FAIL(allocate_pool_units_(
5171client, pool, pool.zone_list_, nullptr, new_allocate_pool, delta_unit_num, module, new_servers))) {
5172LOG_WARN("allocate pool units failed", K(module), KR(ret), K(delta_unit_num), K(pool));
5173}
5174}
5175return ret;
5176}
5177
5178/* Notify creating or dropping unit on ObServer.
5179* 1. Specify @is_delete as true when dropping unit,
5180* and only @tenant_id and @unit will be used in this case.
5181* 2. This function merely sends RPC call, so executor should make sure waiting is called later.
5182* But there is one exception that when @unit is on this server where RS Leader locates,
5183* notification will be locally executed without RPC, which means no need to wait proxy.
5184*/
5185int ObUnitManager::try_notify_tenant_server_unit_resource_(
5186const uint64_t tenant_id,
5187const bool is_delete,
5188ObNotifyTenantServerResourceProxy ¬ify_proxy,
5189const uint64_t unit_config_id,
5190const lib::Worker::CompatMode compat_mode,
5191const share::ObUnit &unit,
5192const bool if_not_grant,
5193const bool skip_offline_server,
5194const bool check_data_version)
5195{
5196int ret = OB_SUCCESS;
5197bool is_alive = false;
5198if (!check_inner_stat()) {
5199ret = OB_INNER_STAT_ERROR;
5200LOG_WARN("check_inner_stat failed", K(ret), K(inited_), K(loaded_));
5201} else if (OB_FAIL(SVR_TRACER.check_server_alive(unit.server_, is_alive))) {
5202LOG_WARN("fail to get server_info", KR(ret), K(unit.server_));
5203} else if (!is_alive && (is_delete || skip_offline_server)) {
5204// do nothing
5205LOG_INFO("ignore not alive server when is_delete or skip_offline_server is true",
5206"server", unit.server_, K(is_delete), K(skip_offline_server));
5207} else if (!is_valid_tenant_id(tenant_id)) {
5208// do nothing, unit not granted
5209} else {
5210// STEP 1: Get and init notifying arg
5211obrpc::TenantServerUnitConfig tenant_unit_server_config;
5212if (!is_delete) {
5213const bool should_check_data_version = check_data_version && is_user_tenant(tenant_id);
5214if (OB_FAIL(build_notify_create_unit_resource_rpc_arg_(
5215tenant_id, unit, compat_mode, unit_config_id, if_not_grant,
5216tenant_unit_server_config))) {
5217LOG_WARN("fail to init tenant_unit_server_config", KR(ret), K(tenant_id), K(is_delete));
5218} else if (should_check_data_version
5219&& OB_FAIL(check_dest_data_version_is_loaded_(tenant_id, unit.server_))) {
5220LOG_WARN("fail to check dest data_version is loaded", KR(ret), K(tenant_id), "dst", unit.server_);
5221}
5222} else {
5223if (OB_FAIL(tenant_unit_server_config.init_for_dropping(tenant_id, is_delete))) {
5224LOG_WARN("fail to init tenant_unit_server_config", KR(ret), K(tenant_id), K(is_delete));
5225}
5226}
5227
5228// STEP 2: Do notification
5229if (OB_FAIL(ret)) {
5230} else if (OB_FAIL(do_notify_unit_resource_(
5231unit.server_, tenant_unit_server_config, notify_proxy))) {
5232LOG_WARN("failed to do_notify_unit_resource", "dst", unit.server_, K(tenant_unit_server_config));
5233if (OB_TENANT_EXIST == ret) {
5234ret = OB_TENANT_RESOURCE_UNIT_EXIST;
5235LOG_USER_ERROR(OB_TENANT_RESOURCE_UNIT_EXIST, tenant_id, to_cstring(unit.server_));
5236}
5237}
5238}
5239return ret;
5240}
5241
5242int ObUnitManager::check_dest_data_version_is_loaded_(
5243const uint64_t tenant_id, const ObAddr &addr)
5244{
5245int ret = OB_SUCCESS;
5246ObTimeoutCtx ctx;
5247const int64_t DEFTAULT_TIMEOUT_TS = 5 * GCONF.rpc_timeout;
5248char ip_buf[OB_IP_STR_BUFF] = "";
5249if (OB_UNLIKELY(!check_inner_stat())) {
5250ret = OB_INNER_STAT_ERROR;
5251LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
5252} else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
5253|| !addr.is_valid()
5254|| OB_ISNULL(proxy_))) {
5255ret = OB_INVALID_ARGUMENT;
5256LOG_WARN("invalid arg", KR(ret), K(tenant_id), K(addr), KP_(proxy));
5257} else if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, DEFTAULT_TIMEOUT_TS))) {
5258LOG_WARN("fail to set default timeout ctx", KR(ret));
5259} else if (OB_UNLIKELY(!addr.ip_to_string(ip_buf, sizeof(ip_buf)))) {
5260ret = OB_ERR_UNEXPECTED;
5261LOG_WARN("fail to convert ip to string", KR(ret), K(tenant_id), K(addr));
5262} else {
5263const int64_t start_timeout_ts = ObTimeUtility::current_time();
5264const int64_t CHECK_INTERVAL_TS = 500 * 1000L; // 500ms
5265const int64_t SLEEP_TS = 100 * 1000L; // 100ms
5266ObSqlString sql;
5267if (OB_FAIL(sql.assign_fmt("SELECT IF(value = '0.0.0.0', 0, 1) AS loaded "
5268"FROM %s WHERE tenant_id = %lu AND name = 'compatible' "
5269"AND svr_ip = '%s' AND svr_port = %d",
5270OB_ALL_VIRTUAL_TENANT_PARAMETER_INFO_TNAME,
5271tenant_id, ip_buf, addr.get_port()))) {
5272LOG_WARN("fail to assign fmt", KR(ret), K(tenant_id), K(addr));
5273}
5274while (OB_SUCC(ret)) {
5275if (OB_UNLIKELY(ctx.is_timeouted())) {
5276ret = OB_TIMEOUT;
5277LOG_WARN("check dest data version timeout", KR(ret),
5278K(start_timeout_ts), "abs_timeout", ctx.get_abs_timeout());
5279} else {
5280SMART_VAR(ObMySQLProxy::MySQLResult, res) {
5281sqlclient::ObMySQLResult *result = NULL;
5282if (OB_FAIL(proxy_->read(res, OB_SYS_TENANT_ID, sql.ptr()))) {
5283LOG_WARN("fail to read by sql", KR(ret), K(sql));
5284} else if (OB_ISNULL(result = res.get_result())) {
5285ret = OB_ERR_UNEXPECTED;
5286LOG_WARN("result is null", KR(ret));
5287} else if (OB_FAIL(result->next())) {
5288if (OB_ITER_END == ret) {
5289ret = OB_SUCCESS;
5290if (REACH_TIME_INTERVAL(CHECK_INTERVAL_TS)) {
5291LOG_WARN_RET(OB_EAGAIN, "check data_version is loaded, but result is empty, try later",
5292K(tenant_id), K(addr));
5293}
5294} else {
5295LOG_WARN("fail to get next row", KR(ret));
5296}
5297} else {
5298int64_t loaded = 0;
5299EXTRACT_INT_FIELD_MYSQL(*result, "loaded", loaded, int64_t);
5300if (OB_SUCC(ret)) {
5301if (1 == loaded) {
5302break;
5303} else if (REACH_TIME_INTERVAL(CHECK_INTERVAL_TS))
5304LOG_WARN_RET(OB_EAGAIN, "check data_version is loaded, but it's not refreshed yet, try later",
5305K(tenant_id), K(addr));
5306}
5307}
5308} // end SMART_VAR
5309
5310if (OB_SUCC(ret)) {
5311ob_usleep(SLEEP_TS);
5312}
5313}
5314} // end while
5315}
5316return ret;
5317}
5318
5319int ObUnitManager::build_notify_create_unit_resource_rpc_arg_(
5320const uint64_t tenant_id,
5321const share::ObUnit &unit,
5322const lib::Worker::CompatMode compat_mode,
5323const uint64_t unit_config_id,
5324const bool if_not_grant,
5325obrpc::TenantServerUnitConfig &rpc_arg) const
5326{
5327int ret = OB_SUCCESS;
5328// get unit_config
5329share::ObUnitConfig *unit_config = nullptr;
5330if (OB_FAIL(get_unit_config_by_id(unit_config_id, unit_config))) {
5331LOG_WARN("fail to get unit config by id", KR(ret));
5332} else if (OB_ISNULL(unit_config)) {
5333ret = OB_ERR_UNEXPECTED;
5334LOG_WARN("unit config is null", KR(ret), "unit_config_id", unit_config_id);
5335}
5336
5337#ifdef OB_BUILD_TDE_SECURITY
5338// get root_key
5339obrpc::ObRootKeyResult root_key;
5340obrpc::ObRootKeyArg get_rootkey_arg;
5341if (OB_FAIL(ret)) {
5342// do nothing
5343} else if (OB_ISNULL(root_service_)) {
5344ret = OB_ERR_UNEXPECTED;
5345LOG_WARN("root_service_ is nullptr", KR(ret), KP(root_service_));
5346} else if (OB_FAIL(get_rootkey_arg.init_for_get(tenant_id))) {
5347LOG_WARN("failed to init get_root_key arg", KR(ret), K(tenant_id));
5348} else if (OB_FAIL(root_service_->handle_get_root_key(get_rootkey_arg, root_key))) {
5349LOG_WARN("fail to get root_key", KR(ret), K(get_rootkey_arg));
5350}
5351#endif
5352
5353// init rpc_arg
5354const bool is_delete = false;
5355if (OB_FAIL(ret)) {
5356} else if (OB_FAIL(rpc_arg.init(tenant_id,
5357unit.unit_id_,
5358compat_mode,
5359*unit_config,
5360ObReplicaType::REPLICA_TYPE_FULL,
5361if_not_grant,
5362is_delete
5363#ifdef OB_BUILD_TDE_SECURITY
5364, root_key
5365#endif
5366))) {
5367LOG_WARN("fail to init rpc_arg", KR(ret), K(tenant_id), K(is_delete));
5368}
5369return ret;
5370}
5371
5372int ObUnitManager::do_notify_unit_resource_(
5373const common::ObAddr server,
5374const obrpc::TenantServerUnitConfig ¬ify_arg,
5375ObNotifyTenantServerResourceProxy ¬ify_proxy)
5376{
5377int ret = OB_SUCCESS;
5378if (GCONF.self_addr_ == server) {
5379// Directly call local interface without using RPC
5380if (OB_FAIL(omt::ObTenantNodeBalancer::get_instance().handle_notify_unit_resource(notify_arg))) {
5381LOG_WARN("fail to handle_notify_unit_resource", K(ret), K(notify_arg));
5382} else {
5383LOG_INFO("call notify resource to server (locally)", KR(ret), "dst", server, K(notify_arg));
5384}
5385} else {
5386int64_t start = ObTimeUtility::current_time();
5387int64_t rpc_timeout = NOTIFY_RESOURCE_RPC_TIMEOUT;
5388if (INT64_MAX != THIS_WORKER.get_timeout_ts()) {
5389rpc_timeout = max(rpc_timeout, THIS_WORKER.get_timeout_remain());
5390}
5391if (OB_FAIL(notify_proxy.call(server, rpc_timeout, notify_arg))) {
5392LOG_WARN("fail to call notify resource to server", KR(ret), K(rpc_timeout),
5393"dst", server, "cost", ObTimeUtility::current_time() - start);
5394} else {
5395LOG_INFO("call notify resource to server", KR(ret), "dst", server, K(notify_arg),
5396"cost", ObTimeUtility::current_time() - start);
5397}
5398}
5399return ret;
5400}
5401
5402int ObUnitManager::rollback_persistent_units_(
5403const common::ObArray<share::ObUnit> &units,
5404const share::ObResourcePool &pool,
5405ObNotifyTenantServerResourceProxy ¬ify_proxy)
5406{
5407int ret = OB_SUCCESS;
5408int tmp_ret = OB_SUCCESS;
5409const bool is_delete = true;
5410ObArray<int> return_ret_array;
5411notify_proxy.reuse();
5412for (int64_t i = 0; i < units.count(); i++) {
5413const ObUnit & unit = units.at(i);
5414const lib::Worker::CompatMode dummy_mode = lib::Worker::CompatMode::INVALID;
5415if (OB_TMP_FAIL(try_notify_tenant_server_unit_resource_(
5416pool.tenant_id_, is_delete, notify_proxy,
5417pool.unit_config_id_, dummy_mode, unit,
5418false/*if_not_grant*/, false/*skip_offline_server*/,
5419false /*check_data_version*/))) {
5420ret = OB_SUCC(ret) ? tmp_ret : ret;
5421LOG_WARN("fail to try notify server unit resource", KR(ret), KR(tmp_ret),
5422K(is_delete), K(pool), K(dummy_mode), K(unit));
5423}
5424}
5425if (OB_TMP_FAIL(notify_proxy.wait_all(return_ret_array))) {
5426LOG_WARN("fail to wait notify resource", KR(ret), K(tmp_ret));
5427ret = OB_SUCC(ret) ? tmp_ret : ret;
5428} else if (OB_FAIL(ret)) {
5429} else {
5430// don't use arg/dest/result here because call() may has failure.
5431ObAddr invalid_addr;
5432for (int64_t i = 0; OB_SUCC(ret) && i < return_ret_array.count(); i++) {
5433const int ret_i = return_ret_array.at(i);
5434const ObAddr &addr = return_ret_array.count() != notify_proxy.get_dests().count() ?
5435invalid_addr : notify_proxy.get_dests().at(i);
5436// if (OB_SUCCESS != ret_i && OB_TENANT_NOT_IN_SERVER != ret_i) {
5437if (OB_SUCCESS != ret_i && OB_TENANT_NOT_IN_SERVER != ret_i) {
5438ret = ret_i;
5439LOG_WARN("fail to mark tenant removed", KR(ret), KR(ret_i), K(addr));
5440}
5441}
5442}
5443LOG_WARN("rollback persistent unit", KR(ret), K(pool), K(units));
5444return ret;
5445}
5446
5447int ObUnitManager::get_tenant_unit_servers(
5448const uint64_t tenant_id,
5449const common::ObZone &zone,
5450common::ObIArray<common::ObAddr> &server_array) const
5451{
5452int ret = OB_SUCCESS;
5453ObArray<share::ObResourcePool *> *pools = nullptr;
5454if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
5455ret = OB_INVALID_ARGUMENT;
5456LOG_WARN("invalid argument", K(ret), K(tenant_id));
5457} else {
5458server_array.reset();
5459int tmp_ret = get_pools_by_tenant_(tenant_id, pools);
5460if (OB_ENTRY_NOT_EXIST == tmp_ret) {
5461// pass, and return empty server array
5462} else if (OB_SUCCESS != tmp_ret) {
5463ret = tmp_ret;
5464LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
5465} else if (nullptr == pools) {
5466ret = OB_ERR_UNEXPECTED;
5467LOG_WARN("pools ptr is null, unexpected", K(ret), K(tenant_id));
5468} else {
5469common::ObArray<common::ObAddr> this_server_array;
5470for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
5471this_server_array.reset();
5472const share::ObResourcePool *pool = pools->at(i);
5473if (OB_UNLIKELY(nullptr == pool)) {
5474ret = OB_ERR_UNEXPECTED;
5475LOG_WARN("pool ptr is null", K(ret), K(tenant_id));
5476} else if (OB_FAIL(get_pool_servers(
5477pool->resource_pool_id_, zone, this_server_array))) {
5478LOG_WARN("fail to get pool server", K(ret),
5479"pool_id", pool->resource_pool_id_, K(zone));
5480} else if (OB_FAIL(append(server_array, this_server_array))) {
5481LOG_WARN("fail to append", K(ret));
5482}
5483}
5484}
5485}
5486return ret;
5487}
5488ERRSIM_POINT_DEF(ERRSIM_UNIT_PERSISTENCE_ERROR);
5489
5490// allocate unit on target zones for specified resource pool
5491//
5492// @param [in] client SQL client
5493// @param [in] pool resource pool which new allocated units belong to
5494// @param [in] zones target zones to allocate units
5495// @param [in] unit_group_id_array unit group id array for new allocated units
5496// @param [in] new_allocate_pool whether to allocate new pool
5497// @param [in] increase_delta_unit_num unit number to be increased
5498// @param [in] module module name for print log
5499// @param [out] new_servers allocated servers for new units
5500//
5501// @ret OB_ZONE_RESOURCE_NOT_ENOUGH zone resource not enough to hold all units
5502// @ret OB_ZONE_SERVER_NOT_ENOUGH zone server not enough to hold all units
5503// @ret OB_SUCCESS success
5504int ObUnitManager::allocate_pool_units_(
5505ObISQLClient &client,
5506const share::ObResourcePool &pool,
5507const common::ObIArray<common::ObZone> &zones,
5508common::ObIArray<uint64_t> *unit_group_id_array,
5509const bool new_allocate_pool,
5510const int64_t increase_delta_unit_num,
5511const char *module,
5512ObIArray<ObAddr> &new_servers)
5513{
5514int ret = OB_SUCCESS;
5515ObUnitConfig *config = NULL;
5516lib::Worker::CompatMode compat_mode = lib::Worker::CompatMode::INVALID;
5517ObArray<ObServerInfoInTable> servers_info;
5518ObArray<ObServerInfoInTable> active_servers_info_of_zone;
5519ObArray<obrpc::ObGetServerResourceInfoResult> active_servers_resource_info_of_zone;
5520
5521if (!check_inner_stat()) {
5522ret = OB_INNER_STAT_ERROR;
5523LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5524} else if (!pool.is_valid() || zones.count() <= 0) {
5525ret = OB_INVALID_ARGUMENT;
5526LOG_WARN("invalid resource pool or zones", K(pool), K(zones), KR(ret));
5527} else if (increase_delta_unit_num <= 0) {
5528ret = OB_INVALID_ARGUMENT;
5529LOG_WARN("invalid argument", K(increase_delta_unit_num), K(ret));
5530} else if (nullptr != unit_group_id_array
5531&& unit_group_id_array->count() != increase_delta_unit_num) {
5532ret = OB_INVALID_ARGUMENT;
5533LOG_WARN("new unit group id array status not match",
5534KR(ret), K(increase_delta_unit_num), KP(unit_group_id_array));
5535} else if (OB_ISNULL(srv_rpc_proxy_) || OB_ISNULL(GCTX.sql_proxy_)) {
5536ret = OB_ERR_UNEXPECTED;
5537LOG_WARN("srv_rpc_proxy_ or GCTX.sql_proxy_ is null", KR(ret), KP(srv_rpc_proxy_), KP(GCTX.sql_proxy_));
5538} else if (is_valid_tenant_id(pool.tenant_id_)
5539&& OB_FAIL(ObCompatModeGetter::get_tenant_mode(pool.tenant_id_, compat_mode))) {
5540LOG_WARN("fail to get tenant compat mode", KR(ret), K(pool.tenant_id_));
5541} else if (OB_FAIL(get_unit_config_by_id(pool.unit_config_id_, config))) {
5542LOG_WARN("get_unit_config_by_id failed", "unit_config_id", pool.unit_config_id_, KR(ret));
5543} else if (OB_ISNULL(config)) {
5544ret = OB_ERR_UNEXPECTED;
5545LOG_WARN("config is null", KP(config), K(ret));
5546} else {
5547ObNotifyTenantServerResourceProxy notify_proxy(
5548*srv_rpc_proxy_,
5549&obrpc::ObSrvRpcProxy::notify_tenant_server_unit_resource);
5550
5551ObArray<ObAddr> excluded_servers;
5552ObArray<ObUnit> units;
5553for (int64_t i = 0; OB_SUCC(ret) && i < zones.count(); ++i) { // for each zone
5554const ObZone &zone = zones.at(i);
5555excluded_servers.reuse();
5556active_servers_info_of_zone.reuse();
5557active_servers_resource_info_of_zone.reuse();
5558const bool ONLY_ACTIVE_SERVERS = true;
5559if (FAILEDx(get_excluded_servers(pool.resource_pool_id_, zone, module,
5560new_allocate_pool, excluded_servers))) {
5561LOG_WARN("get excluded servers fail", KR(ret), K(pool.resource_pool_id_), K(zone),
5562K(module), K(new_allocate_pool));
5563} else if (OB_FAIL(ObServerTableOperator::get_servers_info_of_zone(
5564*GCTX.sql_proxy_,
5565zone,
5566ONLY_ACTIVE_SERVERS,
5567active_servers_info_of_zone))) {
5568LOG_WARN("fail to get servers info of zone", KR(ret), K(zone));
5569} else if (OB_FAIL(get_servers_resource_info_via_rpc(
5570active_servers_info_of_zone,
5571active_servers_resource_info_of_zone))) {
5572LOG_WARN("fail to get active_servers_resource_info_of_zone", KR(ret), K(active_servers_info_of_zone));
5573}
5574
5575for (int64_t j = 0; OB_SUCC(ret) && j < increase_delta_unit_num; ++j) {
5576uint64_t unit_id = OB_INVALID_ID;
5577std::string resource_not_enough_reason;
5578ObAddr server;
5579if (OB_FAIL(choose_server_for_unit(
5580config->unit_resource(),
5581zone,
5582excluded_servers,
5583module,
5584active_servers_info_of_zone,
5585active_servers_resource_info_of_zone,
5586server,
5587resource_not_enough_reason))) {
5588LOG_WARN("choose server for unit failed", K(module), KR(ret), "unit_idx", j, K(increase_delta_unit_num),
5589K(zone), K(excluded_servers), KPC(config));
5590// handle return error info
5591if (OB_ZONE_RESOURCE_NOT_ENOUGH == ret) {
5592LOG_USER_ERROR(OB_ZONE_RESOURCE_NOT_ENOUGH,
5593to_cstring(zone), increase_delta_unit_num, resource_not_enough_reason.c_str());
5594} else if (OB_ZONE_SERVER_NOT_ENOUGH == ret) {
5595LOG_USER_ERROR(OB_ZONE_SERVER_NOT_ENOUGH, to_cstring(zone), increase_delta_unit_num);
5596}
5597} else if (OB_FAIL(excluded_servers.push_back(server))) {
5598LOG_WARN("push_back failed", K(ret));
5599} else if (OB_FAIL(try_persist_unit_info_(
5600notify_proxy,
5601client,
5602zone,
5603pool,
5604compat_mode,
5605(nullptr == unit_group_id_array) ? 0 : unit_group_id_array->at(j),
5606server,
5607new_servers,
5608units))) {
5609LOG_WARN("fail to persist unit info", KR(ret), K(zone), K(pool), K(compat_mode), K(server));
5610}
5611}
5612}
5613int tmp_ret = OB_SUCCESS;
5614if (OB_TMP_FAIL(notify_proxy.wait())) {
5615LOG_WARN("fail to wait notify resource", K(ret), K(tmp_ret));
5616ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
5617} else if (OB_SUCC(ret)) {
5618// arg/dest/result can be used here.
5619}
5620if (is_valid_tenant_id(pool.tenant_id_)) {
5621ret = ERRSIM_UNIT_PERSISTENCE_ERROR ? : ret;
5622}
5623if (OB_FAIL(ret)) {
5624LOG_WARN("start to rollback unit persistence", KR(ret), K(units), K(pool));
5625if(OB_TMP_FAIL(rollback_persistent_units_(units, pool, notify_proxy))) {
5626LOG_WARN("fail to rollback unit persistence", KR(ret), KR(tmp_ret), K(units),
5627K(pool), K(compat_mode));
5628}
5629}
5630}
5631return ret;
5632}
5633
5634int ObUnitManager::try_persist_unit_info_(
5635ObNotifyTenantServerResourceProxy ¬ify_proxy,
5636ObISQLClient &client,
5637const ObZone &zone,
5638const share::ObResourcePool &pool,
5639const lib::Worker::CompatMode &compat_mode,
5640const uint64_t unit_group_id,
5641const ObAddr &server,
5642ObIArray<common::ObAddr> &new_servers,
5643ObIArray<share::ObUnit> &units)
5644{
5645int ret = OB_SUCCESS;
5646ObUnit unit;
5647uint64_t new_unit_id = OB_INVALID_ID;
5648const bool is_delete = false; // is_delete is false when allocate new unit
5649if (!check_inner_stat()) {
5650ret = OB_INNER_STAT_ERROR;
5651LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
5652} else if (OB_UNLIKELY(zone.is_empty())
5653|| OB_UNLIKELY(!server.is_valid())) {
5654ret = OB_INVALID_ARGUMENT;
5655LOG_WARN("invalid argument", KR(ret), K(zone), K(server));
5656} else if (OB_FAIL(fetch_new_unit_id(new_unit_id))) {
5657LOG_WARN("fetch_new_unit_id failed", KR(ret));
5658} else {
5659unit.unit_id_ = new_unit_id;
5660unit.resource_pool_id_ = pool.resource_pool_id_;
5661unit.unit_group_id_ = unit_group_id;
5662unit.server_ = server;
5663unit.status_ = ObUnit::UNIT_STATUS_ACTIVE;
5664unit.replica_type_ = pool.replica_type_;
5665if (OB_FAIL(unit.zone_.assign(zone))) {
5666LOG_WARN("fail to assign zone", KR(ret), K(zone));
5667} else if (OB_FAIL(try_notify_tenant_server_unit_resource_(
5668pool.tenant_id_, is_delete, notify_proxy,
5669pool.unit_config_id_, compat_mode, unit, false/*if not grant*/,
5670false/*skip offline server*/, true /*check_data_version*/))) {
5671LOG_WARN("fail to try notify server unit resource", KR(ret), K(pool), K(is_delete), K(unit));
5672} else if (OB_FAIL(add_unit(client, unit))) {
5673LOG_WARN("add_unit failed", KR(ret), K(unit), K(unit));
5674} else if (OB_FAIL(new_servers.push_back(server))) {
5675LOG_WARN("push_back failed", KR(ret), K(server));
5676} else if (OB_FAIL(units.push_back(unit))) {
5677LOG_WARN("fail to push an element into units", KR(ret), K(unit));
5678}
5679}
5680return ret;
5681}
5682
5683int ObUnitManager::get_excluded_servers(
5684const ObUnit &unit,
5685const ObUnitStat &unit_stat,
5686const char *module,
5687const ObIArray<ObServerInfoInTable> &servers_info, // servers info in unit.zone_
5688const ObIArray<obrpc::ObGetServerResourceInfoResult> &report_servers_resource_info, // active servers' resource info in unit.zone_
5689ObIArray<ObAddr> &servers) const
5690{
5691int ret = OB_SUCCESS;
5692//Add all OBS whose disks do not meet the requirements
5693ObArray<share::ObServerStatus> server_list;
5694ObServerResourceInfo server_resource_info;
5695const bool new_allocate_pool = false;
5696if (OB_FAIL(get_excluded_servers(unit.resource_pool_id_, unit.zone_, module,
5697new_allocate_pool, servers))) {
5698LOG_WARN("fail to get excluded_servers", K(ret), K(unit), K(new_allocate_pool));
5699} else {
5700for (int64_t i = 0; i < servers_info.count() && OB_SUCC(ret); i++) {
5701const ObServerInfoInTable &server_info = servers_info.at(i);
5702const ObAddr &server = server_info.get_server();
5703bool is_exclude = false;
5704server_resource_info.reset();
5705if (!server_info.can_migrate_in()) {
5706is_exclude = true;
5707LOG_INFO("server can't migrate in, push into excluded_array", K(server_info), K(module));
5708} else if (OB_FAIL(ObRootUtils::get_server_resource_info(
5709report_servers_resource_info,
5710server,
5711server_resource_info))) {
5712// server which can be migrated in must have its resource_info
5713LOG_WARN("fail to get server_resource_info", KR(ret), K(report_servers_resource_info), K(server));
5714} else {
5715int64_t required_size = unit_stat.get_required_size() + server_resource_info.disk_in_use_;
5716int64_t total_size = server_resource_info.disk_total_;
5717if (total_size <= required_size || total_size <= 0) {
5718is_exclude = true;
5719LOG_INFO("server total size no bigger than required size", K(module), K(required_size),
5720K(total_size), K(unit_stat), K(server_resource_info));
5721} else if (required_size <= 0) {
5722//nothing todo
5723} else {
5724int64_t required_percent = (100 * required_size) / total_size;
5725int64_t limit_percent = GCONF.data_disk_usage_limit_percentage;
5726if (required_percent > limit_percent) {
5727is_exclude = true;
5728LOG_INFO("server disk percent will out of control;", K(module), K(required_percent), K(limit_percent),
5729K(required_size), K(total_size));
5730}
5731}
5732}
5733if (!is_exclude) {
5734//nothing todo
5735} else if (has_exist_in_array(servers, server)) {
5736//nothing todo
5737} else if (OB_FAIL(servers.push_back(server))) {
5738LOG_WARN("fail to push back", KR(ret), K(server));
5739}
5740}
5741}
5742return ret;
5743}
5744
5745// get excluded servers for resource pool on target zone.
5746//
5747// 1. resource pool units servers on target zone
5748// 2. tenant all resource pool units servers on target zone
5749//
5750// FIXME: 4.0 not support resource pool intersect in zone, here need not consider multiple pools of tenant
5751//
5752// @param [in] resource_pool_id specified resource pool id
5753// @param [in] zone specified zone which may be empty that means all zones
5754// @param [in] new_allocate_pool new allocate pool
5755// @param [out] servers returned excluded servers
5756int ObUnitManager::get_excluded_servers(const uint64_t resource_pool_id,
5757const ObZone &zone,
5758const char *module,
5759const bool new_allocate_pool,
5760ObIArray<ObAddr> &excluded_servers) const
5761{
5762int ret = OB_SUCCESS;
5763share::ObResourcePool *pool = NULL;
5764int64_t tenant_id = OB_INVALID_ID;
5765common::ObArray<common::ObAddr> sys_standalone_servers;
5766common::ObArray<share::ObResourcePool *> *all_pools = NULL;
5767
5768excluded_servers.reset();
5769if (!check_inner_stat()) {
5770ret = OB_INNER_STAT_ERROR;
5771LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5772} else if (OB_UNLIKELY(OB_INVALID_ID == resource_pool_id)) {
5773ret = OB_INVALID_ARGUMENT;
5774LOG_WARN("invalid resource pool id", KR(ret), K(resource_pool_id));
5775} else if (new_allocate_pool) {
5776//nothing todo
5777} else if (OB_FAIL(get_resource_pool_by_id(resource_pool_id, pool))) {
5778LOG_WARN("fail to get resource pool by id", K(ret), K(resource_pool_id));
5779} else if (FALSE_IT(tenant_id = pool->tenant_id_)) {
5780//nothing todo
5781} else if (! is_valid_tenant_id(tenant_id)) {
5782// The pool does not belong to any tenant, only get resource pool servers
5783if (OB_FAIL(get_pool_servers(resource_pool_id, zone, excluded_servers))) {
5784LOG_WARN("get_pool_servers failed", "resource pool id",
5785resource_pool_id, K(zone), KR(ret));
5786}
5787}
5788// get all tenant resource pool related servers on target zone
5789else if (OB_FAIL(get_tenant_unit_servers(tenant_id, zone, excluded_servers))) {
5790LOG_WARN("get tennat unit server fail", KR(ret), K(tenant_id), K(zone));
5791}
5792
5793if (OB_SUCC(ret) && GCONF.enable_sys_unit_standalone) {
5794// When the system tenant is deployed independently,
5795// the server where the unit of the system tenant is located is also required as the executed servers
5796if (OB_FAIL(get_tenant_unit_servers(OB_SYS_TENANT_ID, zone, sys_standalone_servers))) {
5797LOG_WARN("fail to get tenant unit servers", KR(ret), K(zone));
5798} else if (OB_FAIL(append(excluded_servers, sys_standalone_servers))) {
5799LOG_WARN("fail to append other excluded servers", K(ret));
5800}
5801}
5802
5803LOG_INFO("get tenant resource pool servers and sys standalone servers as excluded servers",
5804K(module), K(new_allocate_pool),
5805KR(ret),
5806K(resource_pool_id),
5807K(tenant_id),
5808K(zone),
5809"enable_sys_unit_standalone", GCONF.enable_sys_unit_standalone,
5810K(excluded_servers),
5811K(sys_standalone_servers));
5812return ret;
5813}
5814
5815
5816int ObUnitManager::get_pools_servers(const common::ObIArray<share::ObResourcePool *> &pools,
5817common::hash::ObHashMap<common::ObAddr, int64_t> &server_ref_count_map) const
5818{
5819int ret = OB_SUCCESS;
5820if (!check_inner_stat()) {
5821ret = OB_INNER_STAT_ERROR;
5822LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5823} else if (pools.count() <= 0 || !server_ref_count_map.created()) {
5824ret = OB_INVALID_ARGUMENT;
5825LOG_WARN("pools is empty", K(pools),
5826"server_ref_count_map created", server_ref_count_map.created(), K(ret));
5827} else {
5828ObArray<ObAddr> servers;
5829const ObZone all_zone;
5830FOREACH_CNT_X(pool, pools, OB_SUCCESS == ret) {
5831servers.reuse();
5832if (NULL == *pool) {
5833ret = OB_INVALID_ARGUMENT;
5834LOG_WARN("pool is null", "pool", *pool, K(ret));
5835} else if (OB_FAIL(get_pool_servers((*pool)->resource_pool_id_, all_zone, servers))) {
5836LOG_WARN("get pool servers failed",
5837"pool id", (*pool)->resource_pool_id_, K(all_zone), K(ret));
5838} else {
5839FOREACH_CNT_X(server, servers, OB_SUCCESS == ret) {
5840int64_t server_ref_count = 0;
5841if (OB_FAIL(get_server_ref_count(server_ref_count_map, *server, server_ref_count))) {
5842if (OB_ENTRY_NOT_EXIST == ret) {
5843server_ref_count = 1;
5844ret = OB_SUCCESS;
5845} else {
5846LOG_WARN("get server ref count failed", "server", *server, K(ret));
5847}
5848} else {
5849++server_ref_count;
5850}
5851if (OB_SUCC(ret)) {
5852if (OB_FAIL(set_server_ref_count(server_ref_count_map, *server, server_ref_count))) {
5853LOG_WARN("set server ref count failed",
5854"server", *server, K(server_ref_count), K(ret));
5855}
5856}
5857}
5858}
5859}
5860}
5861return ret;
5862}
5863
5864int ObUnitManager::get_pool_servers(const uint64_t resource_pool_id,
5865const ObZone &zone,
5866ObIArray<ObAddr> &servers) const
5867{
5868int ret = OB_SUCCESS;
5869ObArray<ObUnit *> *units = NULL;
5870if (!check_inner_stat()) {
5871ret = OB_INNER_STAT_ERROR;
5872LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5873} else if (OB_INVALID_ID == resource_pool_id) {
5874// don't need to check zone, can be empty
5875ret = OB_INVALID_ARGUMENT;
5876LOG_WARN("invalid resource_pool_id", K(resource_pool_id), K(ret));
5877} else if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
5878LOG_WARN("get_units_by_pool failed", K(resource_pool_id), K(ret));
5879} else if (NULL == units) {
5880ret = OB_ERR_UNEXPECTED;
5881LOG_WARN("units is null", KP(units), K(ret));
5882} else {
5883for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
5884if (NULL == units->at(i)) {
5885ret = OB_ERR_UNEXPECTED;
5886LOG_WARN("unit is null", "unit", OB_P(units->at(i)), K(ret));
5887} else if (!zone.is_empty() && zone != units->at(i)->zone_) {
5888continue;
5889} else {
5890if (OB_SUCCESS == ret && units->at(i)->migrate_from_server_.is_valid()) {
5891if (OB_FAIL(servers.push_back(units->at(i)->migrate_from_server_))) {
5892LOG_WARN("push_back failed", K(ret));
5893}
5894}
5895
5896if (OB_SUCCESS == ret && units->at(i)->server_.is_valid()) {
5897if (OB_FAIL(servers.push_back(units->at(i)->server_))) {
5898LOG_WARN("push_back failed", K(ret));
5899}
5900}
5901}
5902}
5903}
5904return ret;
5905}
5906
5907// choose server for target one unit
5908//
5909// @param [in] config target unit resource
5910// @param [in] zone target zone
5911// @param [in] excluded_servers excluded servers which can not allocate unit
5912// @param [in] module module name for log print
5913// @param [out] server choosed server for unit
5914// @param [out] resource_not_enough_reason reason for resource not enough,
5915// is valid when ret = OB_ZONE_RESOURCE_NOT_ENOUGH
5916//
5917// @ret OB_SUCCESS on success
5918// @ret OB_ZONE_RESOURCE_NOT_ENOUGH zone resource not enough to hold new unit
5919// @ret OB_ZONE_SERVER_NOT_ENOUGH all valid servers are excluded, no server to hold new unit
5920int ObUnitManager::choose_server_for_unit(
5921const ObUnitResource &config,
5922const ObZone &zone,
5923const ObArray<ObAddr> &excluded_servers,
5924const char *module,
5925const ObIArray<ObServerInfoInTable> &active_servers_info, // active_servers_info of the give zone,
5926const ObIArray<obrpc::ObGetServerResourceInfoResult> &active_servers_resource_info, // active_servers_resource_info of the give zone
5927ObAddr &choosed_server,
5928std::string &resource_not_enough_reason) const
5929{
5930int ret = OB_SUCCESS;
5931ObArray<ObServerStatus> statuses;
5932ObArray<ObUnitPlacementStrategy::ObServerResource> server_resources;
5933ObArray<ObServerInfoInTable> servers_info;
5934ObArray<obrpc::ObGetServerResourceInfoResult> report_servers_resource_info;
5935if (!check_inner_stat()) {
5936ret = OB_INNER_STAT_ERROR;
5937LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
5938} else if (!config.is_valid() || zone.is_empty()) {
5939// excluded_servers can be empty
5940ret = OB_INVALID_ARGUMENT;
5941LOG_WARN("invalid config", KR(ret), K(config), K(zone));
5942} else if (OB_FAIL(build_server_resources_(active_servers_resource_info, server_resources))) {
5943LOG_WARN("fail to build server resources", KR(ret), K(active_servers_resource_info));
5944} else if (OB_FAIL(do_choose_server_for_unit_(config, zone, excluded_servers, active_servers_info,
5945server_resources, module, choosed_server, resource_not_enough_reason))) {
5946LOG_WARN("fail to choose server for unit", K(module), KR(ret), K(config), K(zone),
5947K(excluded_servers), K(servers_info), K(server_resources),
5948"resource_not_enough_reason", resource_not_enough_reason.c_str());
5949}
5950return ret;
5951}
5952
5953int ObUnitManager::check_server_status_valid_and_construct_log_(
5954const share::ObServerInfoInTable &server_info,
5955const bool for_clone_tenant,
5956bool &is_server_valid,
5957std::string ¬_valid_reason) const
5958{
5959int ret = OB_SUCCESS;
5960is_server_valid = false;
5961const ObAddr &server = server_info.get_server();
5962if (!check_inner_stat()) {
5963ret = OB_INNER_STAT_ERROR;
5964LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
5965} else if (OB_UNLIKELY(!server_info.is_valid())) {
5966ret = OB_INVALID_ARGUMENT;
5967LOG_WARN("invalid argument", KR(ret), K(server_info));
5968} else if (!for_clone_tenant && !server_info.is_active()) {
5969// server is inactive
5970is_server_valid = false;
5971not_valid_reason = not_valid_reason + "server '" + to_cstring(server) + "' is not active\n";
5972} else if (server_info.is_migrate_in_blocked()) {
5973// server is block-migrate-in
5974is_server_valid = false;
5975not_valid_reason = not_valid_reason + "server '" + to_cstring(server) + "' is blocked migrate-in\n";
5976} else {
5977is_server_valid = true;
5978}
5979return ret;
5980}
5981
5982int ObUnitManager::check_server_resource_enough_and_construct_log_(
5983const ObUnitPlacementStrategy::ObServerResource &server_resource,
5984const share::ObUnitResource &config,
5985bool &is_resource_enough,
5986std::string &resource_not_enough_reason) const
5987{
5988int ret = OB_SUCCESS;
5989is_resource_enough = false;
5990double hard_limit = 1.0;
5991const ObAddr &server = server_resource.get_server();
5992ObResourceType not_enough_resource = RES_MAX;
5993AlterResourceErr not_enough_resource_config = ALT_ERR;
5994
5995if (!check_inner_stat()) {
5996ret = OB_INNER_STAT_ERROR;
5997LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
5998} else if (OB_FAIL(get_hard_limit(hard_limit))) {
5999LOG_WARN("get_hard_limit failed", KR(ret));
6000} else if (FALSE_IT(is_resource_enough = check_resource_enough_for_unit_(
6001server_resource, config, hard_limit,
6002not_enough_resource, not_enough_resource_config))) {
6003// shall never be here
6004} else if (!is_resource_enough) {
6005resource_not_enough_reason =
6006resource_not_enough_reason + "server '" + to_cstring(server) + "' "
6007+ resource_type_to_str(not_enough_resource) + " resource not enough\n";
6008}
6009return ret;
6010}
6011
6012int ObUnitManager::construct_valid_servers_resource_(
6013const ObZone &zone,
6014const share::ObUnitResource &config,
6015const ObIArray<ObAddr> &excluded_servers,
6016const ObIArray<share::ObServerInfoInTable> &servers_info,
6017const ObIArray<ObUnitPlacementStrategy::ObServerResource> &server_resources,
6018const char *module,
6019const bool for_clone_tenant,
6020int64_t ¬_excluded_server_count,
6021std::string &resource_not_enough_reason,
6022ObIArray<ObUnitPlacementStrategy::ObServerResource> &valid_server_resources) const
6023{
6024int ret = OB_SUCCESS;
6025not_excluded_server_count = 0;
6026valid_server_resources.reset();
6027if (OB_UNLIKELY(servers_info.count() != server_resources.count())
6028|| OB_UNLIKELY(zone.is_empty())) {
6029ret = OB_INVALID_ARGUMENT;
6030LOG_WARN("invalid argument", KR(ret), K(servers_info), K(server_resources), K(zone));
6031} else {
6032for (int64_t i = 0; OB_SUCC(ret) && i < servers_info.count(); ++i) { // for each active servers
6033ObResourceType not_enough_resource = RES_MAX;
6034AlterResourceErr not_enough_resource_config = ALT_ERR;
6035const ObServerInfoInTable &server_info = servers_info.at(i);
6036const ObAddr &server = server_info.get_server();
6037const ObUnitPlacementStrategy::ObServerResource &server_resource = server_resources.at(i);
6038bool is_server_valid = false;
6039bool is_resource_enough = false;
6040
6041if (has_exist_in_array(excluded_servers, server)) {
6042// excluded servers are expected, need not show in reason
6043continue;
6044} else {
6045not_excluded_server_count++;
6046if (OB_FAIL(check_server_status_valid_and_construct_log_(
6047server_info,
6048for_clone_tenant,
6049is_server_valid,
6050resource_not_enough_reason))) {
6051LOG_WARN("fail to check server status", KR(ret), K(server_info), K(for_clone_tenant));
6052} else if (!is_server_valid) {
6053if (for_clone_tenant) {
6054ret = OB_OP_NOT_ALLOW;
6055LOG_WARN("[CLONE_TENANT_UNIT] server with invalid status, can not create clone tenant resource pool",
6056KR(ret), K(server_info), K(is_server_valid));
6057LOG_USER_ERROR(OB_OP_NOT_ALLOW, "server is block migrate in, create clone tenant resource pool");
6058} else {
6059LOG_WARN("[CHOOSE_SERVER_FOR_UNIT] server can not migrate in", K(module), K(i), K(server_info));
6060continue;
6061}
6062} else if (OB_FAIL(check_server_resource_enough_and_construct_log_(
6063server_resource,
6064config,
6065is_resource_enough,
6066resource_not_enough_reason))) {
6067LOG_WARN("fail to check server resource", KR(ret), K(server_resource), K(config));
6068} else if (is_resource_enough) {
6069LOG_INFO("[CHOOSE_SERVER_FOR_UNIT] find available server", K(module), K(i),
6070K(server_resource), "request_unit_config", config);
6071if (OB_FAIL(valid_server_resources.push_back(server_resource))) {
6072LOG_WARN("failed to push into array", KR(ret), K(server_resource));
6073}
6074} else {
6075if (for_clone_tenant) {
6076ret = OB_ZONE_RESOURCE_NOT_ENOUGH;
6077LOG_WARN("resource not enough", KR(ret), K(server_resource), K(config));
6078LOG_USER_ERROR(OB_ZONE_RESOURCE_NOT_ENOUGH,
6079to_cstring(zone), servers_info.count(), resource_not_enough_reason.c_str());
6080} else {
6081LOG_INFO("[CHOOSE_SERVER_FOR_UNIT] server resource not enough", K(module), K(i),
6082"not_enough_resource", resource_type_to_str(not_enough_resource),
6083"not_enough_resource_config", alter_resource_err_to_str(not_enough_resource_config),
6084K(server_resource), "request_unit_config", config);
6085}
6086}
6087}
6088}
6089}
6090return ret;
6091}
6092
6093int ObUnitManager::do_choose_server_for_unit_(const ObUnitResource &config,
6094const ObZone &zone,
6095const ObArray<ObAddr> &excluded_servers,
6096const ObIArray<share::ObServerInfoInTable> &servers_info,
6097const ObIArray<ObUnitPlacementStrategy::ObServerResource> &server_resources,
6098const char *module,
6099ObAddr &choosed_server,
6100std::string &resource_not_enough_reason) const
6101{
6102LOG_INFO("[CHOOSE_SERVER_FOR_UNIT] begin", K(module), K(zone), K(excluded_servers), K(config));
6103
6104int ret = OB_SUCCESS;
6105double hard_limit = 1.0;
6106ObArray<ObUnitPlacementStrategy::ObServerResource> valid_server_resources;
6107bool for_clone_tenant = false;
6108
6109choosed_server.reset();
6110
6111if (OB_UNLIKELY(zone.is_empty())) {
6112ret = OB_INVALID_ARGUMENT;
6113LOG_WARN("zone is empty, unexpected", KR(ret), K(zone));
6114} else if (servers_info.count() != server_resources.count()) {
6115ret = OB_INVALID_ARGUMENT;
6116LOG_WARN("invalid servers_info and server_resources array", KR(ret), K(servers_info), K(server_resources));
6117} else if (OB_FAIL(get_hard_limit(hard_limit))) {
6118LOG_WARN("get_hard_limit failed", K(ret));
6119} else {
6120int64_t not_excluded_server_count = 0;
6121// 1. construct valid servers resource
6122if (OB_FAIL(construct_valid_servers_resource_(
6123zone,
6124config,
6125excluded_servers,
6126servers_info,
6127server_resources,
6128module,
6129for_clone_tenant,
6130not_excluded_server_count,
6131resource_not_enough_reason,
6132valid_server_resources))) {
6133LOG_WARN("fail to construct valid servers resource", KR(ret), K(zone), K(config), K(excluded_servers),
6134K(servers_info), K(server_resources), K(module), K(for_clone_tenant));
6135} else {
6136if (0 == not_excluded_server_count) {
6137ret = OB_ZONE_SERVER_NOT_ENOUGH;
6138LOG_WARN("zone server not enough to hold all units", K(module), KR(ret), K(zone), K(excluded_servers),
6139K(servers_info));
6140} else if (valid_server_resources.count() <= 0) {
6141ret = OB_ZONE_RESOURCE_NOT_ENOUGH;
6142LOG_WARN("zone resource is not enough to hold a new unit", K(module), KR(ret), K(zone),
6143K(config), K(excluded_servers),
6144"resource_not_enough_reason", resource_not_enough_reason.c_str());
6145} else {
6146// 2. choose the server
6147ObUnitPlacementDPStrategy unit_placement;
6148if (OB_FAIL(unit_placement.choose_server(valid_server_resources, config, module, choosed_server))) {
6149LOG_WARN("failed to choose server for unit", K(ret), K(config));
6150}
6151}
6152}
6153}
6154LOG_INFO("[CHOOSE_SERVER_FOR_UNIT] end", K(module), KR(ret), K(choosed_server), K(zone), K(excluded_servers),
6155K(config), K(valid_server_resources),
6156"resource_not_enough_reason", resource_not_enough_reason.c_str());
6157return ret;
6158}
6159
6160int ObUnitManager::compute_server_resource_(
6161const obrpc::ObGetServerResourceInfoResult &report_server_resource_info,
6162ObUnitPlacementStrategy::ObServerResource &server_resource) const
6163{
6164int ret = OB_SUCCESS;
6165ObUnitConfig sum_load;
6166ObArray<ObUnitLoad> *unit_loads = NULL;
6167const ObAddr &server = report_server_resource_info.get_server();
6168const ObServerResourceInfo &report_resource = report_server_resource_info.get_resource_info();
6169if (OB_UNLIKELY(!report_server_resource_info.is_valid())) {
6170ret = OB_ERR_UNEXPECTED;
6171LOG_WARN("invalid argument", KR(ret), K(report_server_resource_info));
6172} else if (OB_FAIL(get_loads_by_server(server, unit_loads))) {
6173if (OB_ENTRY_NOT_EXIST != ret) {
6174LOG_WARN("get_loads_by_server failed", "server", server, KR(ret));
6175} else {
6176ret = OB_SUCCESS;
6177}
6178} else if (OB_ISNULL(unit_loads)) {
6179ret = OB_ERR_UNEXPECTED;
6180LOG_WARN("unit_loads is null", KR(ret), KP(unit_loads));
6181} else if (OB_FAIL(calc_sum_load(unit_loads, sum_load))) {
6182LOG_WARN("calc_sum_load failed", KR(ret), KP(unit_loads));
6183}
6184
6185if (OB_SUCC(ret)) {
6186// Unit resource information is persisted on the observer side,
6187// The unit_load seen on the rs side is only the resource view managed by rs itself,
6188// It is actually inaccurate to judge whether the resources are sufficient based on the resource view of rs itself,
6189// Need to consider the persistent resources of the unit resource information on the observer side.
6190// The persistent information of the unit on the observer side is regularly reported to rs by the observer through the heartbeat.
6191// When performing allocation, rs reports the maximum value of resource information from its own resource view
6192// and observer side as a reference for unit resource allocation
6193server_resource.addr_ = server;
6194server_resource.assigned_[RES_CPU] = sum_load.min_cpu() > report_resource.report_cpu_assigned_
6195? sum_load.min_cpu() : report_resource.report_cpu_assigned_;
6196server_resource.max_assigned_[RES_CPU] = sum_load.max_cpu() > report_resource.report_cpu_max_assigned_
6197? sum_load.max_cpu() : report_resource.report_cpu_max_assigned_;
6198server_resource.capacity_[RES_CPU] = report_resource.cpu_;
6199server_resource.assigned_[RES_MEM] = sum_load.memory_size() > report_resource.report_mem_assigned_
6200? static_cast<double>(sum_load.memory_size())
6201: static_cast<double>(report_resource.report_mem_assigned_);
6202server_resource.max_assigned_[RES_MEM] = server_resource.assigned_[RES_MEM];
6203server_resource.capacity_[RES_MEM] = static_cast<double>(report_resource.mem_total_);
6204server_resource.assigned_[RES_LOG_DISK] = static_cast<double>(sum_load.log_disk_size());
6205server_resource.max_assigned_[RES_LOG_DISK] = static_cast<double>(sum_load.log_disk_size());
6206server_resource.capacity_[RES_LOG_DISK] = static_cast<double>(report_resource.log_disk_total_);
6207}
6208
6209LOG_INFO("compute server resource", KR(ret),
6210"server", server,
6211K(server_resource),
6212"report_resource_info", report_resource,
6213"valid_unit_sum", sum_load,
6214"valid_unit_count", unit_loads != NULL ? unit_loads->count(): 0);
6215return ret;
6216}
6217
6218// check resource enough for unit
6219//
6220// @param [in] u demands resource that may have some invalid items, need not check valid
6221// @param [out] not_enough_resource returned resource type that is not enough
6222// @param [out] not_enough_resource_config returned resource config type that is not enough
6223bool ObUnitManager::check_resource_enough_for_unit_(
6224const ObUnitPlacementStrategy::ObServerResource &r,
6225const ObUnitResource &u,
6226const double hard_limit,
6227ObResourceType ¬_enough_resource,
6228AlterResourceErr ¬_enough_resource_config) const
6229{
6230bool is_enough = false; // default is false
6231
6232if (u.is_max_cpu_valid() &&
6233r.capacity_[RES_CPU] * hard_limit < r.max_assigned_[RES_CPU] + u.max_cpu()) {
6234not_enough_resource = RES_CPU;
6235not_enough_resource_config = MAX_CPU;
6236} else if (u.is_min_cpu_valid() &&
6237r.capacity_[RES_CPU] < r.assigned_[RES_CPU] + u.min_cpu()) {
6238not_enough_resource = RES_CPU;
6239not_enough_resource_config = MIN_CPU;
6240} else if (u.is_memory_size_valid() &&
6241r.capacity_[RES_MEM] < r.assigned_[RES_MEM] + u.memory_size()) {
6242not_enough_resource = RES_MEM;
6243not_enough_resource_config = MEMORY;
6244} else if (u.is_log_disk_size_valid() &&
6245r.capacity_[RES_LOG_DISK] < r.assigned_[RES_LOG_DISK] + u.log_disk_size()) {
6246not_enough_resource = RES_LOG_DISK;
6247not_enough_resource_config = LOG_DISK;
6248} else {
6249is_enough = true;
6250not_enough_resource = RES_MAX;
6251not_enough_resource_config = ALT_ERR;
6252}
6253
6254if (! is_enough) {
6255_LOG_INFO("server %s resource '%s' is not enough for unit. hard_limit=%.6g, server_resource=%s, "
6256"demands=%s",
6257resource_type_to_str(not_enough_resource),
6258alter_resource_err_to_str(not_enough_resource_config),
6259hard_limit,
6260to_cstring(r),
6261to_cstring(u));
6262}
6263return is_enough;
6264}
6265
6266
6267// demand_resource may have some invalid items, need not check valid for demand_resource
6268int ObUnitManager::have_enough_resource(const obrpc::ObGetServerResourceInfoResult &report_server_resource_info,
6269const ObUnitResource &demand_resource,
6270const double hard_limit,
6271bool &is_enough,
6272AlterResourceErr &err_index) const
6273{
6274int ret = OB_SUCCESS;
6275ObResourceType not_enough_resource = RES_MAX;
6276ObUnitPlacementStrategy::ObServerResource server_resource;
6277err_index = ALT_ERR;
6278
6279if (!check_inner_stat()) {
6280ret = OB_INNER_STAT_ERROR;
6281LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
6282} else if (!report_server_resource_info.is_valid() || hard_limit <= 0) {
6283ret = OB_ERR_UNEXPECTED;
6284LOG_WARN("invalid argument", K(report_server_resource_info), K(hard_limit), K(ret));
6285} else if (OB_FAIL(compute_server_resource_(report_server_resource_info, server_resource))) {
6286LOG_WARN("compute server resource fail", KR(ret), K(report_server_resource_info));
6287} else {
6288is_enough = check_resource_enough_for_unit_(server_resource, demand_resource, hard_limit,
6289not_enough_resource, err_index);
6290}
6291return ret;
6292}
6293int ObUnitManager::check_enough_resource_for_delete_server(
6294const ObAddr &server,
6295const ObZone &zone)
6296{
6297int ret = OB_SUCCESS;
6298// get_servers_of_zone
6299ObArray<obrpc::ObGetServerResourceInfoResult> report_servers_resource_info;
6300ObArray<ObServerInfoInTable> servers_info_of_zone;
6301bool empty = false;
6302const bool ONLY_ACTIVE_SERVERS = true;
6303if (OB_ISNULL(GCTX.sql_proxy_)) {
6304ret = OB_ERR_UNEXPECTED;
6305LOG_WARN("GCTX.sql_proxy_ is null", KR(ret), KP(GCTX.sql_proxy_));
6306} else if (OB_UNLIKELY(!server.is_valid() || zone.is_empty())) {
6307ret = OB_INVALID_ARGUMENT;
6308LOG_WARN("invalid server or zone", KR(ret), K(server), K(zone));
6309} else if (OB_FAIL(ut_operator_.check_server_empty(server, empty))) {
6310// the validity of the server is checked here
6311LOG_WARN("fail to check whether the server is empty", KR(ret));
6312} else if (empty) {
6313//nothing todo
6314} else if (OB_FAIL(ObServerTableOperator::get_servers_info_of_zone(
6315*GCTX.sql_proxy_,
6316zone,
6317ONLY_ACTIVE_SERVERS,
6318servers_info_of_zone))) {
6319LOG_WARN("fail to get servers info of zone", KR(ret), K(zone));
6320} else if (OB_FAIL(get_servers_resource_info_via_rpc(servers_info_of_zone, report_servers_resource_info))) {
6321LOG_WARN("fail to get servers_resouce_info via rpc", KR(ret), K(servers_info_of_zone), K(report_servers_resource_info));
6322} else if (OB_FAIL(check_enough_resource_for_delete_server_(
6323server,
6324zone,
6325servers_info_of_zone,
6326report_servers_resource_info))) {
6327LOG_WARN("fail to check enough resource for delete server", KR(ret), K(server), K(zone),
6328K(servers_info_of_zone), K(report_servers_resource_info));
6329} else {}
6330return ret;
6331}
6332int ObUnitManager::get_servers_resource_info_via_rpc(
6333const ObIArray<share::ObServerInfoInTable> &servers_info,
6334ObIArray<obrpc::ObGetServerResourceInfoResult> &report_servers_resource_info) const
6335{
6336int ret = OB_SUCCESS;
6337int tmp_ret = OB_SUCCESS;
6338ObTimeoutCtx ctx;
6339obrpc::ObGetServerResourceInfoArg arg;
6340ObArray<obrpc::ObGetServerResourceInfoResult> tmp_report_servers_resource_info;
6341report_servers_resource_info.reset();
6342if (OB_UNLIKELY(servers_info.count() < 0)) {
6343ret = OB_INVALID_ARGUMENT;
6344LOG_WARN("servers_info.count() should be >= 0", KR(ret), K(servers_info.count()));
6345} else if (0 == servers_info.count()) {
6346// do nothing
6347} else if (!ObHeartbeatService::is_service_enabled()) { // old logic
6348ObServerResourceInfo resource_info;
6349obrpc::ObGetServerResourceInfoResult result;
6350for (int64_t i = 0; OB_SUCC(ret) && i < servers_info.count(); i++) {
6351const ObAddr &server = servers_info.at(i).get_server();
6352resource_info.reset();
6353result.reset();
6354if (OB_FAIL(server_mgr_.get_server_resource_info(server, resource_info))) {
6355LOG_WARN("fail to get server resource info", KR(ret), K(server));
6356} else if (OB_FAIL(result.init(server, resource_info))) {
6357LOG_WARN("fail to init", KR(ret), K(server));
6358} else if (OB_FAIL(report_servers_resource_info.push_back(result))) {
6359LOG_WARN("fail to push an element into report_servers_resource_info", KR(ret), K(result));
6360}
6361}
6362} else { // new logic
6363if (OB_ISNULL(srv_rpc_proxy_)) {
6364ret = OB_ERR_UNEXPECTED;
6365LOG_WARN("srv_rpc_proxy_ is null", KR(ret), KP(srv_rpc_proxy_));
6366} else if (OB_FAIL(ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
6367LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
6368} else {
6369ObGetServerResourceInfoProxy proxy(*srv_rpc_proxy_, &obrpc::ObSrvRpcProxy::get_server_resource_info);
6370for (int64_t i = 0; OB_SUCC(ret) && i < servers_info.count(); i++) {
6371const ObServerInfoInTable & server_info = servers_info.at(i);
6372arg.reset();
6373if (OB_UNLIKELY(!server_info.is_valid())) {
6374ret = OB_INVALID_ARGUMENT;
6375LOG_WARN("invalid server_info", KR(ret), K(server_info));
6376} else {
6377const ObAddr &server = server_info.get_server();
6378const int64_t time_out = ctx.get_timeout();
6379if (OB_FAIL(arg.init(GCTX.self_addr()))) {
6380LOG_WARN("fail to init arg", KR(ret), K(GCTX.self_addr()));
6381} else if (OB_FAIL(proxy.call(
6382server,
6383time_out,
6384GCONF.cluster_id,
6385OB_SYS_TENANT_ID,
6386arg))) {
6387LOG_WARN("fail to send get_server_resource_info rpc", KR(ret), KR(tmp_ret), K(server),
6388K(time_out), K(arg));
6389}
6390}
6391}
6392if (OB_TMP_FAIL(proxy.wait())) {
6393LOG_WARN("fail to wait all batch result", KR(ret), KR(tmp_ret));
6394ret = OB_SUCC(ret) ? tmp_ret : ret;
6395} else if (OB_SUCC(ret)) {
6396ARRAY_FOREACH_X(proxy.get_results(), idx, cnt, OB_SUCC(ret)) {
6397const obrpc::ObGetServerResourceInfoResult *rpc_result = proxy.get_results().at(idx);
6398if (OB_ISNULL(rpc_result)) {
6399ret = OB_ERR_UNEXPECTED;
6400LOG_WARN("rpc_result is null", KR(ret), KP(rpc_result));
6401} else if (OB_UNLIKELY(!rpc_result->is_valid())) {
6402ret = OB_INVALID_ARGUMENT;
6403LOG_WARN("rpc_result is invalid", KR(ret), KPC(rpc_result));
6404} else if (OB_FAIL(tmp_report_servers_resource_info.push_back(*rpc_result))) {
6405LOG_WARN("fail to push an element into tmp_report_servers_resource_info", KR(ret), KPC(rpc_result));
6406}
6407}
6408}
6409}
6410// get ordered report_servers_resource_info: since when processing resource_info,
6411// we assume servers_info.at(i).get_server() = report_servers_resource_info.at(i).get_server()
6412if (FAILEDx(order_report_servers_resource_info_(
6413servers_info,
6414tmp_report_servers_resource_info,
6415report_servers_resource_info ))) {
6416LOG_WARN("fail to order report_servers_resource_info", KR(ret),
6417K(servers_info.count()), K(tmp_report_servers_resource_info.count()),
6418K(servers_info), K(tmp_report_servers_resource_info));
6419}
6420}
6421return ret;
6422}
6423
6424int ObUnitManager::order_report_servers_resource_info_(
6425const ObIArray<share::ObServerInfoInTable> &servers_info,
6426const ObIArray<obrpc::ObGetServerResourceInfoResult> &report_servers_resource_info,
6427ObIArray<obrpc::ObGetServerResourceInfoResult> &ordered_report_servers_resource_info)
6428{
6429// target: servers_info.at(i).get_server() = ordered_report_servers_resource_info.at(i).get_server()
6430int ret = OB_SUCCESS;
6431ordered_report_servers_resource_info.reset();
6432if (servers_info.count() != report_servers_resource_info.count()) {
6433ret = OB_INVALID_ARGUMENT;
6434LOG_WARN("the size of servers_info should be equal to the size of report_servers_resource_info",
6435KR(ret), K(servers_info.count()), K(report_servers_resource_info.count()),
6436K(servers_info), K(report_servers_resource_info));
6437} else {
6438for (int64_t i = 0; OB_SUCC(ret) && i < servers_info.count(); i++) {
6439bool find_server = false;
6440for (int64_t j = 0; OB_SUCC(ret) && !find_server && j < report_servers_resource_info.count(); j++) {
6441const obrpc::ObGetServerResourceInfoResult &server_resource_info = report_servers_resource_info.at(j);
6442if (servers_info.at(i).get_server() == server_resource_info.get_server()) {
6443find_server = true;
6444if (OB_FAIL(ordered_report_servers_resource_info.push_back(server_resource_info))) {
6445LOG_WARN("fail to push an element into ordered_report_servers_resource_info",
6446KR(ret), K(server_resource_info));
6447}
6448}
6449}
6450if(OB_SUCC(ret) && !find_server) {
6451ret = OB_ERR_UNEXPECTED;
6452LOG_WARN("server not exists in report_servers_resource_info",
6453K(servers_info.at(i)), K(report_servers_resource_info));
6454}
6455}
6456}
6457return ret;
6458}
6459int ObUnitManager::get_server_resource_info_via_rpc(
6460const share::ObServerInfoInTable &server_info,
6461obrpc::ObGetServerResourceInfoResult &report_server_resource_info) const
6462{
6463int ret = OB_SUCCESS;
6464ObArray<share::ObServerInfoInTable> servers_info;
6465ObArray<obrpc::ObGetServerResourceInfoResult> report_resource_info_array;
6466report_server_resource_info.reset();
6467if (OB_UNLIKELY(!server_info.is_valid())) {
6468ret = OB_INVALID_ARGUMENT;
6469LOG_WARN("server_info is invalid", KR(ret), K(server_info));
6470} else if (OB_FAIL(servers_info.push_back(server_info))) {
6471LOG_WARN("fail to push an element into servers_info", KR(ret), K(server_info));
6472} else if (OB_FAIL(get_servers_resource_info_via_rpc(servers_info, report_resource_info_array))) {
6473LOG_WARN("fail to execute get_servers_resource_info_via_rpc", KR(ret), K(servers_info));
6474} else if (OB_UNLIKELY(1 != report_resource_info_array.count())) {
6475ret = OB_ERR_UNEXPECTED;
6476LOG_WARN("report_resource_info_array.count() should be one", KR(ret), K(report_resource_info_array.count()));
6477} else if (OB_FAIL(report_server_resource_info.assign(report_resource_info_array.at(0)))) {
6478LOG_WARN("fail to assign report_server_resource_info", KR(ret), K(report_resource_info_array.at(0)));
6479}
6480return ret;
6481}
6482int ObUnitManager::check_enough_resource_for_delete_server_(
6483const ObAddr &server,
6484const ObZone &zone,
6485const ObIArray<share::ObServerInfoInTable> &servers_info,
6486const ObIArray<obrpc::ObGetServerResourceInfoResult> &report_servers_resource_info)
6487{
6488int ret = OB_SUCCESS;
6489ObArray<ObUnitManager::ObUnitLoad> *unit_loads = NULL;
6490ObArray<ObUnitPlacementStrategy::ObServerResource> initial_servers_resources;
6491SpinRLockGuard guard(lock_);
6492bool empty = false;
6493if (OB_UNLIKELY(zone.is_empty())) {
6494ret = OB_INVALID_ARGUMENT;
6495LOG_WARN("zone is invalid", KR(ret), K(zone), K(server));
6496} else if (OB_FAIL(ut_operator_.check_server_empty(server, empty))) {
6497LOG_WARN("fail to check server empty", K(ret));
6498} else if (empty) {
6499//nothing todo
6500} else {
6501if (OB_FAIL(get_loads_by_server(server, unit_loads))) {
6502LOG_WARN("fail to get loads by server", K(ret));
6503} else if (OB_FAIL(build_server_resources_(report_servers_resource_info, initial_servers_resources))) {
6504LOG_WARN("fail to build server resources", KR(ret), K(report_servers_resource_info));
6505} else {
6506for (int64_t i = 0; i < unit_loads->count() && OB_SUCC(ret); ++i) {
6507std::string resource_not_enough_reason;
6508if (OB_FAIL(check_server_have_enough_resource_for_delete_server_(
6509unit_loads->at(i),
6510zone,
6511servers_info,
6512initial_servers_resources,
6513resource_not_enough_reason))) {
6514LOG_WARN("fail to check server have enough resource for delete server",
6515K(ret),
6516K(zone),
6517K(initial_servers_resources),
6518K(i),
6519K(unit_loads),
6520K(resource_not_enough_reason.c_str()));
6521
6522// handle return error info
6523if (OB_ZONE_SERVER_NOT_ENOUGH == ret) {
6524std::string err_msg;
6525const ObUnit *unit = unit_loads->at(i).unit_;
6526uint64_t unit_id = (NULL == unit ? 0 : unit->unit_id_);
6527
6528err_msg = err_msg + "can not migrate out unit '" + to_cstring(unit_id) +
6529"', no other available servers on zone '" + to_cstring(zone) +
6530"', delete server not allowed";
6531LOG_USER_ERROR(OB_DELETE_SERVER_NOT_ALLOWED, err_msg.c_str());
6532} else if (OB_ZONE_RESOURCE_NOT_ENOUGH == ret) {
6533std::string err_msg;
6534const ObUnit *unit = unit_loads->at(i).unit_;
6535uint64_t unit_id = (NULL == unit ? 0 : unit->unit_id_);
6536
6537err_msg = err_msg + "can not migrate out all units, zone '" + to_cstring(zone) +
6538"' resource not enough, delete server not allowed. "
6539"You can check resource info by views: DBA_OB_UNITS, GV$OB_UNITS, GV$OB_SERVERS.\n"
6540+ resource_not_enough_reason.c_str();
6541LOG_USER_ERROR(OB_DELETE_SERVER_NOT_ALLOWED, err_msg.c_str());
6542}
6543}
6544} //end for unit_loads
6545}
6546}
6547return ret;
6548}
6549int ObUnitManager::check_server_have_enough_resource_for_delete_server_(
6550const ObUnitLoad &unit_load,
6551const common::ObZone &zone,
6552const ObIArray<share::ObServerInfoInTable> &servers_info,
6553ObIArray<ObUnitPlacementStrategy::ObServerResource> &initial_servers_resources,
6554std::string &resource_not_enough_reason)
6555{
6556int ret = OB_SUCCESS;
6557double hard_limit = 1.0;
6558ObArray<ObUnitPlacementStrategy::ObServerResource> servers_resources;
6559ObArray<ObAddr> excluded_servers;
6560ObAddr choosed_server;
6561const ObUnitConfig *config = unit_load.unit_config_;
6562const char *module = "DELETE_SERVER";
6563const bool new_allocate_pool = false;
6564
6565if (!check_inner_stat()) {
6566ret = OB_INNER_STAT_ERROR;
6567LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
6568} else if (OB_ISNULL(config) || OB_UNLIKELY(! config->is_valid())) {
6569ret = OB_INVALID_ARGUMENT;
6570LOG_WARN("unit config ptr is null", KR(ret), KPC(config));
6571} else if (OB_UNLIKELY(zone.is_empty())) {
6572ret = OB_INVALID_ARGUMENT;
6573LOG_WARN("zone is empty, unexpected", KR(ret), K(zone));
6574} else if (servers_info.count() != initial_servers_resources.count()) {
6575ret = OB_INVALID_ARGUMENT;
6576LOG_WARN("servers_info does not match initial_servers_resources", KR(ret), K(servers_info),
6577K(initial_servers_resources));
6578} else if (OB_ISNULL(unit_load.unit_)) {
6579ret = OB_ERR_UNEXPECTED;
6580LOG_WARN("unit ptr is null", K(ret));
6581} else if (unit_load.unit_->migrate_from_server_.is_valid()) {
6582// In a state of migration, there must be a place to migrate
6583} else if (OB_FAIL(get_excluded_servers(unit_load.unit_->resource_pool_id_, unit_load.unit_->zone_, module,
6584new_allocate_pool, excluded_servers))) {
6585LOG_WARN("fail to get excluded server", K(module), KR(ret), KPC(unit_load.unit_), K(new_allocate_pool));
6586} else if (OB_FAIL(do_choose_server_for_unit_(config->unit_resource(), zone,
6587excluded_servers, servers_info, initial_servers_resources,
6588module, choosed_server, resource_not_enough_reason))) {
6589// choose right server for target unit
6590LOG_WARN("choose server for unit fail", K(module), KR(ret), K(zone), KPC(config),
6591K(excluded_servers), K(servers_info), K(initial_servers_resources),
6592"resource_not_enough_reason", resource_not_enough_reason.c_str());
6593} else {
6594// sum target unit resource config on choosed server resource
6595int64_t choosed_index = -1;
6596for (int64_t i = 0; choosed_index < 0 && i < initial_servers_resources.count(); i++) {
6597if (initial_servers_resources.at(i).addr_ == choosed_server) {
6598choosed_index = i;
6599}
6600}
6601
6602if (OB_UNLIKELY(choosed_index < 0 || choosed_index >= initial_servers_resources.count())) {
6603ret = OB_ERR_UNEXPECTED;
6604LOG_WARN("can not find choosed_server in initial_servers_resources, or invalid choosed_index", KR(ret),
6605K(choosed_index), K(choosed_server), K(initial_servers_resources));
6606} else if (OB_FAIL(sum_servers_resources(initial_servers_resources.at(choosed_index), *config))) {
6607LOG_WARN("fail to sum servers resources", KR(ret), K(initial_servers_resources),
6608KPC(config));
6609}
6610}
6611return ret;
6612}
6613
6614int ObUnitManager::build_server_resources_(
6615const ObIArray<obrpc::ObGetServerResourceInfoResult> &report_servers_resource_info,
6616ObIArray<ObUnitPlacementStrategy::ObServerResource> &servers_resources) const
6617{
6618int ret = OB_SUCCESS;
6619for (int64_t i = 0; OB_SUCC(ret) && i < report_servers_resource_info.count(); ++i) {
6620const obrpc::ObGetServerResourceInfoResult &report_resource_info = report_servers_resource_info.at(i);
6621ObUnitPlacementStrategy::ObServerResource server_resource;
6622
6623if (OB_FAIL(compute_server_resource_(report_resource_info, server_resource))) {
6624LOG_WARN("compute server resource fail", KR(ret), K(report_resource_info));
6625} else if (OB_FAIL(servers_resources.push_back(server_resource))) {
6626LOG_WARN("fail to push back", KR(ret), K(server_resource));
6627}
6628}
6629return ret;
6630}
6631
6632int ObUnitManager::sum_servers_resources(ObUnitPlacementStrategy::ObServerResource &server_resource,
6633const share::ObUnitConfig &unit_config)
6634{
6635int ret = OB_SUCCESS;
6636server_resource.assigned_[RES_CPU] = server_resource.assigned_[RES_CPU] +
6637unit_config.min_cpu();
6638server_resource.max_assigned_[RES_CPU] = server_resource.max_assigned_[RES_CPU] +
6639unit_config.max_cpu();
6640server_resource.assigned_[RES_MEM] = server_resource.assigned_[RES_MEM] +
6641static_cast<double>(unit_config.memory_size());
6642server_resource.max_assigned_[RES_MEM] = server_resource.max_assigned_[RES_MEM] +
6643static_cast<double>(unit_config.memory_size());
6644server_resource.assigned_[RES_LOG_DISK] = server_resource.assigned_[RES_LOG_DISK] +
6645static_cast<double>(unit_config.log_disk_size());
6646server_resource.max_assigned_[RES_LOG_DISK] = server_resource.max_assigned_[RES_LOG_DISK] +
6647static_cast<double>(unit_config.log_disk_size());
6648return ret;
6649}
6650
6651int ObUnitManager::add_unit(ObISQLClient &client, const ObUnit &unit)
6652{
6653int ret = OB_SUCCESS;
6654if (!check_inner_stat()) {
6655ret = OB_INNER_STAT_ERROR;
6656LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
6657} else if (!unit.is_valid()) {
6658ret = OB_INVALID_ARGUMENT;
6659LOG_WARN("invalid argument", K(unit), K(ret));
6660} else {
6661ObUnit *new_unit = NULL;
6662if (OB_SUCCESS == (ret = get_unit_by_id(unit.unit_id_, new_unit))) {
6663ret = OB_ENTRY_EXIST;
6664LOG_WARN("unit already exist, can't add", K(unit), K(ret));
6665} else if (OB_ENTRY_NOT_EXIST != ret) {
6666LOG_WARN("get_unit_by_id failed", "unit_id", unit.unit_id_, K(ret));
6667} else {
6668ret = OB_SUCCESS;
6669}
6670
6671if (OB_FAIL(ret)) {
6672} else if (NULL == (new_unit = allocator_.alloc())) {
6673ret = OB_ALLOCATE_MEMORY_FAILED;
6674LOG_ERROR("alloc unit failed", K(ret));
6675} else {
6676if (OB_FAIL(ut_operator_.update_unit(client, unit, false/*need_check_conflict_with_clone*/))) {
6677LOG_WARN("update_unit failed", K(unit), K(ret));
6678} else {
6679*new_unit = unit;
6680if (OB_FAIL(insert_unit(new_unit))) {
6681LOG_WARN("insert_unit failed", "new unit", *new_unit, K(ret));
6682} else {
6683ROOTSERVICE_EVENT_ADD("unit", "create_unit",
6684"unit_id", unit.unit_id_,
6685"server", unit.server_);
6686}
6687}
6688if (OB_FAIL(ret)) {
6689//avoid memory leak
6690allocator_.free(new_unit);
6691new_unit = NULL;
6692}
6693}
6694}
6695return ret;
6696}
6697
6698int ObUnitManager::alter_pool_unit_config(share::ObResourcePool *pool,
6699const ObUnitConfigName &config_name)
6700{
6701int ret = OB_SUCCESS;
6702ObUnitConfig *config = NULL;
6703ObUnitConfig *alter_config = NULL;
6704common::ObSEArray<share::ObResourcePool *, 1> pools;
6705if (!check_inner_stat()) {
6706ret = OB_INNER_STAT_ERROR;
6707LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
6708} else if (NULL == pool) {
6709ret = OB_INVALID_ARGUMENT;
6710LOG_WARN("pool is null", K(ret));
6711} else if (config_name.is_empty()) {
6712ret = OB_INVALID_ARGUMENT;
6713LOG_WARN("config_name is empty", K(config_name), K(ret));
6714} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, config))) {
6715if (OB_ENTRY_NOT_EXIST != ret) {
6716LOG_WARN("get_unit_config_by_id failed", "unit_config_id", pool->unit_config_id_, K(ret));
6717} else {
6718ret = OB_RESOURCE_UNIT_NOT_EXIST;
6719LOG_WARN("unit config not exist", "config_id", pool->unit_config_id_, K(ret));
6720}
6721} else if (NULL == config) {
6722ret = OB_ERR_UNEXPECTED;
6723LOG_WARN("config is null", KP(config), K(ret));
6724} else if (OB_FAIL(get_unit_config_by_name(config_name, alter_config))) {
6725if (OB_ENTRY_NOT_EXIST != ret) {
6726LOG_WARN("get_unit_config_by_name failed", K(config_name), K(ret));
6727} else {
6728ret = OB_RESOURCE_UNIT_NOT_EXIST;
6729LOG_USER_ERROR(OB_RESOURCE_UNIT_NOT_EXIST, to_cstring(config_name));
6730LOG_WARN("unit config not exist", K(config_name), K(ret));
6731}
6732} else if (NULL == alter_config) {
6733ret = OB_ERR_UNEXPECTED;
6734LOG_WARN("alter_config is null", KP(alter_config), K(ret));
6735} else if (config_name == config->name()) {
6736// do nothing
6737} else if (REPLICA_TYPE_FULL == pool->replica_type_
6738&& alter_config->unit_resource().memory_size() < GCONF.__min_full_resource_pool_memory) {
6739ret = OB_NOT_SUPPORTED;
6740LOG_WARN("full resource pool memory size illegal", K(ret));
6741LOG_USER_ERROR(OB_NOT_SUPPORTED, "unit MEMORY_SIZE less than __min_full_resource_pool_memory");
6742} else if (OB_FAIL(pools.push_back(pool))) {
6743LOG_WARN("push back pool into array fail", KR(ret), K(pool), K(pools));
6744} else if (OB_FAIL(check_expand_resource_(
6745"ALTER_RESOURCE_POOL_UNIT_CONFIG",
6746pools,
6747config->unit_resource(),
6748alter_config->unit_resource()))) {
6749LOG_WARN("check_expand_config failed", KR(ret), KPC(pool), KPC(config), KPC(alter_config));
6750} else if (OB_FAIL(check_shrink_resource_(pools, config->unit_resource(),
6751alter_config->unit_resource()))) {
6752LOG_WARN("check_shrink_resource_ failed", KPC(pool), KPC(config), KPC(alter_config), KR(ret));
6753} else if (OB_FAIL(change_pool_config(pool, config, alter_config))) {
6754LOG_WARN("change_pool_config failed", "pool", *pool, "config", *config,
6755"alter_config", *alter_config, K(ret));
6756}
6757return ret;
6758}
6759
6760// shrink pool unit num should only work on not-granted pool.
6761// routine that calls this function should ensure that.
6762int ObUnitManager::shrink_pool_unit_num(
6763share::ObResourcePool *pool,
6764const int64_t alter_unit_num,
6765const common::ObIArray<uint64_t> &delete_unit_id_array)
6766{
6767int ret = OB_SUCCESS;
6768if (OB_UNLIKELY(NULL == pool || alter_unit_num <= 0)) {
6769ret = OB_INVALID_ARGUMENT;
6770LOG_WARN("invalid argument", K(ret), KP(pool), K(alter_unit_num));
6771} else if (pool->is_granted_to_tenant()) {
6772ret = OB_ERR_UNEXPECTED;
6773LOG_WARN("unexpected pool status", KR(ret), KPC(pool));
6774} else {
6775ObArray<uint64_t> sort_unit_id_array;
6776for (int64_t i = 0; OB_SUCC(ret) && i < delete_unit_id_array.count(); ++i) {
6777if (OB_FAIL(sort_unit_id_array.push_back(delete_unit_id_array.at(i)))) {
6778LOG_WARN("fail to push back", K(ret));
6779}
6780}
6781std::sort(sort_unit_id_array.begin(), sort_unit_id_array.end());
6782for (int64_t i = 0; OB_SUCC(ret) && i < sort_unit_id_array.count() - 1; ++i) {
6783if (sort_unit_id_array.at(i) == sort_unit_id_array.at(i + 1)) {
6784ret = OB_NOT_SUPPORTED;
6785LOG_WARN("delete same unit more than once not supported", K(ret));
6786LOG_USER_ERROR(OB_NOT_SUPPORTED, "delete same unit more than once");
6787}
6788}
6789if (FAILEDx(shrink_not_granted_pool(pool, alter_unit_num, delete_unit_id_array))) {
6790LOG_WARN("fail to shrink not granted pool", KR(ret));
6791}
6792}
6793return ret;
6794}
6795
6796int ObUnitManager::build_sorted_zone_unit_ptr_array(
6797share::ObResourcePool *pool,
6798common::ObIArray<ZoneUnitPtr> &zone_unit_ptrs)
6799{
6800int ret = OB_SUCCESS;
6801common::ObArray<share::ObUnit *> *units = NULL;
6802zone_unit_ptrs.reset();
6803if (OB_UNLIKELY(NULL == pool)) {
6804ret = OB_INVALID_ARGUMENT;
6805LOG_WARN("invalid argument", K(ret), KP(pool));
6806} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
6807LOG_WARN("fail to get units by pool", K(ret), "pool_id", pool->resource_pool_id_);
6808} else if (OB_UNLIKELY(NULL == units)) {
6809ret = OB_ERR_UNEXPECTED;
6810LOG_WARN("units ptr is null", K(ret), KP(units));
6811} else {
6812// traverse all unit in units
6813for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
6814ObUnit *this_unit = units->at(i);
6815if (OB_UNLIKELY(NULL == this_unit)) {
6816ret = OB_ERR_UNEXPECTED;
6817LOG_WARN("unit ptr is null", K(ret), KP(this_unit));
6818} else {
6819// aggregate units with the same zone
6820int64_t index = 0;
6821for (; OB_SUCC(ret) && index < zone_unit_ptrs.count(); ++index) {
6822if (this_unit->zone_ == zone_unit_ptrs.at(index).zone_) {
6823break;
6824}
6825}
6826if (OB_FAIL(ret)) {
6827} else if (index >= zone_unit_ptrs.count()) {
6828ZoneUnitPtr zone_unit_ptr;
6829zone_unit_ptr.zone_ = this_unit->zone_;
6830if (OB_FAIL(zone_unit_ptrs.push_back(zone_unit_ptr))) {
6831LOG_WARN("fail to push back", K(ret));
6832}
6833}
6834if (OB_FAIL(ret)) {
6835} else if (index >= zone_unit_ptrs.count()) {
6836ret = OB_ERR_UNEXPECTED;
6837LOG_WARN("unexpected index", K(ret), K(index),
6838"zone_unit_count", zone_unit_ptrs.count());
6839} else if (this_unit->zone_ != zone_unit_ptrs.at(index).zone_) {
6840ret = OB_ERR_UNEXPECTED;
6841LOG_WARN("zone not match", K(ret), "left_zone", this_unit->zone_,
6842"right_zone", zone_unit_ptrs.at(index).zone_);
6843} else if (OB_FAIL(zone_unit_ptrs.at(index).unit_ptrs_.push_back(this_unit))) {
6844LOG_WARN("fail to push back", K(ret), K(index));
6845} else {} // good, no more to do
6846}
6847}
6848for (int64_t i = 0; OB_SUCC(ret) && i < zone_unit_ptrs.count(); ++i) {
6849// sort each zone unit ptr using group id
6850ZoneUnitPtr &zone_unit_ptr = zone_unit_ptrs.at(i);
6851if (OB_FAIL(zone_unit_ptr.sort_by_unit_id_desc())) {
6852LOG_WARN("fail to sort unit", K(ret));
6853} else {} // good, unit num match
6854}
6855}
6856return ret;
6857}
6858
6859int ObUnitManager::check_shrink_unit_num_zone_condition(
6860share::ObResourcePool *pool,
6861const int64_t alter_unit_num,
6862const common::ObIArray<uint64_t> &delete_unit_id_array)
6863{
6864int ret = OB_SUCCESS;
6865if (OB_UNLIKELY(NULL == pool || alter_unit_num <= 0)) {
6866ret = OB_INVALID_ARGUMENT;
6867LOG_WARN("invalid argument", K(ret), KP(pool), K(alter_unit_num));
6868} else if (delete_unit_id_array.count() <= 0) {
6869// good, we choose deleting set all by ourselves
6870} else if (pool->unit_count_ <= alter_unit_num) {
6871ret = OB_ERR_UNEXPECTED;
6872LOG_WARN("should be a shrink pool operation", K(ret),
6873"cur_unit_num", pool->unit_count_,
6874"new_unit_num", alter_unit_num);
6875} else {
6876int64_t delta = pool->unit_count_ - alter_unit_num;
6877const common::ObIArray<common::ObZone> &zone_list = pool->zone_list_;
6878common::ObArray<ZoneUnitPtr> delete_zone_unit_ptrs;
6879for (int64_t i = 0; OB_SUCC(ret) && i < delete_unit_id_array.count(); ++i) {
6880ObUnit *this_unit = NULL;
6881if (OB_FAIL(get_unit_by_id(delete_unit_id_array.at(i), this_unit))) {
6882LOG_WARN("fail to get unit by id", K(ret));
6883} else if (OB_UNLIKELY(NULL == this_unit)) {
6884ret = OB_ERR_UNEXPECTED;
6885LOG_WARN("unit ptr is null", K(ret), KP(this_unit));
6886} else if (this_unit->resource_pool_id_ != pool->resource_pool_id_) {
6887ret = OB_NOT_SUPPORTED;
6888LOG_WARN("do not support shrink unit belonging to other pool");
6889LOG_USER_ERROR(OB_NOT_SUPPORTED, "shrink unit belonging to other pool");
6890} else if (!has_exist_in_array(zone_list, this_unit->zone_)) {
6891ret = OB_ERR_UNEXPECTED;
6892LOG_WARN("unit zone not match", K(ret), K(zone_list), "unit_zone", this_unit->zone_);
6893} else {
6894int64_t index = 0;
6895for (; OB_SUCC(ret) && index < delete_zone_unit_ptrs.count(); ++index) {
6896if (this_unit->zone_ == delete_zone_unit_ptrs.at(index).zone_) {
6897break;
6898}
6899}
6900if (OB_FAIL(ret)) {
6901} else if (index >= delete_zone_unit_ptrs.count()) {
6902ZoneUnitPtr delete_zone_unit_ptr;
6903delete_zone_unit_ptr.zone_ = this_unit->zone_;
6904if (OB_FAIL(delete_zone_unit_ptrs.push_back(delete_zone_unit_ptr))) {
6905LOG_WARN("fail to push back", K(ret));
6906}
6907}
6908if (OB_FAIL(ret)) {
6909} else if (index >= delete_zone_unit_ptrs.count()) {
6910ret = OB_ERR_UNEXPECTED;
6911LOG_WARN("unexpected index", K(ret), K(index),
6912"delete_zone_unit_count", delete_zone_unit_ptrs.count());
6913} else if (this_unit->zone_ != delete_zone_unit_ptrs.at(index).zone_) {
6914ret = OB_ERR_UNEXPECTED;
6915LOG_WARN("zone not match", K(ret), "left_zone", this_unit->zone_,
6916"right_zone", delete_zone_unit_ptrs.at(index).zone_);
6917} else if (OB_FAIL(delete_zone_unit_ptrs.at(index).unit_ptrs_.push_back(this_unit))) {
6918LOG_WARN("fail to push back", K(ret), K(index));
6919} else {} // good, no more to do
6920}
6921}
6922if (OB_SUCC(ret)) {
6923if (delete_zone_unit_ptrs.count() != zone_list.count()) {
6924ret = OB_NOT_SUPPORTED;
6925LOG_WARN("do not support shrink unit num to different value on different zone", K(ret));
6926LOG_USER_ERROR(OB_NOT_SUPPORTED, "shrink unit num to different value on different zone");
6927}
6928}
6929if (OB_SUCC(ret)) {
6930for (int64_t i = 0; OB_SUCC(ret) && i < delete_zone_unit_ptrs.count(); ++i) {
6931if (delta != delete_zone_unit_ptrs.at(i).unit_ptrs_.count()) {
6932ret = OB_NOT_SUPPORTED;
6933LOG_WARN("shrink mismatching unit num and unit id list not support", K(ret));
6934LOG_USER_ERROR(OB_NOT_SUPPORTED, "shrink mismatching unit num and unit id list");
6935} else {} // good, go on to check next
6936}
6937}
6938}
6939return ret;
6940}
6941
6942int ObUnitManager::fill_delete_unit_ptr_array(
6943share::ObResourcePool *pool,
6944const common::ObIArray<uint64_t> &delete_unit_id_array,
6945const int64_t alter_unit_num,
6946common::ObIArray<ObUnit *> &output_delete_unit_ptr_array)
6947{
6948int ret = OB_SUCCESS;
6949output_delete_unit_ptr_array.reset();
6950if (delete_unit_id_array.count() > 0) {
6951// The alter resource pool shrinkage specifies the deleted unit, just fill it in directly
6952for (int64_t i = 0; OB_SUCC(ret) && i < delete_unit_id_array.count(); ++i) {
6953ObUnit *unit = NULL;
6954if (OB_FAIL(get_unit_by_id(delete_unit_id_array.at(i), unit))) {
6955LOG_WARN("fail to get unit by id", K(ret));
6956} else if (NULL == unit) {
6957ret = OB_ERR_UNEXPECTED;
6958LOG_WARN("unit ptr is null", K(ret), KP(unit));
6959} else if (OB_FAIL(output_delete_unit_ptr_array.push_back(unit))) {
6960LOG_WARN("fail to push back", K(ret));
6961} else {} // no more to do
6962}
6963} else {
6964common::ObArray<ZoneUnitPtr> zone_unit_ptrs;
6965if (OB_UNLIKELY(NULL == pool)) {
6966ret = OB_ERR_UNEXPECTED;
6967LOG_WARN("invalid argument", K(ret), KP(pool));
6968} else if (OB_FAIL(build_sorted_zone_unit_ptr_array(pool, zone_unit_ptrs))) {
6969LOG_WARN("fail to build sorted zone unit ptr array", K(ret));
6970} else if (zone_unit_ptrs.count() <= 0) {
6971ret = OB_ERR_UNEXPECTED;
6972LOG_WARN("zone unit ptrs has no element", K(ret), "zone_unit_cnt", zone_unit_ptrs.count());
6973} else {
6974for (int64_t i = 0; OB_SUCC(ret) && i < zone_unit_ptrs.count(); ++i) {
6975const ZoneUnitPtr &zone_unit_ptr = zone_unit_ptrs.at(i);
6976for (int64_t j = alter_unit_num; OB_SUCC(ret) && j < zone_unit_ptr.unit_ptrs_.count(); ++j) {
6977ObUnit *unit = zone_unit_ptr.unit_ptrs_.at(j);
6978if (OB_UNLIKELY(NULL == unit)) {
6979ret = OB_ERR_UNEXPECTED;
6980LOG_WARN("unit ptr is null", K(ret), KP(unit), K(i), K(j));
6981} else if (OB_FAIL(output_delete_unit_ptr_array.push_back(unit))) {
6982LOG_WARN("fail to push back", K(ret));
6983} else {} // no more to do
6984}
6985}
6986}
6987}
6988return ret;
6989}
6990
6991
6992// the resource pool don't grant any tenants shrink directly.
6993// step:
6994// 1. clear __all_unit, change the unit num in __all_resouce_pool
6995// 2. clear the unit info in memory structure, change the unit_num in memroy structure resource pool
6996int ObUnitManager::shrink_not_granted_pool(
6997share::ObResourcePool *pool,
6998const int64_t alter_unit_num,
6999const common::ObIArray<uint64_t> &delete_unit_id_array)
7000{
7001int ret = OB_SUCCESS;
7002common::ObMySQLTransaction trans;
7003if (OB_UNLIKELY(NULL == pool || alter_unit_num <= 0)) {
7004ret = OB_INVALID_ARGUMENT;
7005LOG_WARN("invalid argument", K(ret), KP(pool), K(alter_unit_num));
7006} else if (is_valid_tenant_id(pool->tenant_id_)) {
7007ret = OB_ERR_UNEXPECTED;
7008LOG_WARN("pool already grant to some tenant", K(ret), "tenant_id", pool->tenant_id_);
7009} else if (pool->unit_count_ <= alter_unit_num) {
7010ret = OB_ERR_UNEXPECTED;
7011LOG_WARN("should be a shrink pool operation", K(ret),
7012"cur_unit_num", pool->unit_count_,
7013"new_unit_num", alter_unit_num);
7014} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
7015LOG_WARN("start transaction failed", K(ret));
7016} else {
7017common::ObArray<ObUnit *> output_delete_unit_ptr_array;
7018common::ObArray<uint64_t> output_delete_unit_id_array;
7019share::ObResourcePool new_pool;
7020if (OB_FAIL(new_pool.assign(*pool))) {
7021LOG_WARN("fail to assign new pool", K(ret));
7022} else {
7023new_pool.unit_count_ = alter_unit_num;
7024}
7025if (OB_FAIL(ret)) {
7026} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, false/*need_check_conflict_with_clone*/))) {
7027LOG_WARN("fail to update resource pool", K(ret));
7028} else if (OB_FAIL(check_shrink_unit_num_zone_condition(pool, alter_unit_num, delete_unit_id_array))) {
7029LOG_WARN("fail to check shrink unit num zone condition", K(ret));
7030} else if (OB_FAIL(fill_delete_unit_ptr_array(
7031pool, delete_unit_id_array, alter_unit_num, output_delete_unit_ptr_array))) {
7032LOG_WARN("fail to fill delete unit id array", K(ret));
7033} else if (output_delete_unit_ptr_array.count() <= 0) {
7034ret = OB_ERR_UNEXPECTED;
7035LOG_WARN("zone unit ptrs has no element", K(ret),
7036"zone_unit_cnt", output_delete_unit_ptr_array.count());
7037} else {
7038for (int64_t i = 0; OB_SUCC(ret) && i < output_delete_unit_ptr_array.count(); ++i) {
7039const ObUnit *unit = output_delete_unit_ptr_array.at(i);
7040if (OB_UNLIKELY(NULL == unit)) {
7041ret = OB_ERR_UNEXPECTED;
7042LOG_WARN("unit ptr is null", K(ret), KP(unit));
7043} else if (OB_FAIL(ut_operator_.remove_unit(trans, *unit))) {
7044LOG_WARN("fail to remove unit", K(ret), "unit", *unit);
7045} else if (OB_FAIL(output_delete_unit_id_array.push_back(unit->unit_id_))) {
7046LOG_WARN("fail to push back", K(ret));
7047} else {} // no more to do
7048}
7049}
7050// however, we need to end this transaction
7051const bool commit = (OB_SUCCESS == ret);
7052int tmp_ret = OB_SUCCESS;
7053if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
7054LOG_WARN("trans end failed", K(tmp_ret), K(commit));
7055ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
7056}
7057if (OB_FAIL(ret)) {
7058} else if (OB_FAIL(delete_inmemory_units(pool->resource_pool_id_, output_delete_unit_id_array))) {
7059LOG_WARN("fail to delete unit groups", K(ret));
7060} else {
7061pool->unit_count_ = alter_unit_num;
7062}
7063}
7064return ret;
7065}
7066
7067int ObUnitManager::check_shrink_granted_pool_allowed_by_migrate_unit(
7068share::ObResourcePool *pool,
7069const int64_t alter_unit_num,
7070bool &is_allowed)
7071{
7072int ret = OB_SUCCESS;
7073UNUSED(alter_unit_num);
7074is_allowed = true;
7075common::ObArray<share::ObUnit *> *units = NULL;
7076if (OB_UNLIKELY(NULL == pool || alter_unit_num <= 0)) {
7077ret = OB_INVALID_ARGUMENT;
7078LOG_WARN("invalid argument", K(ret), KP(pool), K(alter_unit_num));
7079} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
7080LOG_WARN("fail to get units by pool", K(ret));
7081} else if (OB_UNLIKELY(NULL == units)) {
7082ret = OB_ERR_UNEXPECTED;
7083LOG_WARN("unit ptr is null", K(ret));
7084} else {
7085for (int64_t i = 0; OB_SUCC(ret) && is_allowed && i < units->count(); ++i) {
7086const ObUnit *unit = units->at(i);
7087if (OB_UNLIKELY(NULL == unit)) {
7088ret = OB_ERR_UNEXPECTED;
7089LOG_WARN("unit ptr is null", K(ret), KP(unit));
7090} else if (unit->migrate_from_server_.is_valid()) {
7091is_allowed = false;
7092} else {} // unit not in migrating, check next
7093}
7094}
7095return ret;
7096}
7097
7098int ObUnitManager::check_all_pools_granted(
7099const common::ObIArray<share::ObResourcePool *> &pools,
7100bool &all_granted)
7101{
7102int ret = OB_SUCCESS;
7103all_granted = true;
7104for (int64_t i = 0; all_granted && OB_SUCC(ret) && i < pools.count(); ++i) {
7105if (NULL == pools.at(i)) {
7106ret = OB_ERR_UNEXPECTED;
7107LOG_WARN("pool ptr is null", K(ret), K(i));
7108} else if (!is_valid_tenant_id(pools.at(i)->tenant_id_)) {
7109all_granted = false;
7110} else {} // go on check next
7111}
7112return ret;
7113}
7114
7115//alter 14x add the new locality F/L@ZONE;
7116//temporarily logonly_unit = 1 does not support scaling,
7117//so only the unit num of non-logonly_unit can be reduced;
7118//Here it is only judged whether the number of units on non-logonly_unit satisfies locality;
7119//The goal of this function is to determine whether the distribution of the current unit meets the requirements of locality
7120//check in two parts:
7121//1. First check whether the logonly unit meets the requirements
7122//2. second check whether the non-logonly unit meets the requirements
7123int ObUnitManager::do_check_shrink_granted_pool_allowed_by_locality(
7124const common::ObIArray<share::ObResourcePool *> &pools,
7125const common::ObIArray<common::ObZone> &schema_zone_list,
7126const ZoneLocalityIArray &zone_locality,
7127const ObIArray<int64_t> &new_unit_nums,
7128bool &is_allowed)
7129{
7130int ret = OB_SUCCESS;
7131UNUSED(schema_zone_list);
7132is_allowed = true;
7133common::hash::ObHashMap<common::ObZone, UnitNum> zone_unit_num_map;
7134const int64_t BUCKET_SIZE = 2 * MAX_ZONE_NUM;
7135if (OB_UNLIKELY(pools.count() <= 0
7136|| new_unit_nums.count() <= 0
7137|| new_unit_nums.count() != pools.count())) {
7138ret = OB_INVALID_ARGUMENT;
7139LOG_WARN("invalid argument", K(ret), K(pools.count()), K(new_unit_nums.count()));
7140} else if (OB_FAIL(zone_unit_num_map.create(BUCKET_SIZE, ObModIds::OB_RS_UNIT_MANAGER))) {
7141LOG_WARN("fail to create map", K(ret));
7142} else {
7143for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
7144const int64_t pool_unit_num = new_unit_nums.at(i);
7145const share::ObResourcePool *pool = pools.at(i);
7146if (OB_UNLIKELY(nullptr == pool)) {
7147ret = OB_ERR_UNEXPECTED;
7148LOG_WARN("pool ptr is null", K(ret));
7149} else {
7150const common::ObIArray<common::ObZone> &pool_zone_list = pool->zone_list_;
7151for (int64_t j = 0; OB_SUCC(ret) && j < pool_zone_list.count(); ++j) {
7152const common::ObZone &zone = pool_zone_list.at(j);
7153const int32_t overwrite = 1;
7154UnitNum unit_num_set;
7155int tmp_ret = zone_unit_num_map.get_refactored(zone, unit_num_set);
7156if (OB_SUCCESS == tmp_ret) {
7157// bypass
7158} else if (OB_HASH_NOT_EXIST == tmp_ret) {
7159unit_num_set.reset();
7160} else {
7161ret = OB_ERR_UNEXPECTED;
7162LOG_WARN("fail to get from map", K(ret));
7163}
7164if (OB_FAIL(ret)) {
7165} else if (REPLICA_TYPE_FULL == pool->replica_type_) {
7166unit_num_set.full_unit_num_ += pool_unit_num;
7167} else if (REPLICA_TYPE_LOGONLY == pool->replica_type_) {
7168unit_num_set.logonly_unit_num_ += pool_unit_num;
7169} else {
7170ret = OB_ERR_UNEXPECTED;
7171LOG_WARN("pool replica type unexpected", K(ret), "pool", *pool);
7172}
7173if (OB_FAIL(ret)) {
7174} else if (OB_FAIL(zone_unit_num_map.set_refactored(zone, unit_num_set, overwrite))) {
7175LOG_WARN("fail to set map", K(ret));
7176}
7177}
7178}
7179}
7180for (int64_t i = 0; is_allowed && OB_SUCC(ret) && i < zone_locality.count(); ++i) {
7181const share::ObZoneReplicaAttrSet &zone_replica_attr = zone_locality.at(i);
7182int64_t full_unit_num = 0;
7183int64_t logonly_unit_num = 0;
7184for (int64_t j = 0; OB_SUCC(ret) && j < zone_replica_attr.zone_set_.count(); ++j) {
7185const common::ObZone &zone = zone_replica_attr.zone_set_.at(j);
7186UnitNum unit_num_set;
7187if (OB_FAIL(zone_unit_num_map.get_refactored(zone, unit_num_set))) {
7188LOG_WARN("fail to get refactored", K(ret));
7189} else {
7190full_unit_num += unit_num_set.full_unit_num_;
7191logonly_unit_num += unit_num_set.logonly_unit_num_;
7192}
7193}
7194if (OB_SUCC(ret)) {
7195const int64_t specific_num = zone_replica_attr.get_specific_replica_num();
7196const int64_t except_l_specific_num = specific_num
7197- zone_replica_attr.get_logonly_replica_num()
7198- zone_replica_attr.get_encryption_logonly_replica_num();
7199const int64_t total_unit_num = full_unit_num + logonly_unit_num;
7200is_allowed = (total_unit_num >= specific_num && full_unit_num >= except_l_specific_num);
7201}
7202}
7203}
7204return ret;
7205}
7206
7207// Scaling also needs to consider the locality of the tenant or table under the tenant.
7208// There are several situations that need to be considered:
7209// 1 Although the resource pool has been granted to a tenant,
7210// but the zone of the resource pool may not be in the tenant's zone list.
7211// For example: tenant has two pools : pool1(z1,z2,z3),pool2(z4,z5,z6),
7212// The locality of tenant is F@z1,F@z2,F@z3,F@z4,
7213// tenant the zone_list is (z1, z2, z3, z4). In this case,
7214// only z4 needs to be considered when shrinkg pool2 unit num.
7215// 2 The locality of the tenant may include zone locality and region locality.
7216// For zone locality, it is only necessary to consider that
7217// the unit num of the zone after scaling is not less than the number of copies of the locality in this zone.
7218// 3 For region locality,
7219// it is necessary to satisfy that the sum of unit num of all zones in the region under
7220// this tenant is not less than the number of locality replicas on the region.
7221// For example: tenant has two pools, pool1(z1,z2) and pool2(z3,z4),
7222// the current pool1_unit_num = 2, pool2_unit_num = 2,
7223// where z1, z4 belong to region SH, z2, z3 belong to region HZ, and locality is F{2},R{2}@SH,F{2},R{2}@HZ.
7224// We try to compress the unit_num of pool2 to 1,
7225// the total number of units in region SH after compression is 3,
7226// and the total number of units in region HZ is 3,
7227// which is not enough to accommodate the number of copies of locality.
7228// Therefore, compressing the unit num of pool2 to 1 is not allowed.
7229//The specific implementation is to traverse each zone in the zone list of the resource pool:
7230//1 The zone does not exist in the tenant's zone list, skip it directly;
7231//2 The zone exists in the tenant's zone locality.
7232// It is necessary to compare whether the compressed unit num is enough to accommodate
7233// the number of locality replicas in the zone;
7234//3 If the zone does not exist in the tenant's zone locality, save the unit num in the region_unit_num_container.
7235//4 Save the zones of other resource pools under the tenant to the region zone container,
7236// and compare whether the unit num is sufficient
7237int ObUnitManager::check_shrink_granted_pool_allowed_by_tenant_locality(
7238share::schema::ObSchemaGetterGuard &schema_guard,
7239const uint64_t tenant_id,
7240const common::ObIArray<share::ObResourcePool *> &pools,
7241const common::ObIArray<int64_t> &new_unit_nums,
7242bool &is_allowed)
7243{
7244int ret = OB_SUCCESS;
7245const share::schema::ObTenantSchema *tenant_schema = NULL;
7246common::ObArray<common::ObZone> tenant_zone_list;
7247if (OB_UNLIKELY(! is_valid_tenant_id(tenant_id))) {
7248ret = OB_INVALID_ARGUMENT;
7249LOG_WARN("invalid argument", K(ret), K(tenant_id));
7250} else if (OB_FAIL(schema_guard.get_tenant_info(tenant_id, tenant_schema))) {
7251LOG_WARN("fail to get tenant info", K(ret), K(tenant_id));
7252} else if (NULL == tenant_schema) {
7253ret = OB_ERR_UNEXPECTED;
7254LOG_WARN("tenant schema is null", K(ret), KP(tenant_schema));
7255} else if (OB_FAIL(tenant_schema->get_zone_list(tenant_zone_list))) {
7256LOG_WARN("fail to get zone list", K(ret));
7257} else {
7258ObArray<ObZoneReplicaNumSet> zone_locality;
7259if (OB_FAIL(tenant_schema->get_zone_replica_attr_array(zone_locality))) {
7260LOG_WARN("fail to assign", K(ret));
7261} else if (OB_FAIL(do_check_shrink_granted_pool_allowed_by_locality(
7262pools, tenant_zone_list, zone_locality, new_unit_nums, is_allowed))) {
7263LOG_WARN("fail to do check shrink by locality", K(ret));
7264} else {} // no more to do
7265}
7266return ret;
7267}
7268
7269// Currently supports tenant-level and table-level locality,
7270// and check shrinkage needs to be checked at the same time two levels of locality, tenant and table.
7271// 1 The tenant level is more intuitive.
7272// directly compare the zone/region locality involved with the reduced unit num.
7273// 2 Three situations need to be considered at the table level:
7274// 2.1 Virtual tables, index tables, etc. without entity partitions, ignore them
7275// 2.2 The table with entity partition whose table locality is empty,
7276// inherited from tenant, has been checked, and skipped;
7277// 2.3 Tables with entity partitions whose table locality is not empty are checked according to table locality
7278int ObUnitManager::check_shrink_granted_pool_allowed_by_locality(
7279share::ObResourcePool *pool,
7280const int64_t alter_unit_num,
7281bool &is_allowed)
7282{
7283int ret = OB_SUCCESS;
7284share::schema::ObSchemaGetterGuard schema_guard;
7285const share::schema::ObTenantSchema *tenant_schema = NULL;
7286common::ObArray<share::ObResourcePool *> *pool_list = nullptr;
7287common::ObArray<share::ObResourcePool *> new_pool_list;
7288common::ObArray<int64_t> new_unit_nums;
7289if (OB_UNLIKELY(NULL == pool || alter_unit_num <= 0)) {
7290ret = OB_INVALID_ARGUMENT;
7291LOG_WARN("invalid argument", K(ret), KP(pool), K(alter_unit_num));
7292} else if (OB_ISNULL(schema_service_)) {
7293ret = OB_NOT_INIT;
7294LOG_WARN("schema service is null", K(schema_service_), KR(ret));
7295} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(pool->tenant_id_, schema_guard))) {
7296LOG_WARN("fail to get tenant schema guard", KR(ret), K(pool->tenant_id_));
7297} else if (OB_FAIL(schema_guard.get_tenant_info(pool->tenant_id_, tenant_schema))) {
7298LOG_WARN("fail to get tenant info", K(ret), "tenant_id", pool->tenant_id_);
7299} else if (OB_UNLIKELY(NULL == tenant_schema)) {
7300ret = OB_ERR_UNEXPECTED;
7301LOG_WARN("tenant schema is null", K(ret), KP(tenant_schema));
7302} else if (OB_FAIL(get_pools_by_tenant_(tenant_schema->get_tenant_id(), pool_list))) {
7303LOG_WARN("fail to get pools by tenant", K(ret));
7304} else if (OB_UNLIKELY(nullptr == pool_list)) {
7305ret = OB_ERR_UNEXPECTED;
7306LOG_WARN("pool list ptr is null", K(ret));
7307} else {
7308for (int64_t i = 0; OB_SUCC(ret) && i < pool_list->count(); ++i) {
7309share::ObResourcePool *this_pool = pool_list->at(i);
7310if (OB_UNLIKELY(nullptr == this_pool)) {
7311ret = OB_ERR_UNEXPECTED;
7312LOG_WARN("this pool ptr is null", K(ret));
7313} else if (OB_FAIL(new_pool_list.push_back(this_pool))) {
7314LOG_WARN("fail to to push back", K(ret));
7315} else if (OB_FAIL(new_unit_nums.push_back(
7316this_pool->resource_pool_id_ == pool->resource_pool_id_
7317? alter_unit_num : this_pool->unit_count_))) {
7318LOG_WARN("fail to push back", K(ret));
7319}
7320}
7321if (OB_FAIL(ret)) {
7322} else if (OB_FAIL(check_shrink_granted_pool_allowed_by_tenant_locality(
7323schema_guard, pool->tenant_id_, new_pool_list, new_unit_nums, is_allowed))) {
7324LOG_WARN("fail to check shrink by tenant locality", K(ret));
7325} else {} // no more to do
7326}
7327return ret;
7328}
7329
7330int ObUnitManager::check_shrink_granted_pool_allowed_by_alter_locality(
7331share::ObResourcePool *pool,
7332bool &is_allowed)
7333{
7334int ret = OB_SUCCESS;
7335rootserver::ObRootService *root_service = NULL;
7336bool in_alter_locality = true;
7337if (OB_UNLIKELY(NULL == pool)) {
7338ret = OB_INVALID_ARGUMENT;
7339LOG_WARN("invalid argument", K(ret), KP(pool));
7340} else if (OB_UNLIKELY(!is_valid_tenant_id(pool->tenant_id_))) {
7341ret = OB_INVALID_ARGUMENT;
7342LOG_WARN("invalid tenant id", K(ret), "tenant_id", pool->tenant_id_);
7343} else if (OB_UNLIKELY(NULL == (root_service = GCTX.root_service_))) {
7344ret = OB_ERR_UNEXPECTED;
7345LOG_WARN("rootservice is null", K(ret));
7346} else if (OB_FAIL(root_service->check_tenant_in_alter_locality(
7347pool->tenant_id_, in_alter_locality))) {
7348LOG_WARN("fail to check tenant in alter locality", K(ret), "tenant_id", pool->tenant_id_);
7349} else if (in_alter_locality) {
7350is_allowed = false;
7351LOG_USER_ERROR(OB_OP_NOT_ALLOW, "shrink pool unit num while altering locality");
7352} else {} // no more to do
7353return ret;
7354}
7355
7356// The shrinking operation of the granted resource pool requires the following pre-checks
7357// 1 The design avoids simultaneous migration and shrinkage of units.
7358// Therefore, it is necessary to check whether all the units contained in the current resource pool are in the migration state before shrinking.
7359// If so, shrinking operations are temporarily not allowed, and the migration needs to be completed.
7360// 2 The scaling operation also needs to consider locality.
7361// The number of copies of locality cannot exceed the number of units after scaling.
7362// For example, when the locality is F, R@zone1, the unit num in zone1 cannot be reduced to 1.
7363// 3 Locality changes and scaling under the same tenant are not allowed to be performed at the same time
7364int ObUnitManager::check_shrink_granted_pool_allowed(
7365share::ObResourcePool *pool,
7366const int64_t alter_unit_num,
7367bool &is_allowed)
7368{
7369int ret = OB_SUCCESS;
7370if (OB_UNLIKELY(NULL == pool || alter_unit_num <= 0)) {
7371ret = OB_INVALID_ARGUMENT;
7372LOG_WARN("invalid argument", K(ret), KP(pool), K(alter_unit_num));
7373} else if (OB_GTS_TENANT_ID == pool->tenant_id_) {
7374is_allowed = true;
7375} else if (OB_FAIL(check_shrink_granted_pool_allowed_by_migrate_unit(pool, alter_unit_num, is_allowed))) {
7376LOG_WARN("fail to check by migrate unit", K(ret));
7377} else if (!is_allowed) {
7378LOG_USER_ERROR(OB_OP_NOT_ALLOW, "shrink pool unit num while unit migrating");
7379} else if (OB_FAIL(check_shrink_granted_pool_allowed_by_locality(pool, alter_unit_num, is_allowed))) {
7380LOG_WARN("fail to check by locality", K(ret));
7381} else if (!is_allowed) {
7382LOG_USER_ERROR(OB_OP_NOT_ALLOW, "shrink pool unit num causing not enough locality");
7383} else if (OB_FAIL(check_shrink_granted_pool_allowed_by_alter_locality(pool, is_allowed))) {
7384LOG_WARN("fail to check shrink granted pool allowed by alter locality", K(ret));
7385} else if (!is_allowed) {
7386LOG_USER_ERROR(OB_OP_NOT_ALLOW, "shrink pool unit num while altering locality");
7387}
7388return ret;
7389}
7390
7391int ObUnitManager::complete_migrate_unit_rs_job_in_pool(
7392const int64_t resource_pool_id,
7393const int result_ret,
7394common::ObMySQLTransaction &trans)
7395{
7396int ret = OB_SUCCESS;
7397ObArray<ObUnit *> *units = NULL;
7398if (!inited_) {
7399ret = OB_NOT_INIT;
7400LOG_WARN("not init", K(ret));
7401} else if (OB_INVALID_ID == resource_pool_id) {
7402ret = OB_INVALID_ARGUMENT;
7403LOG_WARN("invalid argument", K(resource_pool_id), K(ret));
7404} else if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
7405LOG_WARN("fail to get unit by pool", K(resource_pool_id), K(ret));
7406} else if (OB_UNLIKELY(NULL == units)) {
7407ret = OB_ERR_UNEXPECTED;
7408LOG_WARN("units is null", KP(units), K(ret));
7409} else {
7410for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
7411const ObUnit *unit = units->at(i);
7412if (OB_UNLIKELY(NULL == unit)) {
7413ret = OB_ERR_UNEXPECTED;
7414LOG_WARN("unit should not be null", K(ret));
7415} else if (unit->is_manual_migrate()) {
7416char ip_buf[common::MAX_IP_ADDR_LENGTH];
7417(void)unit->server_.ip_to_string(ip_buf, common::MAX_IP_ADDR_LENGTH);
7418int64_t job_id = 0;
7419int tmp_ret = RS_JOB_FIND(MIGRATE_UNIT, job_id, *proxy_,
7420"unit_id", unit->unit_id_,
7421"svr_ip", ip_buf,
7422"svr_port", unit->server_.get_port());
7423if (OB_SUCCESS == tmp_ret && job_id > 0) {
7424if (OB_FAIL(RS_JOB_COMPLETE(job_id, result_ret, trans))) {
7425LOG_WARN("all_rootservice_job update failed", K(ret), K(result_ret), K(job_id));
7426}
7427}
7428}
7429}
7430}
7431return ret;
7432}
7433
7434/* the routine that calls the expand_pool_unit_num shall
7435* ensure that this pool is not granted to any tenant
7436*/
7437int ObUnitManager::expand_pool_unit_num_(
7438share::ObResourcePool *pool,
7439const int64_t alter_unit_num)
7440{
7441int ret = OB_SUCCESS;
7442const char *module = "ALTER_RESOURCE_POOL_UNIT_NUM";
7443const bool new_allocate_pool = false;
7444common::ObMySQLTransaction trans;
7445ObArray<ObAddr> new_servers;
7446ObArray<share::ObUnit *> *units = NULL;
7447ObArray<uint64_t> bak_unit_ids;
7448if (OB_UNLIKELY(NULL == pool || alter_unit_num <= pool->unit_count_)) {
7449ret = OB_INVALID_ARGUMENT;
7450LOG_WARN("pool ptr is null", K(ret), "pre_unit_cnt", pool->unit_count_, "cur_unit_cnt", alter_unit_num);
7451} else if (pool->is_granted_to_tenant()) {
7452ret = OB_ERR_UNEXPECTED;
7453LOG_WARN("unexpected pool status", KR(ret), KPC(pool));
7454} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
7455LOG_WARN("start transaction failed", K(ret));
7456} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
7457LOG_WARN("fail to get units by pool", K(ret));
7458} else if (OB_FAIL(extract_unit_ids(*units, bak_unit_ids))) {
7459LOG_WARN("fail to extract unit ids", K(ret));
7460} else if (OB_FAIL(allocate_pool_units_(
7461trans, *pool, pool->zone_list_, nullptr, new_allocate_pool,
7462alter_unit_num - pool->unit_count_, module, new_servers))) {
7463LOG_WARN("arrange units failed", "pool", *pool, K(new_allocate_pool), K(ret));
7464} else {
7465share::ObResourcePool new_pool;
7466if (OB_FAIL(new_pool.assign(*pool))) {
7467LOG_WARN("failed to assign new_poll", K(ret));
7468} else {
7469new_pool.unit_count_ = alter_unit_num;
7470if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, false/*need_check_conflict_with_clone*/))) {
7471LOG_WARN("update_resource_pool failed", K(new_pool), K(ret));
7472}
7473}
7474}
7475
7476if (trans.is_started()) {
7477const bool commit = (OB_SUCC(ret));
7478int temp_ret = OB_SUCCESS;
7479if (OB_SUCCESS != (temp_ret = trans.end(commit))) {
7480LOG_WARN("trans end failed", K(commit), K(temp_ret));
7481ret = (OB_SUCCESS == ret) ? temp_ret : ret;
7482}
7483}
7484
7485if (OB_FAIL(ret)) {
7486// avoid overwrite ret
7487int64_t temp_ret = OB_SUCCESS;
7488if (OB_SUCCESS != (temp_ret = delete_invalid_inmemory_units(pool->resource_pool_id_, bak_unit_ids))) {
7489LOG_WARN("delete unit groups failed", "resource pool id", pool->resource_pool_id_, K(temp_ret));
7490}
7491} else {
7492pool->unit_count_ = alter_unit_num;
7493}
7494return ret;
7495}
7496
7497int ObUnitManager::get_pool_complete_unit_num_and_status(
7498const share::ObResourcePool *pool,
7499int64_t &unit_num_per_zone,
7500int64_t ¤t_unit_num_per_zone,
7501bool &has_unit_num_modification)
7502{
7503int ret = OB_SUCCESS;
7504common::ObArray<share::ObUnit *> *units = NULL;
7505if (OB_UNLIKELY(NULL == pool)) {
7506ret = OB_INVALID_ARGUMENT;
7507LOG_WARN("pool is null", K(ret));
7508} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
7509LOG_WARN("fail to get units by pool", K(ret), "pool_id", pool->resource_pool_id_);
7510} else if (OB_UNLIKELY(NULL == units)) {
7511ret = OB_ERR_UNEXPECTED;
7512LOG_WARN("units is null", K(ret), KP(units), "pool_id", pool->resource_pool_id_);
7513} else if (units->count() <= 0) {
7514ret = OB_ERR_UNEXPECTED;
7515LOG_WARN("total unit num unexpected", K(ret), "total_unit_num", units->count());
7516} else if (pool->zone_list_.count() <= 0) {
7517ret = OB_ERR_UNEXPECTED;
7518LOG_WARN("pool zone list count unexpected", K(ret), "pool_zone_list_count", pool->zone_list_.count());
7519} else {
7520int64_t total_unit_cnt = units->count();
7521int64_t zone_cnt = pool->zone_list_.count();
7522int64_t consult = total_unit_cnt / zone_cnt;
7523if (total_unit_cnt != consult * zone_cnt) {
7524// total_unit_cnt cannot be divisible by zone_cnt,
7525// the number of units in each zone of the resource pool is inconsistent
7526ret = OB_ERR_UNEXPECTED;
7527LOG_WARN("unexpected total unit cnt", K(ret), K(zone_cnt), K(total_unit_cnt));
7528} else {
7529unit_num_per_zone = consult;
7530current_unit_num_per_zone = pool->unit_count_;
7531has_unit_num_modification = false;
7532for (int64_t i = 0; OB_SUCC(ret) && i < units->count() && !has_unit_num_modification; ++i) {
7533const ObUnit *this_unit = units->at(i);
7534if (OB_UNLIKELY(NULL == this_unit)) {
7535ret = OB_ERR_UNEXPECTED;
7536LOG_WARN("unit ptr is null", K(ret), KP(this_unit));
7537} else if (ObUnit::UNIT_STATUS_ACTIVE == this_unit->status_) {
7538// an active unit, go and check next
7539} else if (ObUnit::UNIT_STATUS_DELETING == this_unit->status_) {
7540has_unit_num_modification = true;
7541} else {
7542ret = OB_ERR_UNEXPECTED;
7543LOG_WARN("unexpected unit status", K(ret), "unit_status", this_unit->status_);
7544}
7545}
7546}
7547}
7548return ret;
7549}
7550
7551// According to the unit num of the current resource pool
7552// and the unit_num(alter_unit_num) of the resource pool after the change,
7553// the change type of the current operation is determined.
7554// Let the current num be cur_unit_num, and the num after the change should be alter_unit_num.
7555// The principle is as follows:
7556// 1 cur_unit_num == alter_unit_num, no change, means no operation, no modification
7557// 2 cur_unit_num <alter_unit_num, and there is currently no modification operation of the resource pool and no other unit num,
7558// which is considered to be an expansion operation.
7559// 3 cur_unit_num <alter_unit_num, and the resource pool is shrinking,
7560// the unit_num before shrinking is prev_unit_num,
7561// and alter_unit_num is equal to prev_unit_num,
7562// which is considered to be a shrinking rollback operation.
7563// 4 cur_unit_num> alter_unit_num, and the resource pool has not performed other unit num modification operations,
7564// which is considered to be a shrinking operation
7565int ObUnitManager::determine_alter_unit_num_type(
7566share::ObResourcePool *pool,
7567const int64_t alter_unit_num,
7568AlterUnitNumType &alter_unit_num_type)
7569{
7570int ret = OB_SUCCESS;
7571int64_t complete_unit_num_per_zone = 0; // Contains the unit in the delete state
7572int64_t current_unit_num_per_zone = 0; // unit num in pool->unit_count
7573bool has_unit_num_modification = true;
7574if (OB_UNLIKELY(NULL == pool)) {
7575ret = OB_INVALID_ARGUMENT;
7576LOG_WARN("pool is null", K(ret));
7577} else if (alter_unit_num == pool->unit_count_) {
7578alter_unit_num_type = AUN_NOP; // do nothing
7579} else if (OB_FAIL(get_pool_complete_unit_num_and_status(
7580pool, complete_unit_num_per_zone,
7581current_unit_num_per_zone, has_unit_num_modification))) {
7582LOG_WARN("fail to get pool complete unit num and status", K(ret));
7583} else if (OB_UNLIKELY(complete_unit_num_per_zone <= 0)) {
7584ret = OB_ERR_UNEXPECTED;
7585LOG_WARN("unexpected complete_unit_num", K(ret), K(complete_unit_num_per_zone));
7586} else {
7587if (has_unit_num_modification) { // A unit num change is taking place
7588// pool not granted should not has unit in DELETING status
7589ret = OB_ERR_UNEXPECTED;
7590LOG_WARN("pool not granted is not expected to have unit in DELETING",
7591KR(ret), K(current_unit_num_per_zone), K(complete_unit_num_per_zone));
7592} else {
7593if (alter_unit_num > pool->unit_count_) {
7594alter_unit_num_type = AUN_EXPAND;
7595} else if (alter_unit_num < pool->unit_count_) {
7596alter_unit_num_type = AUN_SHRINK;
7597} else {
7598alter_unit_num_type = AUN_NOP;
7599}
7600}
7601}
7602return ret;
7603}
7604
7605// alter_pool_unit_num changes a single pool's unit_num,
7606// and only works on pool not granted to tenant.
7607int ObUnitManager::alter_pool_unit_num(
7608share::ObResourcePool *pool,
7609int64_t alter_unit_num,
7610const common::ObIArray<uint64_t> &delete_unit_id_array)
7611{
7612int ret = OB_SUCCESS;
7613AlterUnitNumType alter_unit_num_type = AUN_MAX;
7614if (!check_inner_stat()) {
7615ret = OB_INNER_STAT_ERROR;
7616LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
7617} else if (NULL == pool) {
7618ret = OB_INVALID_ARGUMENT;
7619LOG_WARN("pool is null", K(ret));
7620} else if (alter_unit_num <= 0) {
7621ret = OB_INVALID_ARGUMENT;
7622LOG_WARN("invalid alter_unit_num", K(alter_unit_num), K(ret));
7623} else if (pool->is_granted_to_tenant()) {
7624ret = OB_OP_NOT_ALLOW;
7625LOG_WARN("alter pool unit num which is granted to a tenant is not allowed", KR(ret), KPC(pool));
7626LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter pool unit num which is granted to a tenant");
7627} else if (OB_FAIL(determine_alter_unit_num_type(pool, alter_unit_num, alter_unit_num_type))) {
7628LOG_WARN("fail to determine alter unit num type", K(ret));
7629} else if (AUN_NOP == alter_unit_num_type) {
7630// do nothing
7631if (delete_unit_id_array.count() > 0) {
7632ret = OB_NOT_SUPPORTED;
7633LOG_WARN("do not support deleting unit without unit num changed", K(ret));
7634LOG_USER_ERROR(OB_NOT_SUPPORTED, "delete unit without unit num change");
7635} else {} // good
7636} else if (AUN_EXPAND == alter_unit_num_type) {
7637if (delete_unit_id_array.count() > 0) {
7638ret = OB_NOT_SUPPORTED;
7639LOG_WARN("do not support expand pool unit num combined with deleting unit", K(ret));
7640LOG_USER_ERROR(OB_NOT_SUPPORTED, "expand pool unit num combined with deleting unit");
7641} else if (OB_FAIL(expand_pool_unit_num_(pool, alter_unit_num))) {
7642LOG_WARN("fail to expend pool unit num", K(ret), K(alter_unit_num));
7643}
7644} else if (AUN_SHRINK == alter_unit_num_type) {
7645if (OB_FAIL(shrink_pool_unit_num(pool, alter_unit_num, delete_unit_id_array))) {
7646LOG_WARN("fail to shrink pool unit num", K(ret), K(alter_unit_num));
7647}
7648} else if (AUN_ROLLBACK_SHRINK == alter_unit_num_type) {
7649ret = OB_ERR_UNEXPECTED;
7650LOG_WARN("unexpected alter_unit_num_type", KR(ret), K(alter_unit_num));
7651} else if (AUN_MAX == alter_unit_num_type) {
7652ret = OB_OP_NOT_ALLOW;
7653LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter unit num while the previous operation is in progress");
7654LOG_WARN("alter unit num not allowed", K(ret));
7655} else {
7656ret = OB_ERR_UNEXPECTED;
7657LOG_WARN("unexpected alter unit num type", K(ret), K(alter_unit_num_type));
7658}
7659return ret;
7660}
7661
7662int ObUnitManager::get_zone_pools_unit_num(
7663const common::ObZone &zone,
7664const common::ObIArray<share::ObResourcePoolName> &new_pool_name_list,
7665int64_t &total_unit_num,
7666int64_t &full_unit_num,
7667int64_t &logonly_unit_num)
7668{
7669int ret = OB_SUCCESS;
7670SpinRLockGuard guard(lock_);
7671if (!check_inner_stat()) {
7672ret = OB_INNER_STAT_ERROR;
7673LOG_WARN("check_inner_stat failed", K(ret));
7674} else if (zone.is_empty()) {
7675ret = OB_INVALID_ARGUMENT;
7676LOG_WARN("invalid argument", K(ret), K(zone));
7677} else {
7678common::ObArray<share::ObResourcePool *> pool_list;
7679for (int64_t i = 0; OB_SUCC(ret) && i < new_pool_name_list.count(); ++i) {
7680const share::ObResourcePoolName &pool_name = new_pool_name_list.at(i);
7681share::ObResourcePool *pool = NULL;
7682if (OB_FAIL(inner_get_resource_pool_by_name(pool_name, pool))) {
7683LOG_WARN("fail to get resource pool by name", K(ret));
7684} else if (OB_UNLIKELY(NULL == pool)) {
7685ret = OB_ERR_UNEXPECTED;
7686LOG_WARN("pool ptr is null", K(ret), K(pool_name));
7687} else if (OB_FAIL(pool_list.push_back(pool))) {
7688LOG_WARN("fail to push back", K(ret));
7689} else {} // no more to do
7690}
7691if (OB_FAIL(ret)) {
7692} else if (OB_FAIL(inner_get_zone_pools_unit_num(
7693zone, pool_list, total_unit_num, full_unit_num, logonly_unit_num))) {
7694LOG_WARN("fail to inner get pools unit num", K(ret));
7695}
7696}
7697return ret;
7698}
7699
7700int ObUnitManager::check_can_remove_pool_zone_list(
7701const share::ObResourcePool *pool,
7702const common::ObIArray<common::ObZone> &to_be_removed_zones,
7703bool &can_remove)
7704{
7705int ret = OB_SUCCESS;
7706can_remove = true;
7707common::ObArray<share::ObResourcePool *> *pool_list = NULL;
7708share::schema::ObSchemaGetterGuard schema_guard;
7709const share::schema::ObTenantSchema *tenant_schema = NULL;
7710if (OB_UNLIKELY(NULL == pool) || OB_UNLIKELY(to_be_removed_zones.count() <= 0)) {
7711ret = OB_INVALID_ARGUMENT;
7712LOG_WARN("invalid argument", K(ret), KP(pool), K(to_be_removed_zones));
7713} else if (!pool->is_granted_to_tenant()) {
7714can_remove = true; // this pool do not grant to any tenant, can remove zone unit
7715} else if (OB_FAIL(get_pools_by_tenant_(pool->tenant_id_, pool_list))) {
7716LOG_WARN("fail to get pools by tenant", K(ret));
7717} else if (OB_UNLIKELY(NULL == pool_list)) {
7718ret = OB_ERR_UNEXPECTED;
7719LOG_WARN("pool list ptr is null", K(ret));
7720} else if (OB_ISNULL(schema_service_)) {
7721ret = OB_NOT_INIT;
7722LOG_WARN("schema service is null", K(schema_service_), KR(ret));
7723} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(pool->tenant_id_, schema_guard))) {
7724LOG_WARN("fail to get tenant schema guard", KR(ret), K(pool->tenant_id_));
7725} else if (OB_FAIL(schema_guard.get_tenant_info(pool->tenant_id_, tenant_schema))) {
7726LOG_WARN("fail to get tenant schema", K(ret), "tenant_id", pool->tenant_id_);
7727} else if (NULL == tenant_schema) {
7728ret = OB_TENANT_NOT_EXIST;
7729LOG_WARN("tenant schema is null", K(ret));
7730} else if (!tenant_schema->get_previous_locality_str().empty()) {
7731can_remove = false;
7732LOG_WARN("alter pool zone list is not allowed while locality modification",
7733"tenant_id", tenant_schema->get_tenant_id());
7734} else {
7735for (int64_t i = 0; can_remove && OB_SUCC(ret) && i < to_be_removed_zones.count(); ++i) {
7736int64_t total_unit_num = 0;
7737int64_t full_unit_num = 0;
7738int64_t logonly_unit_num = 0;
7739const common::ObZone &zone = to_be_removed_zones.at(i);
7740bool enough = false;
7741if (OB_FAIL(inner_get_zone_pools_unit_num(
7742zone, *pool_list, total_unit_num, full_unit_num, logonly_unit_num))) {
7743LOG_WARN("fail to get zone pools unit num", K(ret));
7744} else if (total_unit_num != full_unit_num + logonly_unit_num) {
7745ret = OB_ERR_UNEXPECTED;
7746LOG_WARN("unit num value not match", K(ret),
7747K(total_unit_num), K(full_unit_num), K(logonly_unit_num));
7748} else {
7749// Reduce the unit of this pool on to be remove zone
7750total_unit_num -= pool->unit_count_;
7751if (common::REPLICA_TYPE_FULL == pool->replica_type_) {
7752full_unit_num -= pool->unit_count_;
7753} else if (common::REPLICA_TYPE_LOGONLY == pool->replica_type_) {
7754logonly_unit_num -= pool->unit_count_;
7755} else {
7756ret = OB_ERR_UNEXPECTED;
7757LOG_WARN("do not support this pool type", K(ret), K(*pool));
7758}
7759}
7760if (OB_FAIL(ret)) {
7761} else if (OB_FAIL(inner_check_schema_zone_unit_enough(
7762zone, total_unit_num, full_unit_num, logonly_unit_num,
7763*tenant_schema, schema_guard, enough))) {
7764LOG_WARN("fail to inner check schema zone unit enough", K(ret));
7765} else if (!enough) {
7766can_remove = false;
7767} else {}
7768}
7769}
7770return ret;
7771}
7772
7773int ObUnitManager::inner_get_zone_pools_unit_num(
7774const common::ObZone &zone,
7775const common::ObIArray<share::ObResourcePool *> &pool_list,
7776int64_t &total_unit_num,
7777int64_t &full_unit_num,
7778int64_t &logonly_unit_num)
7779{
7780int ret = OB_SUCCESS;
7781if (!check_inner_stat()) {
7782ret = OB_INNER_STAT_ERROR;
7783LOG_WARN("check inner stat failed", K(ret));
7784} else if (zone.is_empty()) {
7785ret = OB_INVALID_ARGUMENT;
7786LOG_WARN("invalid argument", K(ret), K(zone));
7787} else {
7788total_unit_num = 0;
7789full_unit_num = 0;
7790logonly_unit_num = 0;
7791for (int64_t i = 0; OB_SUCC(ret) && i < pool_list.count(); ++i) {
7792share::ObResourcePool *pool = pool_list.at(i);
7793if (OB_UNLIKELY(NULL == pool)) {
7794ret = OB_ERR_UNEXPECTED;
7795LOG_WARN("pool ptr is null", K(ret));
7796} else if (!has_exist_in_array(pool->zone_list_, zone)) {
7797//ignore
7798} else {
7799total_unit_num += pool->unit_count_;
7800if (common::REPLICA_TYPE_FULL == pool->replica_type_) {
7801full_unit_num += pool->unit_count_;
7802} else if (common::REPLICA_TYPE_LOGONLY == pool->replica_type_) {
7803logonly_unit_num += pool->unit_count_;
7804} else {
7805ret = OB_ERR_UNEXPECTED;
7806LOG_WARN("do not support this pool type", K(ret), K(*pool));
7807}
7808}
7809}
7810}
7811return ret;
7812}
7813
7814int ObUnitManager::alter_pool_zone_list(
7815share::ObResourcePool *pool,
7816const ObIArray<ObZone> &zone_list)
7817{
7818// The requirement of alter pool_zone_list is currently only for cluster relocation.
7819// Before deleting the zone,
7820// the pool_zone_list that contains the zone in all resource pools needs to be removed from the zone_list..
7821int ret = OB_SUCCESS;
7822if (!check_inner_stat()) {
7823ret = OB_INNER_STAT_ERROR;
7824LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
7825} else if (OB_UNLIKELY(NULL == pool || zone_list.count() <= 0)) {
7826ret = OB_INVALID_ARGUMENT;
7827LOG_WARN("invalid argument", K(ret), KP(pool), "new zone list", zone_list);
7828} else {
7829ObArray<ObZone> new_zone_list;
7830//check repeat
7831for (int64_t i = 0; i < zone_list.count() && OB_SUCC(ret); ++i) {
7832if (has_exist_in_array(new_zone_list, zone_list.at(i))) {
7833ret = OB_OP_NOT_ALLOW;
7834LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter resource pool zone repeat");
7835LOG_WARN("alter resource pool zone repeat not allow", K(ret));
7836} else if (OB_FAIL(new_zone_list.push_back(zone_list.at(i)))) {
7837LOG_WARN("fail to push back", K(ret));
7838} else {}//no more to do
7839}
7840if (OB_SUCC(ret)) {
7841std::sort(new_zone_list.begin(), new_zone_list.end());
7842bool is_add_pool_zone = false;
7843bool is_remove_pool_zone = false;
7844for (int64_t i = 0; i < new_zone_list.count() && OB_SUCC(ret); ++i) {
7845if (!has_exist_in_array(pool->zone_list_, new_zone_list.at(i))) {
7846is_add_pool_zone = true;
7847} else {}//nothing todo
7848}
7849for (int64_t i = 0; i < pool->zone_list_.count() && OB_SUCC(ret); ++i) {
7850if (!has_exist_in_array(new_zone_list, pool->zone_list_.at(i))) {
7851is_remove_pool_zone = true;
7852} else {}//nothing todo
7853}
7854if (is_add_pool_zone && is_remove_pool_zone) {
7855ret = OB_OP_NOT_ALLOW;
7856LOG_USER_ERROR(OB_OP_NOT_ALLOW, "Cannot add and delete zones at the same time");
7857LOG_WARN("Cannot add and delete zones at the same time", K(ret));
7858} else if (is_add_pool_zone) {
7859if (OB_FAIL(add_pool_zone_list(pool, new_zone_list))) {
7860LOG_WARN("fail to add pool zone list", K(ret));
7861}
7862} else {
7863if (OB_FAIL(remove_pool_zone_list(pool, new_zone_list))) {
7864LOG_WARN("fail to remoce pool zone list", K(ret));
7865}
7866}
7867}
7868}
7869return ret;
7870}
7871
7872int ObUnitManager::remove_pool_zone_list(
7873share::ObResourcePool *pool,
7874const ObIArray<ObZone> &zone_list)
7875{
7876int ret = OB_SUCCESS;
7877bool can_remove = false;
7878common::ObArray<common::ObZone> zones_to_be_removed;
7879const common::ObIArray<common::ObZone> &prev_zone_list = pool->zone_list_;
7880if (OB_FAIL(cal_to_be_removed_pool_zone_list(
7881prev_zone_list, zone_list, zones_to_be_removed))) {
7882LOG_WARN("fail to calculate to be removed pool zone list", K(ret));
7883} else if (zones_to_be_removed.count() <= 0) {
7884// no zones need to be removed, return SUCC directly
7885} else if (OB_FAIL(check_can_remove_pool_zone_list(pool, zones_to_be_removed, can_remove))) {
7886LOG_WARN("fail to check can remove pool zon list", K(ret));
7887} else if (!can_remove) {
7888ret = OB_OP_NOT_ALLOW;
7889LOG_WARN("cannot alter resource pool zone list", K(ret),
7890"pool", *pool, K(zones_to_be_removed));
7891LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter resource pool zone list with not empty unit");
7892} else if (OB_FAIL(do_remove_pool_zone_list(pool, zone_list, zones_to_be_removed))) {
7893LOG_WARN("fail to do remove pool zone list", K(ret), "pool", *pool, K(zones_to_be_removed));
7894} else {} // no more to do
7895return ret;
7896}
7897
7898int ObUnitManager::add_pool_zone_list(
7899share::ObResourcePool *pool,
7900const ObIArray<ObZone> &zone_list)
7901{
7902int ret = OB_SUCCESS;
7903bool can_add = false;
7904common::ObArray<common::ObZone> zones_to_be_add;
7905bool is_add_pool_zone_list_allowed = true;
7906if (OB_UNLIKELY(nullptr == pool)) {
7907ret = OB_INVALID_ARGUMENT;
7908LOG_WARN("invalid argument", KR(ret), KP(pool));
7909} else if (! pool->is_granted_to_tenant()) {
7910// good, can do add pool zone list directly
7911is_add_pool_zone_list_allowed = true;
7912} else {
7913if (OB_FAIL(check_expand_zone_resource_allowed_by_old_unit_stat_(
7914pool->tenant_id_, is_add_pool_zone_list_allowed))) {
7915LOG_WARN("fail to check grant pools allowed by unit stat",
7916KR(ret), "tenant_id", pool->tenant_id_);
7917}
7918}
7919
7920if (OB_FAIL(ret)) {
7921// bypass
7922} else if (!is_add_pool_zone_list_allowed) {
7923ret = OB_OP_NOT_ALLOW;
7924LOG_USER_ERROR(OB_OP_NOT_ALLOW, "add pool zone when granted pools of tenant in shrinking");
7925} else if (OB_FAIL(cal_to_be_add_pool_zone_list(
7926pool->zone_list_, zone_list, zones_to_be_add))) {
7927LOG_WARN("fail to calculate to be add pool zone list", K(ret));
7928} else if (zones_to_be_add.count() <= 0) {
7929//no zones need to be add, return SUCC directly
7930} else if (OB_FAIL(check_can_add_pool_zone_list_by_locality(pool, zones_to_be_add, can_add))) {
7931LOG_WARN("fail to check can add pool zone list", K(ret));
7932} else if (!can_add) {
7933ret = OB_OP_NOT_ALLOW;
7934LOG_WARN("cannot alter resource pool zone list", K(ret),
7935"pool", *pool, K(zones_to_be_add));
7936LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter resource pool zone list with not empty unit");
7937} else if (OB_FAIL(do_add_pool_zone_list(pool, zone_list, zones_to_be_add))) {
7938LOG_WARN("fail to do add pool zone list", K(ret), "pool", *pool, K(zones_to_be_add));
7939} else {} // no more to do
7940return ret;
7941}
7942
7943int ObUnitManager::cal_to_be_add_pool_zone_list(
7944const common::ObIArray<common::ObZone> &prev_zone_list,
7945const common::ObIArray<common::ObZone> &cur_zone_list,
7946common::ObIArray<common::ObZone> &to_be_add_zones) const
7947{
7948int ret = OB_SUCCESS;
7949if (OB_UNLIKELY(prev_zone_list.count() <= 0 || cur_zone_list.count() <= 0)) {
7950ret = OB_INVALID_ARGUMENT;
7951LOG_WARN("invalid argument", K(ret),
7952"prev zone list", prev_zone_list,
7953"cur zone list", cur_zone_list);
7954} else {
7955to_be_add_zones.reset();
7956//Check if the added zone exists
7957for (int64_t i = 0; OB_SUCC(ret) && i < cur_zone_list.count(); ++i) {
7958const common::ObZone &this_zone = cur_zone_list.at(i);
7959bool zone_exist = false;
7960if (OB_FAIL(zone_mgr_.check_zone_exist(this_zone, zone_exist))) {
7961LOG_WARN("failed to check zone exists", K(ret), K(this_zone));
7962} else if (!zone_exist) {
7963ret = OB_ZONE_INFO_NOT_EXIST;
7964LOG_WARN("zone not exists", K(ret), K(this_zone));
7965} else {
7966if (has_exist_in_array(prev_zone_list, this_zone)) {
7967//still exist, do nothing
7968} else if (has_exist_in_array(to_be_add_zones, this_zone)) {
7969//just add one time
7970ret = OB_OP_NOT_ALLOW;
7971LOG_USER_ERROR(OB_OP_NOT_ALLOW, "add repeat zone");
7972LOG_WARN("not allow add repeat zone", K(ret));
7973} else if (OB_FAIL(to_be_add_zones.push_back(this_zone))) {
7974LOG_WARN("fail to push back", K(ret));
7975}
7976}
7977}
7978}
7979return ret;
7980}
7981
7982int ObUnitManager::check_can_add_pool_zone_list_by_locality(
7983const share::ObResourcePool *pool,
7984const common::ObIArray<common::ObZone> &to_be_add_zones,
7985bool &can_add)
7986{
7987int ret = OB_SUCCESS;
7988can_add = true;
7989common::ObArray<share::ObResourcePool *> *pool_list = NULL;
7990share::schema::ObSchemaGetterGuard schema_guard;
7991const share::schema::ObTenantSchema *tenant_schema = NULL;
7992if (OB_UNLIKELY(NULL == pool) || OB_UNLIKELY(to_be_add_zones.count() <= 0)) {
7993ret = OB_INVALID_ARGUMENT;
7994LOG_WARN("ivnalid argument", K(ret), KP(pool), K(to_be_add_zones));
7995} else if (! pool->is_granted_to_tenant()) {
7996can_add = true; // not in tenant, can add zone unit
7997} else if (OB_FAIL(get_pools_by_tenant_(pool->tenant_id_, pool_list))) {
7998LOG_WARN("fail to get pools by tenant", K(ret));
7999} else if (OB_ISNULL(schema_service_)) {
8000ret = OB_NOT_INIT;
8001LOG_WARN("schema service is null", K(schema_service_), KR(ret));
8002} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(pool->tenant_id_, schema_guard))) {
8003LOG_WARN("fail to get tenant schema guard", KR(ret), K(pool->tenant_id_));
8004} else if (OB_FAIL(schema_guard.get_tenant_info(pool->tenant_id_, tenant_schema))) {
8005LOG_WARN("fail to get tenant schema", K(ret), "tenant_id", pool->tenant_id_);
8006} else if (NULL == tenant_schema) {
8007ret = OB_SCHEMA_ERROR;
8008LOG_WARN("tenant schema is null", K(ret));
8009} else if (!tenant_schema->get_previous_locality_str().empty()) {//No locality changes are allowed at this time
8010can_add = false;
8011LOG_WARN("alter pool zone list is not allowed while locality modification",
8012"tenant_id", tenant_schema->get_tenant_id());
8013} else {} //nothing todo
8014return ret;
8015}
8016
8017int ObUnitManager::do_add_pool_zone_list(
8018share::ObResourcePool *pool,
8019const common::ObIArray<common::ObZone> &new_zone_list,
8020const common::ObIArray<common::ObZone> &to_be_add_zones)
8021{
8022int ret = OB_SUCCESS;
8023common::ObMySQLTransaction trans;
8024share::ObResourcePool new_pool;
8025const char *module = "ALTER_RESOURCE_POOL_ZONE_LIST";
8026if (!check_inner_stat()) {
8027ret = OB_INNER_STAT_ERROR;
8028LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
8029} else if (OB_UNLIKELY(NULL == pool)
8030|| OB_UNLIKELY(to_be_add_zones.count() <= 0)
8031|| OB_UNLIKELY(new_zone_list.count() <= 0)) {
8032ret = OB_INVALID_ARGUMENT;
8033LOG_WARN("invalid argument", K(ret), KP(pool), K(to_be_add_zones), K(new_zone_list));
8034} else {
8035if (OB_FAIL(new_pool.assign(*pool))) {
8036LOG_WARN("fail to assign new pool", K(ret));
8037} else if (OB_FAIL(new_pool.zone_list_.assign(new_zone_list))) {
8038LOG_WARN("fail to assign new pool zone list", K(ret));
8039} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
8040LOG_WARN("start transaction failed", K(ret));
8041} else {
8042if (OB_FAIL(increase_units_in_zones_(trans, *pool, to_be_add_zones, module))) {
8043LOG_WARN("fail to add units in zones", K(module), KR(ret),
8044"pool id", pool->resource_pool_id_, K(to_be_add_zones));
8045} else if (OB_FAIL(pool->zone_list_.assign(new_zone_list))) {
8046LOG_WARN("fail to update pool zone list in memory", K(ret));
8047} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, false/*need_check_conflict_with_clone*/))) {
8048LOG_WARN("fail to update resource pool", K(ret));
8049} else {} //no more to do
8050if (trans.is_started()) {
8051const bool commit = (OB_SUCC(ret));
8052int tmp_ret = OB_SUCCESS;
8053if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
8054LOG_WARN("fail to end trans", K(commit), K(tmp_ret));
8055ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
8056}
8057} else {}//nothing todo
8058}
8059}
8060return ret;
8061}
8062
8063// allocate new units on new added zones for resource pool
8064int ObUnitManager::increase_units_in_zones_(
8065common::ObISQLClient &client,
8066share::ObResourcePool &pool,
8067const common::ObIArray<common::ObZone> &to_be_add_zones,
8068const char *module)
8069{
8070int ret = OB_SUCCESS;
8071ObArray<uint64_t> new_unit_group_id_array;
8072const bool new_allocate_pool = false; // whether to alloacate new resource pool
8073const int64_t new_unit_count = pool.unit_count_; // new unit count on every zone
8074ObArray<ObAddr> new_servers;
8075
8076for (int64_t i = 0; OB_SUCC(ret) && i < to_be_add_zones.count(); ++i) {
8077bool zone_exist = false;
8078if (OB_FAIL(zone_mgr_.check_zone_exist(to_be_add_zones.at(i), zone_exist))) {
8079LOG_WARN("failed to check zone exists", K(ret), K(to_be_add_zones.at(i)));
8080} else if (!zone_exist) {
8081ret = OB_ZONE_INFO_NOT_EXIST;
8082LOG_WARN("zone not exists", K(ret), K(to_be_add_zones.at(i)));
8083}
8084}
8085
8086if (OB_FAIL(ret)) {
8087} else if (OB_FAIL(get_pool_unit_group_id_(pool, new_unit_group_id_array))) {
8088LOG_WARN("fail to get pool unit group id", KR(ret), K(pool));
8089} else if (OB_FAIL(allocate_pool_units_(client, pool, to_be_add_zones, &new_unit_group_id_array,
8090new_allocate_pool, new_unit_count, module, new_servers))) {
8091LOG_WARN("fail to allocate new units for new added zones", K(module), KR(ret), K(to_be_add_zones), K(pool),
8092K(new_unit_count), K(new_unit_group_id_array));
8093}
8094
8095return ret;
8096}
8097
8098int ObUnitManager::do_remove_pool_zone_list(
8099share::ObResourcePool *pool,
8100const common::ObIArray<common::ObZone> &new_zone_list,
8101const common::ObIArray<common::ObZone> &to_be_removed_zones)
8102{
8103int ret = OB_SUCCESS;
8104common::ObMySQLTransaction trans;
8105share::ObResourcePool new_pool;
8106common::ObArray<common::ObZone> new_zone_list1;
8107if (!check_inner_stat()) {
8108ret = OB_INNER_STAT_ERROR;
8109LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
8110} else if (OB_UNLIKELY(NULL == pool)
8111|| OB_UNLIKELY(to_be_removed_zones.count() <= 0)
8112|| OB_UNLIKELY(new_zone_list.count() <= 0)) {
8113ret = OB_INVALID_ARGUMENT;
8114LOG_WARN("invalid argument", K(ret), KP(pool), K(to_be_removed_zones), K(new_zone_list));
8115} else {
8116if (OB_FAIL(new_pool.assign(*pool))) {
8117LOG_WARN("fail to assign new pool", K(ret));
8118} else if (OB_FAIL(new_pool.zone_list_.assign(new_zone_list))) {
8119LOG_WARN("fail to assign new pool zone list", K(ret));
8120} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
8121LOG_WARN("start transaction failed", K(ret));
8122} else {
8123if (OB_FAIL(ut_operator_.remove_units_in_zones(
8124trans, pool->resource_pool_id_, to_be_removed_zones))) {
8125LOG_WARN("fail to remove units in zones", K(ret),
8126"pool id", pool->resource_pool_id_, K(to_be_removed_zones));
8127} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, false/*need_check_conflict_with_clone*/))) {
8128LOG_WARN("fail to update resource pool", K(ret));
8129} else {} // no more to do
8130if (trans.is_started()) {
8131const bool commit = (OB_SUCC(ret));
8132int tmp_ret = OB_SUCCESS;
8133if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
8134LOG_WARN("fail to end trans", K(commit), K(tmp_ret));
8135ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
8136}
8137}
8138if (OB_FAIL(ret)) {
8139} else if (OB_FAIL(delete_units_in_zones(pool->resource_pool_id_, to_be_removed_zones))) {
8140LOG_WARN("fail to delete units in zones", K(ret),
8141"pool id", pool->resource_pool_id_, K(to_be_removed_zones));
8142} else if (OB_FAIL(pool->zone_list_.assign(new_zone_list))) {
8143LOG_WARN("fail to update pool zone list in memory", K(ret));
8144} else {} // no more to do
8145}
8146}
8147return ret;
8148}
8149
8150int ObUnitManager::cal_to_be_removed_pool_zone_list(
8151const common::ObIArray<common::ObZone> &prev_zone_list,
8152const common::ObIArray<common::ObZone> &cur_zone_list,
8153common::ObIArray<common::ObZone> &to_be_removed_zones) const
8154{
8155int ret = OB_SUCCESS;
8156if (OB_UNLIKELY(prev_zone_list.count() <= 0 || cur_zone_list.count() <= 0)) {
8157ret = OB_INVALID_ARGUMENT;
8158LOG_WARN("invalid argument", K(ret),
8159"prev zone list", prev_zone_list,
8160"cur zone list", cur_zone_list);
8161} else {
8162to_be_removed_zones.reset();
8163// Each zone in cur_zone_list must be included in prev_zone_list
8164for (int64_t i = 0; OB_SUCC(ret) && i < cur_zone_list.count(); ++i) {
8165const common::ObZone &this_zone = cur_zone_list.at(i);
8166if (!has_exist_in_array(prev_zone_list, this_zone)) {
8167ret = OB_NOT_SUPPORTED;
8168LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter resource pool zone list with a new zone");
8169LOG_WARN("alter resource pool zone list with a new zone is not supported", K(ret));
8170} else {} // good
8171}
8172for (int64_t i = 0; OB_SUCC(ret) && i < prev_zone_list.count(); ++i) {
8173const common::ObZone &this_zone = prev_zone_list.at(i);
8174if (has_exist_in_array(cur_zone_list, this_zone)) {
8175// still exist, do nothing
8176} else if (OB_FAIL(to_be_removed_zones.push_back(this_zone))) {
8177LOG_WARN("fail to push back", K(ret));
8178} else {} // no more to do
8179}
8180}
8181return ret;
8182}
8183
8184int ObUnitManager::check_full_resource_pool_memory_condition(
8185const common::ObIArray<share::ObResourcePool *> &pools,
8186const int64_t memory_size) const
8187{
8188int ret = OB_SUCCESS;
8189for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
8190const share::ObResourcePool *pool = pools.at(i);
8191if (OB_UNLIKELY(nullptr == pool)) {
8192ret = OB_ERR_UNEXPECTED;
8193LOG_WARN("pool ptr is null", K(ret), KP(pool));
8194} else if (REPLICA_TYPE_FULL != pool->replica_type_) {
8195// bypass
8196} else if (memory_size < GCONF.__min_full_resource_pool_memory) {
8197ret = OB_NOT_SUPPORTED;
8198LOG_WARN("full resource pool min memory illegal", KR(ret), K(memory_size),
8199"__min_full_resource_pool_memory", (int64_t)GCONF.__min_full_resource_pool_memory);
8200LOG_USER_ERROR(OB_NOT_SUPPORTED, "unit MEMORY_SIZE less than __min_full_resource_pool_memory");
8201}
8202}
8203return ret;
8204}
8205
8206ERRSIM_POINT_DEF(ERRSIM_USE_DUMMY_SERVER);
8207int ObUnitManager::check_expand_resource_(
8208const char *module,
8209const common::ObIArray<share::ObResourcePool *> &pools,
8210const share::ObUnitResource &old_resource,
8211const share::ObUnitResource &new_resource) const
8212{
8213int ret = OB_SUCCESS;
8214common::hash::ObHashMap<ObAddr, int64_t> server_ref_count_map;
8215ObString err_str;
8216AlterResourceErr err_index = ALT_ERR;
8217int temp_ret = OB_SUCCESS;
8218if (!check_inner_stat()) {
8219ret = OB_INNER_STAT_ERROR;
8220LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
8221} else if (pools.count() <= 0) {
8222ret = OB_INVALID_ARGUMENT;
8223LOG_WARN("pools is empty", K(pools), K(ret));
8224} else if (!old_resource.is_valid() || !new_resource.is_valid()) {
8225ret = OB_INVALID_ARGUMENT;
8226LOG_WARN("invalid old_resource or invalid new_resource", K(old_resource), K(new_resource), K(ret));
8227} else if (!new_resource.has_expanded_resource_than(old_resource)) {
8228// skip, no need to check
8229LOG_INFO("new unit_resource has no expanded resource, skip check_expand_resource",
8230KR(ret), K(old_resource), K(new_resource));
8231} else if (OB_FAIL(server_ref_count_map.create(
8232SERVER_REF_COUNT_MAP_BUCKET_NUM, ObModIds::OB_HASH_BUCKET_SERVER_REF_COUNT_MAP))) {
8233LOG_WARN("pool_unit_map_ create failed",
8234"bucket_num", static_cast<int64_t>(SERVER_REF_COUNT_MAP_BUCKET_NUM), K(ret));
8235} else if (OB_FAIL(get_pools_servers(pools, server_ref_count_map))) {
8236LOG_WARN("get pools server failed", K(pools), K(ret));
8237} else {
8238bool can_expand = true;
8239const ObUnitResource delta = new_resource - old_resource;
8240ObUnitResource expand_resource;
8241ObServerInfoInTable server_info;
8242_LOG_INFO("[%s] check_expand_resource begin. old=%s, new=%s, delta=%s", module,
8243to_cstring(old_resource), to_cstring(new_resource), to_cstring(delta));
8244
8245FOREACH_X(iter, server_ref_count_map, OB_SUCCESS == ret) {
8246expand_resource = delta * (iter->second);
8247const ObAddr &server = iter->first;
8248server_info.reset();
8249_LOG_INFO("[%s] check_expand_resource. svr=%s, pools=%ld, expand_resource=%s", module,
8250to_cstring(server), iter->second, to_cstring(expand_resource));
8251if (OB_FAIL(SVR_TRACER.get_server_info(server, server_info))) {
8252LOG_WARN("fail to get server_info", KR(ret), K(server));
8253} else if (OB_UNLIKELY(!server_info.is_active())) {
8254ret = OB_OP_NOT_ALLOW;
8255LOG_WARN("server is inactive, cannot check_expand_resource", KR(ret), K(server), K(server_info));
8256const int64_t ERR_MSG_LEN = 256;
8257char err_msg[ERR_MSG_LEN] = {'\0'};
8258int tmp_ret = OB_SUCCESS;
8259int64_t pos = 0;
8260if (OB_TMP_FAIL(databuff_printf(err_msg, ERR_MSG_LEN, pos,
8261"Server %s is inactive, expanding resource",
8262to_cstring(OB_SUCCESS != ERRSIM_USE_DUMMY_SERVER ? ObAddr() : server)))) {
8263LOG_WARN("format err_msg failed", KR(tmp_ret), KR(ret));
8264} else {
8265LOG_USER_ERROR(OB_OP_NOT_ALLOW, err_msg);
8266}
8267} else if (OB_FAIL(check_expand_resource_(server_info, expand_resource, can_expand, err_index))) {
8268LOG_WARN("check expand resource failed", KR(ret), K(server_info));
8269} else if (!can_expand) {
8270const ObZone &zone = server_info.get_zone();
8271LOG_USER_ERROR(OB_MACHINE_RESOURCE_NOT_ENOUGH, to_cstring(zone), to_cstring(server),
8272alter_resource_err_to_str(err_index));
8273// return ERROR
8274ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
8275}
8276}
8277}
8278return ret;
8279}
8280
8281int ObUnitManager::check_expand_resource_(
8282const share::ObServerInfoInTable &server_info,
8283const ObUnitResource &expand_resource,
8284bool &can_expand,
8285AlterResourceErr &err_index) const
8286{
8287int ret = OB_SUCCESS;
8288double hard_limit = 0;
8289bool can_hold_unit = false;
8290can_expand = true;
8291obrpc::ObGetServerResourceInfoResult report_server_resource_info;
8292// some item of expand_resource may be negative, so we don't check expand_resource here
8293if (!check_inner_stat()) {
8294ret = OB_INNER_STAT_ERROR;
8295LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
8296} else if (!server_info.is_valid()) {
8297ret = OB_INVALID_ARGUMENT;
8298LOG_WARN("invalid server_info", KR(ret), K(server_info));
8299} else if (OB_FAIL(get_hard_limit(hard_limit))) {
8300LOG_WARN("get_hard_limit failed", K(ret));
8301} else if (OB_FAIL(get_server_resource_info_via_rpc(server_info, report_server_resource_info))) {
8302LOG_WARN("get_server_resource_info_via_rpc failed", KR(ret), K(server_info));
8303} else if (OB_FAIL(have_enough_resource(
8304report_server_resource_info,
8305expand_resource,
8306hard_limit,
8307can_hold_unit,
8308err_index))) {
8309LOG_WARN("fail to check have enough resource", KR(ret), K(hard_limit),
8310K(report_server_resource_info), K(expand_resource));
8311} else if (!can_hold_unit) {
8312can_expand = false;
8313// don't need to set ret
8314LOG_WARN("find server can't hold expanded resource", KR(ret), K(server_info),
8315K(report_server_resource_info), K(expand_resource));
8316} else {
8317can_expand = true;
8318}
8319return ret;
8320}
8321
8322int ObUnitManager::check_shrink_resource_(const ObIArray<share::ObResourcePool *> &pools,
8323const ObUnitResource &resource,
8324const ObUnitResource &new_resource) const
8325{
8326int ret = OB_SUCCESS;
8327if (!check_inner_stat()) {
8328ret = OB_INNER_STAT_ERROR;
8329LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
8330} else if (pools.count() <= 0) {
8331ret = OB_INVALID_ARGUMENT;
8332LOG_WARN("pools is empty", K(pools), K(ret));
8333} else if (!resource.is_valid() || !new_resource.is_valid()) {
8334ret = OB_INVALID_ARGUMENT;
8335LOG_WARN("invalid resource or invalid new_resource", K(resource), K(new_resource), K(ret));
8336} else if (!new_resource.has_shrunk_resource_than(resource)) {
8337// skip, no need to check
8338LOG_INFO("new unit_resource has no shrunk resource, skip check_shrink_resource",
8339KR(ret), K(resource), K(new_resource));
8340} else {
8341for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
8342const share::ObResourcePool *pool = pools.at(i);
8343if (OB_UNLIKELY(NULL == pool)) {
8344ret = OB_ERR_UNEXPECTED;
8345LOG_WARN("pool ptr is null", K(ret));
8346} else if (OB_FAIL(check_shrink_resource_(*pool, resource, new_resource))) {
8347LOG_WARN("fail to check shrink resource", KR(ret));
8348} else {} // no more to do
8349}
8350}
8351return ret;
8352}
8353
8354int ObUnitManager::check_shrink_resource_(const share::ObResourcePool &pool,
8355const ObUnitResource &resource,
8356const ObUnitResource &new_resource) const
8357{
8358int ret = OB_SUCCESS;
8359if (!check_inner_stat()) {
8360ret = OB_INNER_STAT_ERROR;
8361LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
8362} else if (!pool.is_valid() || !resource.is_valid() || !new_resource.is_valid()) {
8363ret = OB_INVALID_ARGUMENT;
8364LOG_WARN("invalid pool or invalid resource or invalid new_resource", K(pool),
8365K(resource), K(new_resource), K(ret));
8366} else {
8367if (new_resource.max_cpu() < resource.max_cpu()) {
8368// cpu don't need check
8369}
8370
8371if (new_resource.memory_size() < resource.memory_size()) {
8372if (!pool.is_granted_to_tenant()) {
8373// do nothing
8374} else if (OB_FAIL(check_shrink_memory(pool,resource.memory_size(), new_resource.memory_size()))) {
8375LOG_WARN("check_shrink_memory failed", "tenant_id", pool.tenant_id_,
8376"old_resource_mem", resource.memory_size(),
8377"new_resource_mem", new_resource.memory_size(), KR(ret));
8378}
8379}
8380
8381if (new_resource.log_disk_size() < resource.log_disk_size()) {
8382// log disk don't need check.
8383}
8384}
8385return ret;
8386}
8387
8388int ObUnitManager::check_shrink_memory(
8389const share::ObResourcePool &pool,
8390const int64_t old_memory,
8391const int64_t new_memory) const
8392{
8393int ret = OB_SUCCESS;
8394ObArray<ObUnit *> *units = NULL;
8395ObArray<common::ObAddr> unit_servers;
8396
8397if (!check_inner_stat()) {
8398ret = OB_INNER_STAT_ERROR;
8399LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
8400} else if (! pool.is_granted_to_tenant()) {
8401ret = OB_INVALID_ARGUMENT;
8402LOG_WARN("pool is not granted to valid tenant, invalid pool", KR(ret), K(pool));
8403} else if (old_memory <= 0 || new_memory <= 0 || new_memory >= old_memory) {
8404ret = OB_INVALID_ARGUMENT;
8405LOG_WARN("invalid old_memory or invalid new_memory",
8406K(old_memory), K(new_memory), K(ret));
8407} else if (OB_FAIL(get_units_by_pool(pool.resource_pool_id_, units))) {
8408LOG_WARN("fail to get units by pool", K(ret));
8409} else if (OB_UNLIKELY(NULL == units)) {
8410ret = OB_ERR_UNEXPECTED;
8411LOG_WARN("units ptr is null", K(ret));
8412} else {
8413for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
8414ObUnit *unit = units->at(i);
8415if (OB_UNLIKELY(NULL == unit)) {
8416ret = OB_ERR_UNEXPECTED;
8417LOG_WARN("unit ptr is null", K(ret));
8418} else if (OB_FAIL(unit_servers.push_back(unit->server_))) {
8419LOG_WARN("fail to push back", K(ret));
8420} else if (!unit->migrate_from_server_.is_valid()) {
8421// this unit is not in migrating
8422} else if (OB_FAIL(unit_servers.push_back(unit->migrate_from_server_))) {
8423LOG_WARN("fail to push back", K(ret));
8424}
8425}
8426const double max_used_ratio = 0.9;
8427const double shrink_ratio = static_cast<double>(new_memory)
8428/ static_cast<double>(old_memory);
8429int64_t max_used_memory = 0;
8430ObArray<ObTenantMemstoreInfoOperator::TenantServerMemInfo> mem_infos;
8431ObTenantMemstoreInfoOperator mem_info_operator(*proxy_);
8432if (OB_FAIL(ret)) {
8433// failed
8434} else if (OB_FAIL(mem_info_operator.get(pool.tenant_id_, unit_servers, mem_infos))) {
8435LOG_WARN("mem_info_operator get failed", K(ret));
8436} else {
8437FOREACH_CNT_X(mem_info, mem_infos, OB_SUCCESS == ret) {
8438max_used_memory = static_cast<int64_t>(static_cast<double>(mem_info->memstore_limit_)
8439* shrink_ratio * max_used_ratio);
8440if (mem_info->total_memstore_used_ > max_used_memory) {
8441ret = OB_NOT_SUPPORTED;
8442LOG_USER_ERROR(OB_NOT_SUPPORTED, "requested memory over 90 percent of total available memory");
8443LOG_WARN("new memory will cause memory use percentage over ninety percentage",
8444"mem_info", *mem_info, K(old_memory), K(new_memory),
8445K(max_used_ratio), K(max_used_memory), K(ret));
8446}
8447}
8448}
8449}
8450return ret;
8451}
8452
8453int ObUnitManager::change_pool_config(share::ObResourcePool *pool, ObUnitConfig *config,
8454ObUnitConfig *new_config)
8455{
8456int ret = OB_SUCCESS;
8457if (!check_inner_stat()) {
8458ret = OB_INNER_STAT_ERROR;
8459LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
8460} else if (NULL == pool || NULL == config || NULL == new_config) {
8461ret = OB_INVALID_ARGUMENT;
8462LOG_WARN("invalid argument", KP(pool), KP(config), KP(new_config), K(ret));
8463} else {
8464share::ObResourcePool new_pool;
8465if (OB_FAIL(new_pool.assign(*pool))) {
8466LOG_WARN("failed to assign new_pool", K(ret));
8467}
8468if (OB_SUCC(ret)) {
8469new_pool.unit_config_id_ = new_config->unit_config_id();
8470if (OB_FAIL(ut_operator_.update_resource_pool(*proxy_, new_pool, false/*need_check_conflict_with_clone*/))) {
8471LOG_WARN("ut_operator_ update_resource_pool failed", K(new_pool), K(ret));
8472} else if (OB_FAIL(dec_config_ref_count(config->unit_config_id()))) {
8473LOG_WARN("dec_config_ref_count failed", "unit_config_id",
8474config->unit_config_id(), K(ret));
8475} else if (OB_FAIL(inc_config_ref_count(new_config->unit_config_id()))) {
8476LOG_WARN("inc_config_ref_count failed", "unit_config_id",
8477new_config->unit_config_id(), K(ret));
8478} else if (OB_FAIL(delete_config_pool(config->unit_config_id(), pool))) {
8479LOG_WARN("delete config pool failed", "config id", config->unit_config_id(), K(ret));
8480} else if (OB_FAIL(insert_config_pool(new_config->unit_config_id(), pool))) {
8481LOG_WARN("insert config pool failed", "config id", new_config->unit_config_id(), K(ret));
8482} else if (OB_FAIL(update_pool_load(pool, new_config))) {
8483LOG_WARN("update resource pool load failed", K(ret), "resource_pool", *pool,
8484"unit_config", *new_config);
8485} else {
8486pool->unit_config_id_ = new_config->unit_config_id();
8487}
8488}
8489}
8490return ret;
8491}
8492
8493// The zones of multiple pools have no intersection
8494// 14x new semantics. If it is the source_pool used to store the copy of L, it can be compared
8495int ObUnitManager::check_pool_intersect_(
8496const uint64_t tenant_id,
8497const ObIArray<ObResourcePoolName> &pool_names,
8498bool &intersect)
8499{
8500int ret = OB_SUCCESS;
8501ObSEArray<ObString, OB_DEFAULT_REPLICA_NUM> zones;
8502common::ObArray<share::ObResourcePool *> *pools = NULL;;
8503intersect = false;
8504if (!check_inner_stat()) {
8505ret = OB_INNER_STAT_ERROR;
8506LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), KR(ret));
8507} else if (pool_names.count() <= 0 || !is_valid_tenant_id(tenant_id)) {
8508ret = OB_INVALID_ARGUMENT;
8509LOG_WARN("pool_names is empty", K(pool_names), K(tenant_id), KR(ret));
8510} else {
8511FOREACH_CNT_X(pool_name, pool_names, OB_SUCCESS == ret && !intersect) {
8512share::ObResourcePool *pool = NULL;
8513if (OB_FAIL(inner_get_resource_pool_by_name(*pool_name, pool))) {
8514LOG_WARN("get resource pool by name failed", "pool_name", *pool_name, KR(ret));
8515} else if (NULL == pool) {
8516ret = OB_ERR_UNEXPECTED;
8517LOG_WARN("pool is null", KP(pool), KR(ret));
8518} else {
8519FOREACH_CNT_X(zone, pool->zone_list_, OB_SUCCESS == ret && !intersect) {
8520if (NULL == zone) {
8521ret = OB_ERR_UNEXPECTED;
8522LOG_WARN("unit is null", KR(ret));
8523} else {
8524ObString zone_str;
8525zone_str.assign_ptr(zone->ptr(), static_cast<int32_t>(zone->size()));
8526if (has_exist_in_array(zones, zone_str)) {
8527intersect = true;
8528} else if (OB_FAIL(zones.push_back(zone_str))) {
8529LOG_WARN("push_back failed", KR(ret));
8530}
8531}
8532} // end foreach zone
8533}
8534} // end foreach pool
8535if (OB_FAIL(ret)) {
8536} else if (intersect) {
8537} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
8538if (OB_ENTRY_NOT_EXIST == ret) {
8539// a new tenant, without resource pool already granted
8540ret = OB_SUCCESS;
8541} else {
8542LOG_WARN("fail to get pools by tenant", KR(ret), K(tenant_id));
8543}
8544} else if (OB_UNLIKELY(NULL == pools)) {
8545ret = OB_ERR_UNEXPECTED;
8546LOG_WARN("pools is null", KR(ret), KP(pools));
8547} else {
8548for (int64_t i = 0; !intersect && OB_SUCC(ret) && i < pools->count(); ++i) {
8549const share::ObResourcePool *pool = pools->at(i);
8550if (OB_UNLIKELY(NULL == pool)) {
8551ret = OB_ERR_UNEXPECTED;
8552LOG_WARN("pool ptr is null", KR(ret), KP(pool));
8553} else {
8554for (int64_t j = 0; !intersect && OB_SUCC(ret) && j < zones.count(); ++j) {
8555common::ObZone zone;
8556if (OB_FAIL(zone.assign(zones.at(j).ptr()))) {
8557LOG_WARN("fail to assign zone", KR(ret));
8558} else if (has_exist_in_array(pool->zone_list_, zone)) {
8559intersect = true;
8560} else {} // good
8561}
8562}
8563}
8564}
8565}
8566return ret;
8567}
8568
8569int ObUnitManager::check_pool_ownership_(const uint64_t tenant_id,
8570const common::ObIArray<share::ObResourcePoolName> &pool_names,
8571const bool grant)
8572{
8573int ret = OB_SUCCESS;
8574share::ObResourcePool *pool = NULL;
8575for (int64_t i = 0; OB_SUCC(ret) && i < pool_names.count(); ++i) {
8576if (OB_FAIL(inner_get_resource_pool_by_name(pool_names.at(i), pool))) {
8577LOG_WARN("get resource pool by name failed", "pool_name", pool_names.at(i), KR(ret));
8578} else if (OB_ISNULL(pool)) {
8579ret = OB_ERR_UNEXPECTED;
8580LOG_WARN("pool is null", KP(pool), KR(ret));
8581}
8582if (OB_FAIL(ret)) {
8583} else if (grant) {
8584if (pool->is_granted_to_tenant()) {
8585ret = OB_RESOURCE_POOL_ALREADY_GRANTED;
8586LOG_USER_ERROR(OB_RESOURCE_POOL_ALREADY_GRANTED, to_cstring(pool_names.at(i)));
8587LOG_WARN("pool has already granted to other tenant, can't grant again",
8588KR(ret), K(tenant_id), "pool", *pool);
8589} else {/*good*/}
8590} else {
8591if (!pool->is_granted_to_tenant()) {
8592ret = OB_ERR_UNEXPECTED;
8593LOG_WARN("find pool not granted to any tenant, can not revoke",
8594"pool", *pool, K(tenant_id), KR(ret));
8595} else if (pool->tenant_id_ != tenant_id) {
8596ret = OB_ERR_UNEXPECTED;
8597LOG_WARN("find pool already granted to other tenant, can not revoke",
8598"pool", *pool, K(tenant_id), KR(ret));
8599} else {/*good*/}
8600}
8601}
8602return ret;
8603}
8604
8605int ObUnitManager::construct_pool_units_to_grant_(
8606ObMySQLTransaction &trans,
8607const uint64_t tenant_id,
8608const share::ObResourcePool &new_pool,
8609const common::ObIArray<share::ObUnit *> &zone_sorted_unit_array,
8610const common::ObIArray<uint64_t> &new_ug_ids,
8611const lib::Worker::CompatMode &compat_mode,
8612ObNotifyTenantServerResourceProxy ¬ify_proxy,
8613const uint64_t source_tenant_id,
8614ObIArray<share::ObUnit> &pool_units,
8615const bool check_data_version)
8616{
8617int ret = OB_SUCCESS;
8618pool_units.reset();
8619common::ObArray<share::ObUnitInfo> source_units;
8620common::ObArray<uint64_t> source_ug_ids;
8621if (!check_inner_stat()) {
8622ret = OB_INNER_STAT_ERROR;
8623LOG_WARN("check_inner_stat failed", KR(ret), K_(inited), K_(loaded));
8624} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))
8625|| OB_UNLIKELY(0 >= zone_sorted_unit_array.count())
8626|| OB_UNLIKELY(0 >= new_ug_ids.count())) {
8627ret = OB_INVALID_ARGUMENT;
8628LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(zone_sorted_unit_array),
8629K(new_ug_ids));
8630} else {
8631if (OB_INVALID_TENANT_ID != source_tenant_id) {
8632if (OB_FAIL(inner_get_all_unit_infos_by_tenant_(source_tenant_id, source_units))) {
8633LOG_WARN("fail to get source units of source tenant", KR(ret), K(source_tenant_id));
8634} else if (OB_FAIL(construct_source_unit_group_ids_(source_units, source_ug_ids))) {
8635LOG_WARN("fail to construct source unit group ids", KR(ret), K(source_units));
8636}
8637}
8638ObUnit new_unit;
8639for (int64_t j = 0; OB_SUCC(ret) && j < zone_sorted_unit_array.count(); ++j) {
8640ObUnit *unit = zone_sorted_unit_array.at(j);
8641uint64_t unit_group_id_to_set = 0;
8642new_unit.reset();
8643if (OB_ISNULL(unit)) {
8644ret = OB_ERR_UNEXPECTED;
8645LOG_WARN("unit ptr is null", KR(ret));
8646} else if (OB_FAIL(try_notify_tenant_server_unit_resource_(
8647tenant_id, false /*is_delete*/, notify_proxy,
8648new_pool.unit_config_id_, compat_mode, *unit,
8649false/*if_not_grant*/, false/*skip_offline_server*/,
8650check_data_version))) {
8651LOG_WARN("fail to try notify server unit resource", KR(ret),
8652K(tenant_id), K(compat_mode), KPC(unit));
8653} else if (FALSE_IT(new_unit = *unit)) {
8654// shall never be here
8655} else if (OB_FAIL(construct_unit_group_id_for_unit_(
8656source_tenant_id,
8657source_units,
8658source_ug_ids,
8659*unit,
8660j/*unit_index*/,
8661new_pool.unit_count_,
8662new_ug_ids,
8663unit_group_id_to_set))) {
8664LOG_WARN("fail to construct unit group id for unit", KR(ret), K(source_tenant_id),
8665K(source_units), K(source_ug_ids), KPC(unit), K(j), K(new_pool), K(new_ug_ids));
8666} else if (FALSE_IT(new_unit.unit_group_id_ = unit_group_id_to_set)) {
8667// shall never be here
8668} else if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, false/*need_check_conflict_with_clone*/))) {
8669LOG_WARN("fail to update unit", KR(ret), K(new_unit));
8670} else if (OB_FAIL(pool_units.push_back(*unit))) {
8671LOG_WARN("fail to push an element into pool_units", KR(ret), KPC(unit));
8672}
8673}
8674}
8675return ret;
8676}
8677
8678int ObUnitManager::construct_source_unit_group_ids_(
8679const common::ObIArray<share::ObUnitInfo> &source_units,
8680common::ObIArray<uint64_t> &source_unit_group_ids)
8681{
8682int ret = OB_SUCCESS;
8683source_unit_group_ids.reset();
8684if (OB_UNLIKELY(0 == source_units.count())) {
8685ret = OB_INVALID_ARGUMENT;
8686LOG_WARN("invalid source units", KR(ret), K(source_units));
8687} else {
8688for (int64_t i = 0; OB_SUCC(ret) && i < source_units.count(); ++i) {
8689uint64_t source_unit_group_id = 0;
8690if (!source_units.at(i).unit_.is_active_status()) {
8691// we can ensure all unit belongs to source tenant is active status, so it is unexpected to find an inactive unit
8692ret = OB_STATE_NOT_MATCH;
8693LOG_WARN("unit status is not expected", KR(ret), K(source_units), K(i));
8694} else {
8695source_unit_group_id = source_units.at(i).unit_.unit_group_id_;
8696if (!has_exist_in_array(source_unit_group_ids, source_unit_group_id)) {
8697if (OB_FAIL(source_unit_group_ids.push_back(source_unit_group_id))) {
8698LOG_WARN("fail to add source unit group id into array", KR(ret), K(source_unit_group_id));
8699}
8700}
8701}
8702}
8703}
8704return ret;
8705}
8706
8707int ObUnitManager::construct_unit_group_id_for_unit_(
8708const uint64_t source_tenant_id,
8709const common::ObIArray<share::ObUnitInfo> &source_units,
8710const common::ObIArray<uint64_t> &source_unit_group_ids,
8711const ObUnit &target_unit,
8712const int64_t unit_index,
8713const int64_t unit_num,
8714const common::ObIArray<uint64_t> &new_ug_ids,
8715uint64_t &unit_group_id)
8716{
8717int ret = OB_SUCCESS;
8718unit_group_id = OB_INVALID_ID;
8719common::ObArray<uint64_t> sorted_new_ug_ids;
8720common::ObArray<uint64_t> sorted_source_ug_ids;
8721
8722if (!check_inner_stat()) {
8723ret = OB_INNER_STAT_ERROR;
8724LOG_WARN("check_inner_stat failed", KR(ret), K_(inited), K_(loaded));
8725} else if (OB_UNLIKELY(0 >= unit_num)
8726|| OB_UNLIKELY(0 > unit_index)
8727|| OB_UNLIKELY(new_ug_ids.count() != unit_num)
8728|| OB_UNLIKELY(0 >= new_ug_ids.count())
8729|| OB_UNLIKELY((source_unit_group_ids.count() != new_ug_ids.count() && 0!= source_unit_group_ids.count()))) {
8730ret = OB_INVALID_ARGUMENT;
8731LOG_WARN("invalid argument", KR(ret), K(unit_index), K(source_units), K(source_unit_group_ids),
8732K(unit_num), K(new_ug_ids));
8733} else if (OB_INVALID_TENANT_ID == source_tenant_id) {
8734// for tenant not clone, just allocate new unit group ids by order
8735unit_group_id = new_ug_ids.at(unit_index % (unit_num));
8736} else {
8737// for clone tenant, we have to choose new unit group id for this unit
8738if (OB_FAIL(sorted_new_ug_ids.assign(new_ug_ids))) {
8739LOG_WARN("fail to assign unit group ids", KR(ret), K(new_ug_ids));
8740} else if (OB_FAIL(sorted_source_ug_ids.assign(source_unit_group_ids))) {
8741LOG_WARN("fail to assign source unit group ids", KR(ret), K(source_unit_group_ids));
8742} else {
8743// construct sorted unit group ids first
8744std::sort(sorted_new_ug_ids.begin(), sorted_new_ug_ids.end());
8745std::sort(sorted_source_ug_ids.begin(), sorted_source_ug_ids.end());
8746// for clone tenant, we have to construct unit_group_id for its units
8747// the rule to allocate unit_group_id
8748//
8749// resume source tenant has source_units like below:
8750// ========================================================
8751// | server_addr | source_unit_id | source_unit_group_id |
8752// ========================================================
8753// | server A | 1001 | ug1 |
8754// |------------------------------------------------------|
8755// | server B | 1002 | ug2 |
8756// |------------------------------------------------------|
8757// | server C | 1003 | ug3 |
8758// ========================================================
8759//
8760// And we have 3 new unit group ids belongs to clone tenant, mark them as new_ug4, new_ug5, new_ug6.
8761// And assume unit id for clone tenant is 1004(server B), 1005(server A), 1006(server C).
8762// And assume ug1 > ug3 > ug2
8763// And assume new_ug5 > new_ug6 > new_ug4
8764//
8765// The logic to construct unit_group_id for unit(1004) is firstly to get the unit with same server(B), which is unit 1002.
8766// Then caculate the order of source_unit_group_id(which is ug2) belongs to unit 1002 during all source_group_ids.(The smallest one)
8767// Then get the smallest new unit_group_id which is new_ug4.
8768// After all, the unit group id constructed for unit 1004 is new_ug4.
8769//
8770// ATTENTION:
8771// The main logic here is to gurantee a mapping relationship between source_ug_ids and new_ug_ids by comparing the order.
8772const common::ObAddr target_server = target_unit.server_;
8773uint64_t source_unit_group_id = 0;
8774for (int64_t i = 0; OB_SUCC(ret) && i < source_units.count(); ++i) {
8775if (target_server == source_units.at(i).unit_.server_) {
8776source_unit_group_id = source_units.at(i).unit_.unit_group_id_;
8777int64_t index = OB_INVALID_INDEX_INT64;
8778if (has_exist_in_array(sorted_source_ug_ids, source_unit_group_id, &index)) {
8779unit_group_id = sorted_new_ug_ids.at(index);
8780break;
8781} else {
8782ret = OB_ENTRY_NOT_EXIST;
8783LOG_WARN("can not find unit group id from source ug ids", KR(ret),
8784K(sorted_source_ug_ids), K(source_unit_group_id));
8785}
8786}
8787}
8788}
8789}
8790if (OB_FAIL(ret)) {
8791} else if (OB_UNLIKELY(OB_INVALID_ID == unit_group_id)) {
8792ret = OB_ENTRY_NOT_EXIST;
8793LOG_WARN("can not find a valid unit group id", KR(ret), K(source_tenant_id), K(unit_group_id),
8794K(source_units), K(target_unit), K(sorted_source_ug_ids), K(sorted_new_ug_ids));
8795}
8796return ret;
8797}
8798
8799int ObUnitManager::do_grant_pools_(
8800ObMySQLTransaction &trans,
8801const common::ObIArray<uint64_t> &new_ug_ids,
8802const lib::Worker::CompatMode compat_mode,
8803const ObIArray<ObResourcePoolName> &pool_names,
8804const uint64_t tenant_id,
8805const bool is_bootstrap,
8806const uint64_t source_tenant_id,
8807const bool check_data_version)
8808{
8809int ret = OB_SUCCESS;
8810if (!check_inner_stat()) {
8811ret = OB_INNER_STAT_ERROR;
8812LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), KR(ret));
8813} else if (!is_valid_tenant_id(tenant_id) || pool_names.count() <= 0) {
8814ret = OB_INVALID_ARGUMENT;
8815LOG_WARN("invalid argument", K(tenant_id), K(pool_names), KR(ret));
8816} else if (OB_UNLIKELY(nullptr == srv_rpc_proxy_)) {
8817ret = OB_ERR_UNEXPECTED;
8818LOG_WARN("srv_rpc_proxy_ ptr is null", KR(ret));
8819} else {
8820ObNotifyTenantServerResourceProxy notify_proxy(
8821*srv_rpc_proxy_,
8822&obrpc::ObSrvRpcProxy::notify_tenant_server_unit_resource);
8823share::ObResourcePool new_pool;
8824ObArray<share::ObResourcePool> pools;
8825ObArray<ObArray<ObUnit>> all_pool_units;
8826ObArray<ObUnit> pool_units;
8827for (int64_t i = 0; OB_SUCC(ret) && i < pool_names.count(); ++i) {
8828share::ObResourcePool *pool = NULL;
8829pool_units.reset();
8830common::ObArray<ObUnit *> zone_sorted_unit_array;
8831if (OB_FAIL(inner_get_resource_pool_by_name(pool_names.at(i), pool))) {
8832LOG_WARN("get resource pool by name failed", "pool_name", pool_names.at(i), KR(ret));
8833} else if (OB_ISNULL(pool)) {
8834ret = OB_ERR_UNEXPECTED;
8835LOG_WARN("pool is null", KP(pool), KR(ret));
8836} else if (pool->unit_count_ != new_ug_ids.count()) {
8837ret = OB_ERR_UNEXPECTED;
8838LOG_WARN("count not match", KR(ret), K(tenant_id),
8839"pool", new_pool, K(new_ug_ids));
8840} else if (OB_FAIL(new_pool.assign(*pool))) {
8841LOG_WARN("failed to assign new_pool", KR(ret));
8842} else if (FALSE_IT(new_pool.tenant_id_ = tenant_id)) {
8843// shall never be here
8844} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool,false/*need_check_conflict_with_clone*/))) {
8845LOG_WARN("update_resource_pool failed", K(new_pool), KR(ret));
8846} else if (is_bootstrap) {
8847//no need to notify unit and modify unit group id
8848} else if (OB_FAIL(build_zone_sorted_unit_array_(pool, zone_sorted_unit_array))) {
8849LOG_WARN("failed to generate zone_sorted_unit_array", KR(ret), KPC(pool));
8850} else if (OB_FAIL(construct_pool_units_to_grant_(
8851trans,
8852tenant_id,
8853new_pool,
8854zone_sorted_unit_array,
8855new_ug_ids,
8856compat_mode,
8857notify_proxy,
8858source_tenant_id,
8859pool_units,
8860check_data_version))) {
8861LOG_WARN("fail to construct pool units to grant", KR(ret), K(tenant_id), K(new_pool),
8862K(zone_sorted_unit_array), K(new_ug_ids), K(compat_mode), K(source_tenant_id));
8863} else if (OB_FAIL(all_pool_units.push_back(pool_units))) {
8864LOG_WARN("fail to push an element into all_pool_units", KR(ret), K(pool_units));
8865} else if (OB_FAIL(pools.push_back(new_pool))) {
8866LOG_WARN("fail to push an element into pools", KR(ret), K(new_pool));
8867}
8868}
8869int tmp_ret = OB_SUCCESS;
8870if (OB_TMP_FAIL(notify_proxy.wait())) {
8871LOG_WARN("fail to wait notify resource", KR(ret), K(tmp_ret));
8872ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
8873} else if (OB_SUCC(ret)) {
8874// arg/dest/result can be used here.
8875}
8876ret = ERRSIM_UNIT_PERSISTENCE_ERROR ? : ret;
8877if (OB_FAIL(ret) && pools.count() == all_pool_units.count()) {
8878LOG_WARN("start to rollback unit persistence", KR(ret), K(pools), K(tenant_id));
8879for (int64_t i = 0; i < pools.count(); ++i) {
8880if (OB_TMP_FAIL(rollback_persistent_units_(all_pool_units.at(i), pools.at(i), notify_proxy))) {
8881LOG_WARN("fail to rollback unit persistence", KR(ret), KR(tmp_ret), K(all_pool_units.at(i)),
8882K(pools.at(i)), K(compat_mode));
8883}
8884}
8885}
8886}
8887return ret;
8888}
8889
8890int ObUnitManager::do_revoke_pools_(
8891ObMySQLTransaction &trans,
8892const common::ObIArray<uint64_t> &new_ug_ids,
8893const ObIArray<ObResourcePoolName> &pool_names,
8894const uint64_t tenant_id)
8895{
8896int ret = OB_SUCCESS;
8897const lib::Worker::CompatMode dummy_mode = lib::Worker::CompatMode::INVALID;
8898if (!check_inner_stat()) {
8899ret = OB_INNER_STAT_ERROR;
8900LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), KR(ret));
8901} else if (!is_valid_tenant_id(tenant_id) || pool_names.count() <= 0) {
8902ret = OB_INVALID_ARGUMENT;
8903LOG_WARN("invalid argument", K(tenant_id), K(pool_names), KR(ret));
8904} else if (OB_UNLIKELY(nullptr == srv_rpc_proxy_)) {
8905ret = OB_ERR_UNEXPECTED;
8906LOG_WARN("srv_rpc_proxy_ ptr is null", KR(ret));
8907} else {
8908ObNotifyTenantServerResourceProxy notify_proxy(
8909*srv_rpc_proxy_,
8910&obrpc::ObSrvRpcProxy::notify_tenant_server_unit_resource);
8911share::ObResourcePool new_pool;
8912ObArray<share::ObResourcePool *> shrinking_pools;
8913ObArray<share::ObResourcePool> pools;
8914for (int64_t i = 0; OB_SUCC(ret) && i < pool_names.count(); ++i) {
8915share::ObResourcePool *pool = NULL;
8916bool is_shrinking = false;
8917common::ObArray<ObUnit *> zone_sorted_unit_array;
8918if (OB_FAIL(inner_get_resource_pool_by_name(pool_names.at(i), pool))) {
8919LOG_WARN("get resource pool by name failed", "pool_name", pool_names.at(i), KR(ret));
8920} else if (OB_ISNULL(pool)) {
8921ret = OB_ERR_UNEXPECTED;
8922LOG_WARN("pool is null", KP(pool), KR(ret));
8923} else if (pool->unit_count_ != new_ug_ids.count()) {
8924ret = OB_ERR_UNEXPECTED;
8925LOG_WARN("count not match", KR(ret), K(tenant_id),
8926"pool", new_pool, K(new_ug_ids));
8927} else if (OB_FAIL(inner_check_pool_in_shrinking_(pool->resource_pool_id_, is_shrinking))) { // TODO(cangming.zl): maybe need to move ahead
8928LOG_WARN("inner check pool in shrinking failed", KR(ret), "pool", *pool, K(is_shrinking));
8929} else if (is_shrinking && OB_FAIL(shrinking_pools.push_back(pool))) {
8930LOG_WARN("fail to push back shrinking resource pool before revoked", KR(ret), K(tenant_id), "pool", *pool);
8931} else if (OB_FAIL(new_pool.assign(*pool))) {
8932LOG_WARN("failed to assign new_pool", KR(ret));
8933} else if (FALSE_IT(new_pool.tenant_id_ = OB_INVALID_ID)) {
8934// shall never be here
8935} else if (OB_FAIL(ut_operator_.update_resource_pool(trans, new_pool, false/*need_check_conflict_with_clone*/))) {
8936LOG_WARN("update_resource_pool failed", K(new_pool), KR(ret));
8937} else if (OB_FAIL(build_zone_sorted_unit_array_(pool, zone_sorted_unit_array))) {
8938LOG_WARN("failed to generate zone_sorted_unit_array", KR(ret), KPC(pool));
8939} else {
8940ObUnit new_unit;
8941for (int64_t j = 0; OB_SUCC(ret) && j < zone_sorted_unit_array.count(); ++j) {
8942ObUnit *unit = zone_sorted_unit_array.at(j);
8943new_unit.reset();
8944if (OB_ISNULL(unit)) {
8945ret = OB_ERR_UNEXPECTED;
8946LOG_WARN("unit ptr is null", KR(ret));
8947} else if (OB_FAIL(try_notify_tenant_server_unit_resource_(
8948tenant_id, true /*is_delete*/, notify_proxy,
8949new_pool.unit_config_id_, dummy_mode, *unit,
8950false/*if_not_grant*/, false/*skip_offline_server*/,
8951false /*check_data_version*/))) {
8952LOG_WARN("fail to try notify server unit resource", KR(ret));
8953} else if (FALSE_IT(new_unit = *unit)) {
8954// shall never be here
8955} else if (FALSE_IT(new_unit.unit_group_id_ = new_ug_ids.at(j % (pool->unit_count_)))) {
8956// shall never be here
8957} else if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, false/*need_check_conflict_with_clone*/))) {
8958LOG_WARN("fail to update unit", KR(ret));
8959}
8960}
8961}
8962}
8963// If some of the pools are shrinking, commit these shrinking pools now.
8964if (OB_SUCCESS != ret) {
8965} else if (shrinking_pools.count() > 0 && OB_FAIL(inner_commit_shrink_tenant_resource_pool_(trans, tenant_id, shrinking_pools))) {
8966LOG_WARN("failed to commit shrinking pools in revoking", KR(ret), K(tenant_id));
8967}
8968int tmp_ret = OB_SUCCESS;
8969if (OB_TMP_FAIL(notify_proxy.wait())) {
8970LOG_WARN("fail to wait notify resource", KR(ret), K(tmp_ret));
8971ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
8972} else if (OB_SUCC(ret)) {
8973// arg/dest/result can be used here.
8974}
8975}
8976return ret;
8977}
8978
8979int ObUnitManager::build_zone_sorted_unit_array_(const share::ObResourcePool *pool,
8980common::ObArray<share::ObUnit*> &zone_sorted_units)
8981{
8982int ret = OB_SUCCESS;
8983ObArray<share::ObUnit*> *units;
8984if (!check_inner_stat()) {
8985ret = OB_INNER_STAT_ERROR;
8986LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), KR(ret));
8987} else if (OB_ISNULL(pool)) {
8988ret = OB_INVALID_ARGUMENT;
8989LOG_WARN("pool is nullptr", KR(ret));
8990} else if (OB_FAIL(get_units_by_pool(pool->resource_pool_id_, units))) {
8991LOG_WARN("fail to get units by pool", KR(ret));
8992} else if (OB_ISNULL(units)) {
8993ret = OB_ERR_UNEXPECTED;
8994LOG_WARN("units ptr is null", KR(ret));
8995} else if (OB_FAIL(zone_sorted_units.assign(*units))) {
8996LOG_WARN("fail to assign zone unit array", KR(ret));
8997} else {
8998UnitZoneOrderCmp cmp_operator;
8999std::sort(zone_sorted_units.begin(), zone_sorted_units.end(), cmp_operator);
9000// check unit count in each zone
9001ObUnit *curr_unit = NULL;
9002ObUnit *prev_unit = NULL;
9003int64_t unit_count_per_zone = 0;
9004for (int64_t j = 0; OB_SUCC(ret) && j < zone_sorted_units.count(); ++j) {
9005prev_unit = curr_unit;
9006curr_unit = zone_sorted_units.at(j);
9007if (OB_ISNULL(curr_unit)) {
9008ret = OB_ERR_UNEXPECTED;
9009LOG_WARN("unit ptr is null", KR(ret));
9010} else if (0 == j || curr_unit->zone_ == prev_unit->zone_) {
9011unit_count_per_zone += ObUnit::UNIT_STATUS_ACTIVE == curr_unit->status_ ? 1 : 0;
9012} else if (unit_count_per_zone != pool->unit_count_) {
9013ret = OB_ERR_UNEXPECTED;
9014LOG_WARN("zone unit num doesn't match resource pool's unit_count",
9015KR(ret), "zone", prev_unit->zone_, K(unit_count_per_zone), K(pool->unit_count_));
9016} else {
9017unit_count_per_zone = ObUnit::UNIT_STATUS_ACTIVE == curr_unit->status_ ? 1 : 0;
9018}
9019}
9020if (OB_SUCC(ret) && unit_count_per_zone != pool->unit_count_) {
9021ret = OB_ERR_UNEXPECTED;
9022LOG_WARN("zone unit num doesn't match resource pool's unit_count",
9023KR(ret), "zone", curr_unit->zone_, K(unit_count_per_zone), K(pool->unit_count_));
9024}
9025}
9026return ret;
9027}
9028
9029// this function is only used to commit part of shrinking pools of a tenant when these pools are revoked.
9030int ObUnitManager::inner_commit_shrink_tenant_resource_pool_(
9031common::ObMySQLTransaction &trans, const uint64_t tenant_id, const common::ObArray<share::ObResourcePool *> &pools)
9032{
9033int ret = OB_SUCCESS;
9034if (!check_inner_stat()) {
9035ret = OB_INNER_STAT_ERROR;
9036LOG_WARN("check_inner_stat failed", KR(ret), K(loaded_), K(inited_));
9037} else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id)) {
9038ret = OB_INVALID_ARGUMENT;
9039LOG_WARN("invalid argument", KR(ret), K(tenant_id));
9040} else if (pools.count() <= 0) {
9041ret = OB_INVALID_ARGUMENT;
9042LOG_WARN("pools is empty", KR(ret), K(pools));
9043} else {
9044// first check that pools are all owned by specified tenant
9045FOREACH_CNT_X(pool, pools, OB_SUCCESS == ret) {
9046if (OB_ISNULL(*pool)) {
9047ret = OB_ERR_UNEXPECTED;
9048LOG_WARN("pool is null pointer", KR(ret), KP(*pool));
9049} else if (tenant_id != (*pool)->tenant_id_) {
9050ret = OB_ERR_UNEXPECTED;
9051LOG_WARN("pool is not owned by specified tenant", KR(ret), K(tenant_id), KPC(*pool));
9052}
9053}
9054ObArray<ObArray<uint64_t>> resource_units;
9055if (FAILEDx(commit_shrink_resource_pool_in_trans_(pools, trans, resource_units))) {
9056LOG_WARN("failed to shrink in trans", KR(ret), K(pools));
9057} else if (OB_UNLIKELY(resource_units.count() <= 0)) {
9058ret = OB_ERR_UNEXPECTED;
9059LOG_WARN("resource units is empty", KR(ret), K(resource_units));
9060} else {/* good */}
9061}
9062return ret;
9063}
9064
9065int ObUnitManager::get_zone_units(const ObArray<share::ObResourcePool *> &pools,
9066ObArray<ZoneUnit> &zone_units) const
9067{
9068int ret = OB_SUCCESS;
9069ObArray<ObZone> zones;
9070zone_units.reuse();
9071if (!check_inner_stat()) {
9072ret = OB_INNER_STAT_ERROR;
9073LOG_WARN("check_inner_stat failed", K_(inited), K_(loaded), K(ret));
9074} else if (pools.count() <= 0) {
9075ret = OB_INVALID_ARGUMENT;
9076LOG_WARN("pools is empty", K(pools), K(ret));
9077} else {
9078FOREACH_CNT_X(pool, pools, OB_SUCCESS == ret) {
9079if (NULL == *pool) {
9080ret = OB_INVALID_ARGUMENT;
9081LOG_WARN("pool is null", "pool", OB_P(*pool), K(ret));
9082} else {
9083FOREACH_CNT_X(pool_zone, (*pool)->zone_list_, OB_SUCCESS == ret) {
9084bool find = false;
9085FOREACH_CNT_X(zone, zones, !find) {
9086if (*zone == *pool_zone) {
9087find = true;
9088}
9089}
9090if (!find) {
9091if (OB_FAIL(zones.push_back(*pool_zone))) {
9092LOG_WARN("push_back failed", K(ret));
9093}
9094}
9095}
9096}
9097}
9098
9099ZoneUnit zone_unit;
9100ObArray<ObUnitInfo> unit_infos;
9101FOREACH_CNT_X(zone, zones, OB_SUCCESS == ret) {
9102zone_unit.reset();
9103zone_unit.zone_ = *zone;
9104FOREACH_CNT_X(pool, pools, OB_SUCCESS == ret) {
9105unit_infos.reuse();
9106if (NULL == *pool) {
9107ret = OB_INVALID_ARGUMENT;
9108LOG_WARN("pool is null", "pool", OB_P(*pool), K(ret));
9109} else if (OB_FAIL(inner_get_unit_infos_of_pool_((*pool)->resource_pool_id_, unit_infos))) {
9110LOG_WARN("inner_get_unit_infos_of_pool failed",
9111"pool id", (*pool)->resource_pool_id_, K(ret));
9112} else {
9113FOREACH_CNT_X(unit_info, unit_infos, OB_SUCCESS == ret) {
9114if (unit_info->unit_.zone_ == *zone) {
9115if (OB_FAIL(zone_unit.unit_infos_.push_back(*unit_info))) {
9116LOG_WARN("push_back failed", K(ret));
9117}
9118}
9119}
9120}
9121}
9122if (OB_SUCC(ret)) {
9123if (OB_FAIL(zone_units.push_back(zone_unit))) {
9124LOG_WARN("push_back failed", K(zone_unit), K(ret));
9125}
9126}
9127}
9128}
9129return ret;
9130}
9131
9132int ObUnitManager::get_tenants_of_server(const common::ObAddr &server,
9133common::hash::ObHashSet<uint64_t> &tenant_id_set) const
9134{
9135int ret = OB_SUCCESS;
9136ObArray<ObUnitLoad> *unit_loads = NULL;
9137{
9138SpinRLockGuard guard(lock_);
9139if (!check_inner_stat()) {
9140ret = OB_INNER_STAT_ERROR;
9141LOG_WARN("check inner stat failed", K_(inited), K_(loaded), K(ret));
9142} else if (!server.is_valid()) {
9143ret = OB_INVALID_ARGUMENT;
9144LOG_WARN("server is invalid", K(server), K(ret));
9145} else if (OB_FAIL(get_loads_by_server(server, unit_loads))) {
9146if (OB_ENTRY_NOT_EXIST != ret) {
9147LOG_WARN("get_loads_by_server failed", K(server), K(ret));
9148} else {
9149ret = OB_SUCCESS;
9150// just return empty set
9151}
9152} else if (NULL == unit_loads) {
9153ret = OB_ERR_UNEXPECTED;
9154LOG_WARN("unit_loads is null", KP(unit_loads), K(ret));
9155}
9156if (OB_SUCC(ret) && !OB_ISNULL(unit_loads)) {
9157FOREACH_CNT_X(unit_load, *unit_loads, OB_SUCCESS == ret) {
9158if (!unit_load->is_valid()) {
9159ret = OB_ERR_UNEXPECTED;
9160LOG_WARN("invalid unit_load", "unit_load", *unit_load, K(ret));
9161} else {
9162const uint64_t tenant_id = unit_load->pool_->tenant_id_;
9163if (!is_valid_tenant_id(tenant_id)) {
9164//do nothing
9165} else if (OB_FAIL(tenant_id_set.set_refactored(tenant_id))) {
9166if (OB_HASH_EXIST == ret) {
9167ret = OB_SUCCESS;
9168} else {
9169LOG_WARN("set tenant id failed", K(tenant_id), K(ret));
9170}
9171}
9172}
9173}
9174}
9175}
9176return ret;
9177}
9178
9179int ObUnitManager::check_tenant_on_server(const uint64_t tenant_id,
9180const ObAddr &server, bool &on_server) const
9181{
9182int ret = OB_SUCCESS;
9183if (!check_inner_stat()) {
9184ret = OB_INNER_STAT_ERROR;
9185LOG_WARN("check inner stat failed", K_(inited), K_(loaded), K(ret));
9186} else if (!is_valid_tenant_id(tenant_id) || !server.is_valid()) {
9187ret = OB_INVALID_ARGUMENT;
9188LOG_WARN("invalid tenant_id or invalid server", K(tenant_id), K(server), K(ret));
9189} else {
9190ObArray<uint64_t> pool_ids;
9191ObZone zone;
9192ObArray<ObAddr> servers;
9193if (OB_FAIL(get_pool_ids_of_tenant(tenant_id, pool_ids))) {
9194LOG_WARN("get_pool_ids_of_tenant failed", K(tenant_id), K(ret));
9195} else if (OB_FAIL(SVR_TRACER.get_server_zone(server, zone))) {
9196LOG_WARN("get_server_zone failed", K(server), K(ret));
9197} else {
9198SpinRLockGuard guard(lock_);
9199FOREACH_CNT_X(pool_id, pool_ids, OB_SUCCESS == ret && !on_server) {
9200if (OB_FAIL(get_pool_servers(*pool_id, zone, servers))) {
9201LOG_WARN("get_pool_servers failed", "pool_id", *pool_id, K(zone), K(ret));
9202} else if (has_exist_in_array(servers, server)) {
9203on_server = true;
9204}
9205}
9206}
9207}
9208return ret;
9209}
9210
9211int ObUnitManager::admin_migrate_unit(
9212const uint64_t unit_id,
9213const ObAddr &dst,
9214bool is_cancel)
9215{
9216int ret = OB_SUCCESS;
9217ObUnitInfo unit_info;
9218ObArray<ObAddr> excluded_servers;
9219ObServerInfoInTable dst_server_info;
9220obrpc::ObGetServerResourceInfoResult report_dst_server_resource_info;
9221ObZone src_zone;
9222ObZone dst_zone;
9223double hard_limit = 0;
9224bool can_hold_unit = false;
9225SpinWLockGuard guard(lock_);
9226AlterResourceErr err_index = ALT_ERR;
9227const char *module = "ADMIN_MIGRATE_UNIT";
9228if (!check_inner_stat()) {
9229ret = OB_INNER_STAT_ERROR;
9230LOG_WARN("check inner stat failed", K_(inited), K_(loaded), KR(ret));
9231} else if (OB_INVALID_ID == unit_id) {
9232ret = OB_INVALID_ARGUMENT;
9233LOG_WARN("unit id is invalid", K(unit_id), KR(ret));
9234} else if (!dst.is_valid() && !is_cancel) {
9235ret = OB_INVALID_ARGUMENT;
9236LOG_WARN("dst is invalid", K(dst), KR(ret));
9237} else if (OB_FAIL(get_hard_limit(hard_limit))) {
9238LOG_WARN("get_hard_limit failed", KR(ret));
9239} else if (OB_FAIL(inner_get_unit_info_by_id(unit_id, unit_info))) {
9240if (OB_ENTRY_NOT_EXIST == ret) {
9241LOG_USER_ERROR(OB_ENTRY_NOT_EXIST, "unit_id not existed");
9242}
9243LOG_WARN("get unit info failed", K(unit_id), KR(ret));
9244} else if (ObUnit::UNIT_STATUS_ACTIVE != unit_info.unit_.status_) {
9245ret = OB_OP_NOT_ALLOW;
9246LOG_WARN("migrate a unit which is in deleting status", KR(ret), K(unit_id));
9247LOG_USER_ERROR(OB_OP_NOT_ALLOW, "migrate a unit which is in deleting status");
9248} else if (dst == unit_info.unit_.server_) {
9249// nothing need to do
9250LOG_INFO("migration dst same to src", KR(ret), K(dst), K(unit_info));
9251} else if (dst == unit_info.unit_.migrate_from_server_ || is_cancel) {
9252// cancel migrate unit
9253bool can_migrate_in = false;
9254if (is_cancel && !unit_info.unit_.migrate_from_server_.is_valid()) {
9255ret = OB_ERR_UNEXPECTED;
9256LOG_WARN("failed to cancel migrate unit, may be no migrate task", KR(ret), K(unit_info));
9257LOG_USER_ERROR(OB_ERR_UNEXPECTED,"no migrate task to cancel");
9258} else if (OB_FAIL(SVR_TRACER.check_server_can_migrate_in(
9259unit_info.unit_.migrate_from_server_,
9260can_migrate_in))) {
9261LOG_WARN("fail to check server can_migrate_in", KR(ret), K(unit_info.unit_.migrate_from_server_));
9262} else if (OB_FAIL(cancel_migrate_unit(
9263unit_info.unit_, can_migrate_in, unit_info.pool_.tenant_id_ == OB_GTS_TENANT_ID))) {
9264LOG_WARN("failed to cancel migrate unit", KR(ret), K(unit_info), K(can_migrate_in));
9265}
9266} else if (OB_FAIL(SVR_TRACER.get_server_zone(unit_info.unit_.server_, src_zone))) {
9267LOG_WARN("get server zone failed", "server", unit_info.unit_.server_, KR(ret));
9268} else if (OB_FAIL(SVR_TRACER.get_server_zone(dst, dst_zone))) {
9269if (OB_ENTRY_NOT_EXIST == ret) {
9270LOG_USER_ERROR(OB_ENTRY_NOT_EXIST, "destination server not found in the cluster");
9271}
9272LOG_WARN("get server zone failed", "server", dst, KR(ret));
9273} else if (src_zone != dst_zone) {
9274ret = OB_NOT_SUPPORTED;
9275LOG_WARN("migrate unit between zones is not supported", KR(ret));
9276LOG_USER_ERROR(OB_NOT_SUPPORTED,"migrate unit between zones");
9277} else if (OB_FAIL(get_excluded_servers(unit_info.unit_.resource_pool_id_, unit_info.unit_.zone_,
9278module, false/*new_allocate_pool*/, excluded_servers))) {
9279LOG_WARN("get_excluded_servers failed", "unit", unit_info.unit_, KR(ret));
9280} else if (has_exist_in_array(excluded_servers, dst)) {
9281ret = OB_NOT_SUPPORTED;
9282LOG_USER_ERROR(OB_NOT_SUPPORTED,"hold two units of a tenant in the same server");
9283LOG_WARN("hold two units of a tenant in the same server is not supported", KR(ret));
9284} else if (OB_FAIL(SVR_TRACER.get_server_info(dst, dst_server_info))) {
9285LOG_WARN("get dst_server_info failed", KR(ret), K(dst));
9286} else if (!dst_server_info.can_migrate_in()) {
9287ret = OB_SERVER_MIGRATE_IN_DENIED;
9288LOG_WARN("server can not migrate in", K(dst), K(dst_server_info), KR(ret));
9289} else if (OB_FAIL(get_server_resource_info_via_rpc(dst_server_info, report_dst_server_resource_info))) {
9290LOG_WARN("fail to execute get_server_resource_info_via_rpc", KR(ret), K(dst_server_info));
9291} else if (OB_FAIL(have_enough_resource(
9292report_dst_server_resource_info,
9293unit_info.config_.unit_resource(),
9294hard_limit,
9295can_hold_unit,
9296err_index))) {
9297LOG_WARN("calculate_left_resource failed", KR(ret), K(report_dst_server_resource_info),
9298K(hard_limit), K(err_index));
9299} else if (!can_hold_unit) {
9300ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
9301if (OB_SUCCESS != ERRSIM_USE_DUMMY_SERVER) {
9302LOG_USER_ERROR(OB_MACHINE_RESOURCE_NOT_ENOUGH, "dummy_zone", "127.0.0.1:1000",
9303alter_resource_err_to_str(err_index));
9304} else {
9305LOG_USER_ERROR(OB_MACHINE_RESOURCE_NOT_ENOUGH, to_cstring(dst_zone), to_cstring(dst),
9306alter_resource_err_to_str(err_index));
9307}
9308LOG_WARN("left resource can't hold unit", "server", dst,
9309K(hard_limit), "config", unit_info.config_, KR(ret));
9310} else if (OB_FAIL(migrate_unit_(unit_id, dst, true/*is_manual*/))) {
9311LOG_WARN("migrate unit failed", K(unit_id), "destination", dst, KR(ret));
9312}
9313
9314return ret;
9315}
9316
9317int ObUnitManager::cancel_migrate_unit(
9318const share::ObUnit &unit,
9319const bool migrate_from_server_can_migrate_in,
9320const bool is_gts_unit)
9321{
9322int ret = OB_SUCCESS;
9323if (!migrate_from_server_can_migrate_in && !is_gts_unit) {
9324ret = OB_SERVER_MIGRATE_IN_DENIED;
9325LOG_WARN("server can not migrate in", K(unit.migrate_from_server_), K(migrate_from_server_can_migrate_in), KR(ret));
9326} else {
9327const EndMigrateOp op = REVERSE;
9328if (OB_FAIL(end_migrate_unit(unit.unit_id_, op))) {
9329LOG_WARN("end_migrate_unit failed", "unit_id", unit.unit_id_, K(op), K(ret));
9330} else {
9331LOG_INFO("cancel migrate unit", K(unit));
9332}
9333}
9334return ret;
9335}
9336
9337int ObUnitManager::try_cancel_migrate_unit(const share::ObUnit &unit, bool &is_canceled)
9338{
9339int ret = OB_SUCCESS;
9340bool migrate_from_server_can_migrate_in = false;
9341bool server_can_migrate_in = false;
9342is_canceled = false;
9343if (!check_inner_stat()) {
9344ret = OB_INNER_STAT_ERROR;
9345LOG_WARN("check inner stat failed", K_(inited), K_(loaded), K(ret));
9346} else if (!unit.is_valid()) {
9347ret = OB_INVALID_ARGUMENT;
9348LOG_WARN("invalid unit", K(unit), K(ret));
9349} else if (OB_FAIL(SVR_TRACER.check_server_can_migrate_in(unit.server_, server_can_migrate_in))) {
9350LOG_WARN("check_server_can_migrate_in failed", "server", unit.server_, K(ret));
9351} else if (server_can_migrate_in) {
9352// ignore, do nothing
9353} else if (OB_FAIL(SVR_TRACER.check_server_can_migrate_in(
9354unit.migrate_from_server_,
9355migrate_from_server_can_migrate_in))) {
9356LOG_WARN("get_server_status failed", "server", unit.migrate_from_server_, K(ret));
9357} else if (migrate_from_server_can_migrate_in) {
9358LOG_INFO("unit migrate_from_server can migrate in, "
9359"migrate unit back to migrate_from_server", K(unit), K(migrate_from_server_can_migrate_in));
9360const EndMigrateOp op = REVERSE;
9361if (OB_FAIL(end_migrate_unit(unit.unit_id_, op))) {
9362LOG_WARN("end_migrate_unit failed", "unit_id", unit.unit_id_, K(op), K(ret));
9363} else {
9364is_canceled = true;
9365LOG_INFO("reverse unit migrate success", K(ret), "unit_id", unit.unit_id_, K(op));
9366}
9367}
9368return ret;
9369}
9370
9371int ObUnitManager::get_hard_limit(double &hard_limit) const
9372{
9373int ret = OB_SUCCESS;
9374if (!check_inner_stat()) {
9375ret = OB_INNER_STAT_ERROR;
9376LOG_WARN("check inner stat failed", K_(inited), K_(loaded), K(ret));
9377} else {
9378hard_limit = static_cast<double>(server_config_->resource_hard_limit) / 100;
9379}
9380return ret;
9381}
9382
9383// bug#11873101 issue/11873101
9384// Before attempting to migrate the unit,
9385// check whether the target unit space is sufficient,
9386// if it is insufficient, do not migrate,
9387// and return OB_OP_NOT_ALLOW
9388int ObUnitManager::try_migrate_unit(const uint64_t unit_id,
9389const uint64_t tenant_id,
9390const ObUnitStat &unit_stat,
9391const ObIArray<ObUnitStat> &migrating_unit_stat,
9392const ObAddr &dst,
9393const ObServerResourceInfo &dst_resource_info,
9394const bool is_manual)
9395{
9396int ret = OB_SUCCESS;
9397ObServerStatus server_status;
9398if (unit_id != unit_stat.get_unit_id()) {
9399ret = OB_INVALID_ARGUMENT;
9400LOG_WARN("invalid unit stat", K(unit_id), K(unit_stat), K(ret));
9401} else {
9402int64_t mig_required_size = 0;
9403for (int64_t i = 0; i < migrating_unit_stat.count(); ++i) {
9404mig_required_size += migrating_unit_stat.at(i).get_required_size();
9405}
9406// sstable Space constraints
9407int64_t required_size =
9408mig_required_size + unit_stat.get_required_size() + dst_resource_info.disk_in_use_;
9409int64_t total_size = dst_resource_info.disk_total_;
9410int64_t required_percent = (100 * required_size) / total_size;
9411int64_t limit_percent = GCONF.data_disk_usage_limit_percentage;
9412if (required_percent >= limit_percent) {
9413ret = OB_OP_NOT_ALLOW;
9414LOG_ERROR("migrate unit fail. dest server out of space",
9415K(unit_id), K(unit_stat), K(dst),
9416K(required_size), K(total_size), K(limit_percent), K(ret));
9417}
9418
9419if (FAILEDx(migrate_unit_(unit_id, dst, is_manual))) {
9420LOG_WARN("fail migrate unit", K(unit_id), K(dst), K(ret));
9421}
9422}
9423return ret;
9424}
9425
9426int ObUnitManager::migrate_unit_(const uint64_t unit_id, const ObAddr &dst, const bool is_manual)
9427{
9428int ret = OB_SUCCESS;
9429LOG_INFO("start to migrate unit", KR(ret), K(unit_id), K(dst), K(is_manual));
9430ObUnit *unit = NULL;
9431share::ObResourcePool *pool = NULL;
9432ObZone zone;
9433if (!check_inner_stat()) {
9434ret = OB_INNER_STAT_ERROR;
9435LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
9436} else if (OB_INVALID_ID == unit_id || !dst.is_valid()) {
9437ret = OB_INVALID_ARGUMENT;
9438LOG_WARN("invalid argument", K(unit_id), K(dst), K(ret));
9439} else if (OB_FAIL(get_unit_by_id(unit_id, unit))) {
9440LOG_WARN("get_unit_by_id failed", K(unit_id), K(ret));
9441} else if (OB_ISNULL(unit)) {
9442ret = OB_ERR_UNEXPECTED;
9443LOG_WARN("unit is null", KP(unit), K(ret));
9444} else if (ObUnit::UNIT_STATUS_ACTIVE != unit->status_) {
9445ret = OB_OP_NOT_ALLOW;
9446LOG_WARN("cannot migrate unit which is in deleting", K(ret), K(unit_id));
9447} else if (unit->server_ == dst) {
9448ret = OB_INVALID_ARGUMENT;
9449LOG_WARN("unit->server same as migrate destination server",
9450"unit", *unit, K(dst), K(ret));
9451} else if (OB_FAIL(SVR_TRACER.get_server_zone(dst, zone))) {
9452LOG_WARN("get_server_zone failed", KR(ret), K(dst));
9453} else if (OB_UNLIKELY(zone != unit->zone_)) {
9454ret = OB_NOT_SUPPORTED;
9455LOG_WARN("migrate unit between zones not supported", KR(ret), KP(unit), K(dst), K(zone));
9456} else if (unit->migrate_from_server_.is_valid()) {
9457ret = OB_NOT_SUPPORTED;
9458LOG_WARN("unit is already migrating, cannot migrate any more", "unit", *unit, K(ret));
9459LOG_USER_ERROR(OB_NOT_SUPPORTED, "migrate unit already in migrating status");
9460} else if (OB_FAIL(get_resource_pool_by_id(unit->resource_pool_id_, pool))) {
9461LOG_WARN("get_resource_pool_by_id failed",
9462"resource pool id", unit->resource_pool_id_, K(ret));
9463} else if (OB_ISNULL(pool)) {
9464ret = OB_ERR_UNEXPECTED;
9465LOG_WARN("pool is null", KP(pool), K(ret));
9466} else {
9467const bool granted = pool->is_granted_to_tenant();
9468const ObAddr src = unit->server_;
9469ObUnit new_unit = *unit;
9470new_unit.server_ = dst;
9471new_unit.migrate_from_server_ = granted ? src : ObAddr();
9472new_unit.is_manual_migrate_ = is_manual;
9473
9474LOG_INFO("do migrate unit", KPC(unit), K(new_unit), KPC(pool), K(granted));
9475
9476// STEP 1: try notify unit persistence on destination ObServer
9477if (OB_FAIL(do_migrate_unit_notify_resource_(*pool, new_unit, is_manual, granted))) {
9478LOG_WARN("do_migrate_unit_notify_resource failed", KR(ret), KPC(pool), K(new_unit), K(is_manual), K(granted));
9479}
9480
9481// STEP 2: Update info in inner_table in trans
9482if (OB_FAIL(ret)) {
9483} else if (OB_FAIL(do_migrate_unit_in_trans_(*pool, new_unit, is_manual, granted))) {
9484LOG_WARN("do_migrate_unit_in_trans failed", KR(ret), KPC(pool), K(new_unit), K(is_manual), K(granted));
9485}
9486
9487// STEP 3: Update in-memory info (unit & unit_load & migrate_unit)
9488if (OB_FAIL(ret)) {
9489} else if (OB_FAIL(do_migrate_unit_inmemory_(new_unit, unit, is_manual, granted))) {
9490LOG_WARN("do_migrate_unit_inmemory failed", KR(ret), K(dst), KPC(unit), K(is_manual), K(granted));
9491}
9492
9493// STEP 4: migration succeed, do some postprocess
9494if (OB_SUCC(ret)) {
9495// wakeup rootbalance thread to make disaster_recovery process more quickly
9496root_balance_->wakeup();
9497// add migrate_unit rootservice event
9498ROOTSERVICE_EVENT_ADD("unit", "migrate_unit",
9499"unit_id", unit->unit_id_,
9500"migrate_from_server", unit->migrate_from_server_,
9501"server", unit->server_,
9502"tenant_id", pool->tenant_id_,
9503"manual_migrate", is_manual ? "YES" : "NO");
9504}
9505}
9506LOG_INFO("finish migrate unit", KR(ret), K(unit_id), K(dst), K(is_manual));
9507return ret;
9508}
9509
9510int ObUnitManager::do_migrate_unit_notify_resource_(const share::ObResourcePool &pool,
9511const share::ObUnit &new_unit,
9512const bool is_manual,
9513const bool granted)
9514{
9515int ret = OB_SUCCESS;
9516lib::Worker::CompatMode compat_mode = lib::Worker::CompatMode::INVALID;
9517if (!check_inner_stat()) {
9518ret = OB_INNER_STAT_ERROR;
9519LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
9520} else if (!granted) {
9521// do nothing. If unit is not granted, there's no need to notify observer.
9522} else if (OB_UNLIKELY(nullptr == srv_rpc_proxy_)) {
9523ret = OB_ERR_UNEXPECTED;
9524LOG_WARN("srv_rpc_proxy_ ptr is null", KR(ret));
9525} else if (OB_UNLIKELY(new_unit.resource_pool_id_ != pool.resource_pool_id_)) {
9526ret = OB_INVALID_ARGUMENT;
9527LOG_WARN("new_unit not belong to pool", KR(ret), K(pool), K(new_unit));
9528} else if (OB_FAIL(ObCompatModeGetter::get_tenant_mode(pool.tenant_id_, compat_mode))) {
9529LOG_WARN("fail to get tenant compat mode", KR(ret), K(pool));
9530} else {
9531ObNotifyTenantServerResourceProxy notify_proxy(*srv_rpc_proxy_,
9532&obrpc::ObSrvRpcProxy::notify_tenant_server_unit_resource);
9533// only notify new unit resource on dst server here.
9534// Old unit on src server will be delete later when doing end_migrate
9535if (OB_FAIL(try_notify_tenant_server_unit_resource_(
9536pool.tenant_id_, false/*is_delete*/, notify_proxy, // is_delete is false when migrate unit
9537pool.unit_config_id_, compat_mode, new_unit, false/*if not grant*/,
9538false/*skip offline server*/,
9539true /*check_data_version*/))) {
9540LOG_WARN("fail to try notify server unit resource", K(ret));
9541}
9542int tmp_ret = OB_SUCCESS;
9543if (OB_TMP_FAIL(notify_proxy.wait())) {
9544LOG_WARN("fail to wait notify resource", K(ret), K(tmp_ret));
9545ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
9546} else if (OB_SUCC(ret)) {
9547// arg/dest/result can be used here.
9548}
9549
9550// Rollback persistent unit if persistence failed
9551ret = ERRSIM_UNIT_PERSISTENCE_ERROR ? : ret;
9552if (OB_FAIL(ret)) {
9553LOG_WARN("start to rollback unit persistence", KR(ret), K(new_unit), K(pool.tenant_id_));
9554int tmp_ret = OB_SUCCESS;
9555ObArray<ObUnit> units;
9556if (OB_TMP_FAIL(units.push_back(new_unit))) {
9557LOG_WARN("fail to push an element into units", KR(ret), KR(tmp_ret), K(new_unit));
9558} else if (OB_TMP_FAIL(rollback_persistent_units_(units, pool, notify_proxy))) {
9559LOG_WARN("fail to rollback unit persistence", KR(ret), KR(tmp_ret),
9560K(units), K(pool), K(compat_mode));
9561}
9562}
9563}
9564return ret;
9565}
9566
9567int ObUnitManager::do_migrate_unit_in_trans_(const share::ObResourcePool &pool,
9568const share::ObUnit &new_unit,
9569const bool is_manual,
9570const bool granted)
9571{
9572int ret = OB_SUCCESS;
9573common::ObMySQLTransaction trans;
9574share::ObResourcePool real_pool;
9575if (!check_inner_stat()) {
9576ret = OB_INNER_STAT_ERROR;
9577LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
9578} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
9579LOG_WARN("failed to start trans", K(ret));
9580}
9581// Double check whether exactly unit is granted by querying pool from inner_table.
9582// Because during creating or dropping tenant, there's a period when inner_table
9583// and persistence units are updated while in-memory info not updated yet.
9584// We need lock by SELECT FOR UPDATE to assure no other trans is still updating pool when checking.
9585if (OB_FAIL(ret)) {
9586} else if (OB_FAIL(ut_operator_.get_resource_pool(trans,
9587pool.resource_pool_id_,
9588true/*select_for_update*/,
9589real_pool))) {
9590LOG_WARN("fail to get resource_pools from table", KR(ret));
9591} else {
9592if (pool.is_granted_to_tenant() != real_pool.is_granted_to_tenant()) {
9593ret = OB_ERR_UNEXPECTED;
9594LOG_WARN("in-memory pool info not accurate, cannot migrate unit now.",
9595KR(ret), K(new_unit), K(pool), K(real_pool));
9596}
9597}
9598// Create migrate RS_JOB if it's a manual migration:
9599// * If not granted, the job will be set as complete on creating.
9600// * If granted, the job will be completed when end_migrate_unit is called.
9601if (OB_FAIL(ret)) {
9602} else if (is_manual) {
9603char ip_buf[common::MAX_IP_ADDR_LENGTH];
9604const ObAddr &dst = new_unit.server_;
9605(void)dst.ip_to_string(ip_buf, common::MAX_IP_ADDR_LENGTH);
9606int64_t job_id = 0;
9607if (OB_FAIL(RS_JOB_CREATE_WITH_RET(
9608job_id,
9609ObRsJobType::JOB_TYPE_MIGRATE_UNIT,
9610trans,
9611"unit_id", new_unit.unit_id_,
9612"svr_ip", ip_buf,
9613"svr_port", dst.get_port(),
9614"tenant_id", pool.tenant_id_))) {
9615LOG_WARN("fail to create rs job MIGRATE_UNIT", KR(ret),
9616"tenant_id", pool.tenant_id_,
9617"unit_id", new_unit.unit_id_);
9618} else if (!granted) {
9619// not granted, migration can be done at once, so mark RS_JOB completed
9620if (OB_FAIL(RS_JOB_COMPLETE(job_id, OB_SUCCESS, trans))) {
9621LOG_WARN("all_rootservice_job update failed", K(ret), K(job_id));
9622}
9623}
9624}
9625// Update unit info
9626if (OB_FAIL(ret)) {
9627} else if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, true/*need_check_conflict_with_clone*/))) {
9628LOG_WARN("update_unit failed", K(new_unit), K(ret));
9629}
9630// End this transaction
9631if (trans.is_started()) {
9632int tmp_ret = OB_SUCCESS;
9633if (OB_SUCCESS != (tmp_ret = trans.end(OB_SUCC(ret)))) {
9634ret = OB_SUCC(ret) ? tmp_ret : ret;
9635LOG_WARN("trans commit failed", K(tmp_ret), K(ret));
9636}
9637}
9638return ret;
9639}
9640
9641int ObUnitManager::do_migrate_unit_inmemory_(const share::ObUnit &new_unit,
9642share::ObUnit *unit,
9643const bool is_manual,
9644const bool granted)
9645{
9646int ret = OB_SUCCESS;
9647if (!check_inner_stat()) {
9648ret = OB_INNER_STAT_ERROR;
9649LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
9650} else if (OB_ISNULL(unit)) {
9651ret = OB_ERR_UNEXPECTED;
9652LOG_WARN("unit ptr is null", KR(ret), KP(unit));
9653} else if (OB_UNLIKELY(unit->unit_id_ != new_unit.unit_id_)) {
9654ret = OB_ERR_UNEXPECTED;
9655LOG_WARN("old and new unit id not the same", KR(ret), KPC(unit), K(new_unit));
9656} else {
9657const ObAddr src = unit->server_;
9658const ObAddr dst = new_unit.server_;
9659// do update unit
9660*unit = new_unit;
9661// update unit_load
9662// delete old unit load imediately if pool not granted
9663if (!granted) {
9664if (OB_FAIL(delete_unit_load(src, unit->unit_id_))) {
9665LOG_WARN("delete_unit_load failed", K(src), "unit_id", unit->unit_id_, KR(ret));
9666}
9667}
9668// insert new unit load
9669ObUnitLoad load;
9670if (OB_FAIL(ret)) {
9671} else if (OB_FAIL(gen_unit_load(unit, load))) {
9672LOG_WARN("gen_unit_load failed", "unit", *unit, K(ret));
9673} else if (OB_FAIL(insert_unit_load(dst, load))) {
9674LOG_WARN("insert_unit_load failed", K(dst), K(ret));
9675}
9676// update migrate_unit list
9677if (OB_FAIL(ret)) {
9678} else if (granted) {
9679if (OB_FAIL(insert_migrate_unit(unit->migrate_from_server_, unit->unit_id_))) {
9680LOG_WARN("insert_migrate_unit failed", "unit", *unit, K(ret));
9681}
9682}
9683}
9684return ret;
9685}
9686
9687int ObUnitManager::inner_try_delete_migrate_unit_resource(
9688const uint64_t unit_id,
9689const common::ObAddr &migrate_from_server)
9690{
9691int ret = OB_SUCCESS;
9692ObUnit *unit = NULL;
9693share::ObResourcePool *pool = NULL;
9694share::ObUnitConfig *unit_config = nullptr;
9695lib::Worker::CompatMode compat_mode = lib::Worker::CompatMode::INVALID;
9696bool is_alive = false;
9697if (!check_inner_stat()) {
9698ret = OB_INNER_STAT_ERROR;
9699LOG_WARN("inner stat unexpected", K(ret), K(inited_), K(loaded_));
9700} else if (OB_UNLIKELY(OB_INVALID_ID == unit_id)) {
9701ret = OB_INVALID_ARGUMENT;
9702LOG_WARN("invalid argument", K(ret), K(unit_id));
9703} else if (OB_FAIL(get_unit_by_id(unit_id, unit))) {
9704LOG_WARN("fail to get unit by id", K(ret), K(unit_id));
9705} else if (OB_ISNULL(unit)) {
9706ret = OB_ERR_UNEXPECTED;
9707LOG_WARN("unit ptr is null", K(ret), KP(unit));
9708} else if (!migrate_from_server.is_valid()) {
9709LOG_INFO("unit not in migrating, no need to delete src resource", K(unit_id));
9710} else if (OB_FAIL(SVR_TRACER.check_server_alive(migrate_from_server, is_alive))) {
9711LOG_WARN("fail to check server alive", K(ret), "server", migrate_from_server);
9712} else if (!is_alive) {
9713LOG_INFO("src server not alive, ignore notify",
9714K(unit_id), "server", migrate_from_server);
9715} else if (OB_FAIL(get_resource_pool_by_id(unit->resource_pool_id_, pool))) {
9716LOG_WARN("failed to get pool", K(ret), K(unit));
9717} else if (OB_ISNULL(pool)) {
9718ret = OB_ERR_UNEXPECTED;
9719LOG_WARN("pool ptr is null", K(ret), KP(pool));
9720} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, unit_config))) {
9721LOG_WARN("fail to get unit config by id", K(ret));
9722} else if (OB_UNLIKELY(nullptr == unit_config)) {
9723ret = OB_ERR_UNEXPECTED;
9724LOG_WARN("unit config is null", K(ret), "unit_config_id", pool->unit_config_id_);
9725} else if (!pool->is_granted_to_tenant()) {
9726LOG_INFO("unit is not granted to any tenant", K(ret), "tenant_id", pool->tenant_id_);
9727} else if (OB_FAIL(ObCompatModeGetter::get_tenant_mode(pool->tenant_id_, compat_mode))) {
9728LOG_WARN("fail to get tenant compat mode", K(ret),
9729"tenant_id", pool->tenant_id_, K(unit_id), "pool", *pool);
9730} else {
9731const int64_t rpc_timeout = NOTIFY_RESOURCE_RPC_TIMEOUT;
9732obrpc::TenantServerUnitConfig tenant_unit_server_config;
9733ObNotifyTenantServerResourceProxy notify_proxy(
9734*srv_rpc_proxy_,
9735&obrpc::ObSrvRpcProxy::notify_tenant_server_unit_resource);
9736if (OB_FAIL(tenant_unit_server_config.init_for_dropping(pool->tenant_id_, true/*delete*/))) {
9737LOG_WARN("fail to init tenant server unit config", K(ret), "tenant_id", pool->tenant_id_);
9738} else if (OB_FAIL(notify_proxy.call(
9739migrate_from_server, rpc_timeout, tenant_unit_server_config))) {
9740LOG_WARN("fail to call notify resource to server",
9741K(ret), K(rpc_timeout), "unit", *unit, "dest", migrate_from_server);
9742}
9743int tmp_ret = OB_SUCCESS;
9744if (OB_TMP_FAIL(notify_proxy.wait())) {
9745LOG_WARN("fail to wait notify resource", K(ret), K(tmp_ret));
9746ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
9747}
9748if (OB_SUCC(ret)) {
9749// arg/dest/result can be used here.
9750LOG_INFO("notify resource to server succeed", "unit", *unit, "dest", migrate_from_server);
9751}
9752}
9753return ret;
9754}
9755
9756int ObUnitManager::end_migrate_unit(const uint64_t unit_id, const EndMigrateOp end_migrate_op)
9757{
9758int ret = OB_SUCCESS;
9759uint64_t tenant_id = OB_INVALID_ID;
9760if (!check_inner_stat()) {
9761ret = OB_INNER_STAT_ERROR;
9762LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
9763} else if (OB_INVALID_ID == unit_id) {
9764ret = OB_INVALID_ARGUMENT;
9765LOG_WARN("invalid argument", K(unit_id), K(ret));
9766} else if (end_migrate_op < COMMIT || end_migrate_op > REVERSE) {
9767ret = OB_INVALID_ARGUMENT;
9768LOG_WARN("invalid end_migrate_op", K(end_migrate_op), K(ret));
9769} else {
9770ObUnit *unit = NULL;
9771common::ObMySQLTransaction trans;
9772if (OB_FAIL(get_unit_by_id(unit_id, unit))) {
9773LOG_WARN("get_unit_by_id failed", K(unit_id), K(ret));
9774} else if (NULL == unit) {
9775ret = OB_ERR_UNEXPECTED;
9776LOG_WARN("unit is null", KP(unit), K(ret));
9777} else if (!unit->migrate_from_server_.is_valid()) {
9778// FIXME(jingqian): when can this happened, figure it out
9779ret = OB_SUCCESS;
9780LOG_WARN("unit is not in migrating status, maybe end_migrate_unit has ever called",
9781"unit", *unit, K(ret));
9782} else {
9783const ObAddr migrate_from_server = unit->migrate_from_server_;
9784const ObAddr unit_server = unit->server_;
9785const bool is_manual = unit->is_manual_migrate();
9786ObUnit new_unit = *unit;
9787new_unit.is_manual_migrate_ = false; // clear manual_migrate
9788// generate new unit
9789if (COMMIT == end_migrate_op) {
9790new_unit.migrate_from_server_.reset();
9791} else if (ABORT == end_migrate_op) {
9792new_unit.server_ = unit->migrate_from_server_;
9793new_unit.migrate_from_server_.reset();
9794} else {
9795new_unit.server_ = unit->migrate_from_server_;
9796new_unit.migrate_from_server_ = unit->server_;
9797}
9798
9799// update unit in sys_table and in memory
9800if (OB_FAIL(ret)) {
9801} else if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
9802LOG_WARN("failed to start transaction ", K(ret));
9803} else if (OB_FAIL(ut_operator_.update_unit(trans, new_unit, true/*need_check_conflict_with_clone*/))) {
9804LOG_WARN("ut_operator update unit failed", K(new_unit), K(ret));
9805} else {
9806if (ABORT == end_migrate_op) {
9807if (OB_FAIL(delete_unit_load(unit->server_, unit->unit_id_))) {
9808LOG_WARN("delete_unit_load failed", "unit", *unit, K(ret));
9809}
9810} else if (COMMIT == end_migrate_op) {
9811if (OB_FAIL(delete_unit_load(unit->migrate_from_server_, unit->unit_id_))) {
9812LOG_WARN("delete_unit_load failed", "unit", *unit, K(ret));
9813}
9814}
9815if (OB_SUCC(ret)) {
9816*unit = new_unit;
9817}
9818}
9819
9820// delete migrating unit from migrate_units of migrate_from_server,
9821// if REVERSE == op, add migrating unit to migrate_units of unit_server
9822if (OB_FAIL(ret)) {
9823} else if (OB_FAIL(delete_migrate_unit(migrate_from_server, unit->unit_id_))) {
9824LOG_WARN("delete_migrate_unit failed", K(migrate_from_server),
9825"unit_id", unit->unit_id_, K(ret));
9826} else if (REVERSE == end_migrate_op) {
9827if (OB_FAIL(insert_migrate_unit(unit_server, unit->unit_id_))) {
9828LOG_WARN("insert_migrate_unit failed", K(unit_server), "unit_id",
9829unit->unit_id_, K(ret));
9830}
9831}
9832
9833if (OB_SUCC(ret)) {
9834int tmp_ret = OB_SUCCESS;
9835share::ObResourcePool *pool = NULL;
9836if (OB_SUCCESS != (tmp_ret = get_resource_pool_by_id(unit->resource_pool_id_, pool))) {
9837LOG_WARN("failed to get pool", K(tmp_ret), K(unit));
9838} else {
9839tenant_id = pool->tenant_id_;
9840}
9841ROOTSERVICE_EVENT_ADD("unit", "finish_migrate_unit",
9842"unit_id", unit_id,
9843"end_op", end_migrate_op_type_to_str(end_migrate_op),
9844"migrate_from_server", migrate_from_server,
9845"server", unit_server,
9846"tenant_id", tenant_id,
9847"manual_migrate", is_manual ? "YES" : "NO");
9848
9849// complete the job if exists
9850char ip_buf[common::MAX_IP_ADDR_LENGTH];
9851(void)unit_server.ip_to_string(ip_buf, common::MAX_IP_ADDR_LENGTH);
9852int64_t job_id = 0;
9853tmp_ret = RS_JOB_FIND(MIGRATE_UNIT, job_id, trans, "unit_id", unit_id,
9854"svr_ip", ip_buf, "svr_port", unit_server.get_port());
9855if (OB_SUCCESS == tmp_ret && job_id > 0) {
9856tmp_ret = (end_migrate_op == COMMIT) ? OB_SUCCESS :
9857(end_migrate_op == REVERSE ? OB_CANCELED : OB_TIMEOUT);
9858if (OB_FAIL(RS_JOB_COMPLETE(job_id, tmp_ret, trans))) {
9859LOG_WARN("all_rootservice_job update failed", K(ret), K(job_id));
9860}
9861} else {
9862//Can not find the situation, only the user manually opened will write rs_job
9863LOG_WARN("no rs job", K(ret), K(tmp_ret), K(unit_id));
9864}
9865}
9866const bool commit = OB_SUCC(ret) ? true:false;
9867int tmp_ret = OB_SUCCESS ;
9868if (OB_SUCCESS != (tmp_ret = trans.end(commit))) {
9869LOG_WARN("tran commit failed", K(tmp_ret));
9870}
9871ret = OB_SUCC(ret) ? tmp_ret : ret;
9872
9873if (OB_SUCC(ret) && COMMIT == end_migrate_op && OB_INVALID_ID != tenant_id) {
9874(void)inner_try_delete_migrate_unit_resource(unit_id, migrate_from_server);
9875}
9876}
9877}
9878
9879LOG_INFO("end migrate unit", K(unit_id), K(end_migrate_op), K(ret));
9880return ret;
9881}
9882
9883#define INSERT_ITEM_TO_MAP(map, key, pvalue) \
9884do { \
9885if (OB_FAIL(ret)) { \
9886} else if (OB_FAIL(map.set_refactored(key, pvalue))) { \
9887if (OB_HASH_EXIST == ret) { \
9888LOG_WARN("key already exist", K(key), K(ret)); \
9889} else { \
9890LOG_WARN("map set failed", K(ret)); \
9891} \
9892} else { \
9893} \
9894} while (false)
9895
9896#define SET_ITEM_TO_MAP(map, key, value) \
9897do { \
9898const int overwrite = 1; \
9899if (OB_FAIL(ret)) { \
9900} else if (OB_FAIL(map.set_refactored(key, value, overwrite))) { \
9901LOG_WARN("map set failed", K(ret)); \
9902} else { \
9903} \
9904} while (false)
9905
9906#define INSERT_ARRAY_TO_MAP(map, key, array) \
9907do { \
9908if (OB_FAIL(ret)) { \
9909} else if (OB_FAIL(map.set_refactored(key, array))) { \
9910if (OB_HASH_EXIST == ret) { \
9911LOG_WARN("key already exist", K(key), K(ret)); \
9912} else { \
9913LOG_WARN("map set failed", K(ret)); \
9914} \
9915} else { \
9916} \
9917} while (false)
9918
9919int ObUnitManager::build_unit_map(const ObIArray<ObUnit> &units)
9920{
9921int ret = OB_SUCCESS;
9922// units is empty if invoked during bootstrap
9923if (!inited_) {
9924ret = OB_NOT_INIT;
9925LOG_WARN("not init", K(ret));
9926} else if (OB_FAIL(id_unit_map_.clear())) {
9927LOG_WARN("id_unit_map_ clear failed", K(ret));
9928} else {
9929for (int64_t i = 0; OB_SUCC(ret) && i < units.count(); ++i) {
9930ObUnit *unit = NULL;
9931if (NULL == (unit = allocator_.alloc())) {
9932ret = OB_ALLOCATE_MEMORY_FAILED;
9933LOG_ERROR("alloc unit failed", K(ret));
9934} else {
9935*unit = units.at(i);
9936if (OB_FAIL(insert_unit(unit))) {
9937LOG_WARN("insert_unit failed", "unit", *unit, K(ret));
9938}
9939
9940if (OB_FAIL(ret)) {
9941//avoid memory leak
9942allocator_.free(unit);
9943unit = NULL;
9944}
9945}
9946}
9947}
9948return ret;
9949}
9950
9951int ObUnitManager::build_config_map(const ObIArray<ObUnitConfig> &configs)
9952{
9953int ret = OB_SUCCESS;
9954// configs is empty if invoked during bootstrap
9955if (!inited_) {
9956ret = OB_NOT_INIT;
9957LOG_WARN("not init", K(ret));
9958} else if (OB_FAIL(id_config_map_.clear())) {
9959LOG_WARN("id_config_map_ clear failed", K(ret));
9960} else if (OB_FAIL(name_config_map_.clear())) {
9961LOG_WARN("name_config_map_ clear failed", K(ret));
9962} else {
9963for (int64_t i = 0; OB_SUCC(ret) && i < configs.count(); ++i) {
9964ObUnitConfig *config = NULL;
9965if (NULL == (config = config_allocator_.alloc())) {
9966ret = OB_ALLOCATE_MEMORY_FAILED;
9967LOG_ERROR("alloc unit config failed", K(ret));
9968} else {
9969*config = configs.at(i);
9970if (OB_FAIL(insert_unit_config(config))) {
9971LOG_WARN("insert_unit_config failed", KP(config), K(ret));
9972}
9973
9974if (OB_FAIL(ret)) {
9975config_allocator_.free(config);
9976config = NULL;
9977}
9978}
9979}
9980}
9981return ret;
9982}
9983
9984int ObUnitManager::build_pool_map(const ObIArray<share::ObResourcePool> &pools)
9985{
9986int ret = OB_SUCCESS;
9987// pools is empty if invoked during bootstrap
9988if (!inited_) {
9989ret = OB_NOT_INIT;
9990LOG_WARN("not init", K(ret));
9991} else if (OB_FAIL(id_pool_map_.clear())) {
9992LOG_WARN("id_pool_map_ clear failed", K(ret));
9993} else if (OB_FAIL(name_pool_map_.clear())) {
9994LOG_WARN("name_pool_map_ clear failed", K(ret));
9995} else {
9996for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
9997share::ObResourcePool *pool = NULL;
9998if (NULL == (pool = pool_allocator_.alloc())) {
9999ret = OB_ALLOCATE_MEMORY_FAILED;
10000LOG_ERROR("alloc resource pool failed", K(ret));
10001} else {
10002if (OB_FAIL(pool->assign(pools.at(i)))) {
10003LOG_WARN("failed to assign pool", K(ret));
10004} else {
10005INSERT_ITEM_TO_MAP(id_pool_map_, pool->resource_pool_id_, pool);
10006INSERT_ITEM_TO_MAP(name_pool_map_, pool->name_, pool);
10007if (OB_FAIL(ret)) {
10008} else if (OB_FAIL(inc_config_ref_count(pool->unit_config_id_))) {
10009LOG_WARN("inc_config_ref_count failed", "config id", pool->unit_config_id_, K(ret));
10010} else if (OB_FAIL(insert_config_pool(pool->unit_config_id_, pool))) {
10011LOG_WARN("insert config pool failed", "config id", pool->unit_config_id_, K(ret));
10012}
10013}
10014
10015if (OB_FAIL(ret)) {
10016pool_allocator_.free(pool);
10017pool = NULL;
10018}
10019}
10020}
10021}
10022return ret;
10023}
10024
10025int ObUnitManager::insert_unit_config(ObUnitConfig *config)
10026{
10027int ret = OB_SUCCESS;
10028if (!inited_) {
10029ret = OB_NOT_INIT;
10030LOG_WARN("not init", K(ret));
10031} else if (NULL == config) {
10032ret = OB_INVALID_ARGUMENT;
10033LOG_WARN("config is null", KP(config), K(ret));
10034} else if (!config->is_valid()) {
10035ret = OB_INVALID_ARGUMENT;
10036LOG_WARN("invalid config", "config", *config, K(ret));
10037} else {
10038INSERT_ITEM_TO_MAP(id_config_map_, config->unit_config_id(), config);
10039INSERT_ITEM_TO_MAP(name_config_map_, config->name(), config);
10040int64_t ref_count = 0;
10041SET_ITEM_TO_MAP(config_ref_count_map_, config->unit_config_id(), ref_count);
10042}
10043return ret;
10044}
10045
10046int ObUnitManager::inc_config_ref_count(const uint64_t config_id)
10047{
10048int ret = OB_SUCCESS;
10049if (!inited_) {
10050ret = OB_NOT_INIT;
10051LOG_WARN("not init", K(ret));
10052} else if (OB_INVALID_ID == config_id) {
10053ret = OB_INVALID_ARGUMENT;
10054LOG_WARN("invalid config_id", K(config_id), K(ret));
10055} else {
10056int64_t ref_count = 0;
10057if (OB_FAIL(get_config_ref_count(config_id, ref_count))) {
10058LOG_WARN("get_config_ref_count failed", K(config_id), K(ret));
10059} else {
10060++ref_count;
10061SET_ITEM_TO_MAP(config_ref_count_map_, config_id, ref_count);
10062}
10063}
10064return ret;
10065}
10066
10067int ObUnitManager::dec_config_ref_count(const uint64_t config_id)
10068{
10069int ret = OB_SUCCESS;
10070if (!inited_) {
10071ret = OB_NOT_INIT;
10072LOG_WARN("not init", K(ret));
10073} else if (OB_INVALID_ID == config_id) {
10074ret = OB_INVALID_ARGUMENT;
10075LOG_WARN("invalid config_id", K(config_id), K(ret));
10076} else {
10077int64_t ref_count = 0;
10078if (OB_FAIL(get_config_ref_count(config_id, ref_count))) {
10079LOG_WARN("get_config_ref_count failed", K(config_id), K(ret));
10080} else {
10081--ref_count;
10082SET_ITEM_TO_MAP(config_ref_count_map_, config_id, ref_count);
10083}
10084}
10085return ret;
10086}
10087
10088int ObUnitManager::update_pool_map(share::ObResourcePool *resource_pool)
10089{
10090int ret = OB_SUCCESS;
10091if (!inited_) {
10092ret = OB_NOT_INIT;
10093LOG_WARN("not init", K(ret));
10094} else if (NULL == resource_pool) {
10095ret = OB_INVALID_ARGUMENT;
10096LOG_WARN("resource_pool is null", KP(resource_pool), K(ret));
10097} else if (!resource_pool->is_valid() || OB_INVALID_ID == resource_pool->resource_pool_id_) {
10098ret = OB_INVALID_ARGUMENT;
10099LOG_WARN("invalid resource_pool", "resource_pool", *resource_pool, K(ret));
10100} else {
10101INSERT_ITEM_TO_MAP(id_pool_map_, resource_pool->resource_pool_id_, resource_pool);
10102INSERT_ITEM_TO_MAP(name_pool_map_, resource_pool->name_, resource_pool);
10103}
10104return ret;
10105}
10106
10107int ObUnitManager::insert_unit(ObUnit *unit)
10108{
10109int ret = OB_SUCCESS;
10110if (!inited_) {
10111ret = OB_NOT_INIT;
10112LOG_INFO("not init", K(ret));
10113} else if (NULL == unit) {
10114ret = OB_INVALID_ARGUMENT;
10115LOG_WARN("unit is null", KP(unit), K(ret));
10116} else if (!unit->is_valid()) {
10117ret = OB_INVALID_ARGUMENT;
10118LOG_WARN("invalid unit", "unit", *unit, K(ret));
10119} else {
10120ObArray<ObUnit *> *units = NULL;
10121if (OB_FAIL(get_units_by_pool(unit->resource_pool_id_, units))) {
10122if (OB_ENTRY_NOT_EXIST != ret) {
10123LOG_WARN("get_units_by_pool failed", K(ret));
10124} else {
10125ret = OB_SUCCESS;
10126if (NULL == (units = pool_unit_allocator_.alloc())) {
10127ret = OB_ALLOCATE_MEMORY_FAILED;
10128LOG_ERROR("alloc ObArray<ObUnit *> failed", K(ret));
10129} else {
10130if (OB_FAIL(units->push_back(unit))) {
10131LOG_WARN("push_back failed", K(ret));
10132} else {
10133INSERT_ARRAY_TO_MAP(pool_unit_map_, unit->resource_pool_id_, units);
10134}
10135if (OB_FAIL(ret)) {
10136pool_unit_allocator_.free(units);
10137units = NULL;
10138}
10139}
10140}
10141} else if (NULL == units) {
10142ret = OB_ERR_UNEXPECTED;
10143LOG_WARN("units is null", KP(units), K(ret));
10144} else if (OB_FAIL(units->push_back(unit))) {
10145LOG_WARN("push_back failed", K(ret));
10146}
10147
10148if (OB_SUCC(ret)) {
10149INSERT_ITEM_TO_MAP(id_unit_map_, unit->unit_id_, unit);
10150
10151if (OB_FAIL(ret)) {
10152} else if (OB_FAIL(insert_unit_loads(unit))) {
10153LOG_WARN("insert_unit_loads failed", "unit", *unit, K(ret));
10154}
10155}
10156}
10157return ret;
10158}
10159
10160int ObUnitManager::insert_unit_loads(ObUnit *unit)
10161{
10162int ret = OB_SUCCESS;
10163ObUnitLoad load;
10164if (!inited_) {
10165ret = OB_NOT_INIT;
10166LOG_WARN("not init", K(ret));
10167} else if (NULL == unit) {
10168ret = OB_INVALID_ARGUMENT;
10169LOG_WARN("unit is null", KP(unit), K(ret));
10170} else if (!unit->is_valid()) {
10171ret = OB_INVALID_ARGUMENT;
10172LOG_WARN("invalid unit", "unit", *unit, K(ret));
10173} else if (OB_FAIL(gen_unit_load(unit, load))) {
10174LOG_WARN("gen_unit_load failed", "unit", *unit, K(ret));
10175} else if (OB_FAIL(insert_unit_load(unit->server_, load))) {
10176LOG_WARN("insert_unit_load failed", "server", unit->server_, K(ret));
10177} else {
10178if (OB_SUCCESS == ret && unit->migrate_from_server_.is_valid()) {
10179if (OB_FAIL(insert_unit_load(unit->migrate_from_server_, load))) {
10180LOG_WARN("insert_unit_load failed", "server", unit->migrate_from_server_, K(ret));
10181}
10182}
10183}
10184return ret;
10185}
10186
10187int ObUnitManager::insert_unit_load(const ObAddr &server, const ObUnitLoad &load)
10188{
10189int ret = OB_SUCCESS;
10190ObArray<ObUnitLoad> *loads = NULL;
10191if (!inited_) {
10192ret = OB_NOT_INIT;
10193LOG_WARN("not init", K(ret));
10194} else if (!server.is_valid() || !load.is_valid()) {
10195ret = OB_INVALID_ARGUMENT;
10196LOG_WARN("invalid argument", K(server), K(load), K(ret));
10197} else if (OB_FAIL(get_loads_by_server(server, loads))) {
10198if (OB_ENTRY_NOT_EXIST != ret) {
10199LOG_WARN("get_loads_by_server failed", K(server), K(ret));
10200} else {
10201ret = OB_SUCCESS;
10202// not exist, alloc new array, add to hash map
10203if (NULL == (loads = load_allocator_.alloc())) {
10204ret = OB_ALLOCATE_MEMORY_FAILED;
10205LOG_ERROR("alloc ObArray<ObUnitLoad> failed", K(ret));
10206} else {
10207if (OB_FAIL(loads->push_back(load))) {
10208LOG_WARN("push_back failed", K(ret));
10209} else if (OB_FAIL(insert_load_array(server, loads))) {
10210LOG_WARN("insert_unit_load failed", K(server), K(ret));
10211}
10212if (OB_FAIL(ret)) {
10213// avoid memory leak
10214load_allocator_.free(loads);
10215loads = NULL;
10216}
10217}
10218}
10219} else if (NULL == loads) {
10220ret = OB_ERR_UNEXPECTED;
10221LOG_WARN("loads is null", KP(loads), K(ret));
10222} else {
10223if (OB_FAIL(loads->push_back(load))) {
10224LOG_WARN("push_back failed", K(ret));
10225}
10226}
10227return ret;
10228}
10229
10230int ObUnitManager::insert_load_array(const ObAddr &addr, ObArray<ObUnitLoad> *loads)
10231{
10232int ret = OB_SUCCESS;
10233if (!inited_) {
10234ret = OB_NOT_INIT;
10235LOG_WARN("not init", K(ret));
10236} else if (!addr.is_valid() || NULL == loads) {
10237ret = OB_INVALID_ARGUMENT;
10238LOG_WARN("invalid argument", K(addr), KP(loads), K(ret));
10239} else if (loads->count() <= 0) {
10240ret = OB_INVALID_ARGUMENT;
10241LOG_WARN("loads is empty", "loads count", loads->count(), K(ret));
10242} else {
10243if (OB_FAIL(server_loads_.set_refactored(addr, loads))) {
10244if (OB_HASH_EXIST == ret) {
10245LOG_WARN("load array is not expect to exist", K(addr), K(ret));
10246} else {
10247LOG_WARN("set failed", K(addr), K(ret));
10248}
10249} else {
10250// do nothing
10251}
10252}
10253return ret;
10254}
10255
10256int ObUnitManager::update_pool_load(share::ObResourcePool *pool,
10257share::ObUnitConfig *new_config)
10258{
10259int ret = OB_SUCCESS;
10260if (!inited_) {
10261ret = OB_NOT_INIT;
10262LOG_WARN("not init", K(ret));
10263} else if (NULL == pool || NULL == new_config) {
10264ret = OB_INVALID_ARGUMENT;
10265LOG_WARN("invalid argument", K(ret), KP(pool), KP(new_config));
10266} else {
10267FOREACH_X(sl, server_loads_, OB_SUCC(ret)) {
10268if (NULL == sl->second) {
10269ret = OB_ERR_UNEXPECTED;
10270LOG_WARN("NULL value", K(ret));
10271}
10272FOREACH_X(l, *sl->second, OB_SUCC(ret)) {
10273if (l->pool_ == pool) {
10274l->unit_config_ = new_config;
10275}
10276}
10277}
10278}
10279return ret;
10280}
10281
10282int ObUnitManager::gen_unit_load(ObUnit *unit, ObUnitLoad &load) const
10283{
10284int ret = OB_SUCCESS;
10285if (!inited_) {
10286ret = OB_NOT_INIT;
10287LOG_WARN("not init", K(ret));
10288} else if (NULL == unit) {
10289ret = OB_INVALID_ARGUMENT;
10290LOG_WARN("unit is null", KP(unit), K(ret));
10291} else if (!unit->is_valid()) {
10292ret = OB_INVALID_ARGUMENT;
10293LOG_WARN("unit is invalid", "unit", *unit, K(ret));
10294} else {
10295ObUnitConfig *config = NULL;
10296share::ObResourcePool *pool = NULL;
10297if (OB_FAIL(get_resource_pool_by_id(unit->resource_pool_id_, pool))) {
10298LOG_WARN("get_resource_pool_by_id failed", "pool id", unit->resource_pool_id_, K(ret));
10299} else if (NULL == pool) {
10300ret = OB_ERR_UNEXPECTED;
10301LOG_WARN("pools is null", KP(pool), K(ret));
10302} else if (OB_FAIL(get_unit_config_by_id(pool->unit_config_id_, config))) {
10303LOG_WARN("get_unit_config_by_id failed", "unit config id", pool->unit_config_id_, K(ret));
10304} else if (NULL == config) {
10305ret = OB_ERR_UNEXPECTED;
10306LOG_WARN("config is null", KP(config), K(ret));
10307} else {
10308load.unit_ = unit;
10309load.pool_ = pool;
10310load.unit_config_ = config;
10311}
10312}
10313return ret;
10314}
10315
10316int ObUnitManager::gen_unit_load(const uint64_t unit_id, ObUnitLoad &load) const
10317{
10318int ret = OB_SUCCESS;
10319ObUnit *unit = NULL;
10320if (!inited_) {
10321ret = OB_NOT_INIT;
10322LOG_WARN("not init", K(ret));
10323} else if (OB_INVALID_ID == unit_id) {
10324ret = OB_INVALID_ARGUMENT;
10325LOG_WARN("invalid unit_id", K(unit_id), K(ret));
10326} else if (OB_FAIL(get_unit_by_id(unit_id, unit))) {
10327LOG_WARN("get_unit_by_id failed", K(unit_id), K(ret));
10328} else if (NULL == unit) {
10329ret = OB_ERR_UNEXPECTED;
10330LOG_WARN("unit is null", KP(unit), K(ret));
10331} else if (OB_FAIL(gen_unit_load(unit, load))) {
10332LOG_WARN("gen_unit_load failed", "unit", *unit, K(ret));
10333}
10334return ret;
10335}
10336
10337int ObUnitManager::insert_tenant_pool(const uint64_t tenant_id, share::ObResourcePool *pool)
10338{
10339int ret = OB_SUCCESS;
10340if (!inited_) {
10341ret = OB_NOT_INIT;
10342LOG_WARN("not init", K(ret));
10343} else if (!is_valid_tenant_id(tenant_id) || NULL == pool) {
10344ret = OB_INVALID_ARGUMENT;
10345LOG_WARN("invalid argument", K(tenant_id), KP(pool), K(ret));
10346} else if (OB_FAIL(insert_id_pool(tenant_pools_map_,
10347tenant_pools_allocator_, tenant_id, pool))) {
10348LOG_WARN("insert tenant pool failed", K(tenant_id), KP(pool), K(ret));
10349}
10350
10351return ret;
10352}
10353
10354int ObUnitManager::insert_config_pool(const uint64_t config_id, share::ObResourcePool *pool)
10355{
10356int ret = OB_SUCCESS;
10357if (!inited_) {
10358ret = OB_NOT_INIT;
10359LOG_WARN("not init", K(ret));
10360} else if (OB_INVALID_ID == config_id || NULL == pool) {
10361ret = OB_INVALID_ARGUMENT;
10362LOG_WARN("invalid argument", K(config_id), KP(pool), K(ret));
10363} else if (OB_FAIL(insert_id_pool(config_pools_map_,
10364config_pools_allocator_, config_id, pool))) {
10365LOG_WARN("insert config pool failed", K(config_id), KP(pool), K(ret));
10366}
10367
10368return ret;
10369}
10370
10371int ObUnitManager::insert_id_pool(
10372common::hash::ObHashMap<uint64_t, common::ObArray<share::ObResourcePool *> *> &map,
10373common::ObPooledAllocator<common::ObArray<share::ObResourcePool *> > &allocator,
10374const uint64_t id,
10375share::ObResourcePool *pool)
10376{
10377int ret = OB_SUCCESS;
10378if (!inited_) {
10379ret = OB_NOT_INIT;
10380LOG_WARN("not init", K(ret));
10381} else if (!map.created() || OB_INVALID_ID == id || NULL == pool) {
10382ret = OB_INVALID_ARGUMENT;
10383LOG_WARN("invalid argument", "map created", map.created(), K(id), KP(pool), K(ret));
10384} else {
10385ObArray<share::ObResourcePool *> *pools = NULL;
10386if (OB_FAIL(get_pools_by_id(map, id, pools))) {
10387if (OB_ENTRY_NOT_EXIST != ret) {
10388LOG_WARN("get_pools_by_id failed", K(id), K(ret));
10389} else {
10390ret = OB_SUCCESS;
10391if (NULL == (pools = allocator.alloc())) {
10392ret = OB_ALLOCATE_MEMORY_FAILED;
10393LOG_ERROR("alloc pools failed", K(ret));
10394} else if (OB_FAIL(pools->push_back(pool))) {
10395LOG_WARN("push_back failed", K(ret));
10396} else if (OB_FAIL(insert_id_pool_array(map, id, pools))) {
10397LOG_WARN("insert_id_pool_array failed", K(id), K(ret));
10398}
10399
10400// avoid memory leak
10401if (OB_SUCCESS != ret && NULL != pools) {
10402allocator.free(pools);
10403pools = NULL;
10404}
10405}
10406} else if (NULL == pools) {
10407ret = OB_ERR_UNEXPECTED;
10408LOG_WARN("pools is null", KP(pools), K(ret));
10409} else if (!has_exist_in_array(*pools, pool)) {
10410if (OB_FAIL(pools->push_back(pool))) {
10411LOG_WARN("push_back failed", K(ret));
10412}
10413} else {
10414ret = OB_ERR_UNEXPECTED;
10415LOG_WARN("resource pool already exists", K(ret), K(id), K(pools), K(pool));
10416}
10417}
10418return ret;
10419}
10420
10421int ObUnitManager::insert_id_pool_array(
10422common::hash::ObHashMap<uint64_t, common::ObArray<share::ObResourcePool *> *> &map,
10423const uint64_t id,
10424ObArray<share::ObResourcePool *> *pools)
10425{
10426int ret = OB_SUCCESS;
10427if (!inited_) {
10428ret = OB_NOT_INIT;
10429LOG_WARN("not init", K(ret));
10430} else if (!map.created() || OB_INVALID_ID == id || NULL == pools) {
10431ret = OB_INVALID_ARGUMENT;
10432LOG_WARN("invalid argument", "map created", map.created(), K(id), KP(pools), K(ret));
10433} else {
10434if (OB_FAIL(map.set_refactored(id, pools))) {
10435if (OB_HASH_EXIST == ret) {
10436LOG_WARN("pools is not expect to exist", K(id), K(ret));
10437} else {
10438LOG_WARN("set failed", K(id), K(ret));
10439}
10440} else {
10441// do nothing
10442}
10443}
10444return ret;
10445}
10446
10447int ObUnitManager::insert_migrate_unit(const ObAddr &src_server, const uint64_t unit_id)
10448{
10449int ret = OB_SUCCESS;
10450if (!inited_) {
10451ret = OB_NOT_INIT;
10452LOG_WARN("not init", K(ret));
10453} else if (!src_server.is_valid() || OB_INVALID_ID == unit_id) {
10454ret = OB_INVALID_ARGUMENT;
10455LOG_WARN("invalid argument", K(src_server), K(unit_id), K(ret));
10456} else {
10457ObArray<uint64_t> *migrate_units = NULL;
10458if (OB_FAIL(get_migrate_units_by_server(src_server, migrate_units))) {
10459if (OB_ENTRY_NOT_EXIST != ret) {
10460LOG_WARN("get_migrate_units_by_server failed", K(src_server), K(ret));
10461} else {
10462ret= OB_SUCCESS;
10463if (NULL == (migrate_units = migrate_units_allocator_.alloc())) {
10464ret = OB_ALLOCATE_MEMORY_FAILED;
10465LOG_ERROR("alloc failed", K(ret));
10466} else if (OB_FAIL(migrate_units->push_back(unit_id))) {
10467LOG_WARN("push_back failed", K(ret));
10468} else {
10469INSERT_ARRAY_TO_MAP(server_migrate_units_map_, src_server, migrate_units);
10470}
10471
10472// avoid memory leak
10473if (OB_SUCCESS != ret && NULL != migrate_units) {
10474migrate_units_allocator_.free(migrate_units);
10475migrate_units = NULL;
10476}
10477}
10478} else if (NULL == migrate_units) {
10479ret = OB_ERR_UNEXPECTED;
10480LOG_WARN("migrate_units is null", KP(migrate_units), K(ret));
10481} else {
10482if (OB_FAIL(migrate_units->push_back(unit_id))) {
10483LOG_WARN("push_back failed", K(ret));
10484}
10485}
10486}
10487return ret;
10488}
10489
10490int ObUnitManager::set_server_ref_count(common::hash::ObHashMap<ObAddr, int64_t> &map,
10491const ObAddr &server, const int64_t ref_count) const
10492{
10493int ret = OB_SUCCESS;
10494if (!inited_) {
10495ret = OB_NOT_INIT;
10496LOG_WARN("not init", K(ret));
10497} else if (!map.created() || !server.is_valid() || ref_count <= 0) {
10498ret = OB_INVALID_ARGUMENT;
10499LOG_WARN("invalid argument", "map_created", map.created(), K(server), K(ref_count), K(ret));
10500} else {
10501SET_ITEM_TO_MAP(map, server, ref_count);
10502}
10503return ret;
10504}
10505
10506
10507#undef INSERT_ITEM_TO_MAP
10508#undef SET_ITEM_TO_MAP
10509#undef INSERT_ARRAY_TO_MAP
10510
10511#define DELETE_ITEM_FROM_MAP(map, key) \
10512do { \
10513if (OB_FAIL(ret)) { \
10514} else if (OB_FAIL(map.erase_refactored(key))) { \
10515LOG_WARN("map erase failed", K(key), K(ret)); \
10516} else { \
10517} \
10518} while (false)
10519
10520int ObUnitManager::delete_unit_config(const uint64_t config_id,
10521const ObUnitConfigName &name)
10522{
10523int ret = OB_SUCCESS;
10524if (!inited_) {
10525ret = OB_NOT_INIT;
10526LOG_WARN("not init", K(ret));
10527} else if (OB_INVALID_ID == config_id || name.is_empty()) {
10528ret = OB_INVALID_ARGUMENT;
10529LOG_WARN("invalid argument", K(config_id), K(name), K(ret));
10530} else {
10531DELETE_ITEM_FROM_MAP(id_config_map_, config_id);
10532DELETE_ITEM_FROM_MAP(name_config_map_, name);
10533DELETE_ITEM_FROM_MAP(config_ref_count_map_, config_id);
10534}
10535return ret;
10536}
10537
10538int ObUnitManager::delete_resource_pool(const uint64_t pool_id,
10539const ObResourcePoolName &name)
10540{
10541int ret = OB_SUCCESS;
10542if (!inited_) {
10543ret = OB_NOT_INIT;
10544LOG_WARN("not init", K(ret));
10545} else if (OB_INVALID_ID == pool_id || name.is_empty()) {
10546ret = OB_INVALID_ARGUMENT;
10547LOG_WARN("invalid argument", K(pool_id), K(name), K(ret));
10548} else {
10549DELETE_ITEM_FROM_MAP(id_pool_map_, pool_id);
10550DELETE_ITEM_FROM_MAP(name_pool_map_, name);
10551}
10552return ret;
10553}
10554
10555int ObUnitManager::delete_units_in_zones(
10556const uint64_t resource_pool_id,
10557const common::ObIArray<common::ObZone> &to_be_removed_zones)
10558{
10559int ret = OB_SUCCESS;
10560ObArray<ObUnit *> *units = NULL;
10561ObArray<ObUnit *> left_units;
10562if (!inited_) {
10563ret = OB_NOT_INIT;
10564LOG_WARN("not init", K(ret));
10565} else if (OB_UNLIKELY(OB_INVALID_ID == resource_pool_id)
10566|| OB_UNLIKELY(to_be_removed_zones.count() <= 0)) {
10567ret = OB_INVALID_ARGUMENT;
10568LOG_WARN("invalid argument", K(ret), K(resource_pool_id), K(to_be_removed_zones));
10569} else if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
10570LOG_WARN("fail to get units by pool", K(ret), K(resource_pool_id));
10571} else if (OB_UNLIKELY(NULL == units)) {
10572ret = OB_ERR_UNEXPECTED;
10573LOG_WARN("units is null", K(ret), KP(units));
10574} else {
10575for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
10576const ObUnit *unit = units->at(i);
10577if (OB_UNLIKELY(NULL == unit)) {
10578ret = OB_ERR_UNEXPECTED;
10579LOG_WARN("unit should not be null", "unit", OB_P(units->at(i)), K(ret));
10580} else if (!has_exist_in_array(to_be_removed_zones, unit->zone_)) {
10581if (OB_FAIL(left_units.push_back(units->at(i)))) {
10582LOG_WARN("fail to push back", K(ret));
10583} else {} // no more to do
10584} else if (OB_FAIL(delete_unit_loads(*unit))) {
10585LOG_WARN("fail to delete unit load", K(ret), "unit", *units->at(i));
10586} else {
10587DELETE_ITEM_FROM_MAP(id_unit_map_, unit->unit_id_);
10588if (OB_SUCC(ret)) {
10589if (unit->migrate_from_server_.is_valid()) {
10590//If the unit is being migrated, delete it from the state in memory
10591if (OB_FAIL(delete_migrate_unit(unit->migrate_from_server_,
10592unit->unit_id_))) {
10593LOG_WARN("failed to delete migrate unit", K(ret), "unit", *unit);
10594}
10595}
10596}
10597if (OB_SUCC(ret)) {
10598ROOTSERVICE_EVENT_ADD("unit", "drop_unit",
10599"unit_id", units->at(i)->unit_id_);
10600allocator_.free(units->at(i));
10601units->at(i) = NULL;;
10602}
10603}
10604}
10605if (OB_SUCC(ret)) {
10606if (left_units.count() <= 0) {
10607DELETE_ITEM_FROM_MAP(pool_unit_map_, resource_pool_id);
10608if (OB_SUCC(ret)) {
10609pool_unit_allocator_.free(units);
10610units = NULL;
10611}
10612} else {
10613if (OB_FAIL(units->assign(left_units))) {
10614LOG_WARN("assign failed", K(ret));
10615}
10616}
10617}
10618}
10619return ret;
10620}
10621
10622int ObUnitManager::delete_units_of_pool(const uint64_t resource_pool_id)
10623{
10624int ret = OB_SUCCESS;
10625ObArray<ObUnit *> *units = NULL;
10626if (!inited_) {
10627ret = OB_NOT_INIT;
10628LOG_WARN("not init", K(ret));
10629} else if (OB_INVALID_ID == resource_pool_id) {
10630ret = OB_INVALID_ARGUMENT;
10631LOG_WARN("invalid argument", K(resource_pool_id), K(ret));
10632} else if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
10633LOG_WARN("fail to get unit by pool", K(resource_pool_id), K(ret));
10634} else if (OB_UNLIKELY(NULL == units)) {
10635ret = OB_ERR_UNEXPECTED;
10636LOG_WARN("units is null", KP(units), K(ret));
10637} else {
10638for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
10639const ObUnit *unit = units->at(i);
10640if (OB_UNLIKELY(NULL == unit)) {
10641ret = OB_ERR_UNEXPECTED;
10642LOG_WARN("unit should not be null", K(ret));
10643} else if (OB_FAIL(delete_unit_loads(*unit))) {
10644LOG_WARN("fail to delete unit load", K(ret));
10645} else {
10646DELETE_ITEM_FROM_MAP(id_unit_map_, unit->unit_id_);
10647if (OB_SUCC(ret)) {
10648if (unit->migrate_from_server_.is_valid()) {
10649if (OB_FAIL(delete_migrate_unit(unit->migrate_from_server_,
10650unit->unit_id_))) {
10651LOG_WARN("failed to delete migrate unit", K(ret), "unit", *unit);
10652}
10653}
10654
10655}
10656
10657if (OB_SUCC(ret)) {
10658ROOTSERVICE_EVENT_ADD("unit", "drop_unit",
10659"unit_id", units->at(i)->unit_id_);
10660allocator_.free(units->at(i));
10661units->at(i) = NULL;
10662}
10663}
10664}
10665if (OB_SUCC(ret)) {
10666DELETE_ITEM_FROM_MAP(pool_unit_map_, resource_pool_id);
10667if (OB_SUCC(ret)) {
10668pool_unit_allocator_.free(units);
10669units = NULL;
10670}
10671}
10672}
10673return ret;
10674}
10675
10676int ObUnitManager::delete_invalid_inmemory_units(
10677const uint64_t resource_pool_id,
10678const common::ObIArray<uint64_t> &valid_unit_ids)
10679{
10680int ret = OB_SUCCESS;
10681ObArray<share::ObUnit *> *units = NULL;
10682ObArray<share::ObUnit *> left_units;
10683if (!inited_) {
10684ret = OB_NOT_INIT;
10685LOG_WARN("not init", K(ret));
10686} else if (OB_INVALID_ID == resource_pool_id || valid_unit_ids.count() <= 0) {
10687ret = OB_INVALID_ARGUMENT;
10688LOG_WARN("invalid argument", K(ret), K(resource_pool_id),
10689"valid_unit_cnt", valid_unit_ids.count());
10690} else if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
10691LOG_WARN("fail to get units by pool", K(ret), K(resource_pool_id));
10692} else if (OB_UNLIKELY(NULL == units)) {
10693ret = OB_ERR_UNEXPECTED;
10694LOG_WARN("units is null", KP(units), K(ret));
10695} else {
10696for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
10697if (NULL == units->at(i)) {
10698ret = OB_ERR_UNEXPECTED;
10699LOG_WARN("unit ptr is null", K(ret));
10700} else if (has_exist_in_array(valid_unit_ids, units->at(i)->unit_id_)) {
10701if (OB_FAIL(left_units.push_back(units->at(i)))) {
10702LOG_WARN("push_back failed", K(ret));
10703}
10704} else if (OB_FAIL(delete_unit_loads(*units->at(i)))) {
10705LOG_WARN("fail to delete unit loads", K(ret), "unit", *units->at(i));
10706} else {
10707DELETE_ITEM_FROM_MAP(id_unit_map_, units->at(i)->unit_id_);
10708if (OB_SUCC(ret)) {
10709ROOTSERVICE_EVENT_ADD("unit", "drop_unit",
10710"unit_id", units->at(i)->unit_id_);
10711allocator_.free(units->at(i));
10712units->at(i) = NULL;
10713}
10714}
10715}
10716if (OB_SUCC(ret)) {
10717if (left_units.count() <= 0) {
10718DELETE_ITEM_FROM_MAP(pool_unit_map_, resource_pool_id);
10719if (OB_SUCC(ret)) {
10720pool_unit_allocator_.free(units);
10721units = NULL;
10722}
10723} else {
10724if (OB_FAIL(units->assign(left_units))) {
10725LOG_WARN("assign failed", K(ret));
10726}
10727}
10728}
10729}
10730return ret;
10731}
10732
10733int ObUnitManager::delete_inmemory_units(
10734const uint64_t resource_pool_id,
10735const common::ObIArray<uint64_t> &unit_ids)
10736{
10737int ret = OB_SUCCESS;
10738if (!inited_) {
10739ret = OB_NOT_INIT;
10740LOG_WARN("not init", K(ret));
10741} else if (OB_INVALID_ID == resource_pool_id) {
10742ret = OB_INVALID_ARGUMENT;
10743LOG_WARN("invalid argument", K(resource_pool_id), K(ret));
10744} else {
10745ObArray<ObUnit *> *units = NULL;
10746ObArray<ObUnit *> left_units;
10747if (OB_FAIL(get_units_by_pool(resource_pool_id, units))) {
10748LOG_WARN("get_units_by_pool failed", K(resource_pool_id), K(ret));
10749} else if (NULL == units) {
10750ret = OB_ERR_UNEXPECTED;
10751LOG_WARN("units is null", KP(units), K(ret));
10752} else {
10753for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
10754if (NULL == units->at(i)) {
10755ret = OB_ERR_UNEXPECTED;
10756LOG_WARN("unit should not be null", "unit", OB_P(units->at(i)), K(ret));
10757} else if (!has_exist_in_array(unit_ids, units->at(i)->unit_id_)) {
10758if (OB_FAIL(left_units.push_back(units->at(i)))) {
10759LOG_WARN("push_back failed", K(ret));
10760}
10761} else {
10762if (OB_FAIL(delete_unit_loads(*units->at(i)))) {
10763LOG_WARN("delete_unit_load failed", "unit", *units->at(i), K(ret));
10764} else {
10765DELETE_ITEM_FROM_MAP(id_unit_map_, units->at(i)->unit_id_);
10766if (OB_SUCC(ret)) {
10767ROOTSERVICE_EVENT_ADD("unit", "drop_unit",
10768"unit_id", units->at(i)->unit_id_);
10769allocator_.free(units->at(i));
10770units->at(i) = NULL;
10771}
10772}
10773}
10774}
10775if (OB_SUCC(ret)) {
10776// if all units of pool are deleted, delete item from hashmap
10777if (left_units.count() <= 0) {
10778DELETE_ITEM_FROM_MAP(pool_unit_map_, resource_pool_id);
10779if (OB_SUCC(ret)) {
10780pool_unit_allocator_.free(units);
10781units = NULL;
10782}
10783} else {
10784if (OB_FAIL(units->assign(left_units))) {
10785LOG_WARN("assign failed", K(ret));
10786}
10787}
10788}
10789}
10790}
10791return ret;
10792}
10793
10794int ObUnitManager::delete_unit_loads(const ObUnit &unit)
10795{
10796int ret = OB_SUCCESS;
10797if (!inited_) {
10798ret = OB_NOT_INIT;
10799LOG_WARN("not init", K(ret));
10800} else if (!unit.is_valid()) {
10801ret = OB_INVALID_ARGUMENT;
10802LOG_WARN("invalid unit", K(unit), K(ret));
10803} else {
10804const uint64_t unit_id = unit.unit_id_;
10805if (OB_FAIL(delete_unit_load(unit.server_, unit_id))) {
10806LOG_WARN("delete_unit_load failed", "server", unit.server_, K(unit_id), K(ret));
10807} else {
10808if (unit.migrate_from_server_.is_valid()) {
10809if (OB_FAIL(delete_unit_load(unit.migrate_from_server_, unit_id))) {
10810LOG_WARN("delete_unit_load failed", "server", unit.migrate_from_server_,
10811K(unit_id), K(ret));
10812} else {
10813// do nothing
10814}
10815}
10816}
10817}
10818return ret;
10819}
10820
10821int ObUnitManager::delete_unit_load(const ObAddr &server, const uint64_t unit_id)
10822{
10823int ret = OB_SUCCESS;
10824if (!inited_) {
10825ret = OB_NOT_INIT;
10826LOG_WARN("not init", K(ret));
10827} else if (!server.is_valid() || OB_INVALID_ID == unit_id) {
10828ret = OB_INVALID_ARGUMENT;
10829LOG_WARN("invalid argument", K(server), K(unit_id), K(ret));
10830} else {
10831ObArray<ObUnitLoad> *loads = NULL;
10832if (OB_FAIL(get_loads_by_server(server, loads))) {
10833LOG_WARN("get_loads_by_server failed", K(server), K(ret));
10834} else if (NULL == loads) {
10835ret = OB_ERR_UNEXPECTED;
10836LOG_WARN("loads is null", KP(loads), K(ret));
10837} else {
10838int64_t index = -1;
10839for (int64_t i = 0; OB_SUCC(ret) && i < loads->count(); ++i) {
10840if (loads->at(i).unit_->unit_id_ == unit_id) {
10841index = i;
10842break;
10843}
10844}
10845if (-1 == index) {
10846ret = OB_ENTRY_NOT_EXIST;
10847LOG_WARN("unit load not exist", K(server), K(unit_id), K(ret));
10848} else {
10849for (int64_t i = index; i < loads->count() - 1; ++i) {
10850loads->at(i) = loads->at(i+1);
10851}
10852loads->pop_back();
10853if (0 == loads->count()) {
10854load_allocator_.free(loads);
10855loads = NULL;
10856DELETE_ITEM_FROM_MAP(server_loads_, server);
10857}
10858}
10859}
10860}
10861return ret;
10862}
10863
10864int ObUnitManager::delete_tenant_pool(const uint64_t tenant_id, share::ObResourcePool *pool)
10865{
10866int ret = OB_SUCCESS;
10867if (!inited_) {
10868ret = OB_NOT_INIT;
10869LOG_WARN("not init", K(ret));
10870} else if (!is_valid_tenant_id(tenant_id) || NULL == pool) {
10871ret = OB_INVALID_ARGUMENT;
10872LOG_WARN("invalid argument", K(tenant_id), KP(pool), K(ret));
10873} else if (OB_FAIL(delete_id_pool(tenant_pools_map_,
10874tenant_pools_allocator_, tenant_id, pool))) {
10875LOG_WARN("delete tenant pool failed", K(ret), K(tenant_id), "pool", *pool);
10876}
10877return ret;
10878}
10879
10880int ObUnitManager::delete_config_pool(const uint64_t config_id, share::ObResourcePool *pool)
10881{
10882int ret = OB_SUCCESS;
10883if (!inited_) {
10884ret = OB_NOT_INIT;
10885LOG_WARN("not init", K(ret));
10886} else if (OB_INVALID_ID == config_id || NULL == pool) {
10887ret = OB_INVALID_ARGUMENT;
10888LOG_WARN("invalid argument", K(config_id), KP(pool), K(ret));
10889} else if (OB_FAIL(delete_id_pool(config_pools_map_,
10890config_pools_allocator_, config_id, pool))) {
10891LOG_WARN("delete config pool failed", K(ret), K(config_id), "pool", *pool);
10892}
10893return ret;
10894}
10895
10896int ObUnitManager::delete_id_pool(
10897common::hash::ObHashMap<uint64_t, common::ObArray<share::ObResourcePool *> *> &map,
10898common::ObPooledAllocator<common::ObArray<share::ObResourcePool *> > &allocator,
10899const uint64_t id,
10900share::ObResourcePool *pool)
10901{
10902int ret = OB_SUCCESS;
10903if (!inited_) {
10904ret = OB_NOT_INIT;
10905LOG_WARN("not init", K(ret));
10906} else if (!map.created() || OB_INVALID_ID == id || NULL == pool) {
10907ret = OB_INVALID_ARGUMENT;
10908LOG_WARN("invalid argument", "map created", map.created(), K(id), KP(pool), K(ret));
10909} else {
10910ObArray<share::ObResourcePool *> *pools = NULL;
10911if (OB_FAIL(get_pools_by_id(map, id, pools))) {
10912LOG_WARN("get_pools_by_id failed", K(id), K(ret));
10913} else if (NULL == pools) {
10914ret = OB_ERR_UNEXPECTED;
10915LOG_WARN("pools is null", KP(pools), K(ret));
10916} else {
10917int64_t index = -1;
10918for (int64_t i = 0; i < pools->count(); ++i) {
10919if (pools->at(i) == pool) {
10920index = i;
10921break;
10922}
10923}
10924if (-1 == index) {
10925ret = OB_ENTRY_NOT_EXIST;
10926LOG_WARN("pool not exist", K(id), K(ret));
10927} else if (OB_FAIL(pools->remove(index))) {
10928LOG_WARN("remove failed", K(index), K(ret));
10929} else if (0 == pools->count()) {
10930allocator.free(pools);
10931pools = NULL;
10932DELETE_ITEM_FROM_MAP(map, id);
10933}
10934}
10935}
10936return ret;
10937}
10938
10939int ObUnitManager::delete_migrate_unit(const ObAddr &src_server,
10940const uint64_t unit_id)
10941{
10942int ret = OB_SUCCESS;
10943if (!inited_) {
10944ret = OB_NOT_INIT;
10945LOG_WARN("not init", K(ret));
10946} else if (!src_server.is_valid() || OB_INVALID_ID == unit_id) {
10947ret = OB_INVALID_ARGUMENT;
10948LOG_WARN("invalid argument", K(src_server), K(unit_id), K(ret));
10949} else {
10950ObArray<uint64_t> *migrate_units = NULL;
10951if (OB_FAIL(get_migrate_units_by_server(src_server, migrate_units))) {
10952LOG_WARN("get_migrate_units_by_server failed", K(src_server), K(ret));
10953} else if (NULL == migrate_units) {
10954ret = OB_ERR_UNEXPECTED;
10955LOG_WARN("migrate_units is null", KP(migrate_units), K(ret));
10956} else {
10957int64_t index = -1;
10958for (int64_t i = 0; i < migrate_units->count(); ++i) {
10959if (migrate_units->at(i) == unit_id) {
10960index = i;
10961break;
10962}
10963}
10964if (-1 == index) {
10965ret = OB_ENTRY_NOT_EXIST;
10966LOG_WARN("migrate_unit not exist", K(unit_id), K(ret));
10967} else if (OB_FAIL(migrate_units->remove(index))) {
10968LOG_WARN("remove failed", K(index), K(ret));
10969} else if (0 == migrate_units->count()) {
10970migrate_units_allocator_.free(migrate_units);
10971migrate_units = NULL;
10972DELETE_ITEM_FROM_MAP(server_migrate_units_map_, src_server);
10973}
10974}
10975}
10976return ret;
10977}
10978
10979int ObUnitManager::inner_drop_resource_pool(share::ObResourcePool *pool)
10980{
10981int ret = OB_SUCCESS;
10982
10983if (OB_ISNULL(pool)) {
10984ret = OB_ERR_UNEXPECTED;
10985LOG_WARN("pool is null", KP(pool), K(ret));
10986} else if (pool->is_granted_to_tenant()) {
10987ret = OB_RESOURCE_POOL_ALREADY_GRANTED;
10988LOG_USER_ERROR(OB_RESOURCE_POOL_ALREADY_GRANTED, to_cstring(pool->name_));
10989LOG_WARN("resource pool is granted to tenant, can't not delete it",
10990"tenant_id", pool->tenant_id_, K(ret));
10991} else {
10992common::ObMySQLTransaction trans;
10993if (OB_FAIL(trans.start(proxy_, OB_SYS_TENANT_ID))) {
10994LOG_WARN("start transaction failed", K(ret));
10995} else if (OB_FAIL(remove_resource_pool_unit_in_trans(pool->resource_pool_id_,
10996trans))) {
10997LOG_WARN("failed to remove resource pool and unit", K(ret), K(pool));
10998}
10999if (trans.is_started()) {
11000const bool commit = (OB_SUCC(ret));
11001int temp_ret = OB_SUCCESS;
11002if (OB_SUCCESS != (temp_ret = trans.end(commit))) {
11003LOG_WARN("trans end failed", K(commit), K(temp_ret));
11004ret = (OB_SUCCESS == ret) ? temp_ret : ret;
11005}
11006}
11007
11008if (OB_FAIL(ret)) {
11009} else if (OB_FAIL(delete_resource_pool_unit(pool))) {
11010LOG_WARN("failed to delete resource pool or unit", K(ret), K(pool));
11011}
11012}
11013
11014return ret;
11015}
11016
11017#undef DELETE_ITEM_FROM_MAP
11018
11019#define GET_ITEM_FROM_MAP(map, key, value) \
11020do { \
11021if (OB_FAIL(map.get_refactored(key, value))) { \
11022if (OB_HASH_NOT_EXIST == ret) { \
11023ret = OB_ENTRY_NOT_EXIST; \
11024} else { \
11025LOG_WARN("map get failed", K(key), K(ret)); \
11026} \
11027} else { \
11028} \
11029} while (false)
11030
11031int ObUnitManager::update_unit_load(
11032share::ObUnit *unit,
11033share::ObResourcePool *new_pool)
11034{
11035int ret = OB_SUCCESS;
11036if (OB_UNLIKELY(!inited_)) {
11037ret = OB_NOT_INIT;
11038LOG_WARN("not init", K(ret));
11039} else if (NULL == unit || NULL == new_pool) {
11040ret = OB_INVALID_ARGUMENT;
11041LOG_WARN("invalid argument", K(ret), KP(unit), KP(new_pool));
11042} else {
11043ObArray<ObUnitManager::ObUnitLoad> *server_load = NULL;
11044GET_ITEM_FROM_MAP(server_loads_, unit->server_, server_load);
11045if (OB_FAIL(ret)) {
11046LOG_WARN("fail to get server load", K(ret), "server", unit->server_);
11047} else if (NULL == server_load) {
11048ret = OB_ERR_UNEXPECTED;
11049LOG_WARN("loads ptr is null", K(ret));
11050} else {
11051FOREACH_X(l, *server_load, OB_SUCC(ret)) {
11052if (l->unit_ == unit) {
11053l->pool_ = new_pool;
11054}
11055}
11056}
11057if (OB_FAIL(ret)) {
11058} else if (unit->migrate_from_server_.is_valid()) {
11059ObArray<ObUnitManager::ObUnitLoad> *migrate_from_load = NULL;
11060GET_ITEM_FROM_MAP(server_loads_, unit->migrate_from_server_, migrate_from_load);
11061if (OB_FAIL(ret)) {
11062LOG_WARN("fail to get server load", K(ret),
11063"migrate_from_server", unit->migrate_from_server_);
11064} else if (NULL == migrate_from_load) {
11065ret = OB_ERR_UNEXPECTED;
11066LOG_WARN("loads ptr is null", K(ret));
11067} else {
11068FOREACH_X(l, *migrate_from_load, OB_SUCC(ret)) {
11069if (l->unit_ == unit) {
11070l->pool_ = new_pool;
11071}
11072}
11073}
11074}
11075}
11076return ret;
11077}
11078
11079int ObUnitManager::get_unit_config_by_name(const ObUnitConfigName &name,
11080ObUnitConfig *&config) const
11081{
11082int ret = OB_SUCCESS;
11083config = NULL;
11084if (!inited_) {
11085ret = OB_NOT_INIT;
11086LOG_WARN("not init", K(ret));
11087} else if (name.is_empty()) {
11088ret = OB_INVALID_ARGUMENT;
11089LOG_WARN("invalid name", K(name), K(ret));
11090} else {
11091GET_ITEM_FROM_MAP(name_config_map_, name, config);
11092}
11093return ret;
11094}
11095
11096int ObUnitManager::get_unit_config_by_id(const uint64_t config_id, ObUnitConfig *&config) const
11097{
11098int ret = OB_SUCCESS;
11099config = NULL;
11100if (!inited_) {
11101ret = OB_NOT_INIT;
11102LOG_WARN("not init", K(ret));
11103} else if (OB_INVALID_ID == config_id) {
11104ret = OB_INVALID_ARGUMENT;
11105LOG_WARN("invalid argument", K(config_id), K(ret));
11106} else {
11107GET_ITEM_FROM_MAP(id_config_map_, config_id, config);
11108}
11109return ret;
11110}
11111
11112int ObUnitManager::get_config_ref_count(const uint64_t config_id, int64_t &ref_count) const
11113{
11114int ret = OB_SUCCESS;
11115ref_count = 0;
11116if (!inited_) {
11117ret = OB_NOT_INIT;
11118LOG_WARN("not init", K(ret));
11119} else if (OB_INVALID_ID == config_id) {
11120ret = OB_INVALID_ARGUMENT;
11121LOG_WARN("invalid argument", K(config_id), K(ret));
11122} else {
11123GET_ITEM_FROM_MAP(config_ref_count_map_, config_id, ref_count);
11124if (OB_FAIL(ret)) {
11125if (OB_ENTRY_NOT_EXIST == ret) {
11126} else {
11127LOG_WARN("GET_ITEM_FROM_MAP failed", K(config_id), K(ret));
11128}
11129}
11130}
11131return ret;
11132}
11133
11134int ObUnitManager::get_server_ref_count(common::hash::ObHashMap<ObAddr, int64_t> &map,
11135const ObAddr &server, int64_t &ref_count) const
11136{
11137int ret = OB_SUCCESS;
11138ref_count = 0;
11139if (!inited_) {
11140ret = OB_NOT_INIT;
11141LOG_WARN("not init", K(ret));
11142} else if (!map.created() || !server.is_valid()) {
11143ret = OB_INVALID_ARGUMENT;
11144LOG_WARN("invalid argument", "map created", map.created(), K(server), K(ret));
11145} else {
11146GET_ITEM_FROM_MAP(map, server, ref_count);
11147if (OB_FAIL(ret)) {
11148if (OB_ENTRY_NOT_EXIST == ret) {
11149} else {
11150LOG_WARN("GET_ITEM_FROM_MAP failed", K(server), K(ret));
11151}
11152}
11153}
11154return ret;
11155}
11156
11157int ObUnitManager::check_resource_pool_exist(const share::ObResourcePoolName &resource_pool_name,
11158bool &is_exist)
11159{
11160int ret = OB_SUCCESS;
11161SpinRLockGuard guard(lock_);
11162share::ObResourcePool *pool = NULL;
11163is_exist = false;
11164
11165if (!check_inner_stat()) {
11166ret = OB_INNER_STAT_ERROR;
11167LOG_WARN("check_inner_stat failed", KR(ret), K(inited_), K(loaded_));
11168} else if (resource_pool_name.is_empty()) {
11169ret = OB_INVALID_ARGUMENT;
11170LOG_WARN("invalid argument", KR(ret), K(resource_pool_name));
11171} else if (OB_FAIL(inner_get_resource_pool_by_name(resource_pool_name, pool))) {
11172if (OB_ENTRY_NOT_EXIST != ret) {
11173LOG_WARN("inner_get_resource_pool_by_name failed", KR(ret), K(resource_pool_name));
11174} else {
11175ret = OB_SUCCESS;
11176// is_exist = false
11177}
11178} else if (OB_ISNULL(pool)) {
11179ret = OB_ERR_UNEXPECTED;
11180LOG_WARN("unexpected null", KR(ret), KP(pool), K(resource_pool_name));
11181} else {
11182is_exist = true;
11183}
11184
11185return ret;
11186}
11187
11188int ObUnitManager::inner_get_resource_pool_by_name(
11189const ObResourcePoolName &name,
11190share::ObResourcePool *&pool) const
11191{
11192int ret = OB_SUCCESS;
11193pool = NULL;
11194if (!inited_) {
11195ret = OB_NOT_INIT;
11196LOG_WARN("not init", K(ret));
11197} else if (name.is_empty()) {
11198ret = OB_INVALID_ARGUMENT;
11199LOG_WARN("invalid name", K(name), K(ret));
11200} else {
11201GET_ITEM_FROM_MAP(name_pool_map_, name, pool);
11202}
11203return ret;
11204}
11205
11206int ObUnitManager::get_resource_pool_by_id(const uint64_t pool_id, share::ObResourcePool *&pool) const
11207{
11208int ret = OB_SUCCESS;
11209pool = NULL;
11210if (!inited_) {
11211ret = OB_NOT_INIT;
11212LOG_WARN("not init", K(ret));
11213} else if (OB_INVALID_ID == pool_id) {
11214ret = OB_INVALID_ARGUMENT;
11215LOG_WARN("invalid argument", K(pool_id), K(ret));
11216} else {
11217GET_ITEM_FROM_MAP(id_pool_map_, pool_id, pool);
11218}
11219return ret;
11220}
11221
11222int ObUnitManager::get_units_by_pool(const uint64_t pool_id, ObArray<ObUnit *> *&units) const
11223{
11224int ret = OB_SUCCESS;
11225units = NULL;
11226if (!inited_) {
11227ret = OB_NOT_INIT;
11228LOG_WARN("not init", K(ret));
11229} else if (OB_INVALID_ID == pool_id) {
11230ret = OB_INVALID_ARGUMENT;
11231LOG_WARN("invalid argument", K(pool_id), K(ret));
11232} else {
11233GET_ITEM_FROM_MAP(pool_unit_map_, pool_id, units);
11234}
11235return ret;
11236}
11237
11238int ObUnitManager::get_unit_by_id(const uint64_t unit_id, ObUnit *&unit) const
11239{
11240int ret = OB_SUCCESS;
11241unit = NULL;
11242if (!inited_) {
11243ret = OB_NOT_INIT;
11244LOG_WARN("not init", K(ret));
11245} else if (OB_INVALID_ID == unit_id) {
11246ret = OB_INVALID_ARGUMENT;
11247LOG_WARN("invalid argument", K(unit_id), K(ret));
11248} else {
11249GET_ITEM_FROM_MAP(id_unit_map_, unit_id, unit);
11250}
11251return ret;
11252}
11253
11254int ObUnitManager::get_loads_by_server(const ObAddr &addr,
11255ObArray<ObUnitManager::ObUnitLoad> *&loads) const
11256{
11257int ret = OB_SUCCESS;
11258loads = NULL;
11259if (!inited_) {
11260ret = OB_NOT_INIT;
11261LOG_WARN("not init", K(ret));
11262} else if (!addr.is_valid()) {
11263ret = OB_INVALID_ARGUMENT;
11264LOG_WARN("invalid argument", K(addr), K(ret));
11265} else {
11266GET_ITEM_FROM_MAP(server_loads_, addr, loads);
11267}
11268return ret;
11269}
11270
11271int ObUnitManager::get_pools_by_tenant_(const uint64_t tenant_id,
11272ObArray<share::ObResourcePool *> *&pools) const
11273{
11274int ret = OB_SUCCESS;
11275// meta tenant has no self resource pool, here return user tenant resource pool
11276uint64_t valid_tnt_id = is_meta_tenant(tenant_id) ? gen_user_tenant_id(tenant_id) : tenant_id;
11277
11278pools = NULL;
11279if (!inited_) {
11280ret = OB_NOT_INIT;
11281LOG_WARN("not init", K(ret));
11282} else if (!is_valid_tenant_id(tenant_id)) {
11283ret = OB_INVALID_ARGUMENT;
11284LOG_WARN("invalid argument", K(tenant_id), K(ret));
11285} else if (OB_FAIL(get_pools_by_id(tenant_pools_map_, valid_tnt_id, pools))) {
11286if (OB_ENTRY_NOT_EXIST != ret) {
11287LOG_WARN("get_pools_by_id failed", K(valid_tnt_id), K(ret));
11288}
11289}
11290return ret;
11291}
11292
11293int ObUnitManager::get_pools_by_config(const uint64_t config_id,
11294ObArray<share::ObResourcePool *> *&pools) const
11295{
11296int ret = OB_SUCCESS;
11297pools = NULL;
11298if (!inited_) {
11299ret = OB_NOT_INIT;
11300LOG_WARN("not init", K(ret));
11301} else if (OB_INVALID_ID == config_id) {
11302ret = OB_INVALID_ARGUMENT;
11303LOG_WARN("invalid argument", K(config_id), K(ret));
11304} else if (OB_FAIL(get_pools_by_id(config_pools_map_, config_id, pools))) {
11305if (OB_ENTRY_NOT_EXIST != ret) {
11306LOG_WARN("get_pools_by_id failed", K(config_id), K(ret));
11307}
11308}
11309return ret;
11310}
11311
11312int ObUnitManager::get_pools_by_id(
11313const common::hash::ObHashMap<uint64_t, common::ObArray<share::ObResourcePool *> *> &map,
11314const uint64_t id, ObArray<share::ObResourcePool *> *&pools) const
11315{
11316int ret = OB_SUCCESS;
11317pools = NULL;
11318if (!inited_) {
11319ret = OB_NOT_INIT;
11320LOG_WARN("not init", K(ret));
11321} else if (!map.created() || OB_INVALID_ID == id) {
11322ret = OB_INVALID_ARGUMENT;
11323LOG_WARN("invalid argument", "map created", map.created(), K(id), K(ret));
11324} else {
11325GET_ITEM_FROM_MAP(map, id, pools);
11326}
11327return ret;
11328}
11329
11330int ObUnitManager::inner_check_single_logonly_pool_for_locality(
11331const share::ObResourcePool &pool,
11332const common::ObIArray<share::ObZoneReplicaAttrSet> &zone_locality,
11333bool &is_legal)
11334{
11335int ret = OB_SUCCESS;
11336if (!inited_) {
11337ret = OB_NOT_INIT;
11338LOG_WARN("ObUnitManager not init", K(ret), K(inited_));
11339} else if (REPLICA_TYPE_LOGONLY != pool.replica_type_) {
11340ret = OB_ERR_UNEXPECTED;
11341LOG_WARN("pool replica type unexpected", K(ret), K(pool));
11342} else {
11343is_legal = true;
11344for (int64_t i = 0; is_legal && i < pool.zone_list_.count(); ++i) {
11345const common::ObZone &zone = pool.zone_list_.at(i);
11346for (int64_t j = 0; is_legal && j < zone_locality.count(); ++j) {
11347const common::ObIArray<common::ObZone> &zone_set = zone_locality.at(j).zone_set_;
11348if (zone_set.count() <= 1) {
11349// bypass Non-mixed locality
11350} else { // mixed locality
11351is_legal = !has_exist_in_array(zone_set, zone);
11352}
11353}
11354}
11355}
11356return ret;
11357}
11358
11359int ObUnitManager::inner_check_logonly_pools_for_locality(
11360const common::ObIArray<share::ObResourcePool *> &pools,
11361const common::ObIArray<share::ObZoneReplicaAttrSet> &zone_locality,
11362bool &is_legal)
11363{
11364int ret = OB_SUCCESS;
11365if (!inited_) {
11366ret = OB_NOT_INIT;
11367LOG_WARN("ObUnitManager not init", K(ret), K(inited_));
11368} else if (OB_UNLIKELY(pools.count() <= 0)) {
11369ret = OB_INVALID_ARGUMENT;
11370LOG_WARN("invalid arguemnt", K(ret), "pool_count", pools.count());
11371} else {
11372is_legal = true;
11373for (int64_t i = 0; is_legal && OB_SUCC(ret) && i < pools.count(); ++i) {
11374share::ObResourcePool *pool = pools.at(i);
11375if (OB_UNLIKELY(nullptr == pool)) {
11376ret = OB_ERR_UNEXPECTED;
11377LOG_WARN("pool ptr is null", K(ret), KP(pool));
11378} else if (REPLICA_TYPE_LOGONLY != pool->replica_type_) {
11379// bypass, since this is not logonly pool
11380} else if (OB_FAIL(inner_check_single_logonly_pool_for_locality(
11381*pool, zone_locality, is_legal))) {
11382LOG_WARN("fail to inner check single logonly pool for locality", K(ret));
11383}
11384}
11385}
11386return ret;
11387}
11388
11389int ObUnitManager::inner_check_pools_unit_num_enough_for_locality(
11390const common::ObIArray<share::ObResourcePool *> &pools,
11391const common::ObIArray<common::ObZone> &schema_zone_list,
11392const ZoneLocalityIArray &zone_locality,
11393bool &is_enough)
11394{
11395int ret = OB_SUCCESS;
11396if (!inited_) {
11397ret = OB_NOT_INIT;
11398LOG_WARN("ObUnitManager not init", K(ret), K(inited_));
11399} else if (pools.count() <= 0) {
11400ret = OB_INVALID_ARGUMENT;
11401LOG_WARN("invalid argument", K(ret), K(pools.count()));
11402} else {
11403common::ObArray<int64_t> unit_nums;
11404for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
11405share::ObResourcePool *pool = pools.at(i);
11406if (NULL == pool) {
11407ret = OB_ERR_UNEXPECTED;
11408LOG_WARN("pool ptr is null", K(ret), KP(pool));
11409} else if (OB_FAIL(unit_nums.push_back(pool->unit_count_))) {
11410LOG_WARN("fail to push back", K(ret));
11411} else {} // no more to do
11412}
11413if (OB_FAIL(ret)) {
11414} else if (OB_FAIL(do_check_shrink_granted_pool_allowed_by_locality(
11415pools, schema_zone_list, zone_locality, unit_nums, is_enough))) {
11416LOG_WARN("fail to check pools unit num enough for locality", K(ret));
11417} else {} // no more to do
11418}
11419return ret;
11420}
11421
11422// The legality check consists of two parts
11423// 1 In the locality of the mixed scene, there can be no logonly resource pool
11424// 2 Can the unit num of the resource pool fit all locality copies
11425int ObUnitManager::check_pools_unit_legality_for_locality(
11426const common::ObIArray<share::ObResourcePoolName> &pools,
11427const common::ObIArray<common::ObZone> &schema_zone_list,
11428const ZoneLocalityIArray &zone_locality,
11429bool &is_legal)
11430{
11431int ret = OB_SUCCESS;
11432if (!inited_) {
11433ret = OB_NOT_INIT;
11434LOG_WARN("ObUnitManager not init", K(ret), K(inited_));
11435} else if (pools.count() <= 0) {
11436ret = OB_INVALID_ARGUMENT;
11437LOG_WARN("invalid argument", K(ret), K(pools.count()));
11438} else {
11439SpinRLockGuard guard(lock_);
11440common::ObArray<share::ObResourcePool *> pool_ptrs;
11441for (int64_t i = 0; OB_SUCC(ret) && i < pools.count(); ++i) {
11442share::ObResourcePool *pool_ptr = NULL;
11443if (OB_FAIL(inner_get_resource_pool_by_name(pools.at(i), pool_ptr))) {
11444LOG_WARN("fail to get resource pool by name", K(ret), "pool_name", pools.at(i));
11445} else if (OB_FAIL(pool_ptrs.push_back(pool_ptr))) {
11446LOG_WARN("fail to push back", K(ret));
11447} else {} // no more to do
11448}
11449if (OB_FAIL(ret)) {
11450} else if (OB_FAIL(inner_check_logonly_pools_for_locality(
11451pool_ptrs, zone_locality, is_legal))) {
11452LOG_WARN("fail to check logonly pools for locality", K(ret));
11453} else if (!is_legal) {
11454// no need to check any more
11455} else if (OB_FAIL(inner_check_pools_unit_num_enough_for_locality(
11456pool_ptrs, schema_zone_list, zone_locality, is_legal))) {
11457LOG_WARN("fail to check pools unit num enough for locality", K(ret));
11458} else {} // no more to do
11459}
11460return ret;
11461}
11462
11463int ObUnitManager::get_migrate_units_by_server(const ObAddr &server,
11464common::ObIArray<uint64_t> &migrate_units) const
11465{
11466int ret = OB_SUCCESS;
11467ObArray<uint64_t> *units= NULL;
11468if (OB_FAIL(get_migrate_units_by_server(server, units))) {
11469if (OB_ENTRY_NOT_EXIST == ret) {
11470ret = OB_SUCCESS; // no migrating units
11471} else {
11472LOG_WARN("fail get migrate units by server", K(server), K(ret));
11473}
11474} else {
11475for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
11476const uint64_t unit_id = units->at(i);
11477if (OB_FAIL(migrate_units.push_back(unit_id))) {
11478LOG_WARN("fail push back unit id to array", K(unit_id), K(i), K(ret));
11479}
11480}
11481}
11482return ret;
11483}
11484
11485int ObUnitManager::get_migrate_units_by_server(const ObAddr &server,
11486common::ObArray<uint64_t> *&migrate_units) const
11487{
11488int ret = OB_SUCCESS;
11489migrate_units = NULL;
11490if (!inited_) {
11491ret = OB_NOT_INIT;
11492LOG_WARN("not init", K(ret));
11493} else if (!server.is_valid()) {
11494ret = OB_INVALID_ARGUMENT;
11495LOG_WARN("invalid server", K(server), K(ret));
11496} else {
11497GET_ITEM_FROM_MAP(server_migrate_units_map_, server, migrate_units);
11498}
11499return ret;
11500}
11501
11502#undef DELETE_ITEM_FROM_MAP
11503
11504int ObUnitManager::fetch_new_unit_config_id(uint64_t &config_id)
11505{
11506int ret = OB_SUCCESS;
11507if (!inited_) {
11508ret = OB_NOT_INIT;
11509LOG_WARN("not init", K(ret));
11510} else {
11511ObMaxIdFetcher id_fetcher(*proxy_);
11512uint64_t combine_id = OB_INVALID_ID;
11513if (OB_FAIL(id_fetcher.fetch_new_max_id(
11514OB_SYS_TENANT_ID, OB_MAX_USED_UNIT_CONFIG_ID_TYPE, combine_id))) {
11515LOG_WARN("fetch_max_id failed", "id_type", OB_MAX_USED_UNIT_CONFIG_ID_TYPE, K(ret));
11516} else {
11517config_id = combine_id;
11518}
11519}
11520return ret;
11521}
11522
11523int ObUnitManager::fetch_new_resource_pool_id(uint64_t &resource_pool_id)
11524{
11525int ret = OB_SUCCESS;
11526if (!inited_) {
11527ret = OB_NOT_INIT;
11528LOG_WARN("not init", K(ret));
11529} else {
11530uint64_t combine_id = OB_INVALID_ID;
11531ObMaxIdFetcher id_fetcher(*proxy_);
11532if (OB_FAIL(id_fetcher.fetch_new_max_id(OB_SYS_TENANT_ID,
11533OB_MAX_USED_RESOURCE_POOL_ID_TYPE, combine_id))) {
11534LOG_WARN("fetch_new_max_id failed", "id_type", OB_MAX_USED_RESOURCE_POOL_ID_TYPE, K(ret));
11535} else {
11536resource_pool_id = combine_id;
11537}
11538}
11539return ret;
11540}
11541
11542int ObUnitManager::fetch_new_unit_group_id(uint64_t &unit_group_id)
11543{
11544int ret = OB_SUCCESS;
11545if (OB_UNLIKELY(!inited_)) {
11546ret = OB_NOT_INIT;
11547LOG_WARN("not init", K(ret));
11548} else {
11549uint64_t combine_id = OB_INVALID_ID;
11550ObMaxIdFetcher id_fetcher(*proxy_);
11551if (OB_FAIL(id_fetcher.fetch_new_max_id(OB_SYS_TENANT_ID,
11552OB_MAX_USED_UNIT_GROUP_ID_TYPE, combine_id))) {
11553LOG_WARN("fetch_new_max_id failed", "id_type", OB_MAX_USED_UNIT_ID_TYPE, K(ret));
11554} else {
11555unit_group_id = combine_id;
11556}
11557}
11558return ret;
11559}
11560
11561int ObUnitManager::fetch_new_unit_id(uint64_t &unit_id)
11562{
11563int ret = OB_SUCCESS;
11564if (!inited_) {
11565ret = OB_NOT_INIT;
11566LOG_WARN("not init", K(ret));
11567} else {
11568uint64_t combine_id = OB_INVALID_ID;
11569ObMaxIdFetcher id_fetcher(*proxy_);
11570if (OB_FAIL(id_fetcher.fetch_new_max_id(OB_SYS_TENANT_ID,
11571OB_MAX_USED_UNIT_ID_TYPE, combine_id))) {
11572LOG_WARN("fetch_new_max_id failed", "id_type", OB_MAX_USED_UNIT_ID_TYPE, K(ret));
11573} else {
11574unit_id = combine_id;
11575}
11576}
11577return ret;
11578}
11579
11580int ObUnitManager::check_bootstrap_pool(const share::ObResourcePool &pool)
11581{
11582int ret = OB_SUCCESS;
11583if (!pool.is_valid()) {
11584ret = OB_INVALID_ARGUMENT;
11585LOG_WARN("invalid pool", K(pool), K(ret));
11586} else if (ObUnitConfig::SYS_UNIT_CONFIG_ID == pool.unit_config_id_) {
11587// good
11588} else {
11589ret = OB_INVALID_ARGUMENT;
11590LOG_WARN("pool not sys pool", K(pool), K(ret));
11591}
11592return ret;
11593}
11594
11595int ObUnitManager::inner_get_tenant_zone_full_unit_num(
11596const int64_t tenant_id,
11597const common::ObZone &zone,
11598int64_t &unit_num)
11599{
11600int ret = OB_SUCCESS;
11601ObArray<share::ObResourcePool *> *pools = NULL;
11602if (OB_UNLIKELY(!inited_)) {
11603ret = OB_NOT_INIT;
11604LOG_WARN("not init", K(ret));
11605} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id))) {
11606ret = OB_INVALID_ARGUMENT;
11607LOG_WARN("invalid argument", K(ret), K(tenant_id));
11608} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
11609LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
11610} else if (OB_UNLIKELY(NULL == pools)) {
11611ret = OB_ERR_UNEXPECTED;
11612LOG_WARN("pools ptr is null", K(ret), KP(pools));
11613} else {
11614bool find = false;
11615for (int64_t i = 0; !find && OB_SUCC(ret) && i < pools->count(); ++i) {
11616share::ObResourcePool *pool = pools->at(i);
11617if (NULL == pool) {
11618ret = OB_ERR_UNEXPECTED;
11619LOG_WARN("pool ptr is null", K(ret), KP(pool));
11620} else if (!has_exist_in_array(pool->zone_list_, zone)) {
11621// not in this pool
11622} else if (REPLICA_TYPE_FULL == pool->replica_type_) {
11623unit_num = pool->unit_count_;
11624find = true;
11625} else {} // not a full replica type resource pool, go on to check next
11626}
11627if (OB_FAIL(ret)) {
11628} else if (!find) {
11629unit_num = 0;
11630}
11631}
11632return ret;
11633}
11634
11635int ObUnitManager::get_tenant_zone_unit_loads(
11636const int64_t tenant_id,
11637const common::ObZone &zone,
11638const common::ObReplicaType replica_type,
11639common::ObIArray<ObUnitManager::ObUnitLoad> &unit_loads)
11640{
11641int ret = OB_SUCCESS;
11642ObArray<share::ObResourcePool *> *pools = NULL;
11643unit_loads.reset();
11644if (OB_UNLIKELY(!inited_)) {
11645ret = OB_NOT_INIT;
11646LOG_WARN("not init", K(ret));
11647} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id)
11648|| zone.is_empty()
11649|| !ObReplicaTypeCheck::is_replica_type_valid(replica_type))) {
11650ret = OB_INVALID_ARGUMENT;
11651LOG_WARN("invalid argument", K(ret), K(tenant_id), K(zone), K(replica_type));
11652} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
11653if (OB_ENTRY_NOT_EXIST == ret) {
11654ret = OB_SUCCESS;
11655} else {
11656LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
11657}
11658} else if (OB_UNLIKELY(NULL == pools)) {
11659ret = OB_ERR_UNEXPECTED;
11660LOG_WARN("pool ptr is null", K(ret), KP(pools));
11661} else {
11662unit_loads.reset();
11663share::ObResourcePool *target_pool = NULL;
11664for (int64_t i = 0; NULL == target_pool && OB_SUCC(ret) && i < pools->count(); ++i) {
11665share::ObResourcePool *pool = pools->at(i);
11666if (NULL == pool) {
11667ret = OB_ERR_UNEXPECTED;
11668LOG_WARN("pool ptr is null", K(ret), KP(pool));
11669} else if (!has_exist_in_array(pool->zone_list_, zone)) {
11670// not in this pool
11671} else if (replica_type == pool->replica_type_) {
11672target_pool = pool;
11673} else {} // not a full replica type resource pool, go on to check next
11674}
11675if (OB_FAIL(ret)) {
11676} else if (NULL == target_pool) {
11677ret = OB_ENTRY_NOT_EXIST;
11678} else {
11679ObArray<share::ObUnit *> *units = NULL;
11680if (OB_FAIL(get_units_by_pool(target_pool->resource_pool_id_, units))) {
11681LOG_WARN("fail to get units by pool", K(ret),
11682"pool_id", target_pool->resource_pool_id_);
11683} else if (OB_UNLIKELY(NULL == units)) {
11684ret = OB_ERR_UNEXPECTED;
11685LOG_WARN("units ptr is null", K(ret), KP(units));
11686} else {
11687for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
11688ObUnitLoad unit_load;
11689ObUnit *unit = units->at(i);
11690if (NULL == unit) {
11691ret = OB_ERR_UNEXPECTED;
11692LOG_WARN("unit ptr is null", K(ret));
11693} else if (unit->zone_ != zone) {
11694// not this zone, ignore
11695} else if (OB_FAIL(gen_unit_load(unit, unit_load))) {
11696LOG_WARN("fail to gen unit load", K(ret));
11697} else if (OB_FAIL(unit_loads.push_back(unit_load))) {
11698LOG_WARN("fail to push back", K(ret));
11699} else {} // no more to do
11700}
11701}
11702}
11703}
11704return ret;
11705}
11706
11707int ObUnitManager::get_tenant_zone_all_unit_loads(
11708const int64_t tenant_id,
11709const common::ObZone &zone,
11710common::ObIArray<ObUnitManager::ObUnitLoad> &unit_loads)
11711{
11712int ret = OB_SUCCESS;
11713ObArray<share::ObResourcePool *> *pools = NULL;
11714unit_loads.reset();
11715if (OB_UNLIKELY(!inited_)) {
11716ret = OB_NOT_INIT;
11717LOG_WARN("not init", K(ret));
11718} else if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || zone.is_empty())) {
11719ret = OB_INVALID_ARGUMENT;
11720LOG_WARN("invalid argument", K(ret), K(tenant_id), K(zone));
11721} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
11722if (OB_ENTRY_NOT_EXIST == ret) {
11723ret = OB_SUCCESS;
11724} else {
11725LOG_WARN("fail to get pools by tenant", K(ret), K(tenant_id));
11726}
11727} else if (OB_UNLIKELY(NULL == pools)) {
11728ret = OB_ERR_UNEXPECTED;
11729LOG_WARN("pool ptr is null", K(ret), KP(pools));
11730} else {
11731unit_loads.reset();
11732common::ObArray<share::ObResourcePool *> target_pools;
11733for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
11734share::ObResourcePool *pool = pools->at(i);
11735if (NULL == pool) {
11736ret = OB_ERR_UNEXPECTED;
11737LOG_WARN("pool ptr is null", K(ret), KP(pool));
11738} else if (!has_exist_in_array(pool->zone_list_, zone)) {
11739// not in this pool
11740} else if (OB_FAIL(target_pools.push_back(pool))) {
11741LOG_WARN("fail to push back", K(ret));
11742} else {} // no more to do
11743}
11744for (int64_t i = 0; OB_SUCC(ret) && i < target_pools.count(); ++i) {
11745ObArray<share::ObUnit *> *units = NULL;
11746share::ObResourcePool *target_pool = target_pools.at(i);
11747if (OB_UNLIKELY(NULL == target_pool)) {
11748ret = OB_ERR_UNEXPECTED;
11749LOG_WARN("target pool ptr is null", K(ret), KP(target_pool));
11750} else if (OB_FAIL(get_units_by_pool(target_pool->resource_pool_id_, units))) {
11751LOG_WARN("fail to get units by pool", K(ret),
11752"pool_id", target_pool->resource_pool_id_);
11753} else if (OB_UNLIKELY(NULL == units)) {
11754ret = OB_ERR_UNEXPECTED;
11755LOG_WARN("units ptr is null", K(ret), KP(units));
11756} else {
11757for (int64_t i = 0; OB_SUCC(ret) && i < units->count(); ++i) {
11758ObUnitLoad unit_load;
11759ObUnit *unit = units->at(i);
11760if (NULL == unit) {
11761ret = OB_ERR_UNEXPECTED;
11762LOG_WARN("unit ptr is null", K(ret));
11763} else if (unit->zone_ != zone) {
11764// not this zone, ignore
11765} else if (OB_FAIL(gen_unit_load(unit, unit_load))) {
11766LOG_WARN("fail to gen unit load", K(ret));
11767} else if (OB_FAIL(unit_loads.push_back(unit_load))) {
11768LOG_WARN("fail to push back", K(ret));
11769} else {} // no more to do
11770}
11771}
11772}
11773if (OB_FAIL(ret)) {
11774} else if (unit_loads.count() <= 0) {
11775ret = OB_ENTRY_NOT_EXIST;
11776}
11777}
11778return ret;
11779}
11780
11781int ObUnitManager::get_logonly_unit_by_tenant(const int64_t tenant_id,
11782ObIArray<ObUnitInfo> &logonly_unit_infos)
11783{
11784int ret = OB_SUCCESS;
11785share::schema::ObSchemaGetterGuard schema_guard;
11786if (OB_ISNULL(schema_service_)) {
11787ret = OB_NOT_INIT;
11788LOG_WARN("schema service is null", K(schema_service_), KR(ret));
11789} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
11790LOG_WARN("fail to get tenant schema guard", KR(ret), K(tenant_id));
11791} else if (OB_FAIL(get_logonly_unit_by_tenant(schema_guard, tenant_id, logonly_unit_infos))) {
11792LOG_WARN("get logonly unit by tenant fail", KR(ret), K(tenant_id));
11793}
11794return ret;
11795}
11796
11797int ObUnitManager::get_logonly_unit_by_tenant(share::schema::ObSchemaGetterGuard &schema_guard,
11798const int64_t tenant_id,
11799ObIArray<ObUnitInfo> &logonly_unit_infos)
11800{
11801int ret = OB_SUCCESS;
11802const ObTenantSchema *tenant_schema = NULL;
11803logonly_unit_infos.reset();
11804ObArray<ObUnitInfo> unit_infos;
11805SpinRLockGuard guard(lock_);
11806if (!check_inner_stat()) {
11807ret = OB_INNER_STAT_ERROR;
11808LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
11809} else if (!is_valid_tenant_id(tenant_id)) {
11810ret = OB_INVALID_ARGUMENT;
11811LOG_WARN("invalid argument", K(ret), K(tenant_id));
11812} else if (OB_FAIL(schema_guard.get_tenant_info(tenant_id, tenant_schema))) {
11813LOG_WARN("fail to get tenant info", K(ret), K(tenant_id));
11814} else if (OB_ISNULL(tenant_schema)) {
11815ret = OB_ERR_UNEXPECTED;
11816LOG_WARN("get invalid tenant_schema", K(ret), K(tenant_id));
11817} else if (OB_FAIL(inner_get_active_unit_infos_of_tenant(*tenant_schema, unit_infos))) {
11818LOG_WARN("fail to get active unit", K(ret), K(tenant_id));
11819} else {
11820for (int64_t i = 0; i < unit_infos.count() && OB_SUCC(ret); i++) {
11821if (REPLICA_TYPE_LOGONLY != unit_infos.at(i).unit_.replica_type_) {
11822//nothing todo
11823} else if (OB_FAIL(logonly_unit_infos.push_back(unit_infos.at(i)))) {
11824LOG_WARN("fail to push back", K(ret), K(unit_infos));
11825}
11826}
11827}
11828return ret;
11829}
11830
11831int ObUnitManager::get_unit_infos(const common::ObIArray<share::ObResourcePoolName> &pools,
11832ObIArray<ObUnitInfo> &unit_infos)
11833{
11834int ret = OB_SUCCESS;
11835SpinRLockGuard guard(lock_);
11836unit_infos.reset();
11837if (pools.count() <= 0) {
11838ret = OB_INVALID_ARGUMENT;
11839LOG_WARN("invalid argument", K(ret), K(pools));
11840} else {
11841ObArray<ObUnitInfo> pool_units;
11842share::ObResourcePool *pool = NULL;
11843for (int64_t i = 0; i < pools.count() && OB_SUCC(ret); i++) {
11844pool_units.reset();
11845if (OB_FAIL(inner_get_resource_pool_by_name(pools.at(i), pool))) {
11846LOG_WARN("fail to get resource pool", K(ret), K(i), K(pools));
11847} else if (OB_ISNULL(pool)) {
11848ret = OB_ERR_UNEXPECTED;
11849LOG_WARN("get invalid pool", K(ret), K(pools));
11850} else if (OB_FAIL(inner_get_unit_infos_of_pool_(pool->resource_pool_id_, pool_units))) {
11851LOG_WARN("fail to get unit infos", K(ret), K(*pool));
11852} else {
11853for (int64_t j = 0; j < pool_units.count() && OB_SUCC(ret); j++) {
11854if (OB_FAIL(unit_infos.push_back(pool_units.at(j)))) {
11855LOG_WARN("fail to push back", K(ret), K(pool_units));
11856}
11857}
11858}
11859}
11860}
11861return ret;
11862}
11863
11864int ObUnitManager::get_servers_by_pools(
11865const common::ObIArray<share::ObResourcePoolName> &pools,
11866common::ObIArray<ObAddr> &addrs)
11867{
11868int ret = OB_SUCCESS;
11869addrs.reset();
11870ObArray<share::ObUnitInfo> unit_infos;
11871if (OB_FAIL(get_unit_infos(pools, unit_infos))) {
11872LOG_WARN("fail to get unit infos", KR(ret), K(pools));
11873}
11874for (int64_t i = 0; OB_SUCC(ret) && i < unit_infos.count(); i++) {
11875const share::ObUnitInfo &unit_info = unit_infos.at(i);
11876if (OB_FAIL(addrs.push_back(unit_info.unit_.server_))) {
11877LOG_WARN("fail to push back addr", KR(ret), K(unit_info));
11878}
11879} // end for
11880return ret;
11881}
11882
11883int ObUnitManager::inner_get_active_unit_infos_of_tenant(const ObTenantSchema &tenant_schema,
11884ObIArray<ObUnitInfo> &unit_info)
11885{
11886int ret = OB_SUCCESS;
11887ObArray<uint64_t> pool_ids;
11888uint64_t tenant_id = tenant_schema.get_tenant_id();
11889common::ObArray<common::ObZone> tenant_zone_list;
11890ObArray<share::ObResourcePool *> *pools = NULL;
11891if (!check_inner_stat()) {
11892ret = OB_INNER_STAT_ERROR;
11893LOG_WARN("check_inner_stat failed", K(inited_), K(loaded_), K(ret));
11894} else if (OB_FAIL(tenant_schema.get_zone_list(tenant_zone_list))) {
11895LOG_WARN("fail to get zone list", K(ret));
11896} else if (OB_FAIL(get_pools_by_tenant_(tenant_id, pools))) {
11897if (OB_ENTRY_NOT_EXIST != ret) {
11898LOG_WARN("get_pools_by_tenant failed", K(tenant_id), K(ret));
11899} else {
11900// just return empty pool_ids
11901ret = OB_SUCCESS;
11902LOG_WARN("tenant doesn't own any pool", K(tenant_id), K(ret));
11903}
11904} else if (NULL == pools) {
11905ret = OB_ERR_UNEXPECTED;
11906LOG_WARN("pools is null", KP(pools), K(ret));
11907} else {
11908for (int64_t i = 0; OB_SUCC(ret) && i < pools->count(); ++i) {
11909if (NULL == pools->at(i)) {
11910ret = OB_ERR_UNEXPECTED;
11911LOG_WARN("pool is null", "pool", OB_P(pools->at(i)), K(ret));
11912} else if (OB_FAIL(pool_ids.push_back(pools->at(i)->resource_pool_id_))) {
11913LOG_WARN("push_back failed", K(ret));
11914}
11915}
11916}
11917if (OB_SUCC(ret)) {
11918ObArray<ObUnitInfo> unit_in_pool;
11919for (int64_t i = 0; i < pool_ids.count() && OB_SUCC(ret); i++) {
11920uint64_t pool_id = pool_ids.at(i);
11921unit_in_pool.reset();
11922if (OB_FAIL(inner_get_unit_infos_of_pool_(pool_id, unit_in_pool))) {
11923LOG_WARN("fail to inner get unit infos", K(ret), K(pool_id));
11924} else {
11925for (int64_t j = 0; j < unit_in_pool.count() && OB_SUCC(ret); j++) {
11926if (ObUnit::UNIT_STATUS_ACTIVE != unit_in_pool.at(j).unit_.status_) {
11927//nothing todo
11928} else if (!has_exist_in_array(tenant_zone_list, unit_in_pool.at(j).unit_.zone_)) {
11929//nothing todo
11930} else if (OB_FAIL(unit_info.push_back(unit_in_pool.at(j)))) {
11931LOG_WARN("fail to push back", K(ret), K(unit_in_pool), K(j));
11932}
11933}
11934}
11935}
11936}
11937return ret;
11938}
11939
11940}//end namespace share
11941}//end namespace oceanbase
11942