free new mgr when assign failed and switch back allocator when memory not enough

This commit is contained in:
obdev
2023-07-11 18:18:17 +00:00
committed by ob-robot
parent 21e7012901
commit 871b092354
6 changed files with 274 additions and 207 deletions

View File

@ -755,57 +755,14 @@ int ObMultiVersionSchemaService::put_fallback_schema_to_slot(ObSchemaMgr *&new_m
"schema_version", new_mgr->get_schema_version(),
"eliminated_schema_version", NULL != eli_schema_mgr ?
eli_schema_mgr->get_schema_version() : OB_INVALID_VERSION);
if (OB_NOT_NULL(eli_schema_mgr)) {
FLOG_INFO("[SCHEMA_RELEASE] free schema mgr",
"tenant_id", eli_schema_mgr->get_tenant_id(),
"schema_version", eli_schema_mgr->get_schema_version());
eli_schema_mgr->~ObSchemaMgr();
if (OB_FAIL(schema_mem_mgr.free(static_cast<void *>(eli_schema_mgr)))) {
LOG_WARN("free eli schema mgr falied", K(ret));
} else {
// The allocator of the schema_mgr generated by the schema fallback is independent
// and does not need to be released through switch_allocator.
// For the current use scenarios of OB, liboblog, and agentserver in 2.x, fallback will not consume
// non-latest schema mgr for a long time, and the memory release of schema_mgr generated by fallback
// can be accelerated through background thread inspection.
}
}
}
return ret;
}
int ObMultiVersionSchemaService::alloc_schema_mgr_for_liboblog(
ObSchemaMemMgr &mem_mgr_for_liboblog,
ObSchemaMgr *&schema_mgr)
{
int ret = OB_SUCCESS;
ObSchemaMgr *new_mgr = NULL;
void *tmp_ptr= NULL;
ObIAllocator *allocator = NULL;
if (OB_FAIL(mem_mgr_for_liboblog.alloc(sizeof(ObSchemaMgr), tmp_ptr, &allocator))) {
LOG_WARN("alloc mem for liboblog falied", K(ret));
} else if (OB_ISNULL(allocator) || OB_ISNULL(tmp_ptr)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("tmp ptr or allocator is null", K(ret), K(tmp_ptr), K(allocator));
} else {
new_mgr = new (tmp_ptr) ObSchemaMgr();
schema_mgr = new_mgr;
}
return ret;
}
int ObMultiVersionSchemaService::free_schema_mgr_for_liboblog(
ObSchemaMemMgr &mem_mgr_for_liboblog,
ObSchemaMgr *schema_mgr)
{
int ret = OB_SUCCESS;
if (OB_NOT_NULL(schema_mgr)) {
FLOG_INFO("[SCHEMA_RELEASE] free schema mgr",
"tenant_id", schema_mgr->get_tenant_id(),
"schema_version", schema_mgr->get_schema_version());
schema_mgr->~ObSchemaMgr();
if (OB_FAIL(mem_mgr_for_liboblog.free(static_cast<void *>(schema_mgr)))) {
LOG_ERROR("free schema_mgr for liboblog failed", K(ret), K(schema_mgr));
if (OB_FAIL(schema_mem_mgr.free_schema_mgr(eli_schema_mgr))) {
LOG_WARN("free eli schema mgr falied", KR(ret));
} else {
// The allocator of the schema_mgr generated by the schema fallback is independent
// and does not need to be released through switch_allocator.
// For the current use scenarios of OB, liboblog, and agentserver in 2.x, fallback will not consume
// non-latest schema mgr for a long time, and the memory release of schema_mgr generated by fallback
// can be accelerated through background thread inspection.
}
}
return ret;
@ -924,12 +881,13 @@ int ObMultiVersionSchemaService::fallback_schema_mgr_for_liboblog(
K(schema_status), K(from_version), K(target_version));
}
if (OB_SUCC(ret)) {
bool alloc_for_liboblog = true;
ObSchemaMgr *new_mgr = NULL;
target_mgr_handle.reset();
if (OB_FAIL(fallback_schema_mgr(schema_status, tmp_mgr, target_version))) {
LOG_WARN("fallback schema mgr falied",
K(ret), K(schema_status), K(from_version), K(target_version));
} else if (OB_FAIL(alloc_schema_mgr_for_liboblog(*mem_mgr_for_liboblog, new_mgr))) {
} else if (OB_FAIL(mem_mgr_for_liboblog->alloc_schema_mgr(new_mgr, alloc_for_liboblog))) {
LOG_WARN("alloc schema mgr for liboblog failed",
K(ret), K(schema_status), K(from_version), K(target_version));
} else if (OB_ISNULL(new_mgr)) {
@ -955,10 +913,10 @@ int ObMultiVersionSchemaService::fallback_schema_mgr_for_liboblog(
schema_mgr = new_mgr;
}
}
if (OB_FAIL(ret) && !OB_ISNULL(new_mgr)) {
if (OB_FAIL(ret)) {
int tmp_ret = OB_SUCCESS;
schema_mgr = NULL;
if (OB_SUCCESS != (tmp_ret = free_schema_mgr_for_liboblog(*mem_mgr_for_liboblog, new_mgr))) {
if (OB_TMP_FAIL(mem_mgr_for_liboblog->free_schema_mgr(new_mgr))) {
LOG_ERROR("fail to free schema mgr", K(ret), K(tmp_ret), K(from_version));
}
}
@ -2115,103 +2073,38 @@ int ObMultiVersionSchemaService::add_schema(
schema_mgr_cache = &schema_store->schema_mgr_cache_;
int64_t new_schema_version = schema_mgr_for_cache->get_schema_version();
refreshed_schema_version = schema_store->get_refreshed_version();
ALLOW_NEXT_LOG();
LOG_INFO("add schema",
K(refreshed_schema_version),
K(new_schema_version));
if (refreshed_schema_version > new_schema_version) {
if (OB_ISNULL(schema_mgr_cache)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema_mgr_cache is null", K(ret), K(tenant_id));
} else if (refreshed_schema_version > new_schema_version) {
LOG_WARN("add schema is old",
K(refreshed_schema_version),
K(new_schema_version),
K(received_broadcast_version));
}
void *tmp_ptr = NULL;
ObSchemaMgr *new_mgr = NULL;
ObSchemaMgr *eli_schema_mgr = NULL;
FLOG_INFO("add schema", K(tenant_id), K(refreshed_schema_version), K(new_schema_version));
bool is_exist = false;
if (OB_FAIL(schema_mgr_cache->check_schema_mgr_exist(new_schema_version, is_exist))) {
if (FAILEDx(schema_mgr_cache->check_schema_mgr_exist(new_schema_version, is_exist))) {
LOG_WARN("fail to check schema_mgr exist", K(ret), K(tenant_id), K(new_schema_version));
} else if (is_exist) {
LOG_INFO("schema mgr already exist, just skip", K(ret), K(tenant_id), K(new_schema_version));
} else if (OB_FAIL(mem_mgr->alloc(sizeof(ObSchemaMgr), tmp_ptr))) {
LOG_WARN("alloc mem falied", K(ret));
} else if (FALSE_IT(new_mgr = new (tmp_ptr) ObSchemaMgr)) {
// will not reach here
} else if (OB_FAIL(new_mgr->init())) {
LOG_WARN("init schema mgr falied", K(ret));
} else if (OB_FAIL(new_mgr->assign(*schema_mgr_for_cache))) {
LOG_WARN("assign schema mgr falied", K(ret));
} else if (OB_FAIL(schema_mgr_cache->put(new_mgr, eli_schema_mgr))) {
LOG_WARN("put schema mgr failed", K(ret));
if (OB_EAGAIN == ret) {
FLOG_INFO("[SCHEMA_RELEASE] free schema mgr",
"tenant_id", new_mgr->get_tenant_id(),
"schema_version", new_mgr->get_schema_version());
int64_t tmp_ret = OB_SUCCESS;
new_mgr->~ObSchemaMgr();
const int64_t nsv = new_mgr->get_schema_version();
if (OB_SUCCESS != (tmp_ret = mem_mgr->free(new_mgr))) {
LOG_ERROR("free new_mgr failed", K(tmp_ret), K(nsv));
} else if (OB_FAIL(alloc_and_put_schema_mgr_(*mem_mgr, *schema_mgr_for_cache, *schema_mgr_cache))) {
LOG_WARN("fail to alloc and put schema mgr", KR(ret));
}
// try switch allocator
if (OB_SUCC(ret)) {
bool can_switch = false;
int64_t switch_cnt = ObSchemaService::g_liboblog_mode_ ? init_version_cnt_ : GCONF._max_schema_slot_num;
if (OB_FAIL(mem_mgr->check_can_switch_allocator(switch_cnt, can_switch))) {
LOG_WARN("fail to check can switch allocator", KR(ret));
} else if (can_switch) {
// Switch allocator && rewrite schema_mgr_for_cache_
LOG_INFO("try to switch allocator", KR(ret), K(tenant_id), K(new_schema_version));
if (OB_FAIL(switch_allocator_(*mem_mgr, schema_mgr_for_cache))) {
LOG_WARN("fail to alloc schema mgr after switch allocator", KR(ret), K(tenant_id), K(new_schema_version));
}
}
} else {
LOG_INFO("put schema mgr succeed",
"schema_version", new_mgr->get_schema_version(),
"eliminated_schema_version", NULL != eli_schema_mgr ?
eli_schema_mgr->get_schema_version() : OB_INVALID_VERSION);
if (OB_NOT_NULL(eli_schema_mgr)) {
FLOG_INFO("[SCHEMA_RELEASE] free schema mgr",
"tenant_id", eli_schema_mgr->get_tenant_id(),
"schema_version", eli_schema_mgr->get_schema_version());
eli_schema_mgr->~ObSchemaMgr();
if (OB_FAIL(mem_mgr->free(static_cast<void *>(eli_schema_mgr)))) {
LOG_WARN("free eli schema mgr falied", K(ret));
}
}
// try switch allocator
if (OB_SUCC(ret)) {
bool can_switch = false;
int64_t alloc_cnt = 0;
int64_t switch_cnt = ObSchemaService::g_liboblog_mode_ ? init_version_cnt_ : GCONF._max_schema_slot_num;
if (OB_FAIL(mem_mgr->check_can_switch_allocator(can_switch))) {
LOG_WARN("check can switch allocator falied", K(ret));
} else if (OB_FAIL(mem_mgr->get_cur_alloc_cnt(alloc_cnt))) {
LOG_WARN("get current alloc count falied", K(ret));
} else if (can_switch && alloc_cnt > switch_cnt) {
// Switch allocator && rewrite schema_mgr_for_cache_
LOG_INFO("try to switch allocator", K(ret), K(tenant_id),
"schema_version", schema_mgr_for_cache->get_schema_version());
void *tmp_ptr = NULL;
ObIAllocator *allocator = NULL;
ObSchemaMgr *old_mgr = schema_mgr_for_cache;
ObSchemaMgr *new_mgr = NULL;
bool overwrite = true;
if (OB_FAIL(mem_mgr->switch_allocator())) {
LOG_WARN("switch allocator falied", K(ret));
} else if (OB_FAIL(mem_mgr->alloc(sizeof(ObSchemaMgr), tmp_ptr, &allocator))) {
LOG_WARN("alloc mem falied", K(ret));
} else if (FALSE_IT(new_mgr = new (tmp_ptr) ObSchemaMgr(*allocator))) {
// will not reach here
} else if (OB_FAIL(new_mgr->init())) {
LOG_WARN("init new schema mgr falied", K(ret));
} else if (OB_FAIL(new_mgr->deep_copy(*old_mgr))) {
LOG_WARN("deep copy old schema mgr falied", K(ret));
} else if (OB_FAIL(schema_mgr_for_cache_map_.set_refactored(tenant_id, new_mgr, overwrite))) {
LOG_WARN("fail to get schema mgr for cache", K(ret), K(ret));
} else {
FLOG_INFO("[SCHEMA_RELEASE] free schema mgr",
"tenant_id", old_mgr->get_tenant_id(),
"schema_version", old_mgr->get_schema_version());
old_mgr->~ObSchemaMgr();
if (OB_FAIL(mem_mgr->free(static_cast<void *>(old_mgr)))) {
LOG_WARN("free old schema mgr falied", K(ret));
} else {
schema_mgr_for_cache = new_mgr;
}
}
}
LOG_DEBUG("check can switch", K(ret), K(tenant_id), K(can_switch), K(alloc_cnt), K(switch_cnt));
}
}
if (OB_SUCC(ret)) {
schema_store->update_refreshed_version(new_schema_version);
@ -2226,6 +2119,126 @@ int ObMultiVersionSchemaService::add_schema(
return ret;
}
ERRSIM_POINT_DEF(ERRSIM_PUT_SCHEMA);
ERRSIM_POINT_DEF(ERRSIM_ASSIGN_NEW_MGR);
int ObMultiVersionSchemaService::alloc_and_put_schema_mgr_(
ObSchemaMemMgr &mem_mgr,
ObSchemaMgr &latest_schema_mgr,
ObSchemaMgrCache &schema_mgr_cache)
{
int ret = OB_SUCCESS;
ObSchemaMgr *new_mgr = NULL;
bool alloc_for_liboblog = false;
ObSchemaMgr *eli_schema_mgr = NULL;
const uint64_t tenant_id = latest_schema_mgr.get_tenant_id();
const int64_t schema_version = latest_schema_mgr.get_schema_version();
if (OB_FAIL(mem_mgr.alloc_schema_mgr(new_mgr, alloc_for_liboblog))) {
LOG_WARN("fail to alloc mem", KR(ret));
} else {
if (OB_ISNULL(new_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new_mgr is NULL", KR(ret), K(tenant_id), K(schema_version));
} else if (OB_FAIL(new_mgr->init())) {
LOG_WARN("init schema mgr falied", KR(ret));
} else if (OB_UNLIKELY(ERRSIM_ASSIGN_NEW_MGR)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("turn on error injection ERRSIM_ASSIGN_NEW_MGR", KR(ret));
} else if (OB_FAIL(new_mgr->assign(latest_schema_mgr))) {
LOG_WARN("assign schema mgr falied", KR(ret));
} else if (OB_UNLIKELY(ERRSIM_PUT_SCHEMA)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("turn on error injection ERRSIM_PUT_SCHEMA", KR(ret));
} else if (OB_FAIL(schema_mgr_cache.put(new_mgr, eli_schema_mgr))) {
LOG_WARN("put schema mgr failed", KR(ret));
} else {
LOG_INFO("put schema mgr succeed",
"schema_version", new_mgr->get_schema_version(),
"eliminated_schema_version", NULL != eli_schema_mgr ?
eli_schema_mgr->get_schema_version() : OB_INVALID_VERSION, K(tenant_id));
}
int tmp_ret = OB_SUCCESS;
// whatever put success or put failed, we should try to free eli_schema_mgr
if (OB_TMP_FAIL(mem_mgr.free_schema_mgr(eli_schema_mgr))) {
LOG_ERROR("fail to free eli_schema_mgr", KR(tmp_ret));
ret = OB_SUCC(ret) ? tmp_ret : ret;
}
// whatever assign/put/free schema mgr failed, new schema mgr will be useless, so free it
if (OB_FAIL(ret)) {
LOG_WARN("handle new schema mgr failed", KR(ret), K(schema_version), K(tenant_id));
int tmp_ret = OB_SUCCESS;
if (OB_TMP_FAIL(mem_mgr.free_schema_mgr(new_mgr))) {
LOG_ERROR("fail to free new_mgr", KR(tmp_ret));
}
}
}
return ret;
}
ERRSIM_POINT_DEF(ERRSIM_SET_REFACTOR);
ERRSIM_POINT_DEF(ERRSIM_AFTER_SET_REFACTOR);
int ObMultiVersionSchemaService::switch_allocator_(
ObSchemaMemMgr &mem_mgr,
ObSchemaMgr *&latest_schema_mgr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(latest_schema_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("latest schema mgr is NULL", KR(ret));
} else if (OB_FAIL(mem_mgr.switch_allocator())) {
LOG_WARN("switch allocator falied", KR(ret));
} else {
bool overwrite = true;
bool need_switch_back = true;
bool alloc_for_liboblog = false;
ObSchemaMgr *new_mgr = NULL;
ObSchemaMgr *old_mgr = latest_schema_mgr;
const uint64_t tenant_id = latest_schema_mgr->get_tenant_id();
const int64_t schema_version = latest_schema_mgr->get_schema_version();
if (OB_FAIL(mem_mgr.alloc_schema_mgr(new_mgr, alloc_for_liboblog))) {
LOG_WARN("fail to alloc mem", KR(ret));
} else {
if (OB_ISNULL(new_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new mgr is NULL", KR(ret), K(tenant_id), K(schema_version));
} else if (OB_FAIL(new_mgr->init())) {
LOG_WARN("init new schema mgr falied", K(ret));
} else if (OB_FAIL(new_mgr->deep_copy(*old_mgr))) {
LOG_WARN("deep copy old schema mgr falied", K(ret));
} else if (OB_UNLIKELY(ERRSIM_SET_REFACTOR)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("turn on error injection ERRSIM_SET_REFACTOR", KR(ret));
} else if (OB_FAIL(schema_mgr_for_cache_map_.set_refactored(tenant_id, new_mgr, overwrite))) {
LOG_WARN("fail to set schema mgr for cache", K(ret));
} else {
// handle new schema mgr success, no need to switch back allocator
need_switch_back = false;
latest_schema_mgr = new_mgr;
if (OB_UNLIKELY(ERRSIM_AFTER_SET_REFACTOR)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("turn on error injection ERRSIM_AFTER_SET_REFACTOR", KR(ret));
} else if (OB_FAIL(mem_mgr.free_schema_mgr(old_mgr))) {
// old mgr will be release in try_gc_another_allocator
LOG_ERROR("fail to free old schema mgr", KR(ret));
}
}
}
// switch back allocator when cur allocator can not use
// 1.alloc new schema mgr failed
// 2.handle new schema failed, like deep copy
if (need_switch_back) {
LOG_WARN("after switch allocator, handle schema mgr encounters something wrong", KR(ret), K(tenant_id), K(schema_version));
int tmp_ret = OB_SUCCESS;
if (OB_TMP_FAIL(mem_mgr.switch_back_allocator())) {
LOG_ERROR("switch back allocator falied", KR(tmp_ret));
} else if (OB_TMP_FAIL(mem_mgr.free_schema_mgr(new_mgr))) {
LOG_ERROR("fail to free new_mgr", KR(tmp_ret), K(schema_version));
}
}
}
return ret;
}
int ObMultiVersionSchemaService::async_refresh_schema(
const uint64_t tenant_id,
const int64_t schema_version)
@ -3436,14 +3449,8 @@ int ObMultiVersionSchemaService::try_gc_tenant_schema_mgr(ObSchemaMemMgr *&mem_m
do {
if (OB_FAIL(schema_mgr_cache->try_gc_tenant_schema_mgr(eli_schema_mgr))) {
LOG_WARN("fail to eliminate schema mgr", K(ret), K(tenant_id));
} else if (OB_NOT_NULL(eli_schema_mgr)) {
FLOG_INFO("[SCHEMA_RELEASE] try to gc schema mgr",
"tenant_id", eli_schema_mgr->get_tenant_id(),
"schema_version", eli_schema_mgr->get_schema_version());
eli_schema_mgr->~ObSchemaMgr();
if (OB_FAIL(mem_mgr->free(static_cast<void *>(eli_schema_mgr)))) {
LOG_ERROR("free eli schema mgr falied", K(ret), K(tenant_id));
}
} else if (OB_FAIL(mem_mgr->free_schema_mgr(eli_schema_mgr))) {
LOG_ERROR("free eli schema mgr falied", KR(ret), K(tenant_id));
}
} while (OB_SUCC(ret) && OB_NOT_NULL(eli_schema_mgr));
@ -3547,14 +3554,8 @@ int ObMultiVersionSchemaService::try_gc_another_allocator(
} else if (FALSE_IT(eli_schema_mgr = static_cast<ObSchemaMgr *>(another_ptrs.at(i)))) {
} else if (OB_FAIL(schema_mgr_cache->try_elimiante_schema_mgr(eli_schema_mgr))) {
LOG_WARN("fail to elimiante schema_mgr", K(ret), K(tenant_id), K(eli_schema_mgr));
} else {
FLOG_INFO("[SCHEMA_RELEASE] try to eliminate schema mgr",
"tenant_id", eli_schema_mgr->get_tenant_id(),
"schema_version", eli_schema_mgr->get_schema_version());
eli_schema_mgr->~ObSchemaMgr();
if (OB_FAIL(mem_mgr->free(static_cast<void *>(eli_schema_mgr)))) {
LOG_ERROR("free eli schema mgr falied", K(ret), K(tenant_id));
}
} else if (OB_FAIL(mem_mgr->free_schema_mgr(eli_schema_mgr))) {
LOG_ERROR("free eli schema mgr falied", KR(ret), K(tenant_id));
}
}
if (OB_FAIL(ret)) {

View File

@ -448,9 +448,11 @@ private:
ObSchemaMgrCache &schema_mgr_cache,
ObSchemaMemMgr &schema_mem_mgr,
ObSchemaMgrHandle &handle);
int alloc_schema_mgr_for_liboblog(ObSchemaMemMgr &mem_mgr_for_liboblog, ObSchemaMgr *&schema_mgr);
int free_schema_mgr_for_liboblog(ObSchemaMemMgr &mem_mgr_for_liboblog, ObSchemaMgr *schema_mgr);
int alloc_and_put_schema_mgr_(ObSchemaMemMgr &mem_mgr,
ObSchemaMgr &latest_schema_mgr,
ObSchemaMgrCache &schema_mgr_cache);
int switch_allocator_(ObSchemaMemMgr &mem_mgr,
ObSchemaMgr *&latest_schema_mgr);
private:
static const int64_t MAX_VERSION_COUNT = 64;
static const int64_t MAX_VERSION_COUNT_FOR_LIBOBLOG = 6;

View File

@ -15,6 +15,7 @@
#include "ob_schema_mem_mgr.h"
#include "lib/oblog/ob_log.h"
#include "share/ob_force_print_log.h"
#include "lib/utility/ob_tracepoint.h"
namespace oceanbase
{
@ -63,8 +64,8 @@ int ObSchemaMemMgr::init(const char *label, const uint64_t tenant_id)
//FIXME: The memory split of the subsequent 500 tenants is then set to the corresponding tenant_id
new(&allocator_[0]) ObArenaAllocator(attr, OB_MALLOC_BIG_BLOCK_SIZE);
new(&allocator_[1]) ObArenaAllocator(attr, OB_MALLOC_BIG_BLOCK_SIZE);
all_ptrs_[0].set_attr(attr);
all_ptrs_[1].set_attr(attr);
all_ptrs_[0] = 0;
all_ptrs_[1] = 0;
ptrs_[0].set_attr(attr);
ptrs_[1].set_attr(attr);
tenant_id_ = tenant_id;
@ -83,7 +84,7 @@ bool ObSchemaMemMgr::check_inner_stat() const
return ret;
}
int ObSchemaMemMgr::alloc(const int size, void *&ptr,
int ObSchemaMemMgr::alloc_(const int size, void *&ptr,
ObIAllocator **allocator)
{
int ret = OB_SUCCESS;
@ -91,7 +92,6 @@ int ObSchemaMemMgr::alloc(const int size, void *&ptr,
if (NULL != allocator) {
*allocator = NULL;
}
SpinWLockGuard guard(schema_mem_rwlock_);
if (!check_inner_stat()) {
ret = OB_INNER_STAT_ERROR;
LOG_WARN("inner stat error", K(ret));
@ -104,8 +104,7 @@ int ObSchemaMemMgr::alloc(const int size, void *&ptr,
if (NULL == tmp_ptr) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc mem failed", K(ret), K(size), K(pos_));
} else if (OB_FAIL(all_ptrs_[pos_].push_back(tmp_ptr))) {
LOG_WARN("push back ptr failed", K(ret), K(pos_));
} else if (FALSE_IT(all_ptrs_[pos_]++)) {
} else if (OB_FAIL(ptrs_[pos_].push_back(tmp_ptr))) {
LOG_WARN("push back ptr failed", K(ret), K(pos_));
} else {
@ -115,8 +114,43 @@ int ObSchemaMemMgr::alloc(const int size, void *&ptr,
*allocator = &cur_allocator;
}
}
if (OB_FAIL(ret) && OB_NOT_NULL(tmp_ptr)) {
LOG_WARN("alloc ptr failed", KR(ret), K(tenant_id_), K(size), K(pos_));
int tmp_ret = OB_SUCCESS;
if(OB_TMP_FAIL(free_(tmp_ptr))) {
FLOG_ERROR("fail to free tmp_ptr", KR(ret), KR(tmp_ret));
} else {
ptr = NULL;
}
}
}
return ret;
}
ERRSIM_POINT_DEF(ERRSIM_ALLOC_SCHEMA_MGR);
int ObSchemaMemMgr::alloc_schema_mgr(ObSchemaMgr *&schema_mgr, bool alloc_for_liboblog)
{
int ret = OB_SUCCESS;
void *tmp_ptr = NULL;
ObIAllocator *allocator = NULL;
SpinWLockGuard guard(schema_mem_rwlock_);
if (OB_UNLIKELY(ERRSIM_ALLOC_SCHEMA_MGR)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("turn on error injection ERRSIM_ALLOC_SCHEMA_MGR", KR(ret));
} else if (OB_FAIL(alloc_(sizeof(ObSchemaMgr), tmp_ptr, &allocator))) {
LOG_WARN("alloc memory for schema_mgr falied", KR(ret));
} else if (OB_ISNULL(allocator) || OB_ISNULL(tmp_ptr)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("tmp ptr or allocator is null", KR(ret), K(tmp_ptr), K(allocator));
} else if (alloc_for_liboblog) {
schema_mgr = new (tmp_ptr) ObSchemaMgr();
} else {
schema_mgr = new (tmp_ptr) ObSchemaMgr(*allocator);
}
if (OB_SUCC(ret) && OB_ISNULL(schema_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("new schema mgr is NULL", KR(ret));
}
return ret;
}
@ -166,11 +200,10 @@ int ObSchemaMemMgr::in_current_allocator(const void *ptr, bool &in_curr_allocato
return ret;
}
int ObSchemaMemMgr::free(void *ptr)
int ObSchemaMemMgr::free_(void *ptr)
{
int ret = OB_SUCCESS;
SpinWLockGuard guard(schema_mem_rwlock_);
if (!check_inner_stat()) {
ret = OB_INNER_STAT_ERROR;
LOG_WARN("inner stat error", K(ret));
@ -208,6 +241,28 @@ int ObSchemaMemMgr::free(void *ptr)
return ret;
}
ERRSIM_POINT_DEF(ERRSIM_FREE_SCEHMA_MGR);
int ObSchemaMemMgr::free_schema_mgr(ObSchemaMgr *&schema_mgr)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ERRSIM_FREE_SCEHMA_MGR)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("turn on error injection ERRSIM_FREE_SCEHMA_MGR", KR(ret));
} else if (OB_NOT_NULL(schema_mgr)) {
const uint64_t tenant_id = schema_mgr->get_tenant_id();
const int64_t schema_version = schema_mgr->get_schema_version();
schema_mgr->~ObSchemaMgr();
FLOG_INFO("[SCHEMA_RELEASE] free schema mgr", K(tenant_id), K(schema_version));
SpinWLockGuard guard(schema_mem_rwlock_);
if (OB_FAIL(free_(static_cast<void *>(schema_mgr)))) {
LOG_ERROR("free schema_mgr failed", KR(ret), K(tenant_id), K(schema_version));
} else {
schema_mgr = NULL;
}
}
return ret;
}
int ObSchemaMemMgr::get_cur_alloc_cnt(int64_t &cnt) const
{
int ret = OB_SUCCESS;
@ -218,7 +273,7 @@ int ObSchemaMemMgr::get_cur_alloc_cnt(int64_t &cnt) const
ret = OB_INNER_STAT_ERROR;
LOG_WARN("inner stat error", K(ret));
} else {
cnt = all_ptrs_[pos_].count();
cnt = all_ptrs_[pos_];
}
return ret;
@ -245,7 +300,7 @@ int ObSchemaMemMgr::get_all_alloc_info(common::ObIArray<ObSchemaMemory> &schema_
mem_used = allocator_[pos_].used();
mem_total = allocator_[pos_].total();
used_schema_mgr_cnt = ptrs_[pos_].count();
free_schema_mgr_cnt = all_ptrs_[pos_].count() - used_schema_mgr_cnt;
free_schema_mgr_cnt = all_ptrs_[pos_] - used_schema_mgr_cnt;
schema_mem.init(0, tenant_id, mem_used, mem_total, used_schema_mgr_cnt, free_schema_mgr_cnt);
if (OB_FAIL(schema_mem_infos.push_back(schema_mem))) {
LOG_WARN("fail to push back schema_mem", KR(ret));
@ -253,7 +308,7 @@ int ObSchemaMemMgr::get_all_alloc_info(common::ObIArray<ObSchemaMemory> &schema_
mem_used = allocator_[1 - pos_].used();
mem_total = allocator_[1 - pos_].total();
used_schema_mgr_cnt = ptrs_[1 - pos_].count();
free_schema_mgr_cnt = all_ptrs_[1 - pos_].count() - used_schema_mgr_cnt;
free_schema_mgr_cnt = all_ptrs_[1 - pos_] - used_schema_mgr_cnt;
schema_mem.init(1, tenant_id, mem_used, mem_total, used_schema_mgr_cnt, free_schema_mgr_cnt);
if (OB_FAIL(schema_mem_infos.push_back(schema_mem))) {
LOG_WARN("fail to push back schema_mem", KR(ret));
@ -330,19 +385,22 @@ int ObSchemaMemMgr::is_same_allocator(const void *p1, const void * p2, bool &is_
return ret;
}
int ObSchemaMemMgr::check_can_switch_allocator(bool &can_switch) const
int ObSchemaMemMgr::check_can_switch_allocator(const int64_t &switch_cnt, bool &can_switch) const
{
int ret = OB_SUCCESS;
can_switch = false;
int64_t cur_alloc_cnt = 0;
bool alloc_not_in_use = false;
SpinRLockGuard guard(schema_mem_rwlock_);
if (!check_inner_stat()) {
ret = OB_INNER_STAT_ERROR;
LOG_WARN("inner stat error", K(ret));
} else {
can_switch = 0 == ptrs_[1 - pos_].count();
alloc_not_in_use = 0 == ptrs_[1 - pos_].count();
cur_alloc_cnt = all_ptrs_[pos_];
can_switch = alloc_not_in_use && cur_alloc_cnt > switch_cnt;
}
LOG_TRACE("check can switch", KR(ret), K_(tenant_id), K_(pos), K(can_switch), K(cur_alloc_cnt), K(switch_cnt));
return ret;
}
@ -360,10 +418,25 @@ int ObSchemaMemMgr::switch_allocator()
dump_without_lock_();
} else {
allocator_[1 - pos_].reset();
all_ptrs_[1 - pos_].reset();
all_ptrs_[1 - pos_] = 0;
pos_ = 1 - pos_;
FLOG_INFO("[SCHEMA_RELEASE] switch_allocator", K_(tenant_id), K_(pos));
}
return ret;
}
int ObSchemaMemMgr::switch_back_allocator()
{
int ret = OB_SUCCESS;
SpinWLockGuard guard(schema_mem_rwlock_);
if (!check_inner_stat()) {
ret = OB_INNER_STAT_ERROR;
LOG_WARN("inner stat error", K(ret));
} else {
pos_ = 1 - pos_;
FLOG_WARN("[SCHEMA_RELEASE] schema mgr encounters something wrong, it needs to switch_back_allocator", K_(tenant_id), K_(pos));
}
return ret;
}
@ -382,8 +455,7 @@ void ObSchemaMemMgr::dump_without_lock_() const
"mem_used", allocator_[pos_].used(),
"mem_total", allocator_[pos_].total(),
"cur_ptrs_cnt", ptrs_[pos_].count(),
"used_ptrs_cnt", all_ptrs_[pos_].count(),
"all_ptrs", all_ptrs_[pos_],
"all_ptrs_cnt", all_ptrs_[pos_],
"ptrs", ptrs_[pos_]);
FLOG_INFO("[SCHEMA_STATISTICS] another allocator",
K_(tenant_id),
@ -391,8 +463,7 @@ void ObSchemaMemMgr::dump_without_lock_() const
"mem_used", allocator_[1 - pos_].used(),
"mem_total", allocator_[1 - pos_].total(),
"cur_ptrs_cnt", ptrs_[1 - pos_].count(),
"used_ptrs_cnt", all_ptrs_[1 - pos_].count(),
"all_ptrs", all_ptrs_[1 - pos_],
"all_ptrs_cnt", all_ptrs_[1 - pos_],
"ptrs", ptrs_[1 - pos_]);
}
@ -427,7 +498,7 @@ int ObSchemaMemMgr::try_reset_allocator()
LOG_INFO("allocator is not empty, just skip", K_(tenant_id));
dump_without_lock_();
} else {
all_ptrs_[pos_].reset();
all_ptrs_[pos_] = 0;
allocator_[pos_].reset();
FLOG_INFO("[SCHEMA_RELEASE] reset schema_mem_mgr", K_(tenant_id));
}
@ -437,7 +508,7 @@ int ObSchemaMemMgr::try_reset_allocator()
LOG_INFO("another allocator is not empty, just skip", K_(tenant_id));
dump_without_lock_();
} else {
all_ptrs_[1 - pos_].reset();
all_ptrs_[1 - pos_] = 0;
allocator_[1 - pos_].reset();
FLOG_INFO("[SCHEMA_RELEASE] reset another schema_mem_mgr", K_(tenant_id));
}
@ -455,8 +526,8 @@ int ObSchemaMemMgr::try_reset_another_allocator()
} else if (0 != ptrs_[1 - pos_].count()) {
LOG_INFO("another allocator is not empty, just skip", K_(tenant_id));
dump_without_lock_();
} else if (0 != all_ptrs_[1 - pos_].count()) {
all_ptrs_[1 - pos_].reset();
} else {
all_ptrs_[1 - pos_] = 0;
allocator_[1 - pos_].reset();
FLOG_INFO("[SCHEMA_RELEASE] reset another allocator", K_(tenant_id), "pos", 1 - pos_);
}

View File

@ -17,6 +17,7 @@
#include "share/ob_define.h"
#include "lib/allocator/page_arena.h"
#include "lib/container/ob_array.h"
#include "share/schema/ob_schema_mgr.h"
namespace oceanbase
{
@ -66,14 +67,12 @@ public:
//
int init(const char *label,
const uint64_t tenant_id);
int alloc(const int size, void *&ptr,
common::ObIAllocator **allocator = NULL);
int free(void *ptr);
int get_cur_alloc_cnt(int64_t &cnt) const;
int check_can_switch_allocator(bool &can_switch) const;
int check_can_switch_allocator(const int64_t &switch_cnt, bool &can_switch) const;
int in_current_allocator(const void *ptr, bool &in_curr_allocator);
int is_same_allocator(const void *p1, const void * p2, bool &is_same_allocator);
int switch_allocator();
int switch_back_allocator();
void dump() const;
int check_can_release(bool &can_release) const;
int try_reset_allocator();
@ -81,10 +80,15 @@ public:
int try_reset_another_allocator();
int get_another_ptrs(common::ObArray<void *> &ptrs);
int get_all_alloc_info(common::ObIArray<ObSchemaMemory> &tenant_mem_infos);
int alloc_schema_mgr(ObSchemaMgr *&schema_mgr, bool alloc_for_liboblog);
int free_schema_mgr(ObSchemaMgr *&schema_mgr);
private:
bool check_inner_stat() const;
void dump_without_lock_() const;
int find_ptr(const void *ptr, const int ptrs_pos, int &idx);
int alloc_(const int size, void *&ptr,
common::ObIAllocator **allocator = NULL);
int free_(void *ptr);
private:
DISALLOW_COPY_AND_ASSIGN(ObSchemaMemMgr);
private:
@ -92,7 +96,7 @@ private:
union {
common::ObArenaAllocator allocator_[2];
};
common::ObArray<void *> all_ptrs_[2];
int64_t all_ptrs_[2];
common::ObArray<void *> ptrs_[2];
int pos_;
bool is_inited_;

View File

@ -263,11 +263,7 @@ int ObServerSchemaService::destroy_schema_struct(uint64_t tenant_id)
ret = OB_ERR_UNEXPECTED;
LOG_WARN("mem_mgr is null", K(ret), K(tenant_id));
} else {
FLOG_INFO("[SCHEMA_RELEASE] try release schema_mgr_for_cache", K(ret), K(tenant_id),
"schema_mgr_tenant_id", schema_mgr->get_tenant_id(),
"schema_version", schema_mgr->get_schema_version());
schema_mgr->~ObSchemaMgr();
if (OB_FAIL(mem_mgr->free(static_cast<void *>(schema_mgr)))) {
if (OB_FAIL(mem_mgr->free_schema_mgr(schema_mgr))) {
LOG_ERROR("free schema mgr for cache failed", K(ret), K(tenant_id));
} else {
schema_mgr = NULL;
@ -5537,33 +5533,25 @@ int ObServerSchemaService::init_schema_struct(uint64_t tenant_id)
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(schema_mgr_for_cache_map_.get(tenant_id))) {
void *buffer = NULL;
ObIAllocator *allocator = NULL;
ObSchemaMgr *schema_mgr_for_cache = NULL;
ObSchemaMemMgr *mem_mgr = NULL;
bool alloc_for_liboblog = false;
if (OB_FAIL(mem_mgr_map_.get_refactored(tenant_id, mem_mgr))) {
LOG_WARN("fail to get mem_mgr", K(ret), K(tenant_id));
} else if (OB_ISNULL(mem_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("mem_mgr is null", K(ret), K(tenant_id));
} else if (OB_FAIL(mem_mgr->alloc(sizeof(ObSchemaMgr), buffer, &allocator))) {
} else if (OB_FAIL(mem_mgr->alloc_schema_mgr(schema_mgr_for_cache, alloc_for_liboblog))) {
LOG_WARN("alloc schema mgr failed", K(ret));
} else if (FALSE_IT(schema_mgr_for_cache = new(buffer)ObSchemaMgr(*allocator))) {
// will not reach here
} else if (OB_FAIL(schema_mgr_for_cache->init(tenant_id))) {
LOG_WARN("init schema mgr for cache failed", K(ret));
} else if (OB_FAIL(schema_mgr_for_cache_map_.set_refactored(tenant_id, schema_mgr_for_cache))) {
LOG_WARN("fail to set schema_mgr", K(ret), K(tenant_id));
}
if (OB_FAIL(ret)) {
if (NULL != schema_mgr_for_cache) {
schema_mgr_for_cache->~ObSchemaMgr();
ob_free(buffer);
schema_mgr_for_cache = NULL;
buffer= NULL;
} else if (NULL != buffer) {
ob_free(buffer);
buffer = NULL;
if (OB_FAIL(ret) && OB_NOT_NULL(mem_mgr)) {
int64_t tmp_ret = OB_SUCCESS;
if (OB_TMP_FAIL(mem_mgr->free_schema_mgr(schema_mgr_for_cache))) {
LOG_ERROR("fail to free mem_mgr", KR(ret));
}
}
} else {

View File

@ -40,6 +40,7 @@
#include "sql/engine/expr/ob_expr_frame_info.h"
#include "sql/code_generator/ob_static_engine_expr_cg.h"
#include "observer/ob_inner_sql_connection_pool.h"
#include "share/ls/ob_ls_status_operator.h"
namespace oceanbase
{