[CP] [CP][Bugfix] fix memory leak when tenant has been destroyed
This commit is contained in:
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
using namespace oceanbase::share;
|
using namespace oceanbase::share;
|
||||||
using namespace oceanbase::common;
|
using namespace oceanbase::common;
|
||||||
|
using namespace oceanbase::lib;
|
||||||
|
|
||||||
namespace oceanbase
|
namespace oceanbase
|
||||||
{
|
{
|
||||||
@ -512,9 +513,12 @@ int ObTableApiSessPool::create_node_safe(ObTableApiCredential &credential, ObTab
|
|||||||
LOG_WARN("fail to alloc mem for ObTableApiSessNode", K(ret), K(sizeof(ObTableApiSessNode)));
|
LOG_WARN("fail to alloc mem for ObTableApiSessNode", K(ret), K(sizeof(ObTableApiSessNode)));
|
||||||
} else {
|
} else {
|
||||||
tmp_node = new (buf) ObTableApiSessNode(credential);
|
tmp_node = new (buf) ObTableApiSessNode(credential);
|
||||||
tmp_node->last_active_ts_ = ObTimeUtility::current_time();
|
if (OB_FAIL(tmp_node->init())) {
|
||||||
|
LOG_WARN("fail to init session node", K(ret));
|
||||||
|
} else {
|
||||||
node = tmp_node;
|
node = tmp_node;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -643,6 +647,30 @@ void ObTableApiSessNodeVal::give_back_to_free_list()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ObTableApiSessNode::init()
|
||||||
|
{
|
||||||
|
int ret = OB_SUCCESS;
|
||||||
|
|
||||||
|
if (!is_inited_) {
|
||||||
|
MemoryContext tmp_mem_ctx = nullptr;
|
||||||
|
ContextParam param;
|
||||||
|
param.set_mem_attr(MTL_ID(), "TbSessNod", ObCtxIds::DEFAULT_CTX_ID)
|
||||||
|
.set_properties(lib::ALLOC_THREAD_SAFE);
|
||||||
|
if (OB_FAIL(ROOT_CONTEXT->CREATE_CONTEXT(tmp_mem_ctx, param))) {
|
||||||
|
LOG_WARN("fail to create mem context", K(ret));
|
||||||
|
} else if (OB_ISNULL(tmp_mem_ctx)) {
|
||||||
|
ret = OB_ERR_UNEXPECTED;
|
||||||
|
LOG_WARN("unexpected null mem context ", K(ret));
|
||||||
|
} else {
|
||||||
|
mem_ctx_ = tmp_mem_ctx;
|
||||||
|
last_active_ts_ = ObTimeUtility::fast_current_time();
|
||||||
|
is_inited_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void ObTableApiSessNode::destroy()
|
void ObTableApiSessNode::destroy()
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
@ -653,22 +681,33 @@ void ObTableApiSessNode::destroy()
|
|||||||
ObTableApiSessNodeVal *rm_sess = free_list.remove(sess);
|
ObTableApiSessNodeVal *rm_sess = free_list.remove(sess);
|
||||||
if (OB_NOT_NULL(rm_sess)) {
|
if (OB_NOT_NULL(rm_sess)) {
|
||||||
rm_sess->destroy();
|
rm_sess->destroy();
|
||||||
|
if (OB_NOT_NULL(mem_ctx_)) {
|
||||||
|
mem_ctx_->free(rm_sess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DLIST_FOREACH_REMOVESAFE(sess, used_list) {
|
DLIST_FOREACH_REMOVESAFE(sess, used_list) {
|
||||||
ObTableApiSessNodeVal *rm_sess = used_list.remove(sess);
|
ObTableApiSessNodeVal *rm_sess = used_list.remove(sess);
|
||||||
if (OB_NOT_NULL(rm_sess)) {
|
if (OB_NOT_NULL(rm_sess)) {
|
||||||
rm_sess->destroy();
|
rm_sess->destroy();
|
||||||
|
if (OB_NOT_NULL(mem_ctx_)) {
|
||||||
|
mem_ctx_->free(rm_sess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObLockGuard<ObSpinLock> alloc_guard(allocator_lock_); // lock allocator_
|
}
|
||||||
allocator_.reset();
|
if (OB_NOT_NULL(mem_ctx_)) {
|
||||||
|
DESTROY_CONTEXT(mem_ctx_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ObTableApiSessNode::remove_unused_sess()
|
int ObTableApiSessNode::remove_unused_sess()
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
|
|
||||||
|
if (IS_NOT_INIT) {
|
||||||
|
ret = OB_NOT_INIT;
|
||||||
|
LOG_WARN("session node is not inited", K(ret));
|
||||||
|
} else {
|
||||||
ObDList<ObTableApiSessNodeVal> &free_list = sess_lists_.free_list_;
|
ObDList<ObTableApiSessNodeVal> &free_list = sess_lists_.free_list_;
|
||||||
if (free_list.is_empty()) {
|
if (free_list.is_empty()) {
|
||||||
// do nothing
|
// do nothing
|
||||||
@ -676,14 +715,14 @@ int ObTableApiSessNode::remove_unused_sess()
|
|||||||
ObLockGuard<ObSpinLock> guard(sess_lists_.lock_);
|
ObLockGuard<ObSpinLock> guard(sess_lists_.lock_);
|
||||||
DLIST_FOREACH_REMOVESAFE(sess, free_list) {
|
DLIST_FOREACH_REMOVESAFE(sess, free_list) {
|
||||||
ObTableApiSessNodeVal *rm_sess = free_list.remove(sess);
|
ObTableApiSessNodeVal *rm_sess = free_list.remove(sess);
|
||||||
if (OB_NOT_NULL(rm_sess)) {
|
if (OB_NOT_NULL(rm_sess) && OB_NOT_NULL(mem_ctx_)) {
|
||||||
rm_sess->~ObTableApiSessNodeVal();
|
rm_sess->~ObTableApiSessNodeVal();
|
||||||
ObLockGuard<ObSpinLock> alloc_guard(allocator_lock_); // lock allocator_
|
mem_ctx_->free(rm_sess);
|
||||||
allocator_.free(rm_sess);
|
|
||||||
rm_sess = nullptr;
|
rm_sess = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -696,6 +735,11 @@ int ObTableApiSessNode::remove_unused_sess()
|
|||||||
int ObTableApiSessNode::get_sess_node_val(ObTableApiSessNodeVal *&val)
|
int ObTableApiSessNode::get_sess_node_val(ObTableApiSessNodeVal *&val)
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
|
|
||||||
|
if (IS_NOT_INIT) {
|
||||||
|
ret = OB_NOT_INIT;
|
||||||
|
LOG_WARN("session node is not inited", K(ret));
|
||||||
|
} else {
|
||||||
ObTableApiSessNodeVal *tmp_val = nullptr;
|
ObTableApiSessNodeVal *tmp_val = nullptr;
|
||||||
ObDList<ObTableApiSessNodeVal> &free_list = sess_lists_.free_list_;
|
ObDList<ObTableApiSessNodeVal> &free_list = sess_lists_.free_list_;
|
||||||
ObDList<ObTableApiSessNodeVal> &used_list = sess_lists_.used_list_;
|
ObDList<ObTableApiSessNodeVal> &used_list = sess_lists_.used_list_;
|
||||||
@ -711,6 +755,7 @@ int ObTableApiSessNode::get_sess_node_val(ObTableApiSessNodeVal *&val)
|
|||||||
val = tmp_val;
|
val = tmp_val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -724,14 +769,22 @@ int ObTableApiSessNode::get_sess_node_val(ObTableApiSessNodeVal *&val)
|
|||||||
int ObTableApiSessNode::extend_and_get_sess_val(ObTableApiSessGuard &guard)
|
int ObTableApiSessNode::extend_and_get_sess_val(ObTableApiSessGuard &guard)
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
ObLockGuard<ObSpinLock> alloc_guard(allocator_lock_); // lock allocator_
|
|
||||||
void *buf = nullptr;
|
|
||||||
|
|
||||||
if (OB_ISNULL(buf = allocator_.alloc(sizeof(ObTableApiSessNodeVal)))) {
|
if (IS_NOT_INIT) {
|
||||||
|
ret = OB_NOT_INIT;
|
||||||
|
LOG_WARN("session node is not inited", K(ret));
|
||||||
|
} else if (OB_ISNULL(mem_ctx_)) {
|
||||||
|
ret = OB_ERR_UNEXPECTED;
|
||||||
|
LOG_WARN("memory context is null", K(ret));
|
||||||
|
} else {
|
||||||
|
ObTableApiSessNodeVal *val = nullptr;
|
||||||
|
void *buf = nullptr;
|
||||||
|
ObMemAttr attr(MTL_ID(), "TbSessNodVal", ObCtxIds::DEFAULT_CTX_ID);
|
||||||
|
if (OB_ISNULL(buf = mem_ctx_->allocf(sizeof(ObTableApiSessNodeVal), attr))) {
|
||||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||||
LOG_WARN("fail to alloc mem for ObTableApiSessNodeVal", K(ret), K(sizeof(ObTableApiSessNodeVal)));
|
LOG_WARN("fail to alloc mem for ObTableApiSessNodeVal", K(ret), K(sizeof(ObTableApiSessNodeVal)));
|
||||||
} else {
|
} else {
|
||||||
ObTableApiSessNodeVal *val = new (buf) ObTableApiSessNodeVal(this, credential_.tenant_id_);
|
val = new (buf) ObTableApiSessNodeVal(this, credential_.tenant_id_);
|
||||||
if (OB_FAIL(val->init_sess_info())) {
|
if (OB_FAIL(val->init_sess_info())) {
|
||||||
LOG_WARN("fail to init sess info", K(ret), K(*val));
|
LOG_WARN("fail to init sess info", K(ret), K(*val));
|
||||||
} else {
|
} else {
|
||||||
@ -745,10 +798,13 @@ int ObTableApiSessNode::extend_and_get_sess_val(ObTableApiSessGuard &guard)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OB_FAIL(ret) && OB_NOT_NULL(buf)) {
|
if (OB_FAIL(ret) && OB_NOT_NULL(val)) {
|
||||||
allocator_.free(buf);
|
val->~ObTableApiSessNodeVal();
|
||||||
|
mem_ctx_->free(val);
|
||||||
|
val = nullptr;
|
||||||
buf = nullptr;
|
buf = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,14 +164,16 @@ friend class ObTableApiSessPool;
|
|||||||
friend class ObTableApiSessNodeVal;
|
friend class ObTableApiSessNodeVal;
|
||||||
public:
|
public:
|
||||||
explicit ObTableApiSessNode(ObTableApiCredential &credential)
|
explicit ObTableApiSessNode(ObTableApiCredential &credential)
|
||||||
: allocator_("TbSessNode", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()),
|
: is_inited_(false),
|
||||||
|
mem_ctx_(nullptr),
|
||||||
sess_lists_(),
|
sess_lists_(),
|
||||||
last_active_ts_(0),
|
last_active_ts_(0),
|
||||||
credential_(credential)
|
credential_(credential)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~ObTableApiSessNode() { destroy(); }
|
~ObTableApiSessNode() { destroy(); }
|
||||||
TO_STRING_KV(K_(sess_lists),
|
TO_STRING_KV(K_(is_inited),
|
||||||
|
K_(sess_lists),
|
||||||
K_(last_active_ts),
|
K_(last_active_ts),
|
||||||
K_(credential));
|
K_(credential));
|
||||||
class SessList
|
class SessList
|
||||||
@ -189,6 +191,7 @@ public:
|
|||||||
DISALLOW_COPY_AND_ASSIGN(SessList);
|
DISALLOW_COPY_AND_ASSIGN(SessList);
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
|
int init();
|
||||||
void destroy();
|
void destroy();
|
||||||
bool is_empty() const { return sess_lists_.is_empty(); }
|
bool is_empty() const { return sess_lists_.is_empty(); }
|
||||||
int get_sess_node_val(ObTableApiSessNodeVal *&val);
|
int get_sess_node_val(ObTableApiSessNodeVal *&val);
|
||||||
@ -198,8 +201,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
int extend_and_get_sess_val(ObTableApiSessGuard &guard);
|
int extend_and_get_sess_val(ObTableApiSessGuard &guard);
|
||||||
private:
|
private:
|
||||||
common::ObArenaAllocator allocator_;
|
bool is_inited_;
|
||||||
ObSpinLock allocator_lock_; // for lock allocator_
|
lib::MemoryContext mem_ctx_;
|
||||||
SessList sess_lists_;
|
SessList sess_lists_;
|
||||||
int64_t last_active_ts_;
|
int64_t last_active_ts_;
|
||||||
ObTableApiCredential credential_;
|
ObTableApiCredential credential_;
|
||||||
|
|||||||
@ -132,9 +132,12 @@ TEST_F(TestTableSessPool, mgr_get_session)
|
|||||||
ASSERT_NE(0, node->last_active_ts_);
|
ASSERT_NE(0, node->last_active_ts_);
|
||||||
|
|
||||||
// add mock val to node
|
// add mock val to node
|
||||||
ObTableApiSessNodeVal val(node, MTL_ID());
|
void *buf = nullptr;
|
||||||
val.is_inited_ = true;
|
ObMemAttr attr(MTL_ID(), "TbSessNodVal", ObCtxIds::DEFAULT_CTX_ID);
|
||||||
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(&val));
|
ASSERT_NE(nullptr, buf = node->mem_ctx_->allocf(sizeof(ObTableApiSessNodeVal), attr));
|
||||||
|
ObTableApiSessNodeVal *val = new (buf) ObTableApiSessNodeVal(node, MTL_ID());
|
||||||
|
val->is_inited_ = true;
|
||||||
|
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(val));
|
||||||
|
|
||||||
ObTableApiSessGuard guard;
|
ObTableApiSessGuard guard;
|
||||||
ASSERT_EQ(OB_SUCCESS, mgr->get_sess_info(*mock_cred_, guard));
|
ASSERT_EQ(OB_SUCCESS, mgr->get_sess_info(*mock_cred_, guard));
|
||||||
@ -216,9 +219,12 @@ TEST_F(TestTableSessPool, mgr_sess_recycle)
|
|||||||
// add mock val to node
|
// add mock val to node
|
||||||
ObTableApiSessNode *node;
|
ObTableApiSessNode *node;
|
||||||
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(mock_cred_->hash_val_, node));
|
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(mock_cred_->hash_val_, node));
|
||||||
ObTableApiSessNodeVal val(node, MTL_ID());
|
void *buf = nullptr;
|
||||||
val.is_inited_ = true;
|
ObMemAttr attr(MTL_ID(), "TbSessNodVal", ObCtxIds::DEFAULT_CTX_ID);
|
||||||
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(&val));
|
ASSERT_NE(nullptr, buf = node->mem_ctx_->allocf(sizeof(ObTableApiSessNodeVal), attr));
|
||||||
|
ObTableApiSessNodeVal *val = new (buf) ObTableApiSessNodeVal(node, MTL_ID());
|
||||||
|
val->is_inited_ = true;
|
||||||
|
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(val));
|
||||||
|
|
||||||
ObTableApiSessGuard guard;
|
ObTableApiSessGuard guard;
|
||||||
ASSERT_EQ(OB_SUCCESS, mgr->get_sess_info(*mock_cred_, guard));
|
ASSERT_EQ(OB_SUCCESS, mgr->get_sess_info(*mock_cred_, guard));
|
||||||
|
|||||||
Reference in New Issue
Block a user