Files
oceanbase/src/sql/plan_cache/ob_lib_cache_object_manager.cpp

191 lines
6.8 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX SQL_PC
#include "sql/plan_cache/ob_lib_cache_register.h"
#include "sql/plan_cache/ob_lib_cache_object_manager.h"
#include "sql/plan_cache/ob_plan_cache.h"
#include "observer/ob_req_time_service.h"
namespace oceanbase
{
namespace common
{
class ObIAllocator;
}
namespace sql
{
int ObLCObjectManager::init(int64_t hash_bucket, uint64_t tenant_id)
{
int ret = OB_SUCCESS;
if (OB_FAIL(cache_obj_map_.create(hash::cal_next_prime(hash_bucket),
ObModIds::OB_HASH_BUCKET_LC_STAT,
ObModIds::OB_HASH_NODE_LC_STAT,
tenant_id))) {
LOG_WARN("failed to init cache obj map", K(ret));
} else if (OB_FAIL(alloc_cache_obj_map_.create(hash::cal_next_prime(hash_bucket),
ObModIds::OB_HASH_BUCKET_LC_STAT,
ObModIds::OB_HASH_NODE_LC_STAT,
tenant_id))) {
LOG_WARN("failed to init alloc cache obj map", K(ret));
}
return ret;
}
int ObLCObjectManager::alloc(ObCacheObjGuard& guard,
ObLibCacheNameSpace ns,
uint64_t tenant_id,
MemoryContext &parent_context)
{
int ret = OB_SUCCESS;
lib::MemoryContext entity = NULL;
ObMemAttr mem_attr;
ObILibCacheObject *cache_obj = NULL;
mem_attr.tenant_id_ = tenant_id;
mem_attr.ctx_id_ = ObCtxIds::PLAN_CACHE_CTX_ID;
if (guard.ref_handle_ == MAX_HANDLE) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cache object guard has not been initalized!", K(ret));
} else if (ns <= NS_INVALID || ns >= NS_MAX || OB_ISNULL(LC_CO_ALLOC[ns])) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("out of the max type", K(ret), K(ns));
} else if (FALSE_IT(mem_attr.label_ = LC_NS_TYPE_LABELS[ns])) {
} else if (OB_FAIL(parent_context->CREATE_CONTEXT(entity,
lib::ContextParam().set_mem_attr(mem_attr)))) {
LOG_WARN("create entity failed", K(ret), K(mem_attr));
} else if (OB_ISNULL(entity)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL memory entity", K(ret));
} else {
WITH_CONTEXT(entity) {
if (OB_FAIL(LC_CO_ALLOC[ns](entity, cache_obj, guard.ref_handle_, tenant_id))) {
LOG_WARN("failed to create lib cache node", K(ret), K(ns));
} else {
uint64_t obj_id = allocate_object_id();
cache_obj->object_id_ = obj_id;
if (OB_FAIL(alloc_cache_obj_map_.set_refactored(obj_id, cache_obj))) {
LOG_WARN("failed to add element to hashmap", K(ret));
inner_free(cache_obj);
entity = NULL;
cache_obj = NULL;
}
}
}
}
if (OB_FAIL(ret) && NULL != entity) {
DESTROY_CONTEXT(entity);
entity = NULL;
}
guard.cache_obj_ = cache_obj;
return ret;
}
int ObLCObjectManager::add_cache_obj(ObILibCacheObject *cache_obj)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(cache_obj)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(cache_obj), K(ret));
} else if (OB_FAIL(cache_obj_map_.set_refactored(cache_obj->get_object_id(), cache_obj))) {
LOG_WARN("failed to set element", K(ret), K(cache_obj->get_object_id()));
}
return ret;
}
int ObLCObjectManager::erase_cache_obj(ObCacheObjID id, const CacheRefHandleID ref_handle)
{
int ret = OB_SUCCESS;
ObILibCacheObject *cache_obj = NULL;
if (OB_FAIL(cache_obj_map_.erase_refactored(id, &cache_obj))) {
SQL_PC_LOG(WARN, "failed to erase cache obj", K(ret), K(id));
} else {
SQL_PC_LOG(DEBUG, "succeed to remove cache obj", K(id), K(ret));
if (NULL != cache_obj) {
// set logical deleted time
cache_obj->set_logical_del_time(common::ObTimeUtility::current_monotonic_time());
LOG_DEBUG("set logical del time", K(cache_obj->get_logical_del_time()),
K(cache_obj->get_object_id()),
K(cache_obj->added_lc()),
K(cache_obj));
common_free(cache_obj, ref_handle);
cache_obj = NULL;
}
}
return ret;
}
void ObLCObjectManager::common_free(ObILibCacheObject *cache_obj,
const CacheRefHandleID ref_handle)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(cache_obj)) {
// do nothing
} else {
if (ref_handle != PC_DIAG_HANDLE && !cache_obj->added_lc()) {
cache_obj->set_logical_del_time(ObTimeUtility::current_monotonic_time());
LOG_WARN("set logical del time", K(cache_obj->get_logical_del_time()),
K(cache_obj->added_lc()),
K(cache_obj->get_object_id()),
K(cache_obj->get_tenant_id()),
K(lbt()));
}
int64_t ref_count = cache_obj->dec_ref_count(ref_handle);
if (ref_count > 0) {
// do nothing
} else if (ref_count == 0) {
uint64_t tenant_id = cache_obj->get_tenant_id();
if (OB_FAIL(cache_obj->before_cache_evicted())) {
LOG_WARN("failed to process before_cache_evicted");
} else if (OB_FAIL(destroy_cache_obj(false, cache_obj->get_object_id()))) {
LOG_WARN("failed to destroy cache obj", K(ret));
}
} else {
LOG_ERROR("invalid cache obj ref count", K(ref_count), KP(cache_obj));
}
}
}
int ObLCObjectManager::destroy_cache_obj(const bool is_leaked,
const uint64_t object_id)
{
int ret = OB_SUCCESS;
ObILibCacheObject *to_del_obj;
if (OB_FAIL(alloc_cache_obj_map_.erase_refactored(object_id, &to_del_obj))) {
if (OB_HASH_NOT_EXIST == ret) {
ret = OB_SUCCESS;
} else {
LOG_WARN("failed to erase element from alloc obj list", K(object_id), K(ret));
}
} else if (OB_ISNULL(to_del_obj)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid cache obj", K(to_del_obj));
} else {
to_del_obj->dump_deleted_log_info(!is_leaked);
inner_free(to_del_obj);
}
return ret;
}
void ObLCObjectManager::inner_free(ObILibCacheObject *cache_obj)
{
int ret = OB_SUCCESS;
lib::MemoryContext entity = cache_obj->get_mem_context();
WITH_CONTEXT(entity) { cache_obj->~ObILibCacheObject(); }
cache_obj = NULL;
DESTROY_CONTEXT(entity);
}
} // namespace common
} // namespace oceanbase