/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX STORAGE #include "ob_tenant_meta_memory_mgr.h" #include "lib/alloc/ob_malloc_allocator.h" #include "share/schema/ob_multi_version_schema_service.h" #include "share/schema/ob_schema_getter_guard.h" using namespace oceanbase::common; using namespace oceanbase::storage; using namespace oceanbase::share::schema; using namespace oceanbase::lib; ObTenantMetaMemoryMgr::ObTenantMetaMemoryMgr() : tenant_meta_memory_map_(), is_inited_(false) {} ObTenantMetaMemoryMgr::~ObTenantMetaMemoryMgr() { destroy(); } void ObTenantMetaMemoryMgr::destroy() { lib::ObLockGuard guard(lock_); tenant_meta_memory_map_.destroy(); is_inited_ = false; } int ObTenantMetaMemoryMgr::try_update_tenant_info(const uint64_t tenant_id, const int64_t schema_version) { lib::ObLockGuard guard(lock_); ObArenaAllocator allocator(ObModIds::OB_META_MEMORY_BUFFER); int ret = OB_SUCCESS; TenantInfo tenant_info; if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; LOG_WARN("ObTenantMetaMemoryMgr has not been inited", K(ret)); } else if (OB_INVALID_ID == tenant_id || schema_version < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(tenant_id), K(schema_version)); } else if (OB_FAIL(tenant_meta_memory_map_.get_refactored(tenant_id, tenant_info))) { if (OB_HASH_NOT_EXIST == ret) { ret = OB_SUCCESS; } else { LOG_WARN("fail to get tenant meta memory", K(ret), K(tenant_id)); } } if (OB_SUCC(ret)) { ObSchemaGetterGuard schema_guard; const int64_t tenant_memory_limit = lib::get_tenant_memory_limit(tenant_id); int64_t memory_percentage = 0; // tenant_schema does not need to check full schema if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_full_schema_guard(tenant_id, schema_guard))) { LOG_WARN("fail to get schema guard", K(ret), K(tenant_id)); } else if (OB_FAIL( schema_guard.get_tenant_meta_reserved_memory_percentage(tenant_id, allocator, memory_percentage))) { if (OB_ENTRY_NOT_EXIST == ret) { ret = OB_SUCCESS; // maybe the tenant is dropped } else { LOG_WARN("fail to get tenant meta reversed memory percentage", K(ret)); } } else { const int64_t reserved_memory_size = tenant_memory_limit * memory_percentage / 100; const int64_t long_term_meta_reserved_size = reserved_memory_size / 2; const int64_t short_term_meta_reserved_size = reserved_memory_size / 2; if (schema_version > tenant_info.schema_version_ || (reserved_memory_size > 0 && reserved_memory_size != tenant_info.memory_size_)) { tenant_info.schema_version_ = std::max(schema_version, tenant_info.schema_version_); tenant_info.memory_size_ = reserved_memory_size; if (OB_FAIL(ObMallocAllocator::get_instance()->set_tenant_ctx_idle( tenant_id, ObCtxIds::STORAGE_LONG_TERM_META_CTX_ID, long_term_meta_reserved_size))) { if (OB_TENANT_NOT_EXIST != ret) { LOG_WARN("fail to set tenant ctx idle", K(ret)); } else { ret = OB_SUCCESS; } } else if (OB_FAIL(ObMallocAllocator::get_instance()->set_tenant_ctx_idle( tenant_id, ObCtxIds::STORAGE_SHORT_TERM_META_CTX_ID, short_term_meta_reserved_size))) { if (OB_TENANT_NOT_EXIST != ret) { LOG_WARN("fail to set tenant ctx idle", K(ret)); } else { ret = OB_SUCCESS; } } else if (OB_FAIL(tenant_meta_memory_map_.set_refactored(tenant_id, tenant_info, true /*overwrite*/))) { LOG_WARN("fail to update tenant meta memory map", K(ret)); } else { LOG_INFO("succ to update tenant meta reserved memory size", K(tenant_id), K(reserved_memory_size), K(long_term_meta_reserved_size), K(short_term_meta_reserved_size)); } } } } return ret; } int ObTenantMetaMemoryMgr::init() { int ret = OB_SUCCESS; if (OB_UNLIKELY(is_inited_)) { ret = OB_INIT_TWICE; LOG_WARN("ObTenantMetaMemoryMgr has been inited twice", K(ret)); } else if (OB_FAIL(tenant_meta_memory_map_.create(DEFAULT_BUCKET_NUM, ObModIds::OB_META_MEMORY_MGR))) { LOG_WARN("fail to create map", K(ret)); } else { is_inited_ = true; } return ret; } ObTenantMetaMemoryMgr& ObTenantMetaMemoryMgr::get_instance() { static ObTenantMetaMemoryMgr instance; return instance; }