fix memory leak in VSliceAlloc
This commit is contained in:
33
deps/oblib/src/lib/allocator/ob_slice_alloc.h
vendored
33
deps/oblib/src/lib/allocator/ob_slice_alloc.h
vendored
@ -131,9 +131,11 @@ public:
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
uint32_t total() { return total_; }
|
uint32_t total() { return total_; }
|
||||||
|
int32_t stock() { return stock_; }
|
||||||
|
int32_t remain() { return stock_ > K ? stock_ - K : (stock_ < 0 ? stock_ + K : stock_); }
|
||||||
bool acquire() { return dec_if_gt(K, K) > K; }
|
bool acquire() { return dec_if_gt(K, K) > K; }
|
||||||
bool release() { return faa(-K) > 0; }
|
bool release() { return faa(-K) > 0; }
|
||||||
bool recyle() {
|
bool recycle() {
|
||||||
int32_t total = total_;
|
int32_t total = total_;
|
||||||
return inc_if_lt(2 * K, -K + total) == -K + total;
|
return inc_if_lt(2 * K, -K + total) == -K + total;
|
||||||
}
|
}
|
||||||
@ -271,13 +273,37 @@ public:
|
|||||||
LIB_LOG(INFO, "ObSliceAlloc init finished", K(bsize_), K(isize_), K(slice_limit_), KP(tmallocator_));
|
LIB_LOG(INFO, "ObSliceAlloc init finished", K(bsize_), K(isize_), K(slice_limit_), KP(tmallocator_));
|
||||||
}
|
}
|
||||||
~ObSliceAlloc() {
|
~ObSliceAlloc() {
|
||||||
tmallocator_ = NULL;
|
destroy();
|
||||||
}
|
}
|
||||||
int init(const int size, const int block_size, BlockAlloc& block_alloc, const ObMemAttr& attr) {
|
int init(const int size, const int block_size, BlockAlloc& block_alloc, const ObMemAttr& attr) {
|
||||||
int ret = common::OB_SUCCESS;
|
int ret = common::OB_SUCCESS;
|
||||||
new(this)ObSliceAlloc(size, attr, block_size, block_alloc, NULL);
|
new(this)ObSliceAlloc(size, attr, block_size, block_alloc, NULL);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
void destroy() {
|
||||||
|
for(int i = MAX_ARENA_NUM - 1; i >= 0; i--) {
|
||||||
|
Arena& arena = arena_[i];
|
||||||
|
Block* old_blk = arena.clear();
|
||||||
|
if (NULL != old_blk) {
|
||||||
|
blk_ref_[ObBlockSlicer::hash((uint64_t)old_blk) % MAX_REF_NUM].sync();
|
||||||
|
if (old_blk->release()) {
|
||||||
|
blk_list_.add(&old_blk->dlink_);
|
||||||
|
if (old_blk->recycle()) {
|
||||||
|
destroy_block(old_blk);
|
||||||
|
} else {
|
||||||
|
_LIB_LOG(ERROR, "there was memory leak, stock=%d, remain=%d", old_blk->stock(), old_blk->remain());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObDLink* dlink = nullptr;
|
||||||
|
if (OB_NOT_NULL(dlink = blk_list_.top())) {
|
||||||
|
Block* blk = CONTAINER_OF(dlink, Block, dlink_);
|
||||||
|
_LIB_LOG(ERROR, "there was memory leak, stock=%d, remain=%d", blk->stock(), blk->remain());
|
||||||
|
}
|
||||||
|
tmallocator_ = NULL;
|
||||||
|
bsize_ = 0;
|
||||||
|
}
|
||||||
void set_nway(int nway) {
|
void set_nway(int nway) {
|
||||||
if (nway <= 0) {
|
if (nway <= 0) {
|
||||||
nway = 1;
|
nway = 1;
|
||||||
@ -351,6 +377,7 @@ public:
|
|||||||
Block* blk = item->host_;
|
Block* blk = item->host_;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
abort_unless(blk->get_slice_alloc() == this);
|
abort_unless(blk->get_slice_alloc() == this);
|
||||||
|
abort_unless(bsize_ != 0);
|
||||||
#else
|
#else
|
||||||
if (this != blk->get_slice_alloc()) {
|
if (this != blk->get_slice_alloc()) {
|
||||||
LIB_LOG(ERROR, "blk is freed or alloced by different slice_alloc", K(this), K(blk->get_slice_alloc()));
|
LIB_LOG(ERROR, "blk is freed or alloced by different slice_alloc", K(this), K(blk->get_slice_alloc()));
|
||||||
@ -391,7 +418,7 @@ private:
|
|||||||
}
|
}
|
||||||
void add_to_blist(Block* blk) {
|
void add_to_blist(Block* blk) {
|
||||||
blk_list_.add(&blk->dlink_);
|
blk_list_.add(&blk->dlink_);
|
||||||
if (blk->recyle()) {
|
if (blk->recycle()) {
|
||||||
destroy_block(blk);
|
destroy_block(blk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
deps/oblib/src/lib/allocator/ob_vslice_alloc.h
vendored
26
deps/oblib/src/lib/allocator/ob_vslice_alloc.h
vendored
@ -25,6 +25,7 @@ namespace common
|
|||||||
extern ObBlockAllocMgr default_blk_alloc;
|
extern ObBlockAllocMgr default_blk_alloc;
|
||||||
class ObBlockVSlicer
|
class ObBlockVSlicer
|
||||||
{
|
{
|
||||||
|
friend class ObVSliceAlloc;
|
||||||
public:
|
public:
|
||||||
static const uint32_t ITEM_MAGIC_CODE = 0XCCEEDDF1;
|
static const uint32_t ITEM_MAGIC_CODE = 0XCCEEDDF1;
|
||||||
static const uint32_t ITEM_MAGIC_CODE_MASK = 0XFFFFFFF0;
|
static const uint32_t ITEM_MAGIC_CODE_MASK = 0XFFFFFFF0;
|
||||||
@ -72,6 +73,7 @@ private:
|
|||||||
|
|
||||||
class ObVSliceAlloc : public common::ObIAllocator
|
class ObVSliceAlloc : public common::ObIAllocator
|
||||||
{
|
{
|
||||||
|
friend class ObBlockVSlicer;
|
||||||
public:
|
public:
|
||||||
enum { MAX_ARENA_NUM = 32, DEFAULT_BLOCK_SIZE = OB_MALLOC_NORMAL_BLOCK_SIZE };
|
enum { MAX_ARENA_NUM = 32, DEFAULT_BLOCK_SIZE = OB_MALLOC_NORMAL_BLOCK_SIZE };
|
||||||
typedef ObBlockAllocMgr BlockAlloc;
|
typedef ObBlockAllocMgr BlockAlloc;
|
||||||
@ -91,12 +93,31 @@ public:
|
|||||||
ObVSliceAlloc(): nway_(0), bsize_(0), blk_alloc_(default_blk_alloc) {}
|
ObVSliceAlloc(): nway_(0), bsize_(0), blk_alloc_(default_blk_alloc) {}
|
||||||
ObVSliceAlloc(const ObMemAttr &attr, int block_size = DEFAULT_BLOCK_SIZE, BlockAlloc &blk_alloc = default_blk_alloc)
|
ObVSliceAlloc(const ObMemAttr &attr, int block_size = DEFAULT_BLOCK_SIZE, BlockAlloc &blk_alloc = default_blk_alloc)
|
||||||
: nway_(1), bsize_(block_size), mattr_(attr), blk_alloc_(blk_alloc) {}
|
: nway_(1), bsize_(block_size), mattr_(attr), blk_alloc_(blk_alloc) {}
|
||||||
virtual ~ObVSliceAlloc() override {}
|
virtual ~ObVSliceAlloc() override { destroy(); }
|
||||||
int init(int block_size, BlockAlloc& block_alloc, const ObMemAttr& attr) {
|
int init(int block_size, BlockAlloc& block_alloc, const ObMemAttr& attr) {
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
new(this)ObVSliceAlloc(attr, block_size, block_alloc);
|
new(this)ObVSliceAlloc(attr, block_size, block_alloc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
void destroy() {
|
||||||
|
for(int i = MAX_ARENA_NUM - 1; i >= 0; i--) {
|
||||||
|
Arena& arena = arena_[i];
|
||||||
|
Block* old_blk = arena.clear();
|
||||||
|
if (NULL != old_blk) {
|
||||||
|
int64_t old_pos = INT64_MAX;
|
||||||
|
if (old_blk->freeze(old_pos)) {
|
||||||
|
arena.sync();
|
||||||
|
if (old_blk->retire(old_pos)) {
|
||||||
|
destroy_block(old_blk);
|
||||||
|
} else {
|
||||||
|
// can not monitor all leak !!!
|
||||||
|
LIB_LOG(ERROR, "there was memory leak", K(old_blk->ref_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bsize_ = 0;
|
||||||
|
}
|
||||||
void set_nway(int nway) {
|
void set_nway(int nway) {
|
||||||
if (nway <= 0) {
|
if (nway <= 0) {
|
||||||
nway = 1;
|
nway = 1;
|
||||||
@ -182,12 +203,13 @@ public:
|
|||||||
#ifdef OB_USE_ASAN
|
#ifdef OB_USE_ASAN
|
||||||
::free(p);
|
::free(p);
|
||||||
#else
|
#else
|
||||||
if (bsize_ > 0 && NULL != p) {
|
if (NULL != p) {
|
||||||
Block::Item* item = (Block::Item*)p - 1;
|
Block::Item* item = (Block::Item*)p - 1;
|
||||||
abort_unless(Block::ITEM_MAGIC_CODE == item->MAGIC_CODE_);
|
abort_unless(Block::ITEM_MAGIC_CODE == item->MAGIC_CODE_);
|
||||||
Block* blk = item->host_;
|
Block* blk = item->host_;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
abort_unless(blk->get_vslice_alloc() == this);
|
abort_unless(blk->get_vslice_alloc() == this);
|
||||||
|
abort_unless(bsize_ != 0);
|
||||||
#else
|
#else
|
||||||
if (this != blk->get_vslice_alloc()) {
|
if (this != blk->get_vslice_alloc()) {
|
||||||
LIB_LOG(ERROR, "blk is freed or alloced by different vslice_alloc", K(this), K(blk->get_vslice_alloc()));
|
LIB_LOG(ERROR, "blk is freed or alloced by different vslice_alloc", K(this), K(blk->get_vslice_alloc()));
|
||||||
|
|||||||
16
deps/oblib/src/lib/hash/ob_linear_hash_map.h
vendored
16
deps/oblib/src/lib/hash/ob_linear_hash_map.h
vendored
@ -182,10 +182,18 @@ struct ShareMemMgrTag { };
|
|||||||
/* Don't use this mode unless you know what it means. */
|
/* Don't use this mode unless you know what it means. */
|
||||||
struct UniqueMemMgrTag { };
|
struct UniqueMemMgrTag { };
|
||||||
|
|
||||||
|
// avoid allocator destructed before HashMap
|
||||||
|
template <typename Key, typename Value, typename MemMgrTag>
|
||||||
|
struct ConstructGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConstructGuard();
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Key, typename Value, typename MemMgrTag = ShareMemMgrTag>
|
template <typename Key, typename Value, typename MemMgrTag = ShareMemMgrTag>
|
||||||
class ObLinearHashMap
|
class ObLinearHashMap : public ConstructGuard<Key, Value, MemMgrTag>
|
||||||
{
|
{
|
||||||
|
friend class ConstructGuard<Key, Value, MemMgrTag>;
|
||||||
private:
|
private:
|
||||||
/* Entry. */
|
/* Entry. */
|
||||||
struct Node
|
struct Node
|
||||||
@ -2372,6 +2380,12 @@ bool ObLinearHashMap<Key, Value, MemMgrTag>::DoRemoveIfOnBkt<Function>::operator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value, typename MemMgrTag>
|
||||||
|
ConstructGuard<Key, Value, MemMgrTag>::ConstructGuard()
|
||||||
|
{
|
||||||
|
auto& t = ObLinearHashMap<Key, Value, MemMgrTag>::HashMapMemMgrCore::get_instance();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -283,6 +283,7 @@ TEST_F(TestIOStruct, IOAllocator)
|
|||||||
TEST_F(TestIOStruct, IORequest)
|
TEST_F(TestIOStruct, IORequest)
|
||||||
{
|
{
|
||||||
ObTenantIOManager tenant_io_mgr;
|
ObTenantIOManager tenant_io_mgr;
|
||||||
|
tenant_io_mgr.inc_ref();
|
||||||
ASSERT_SUCC(tenant_io_mgr.io_allocator_.init(TEST_TENANT_ID, IO_MEMORY_LIMIT));
|
ASSERT_SUCC(tenant_io_mgr.io_allocator_.init(TEST_TENANT_ID, IO_MEMORY_LIMIT));
|
||||||
ObRefHolder<ObTenantIOManager> holder(&tenant_io_mgr);
|
ObRefHolder<ObTenantIOManager> holder(&tenant_io_mgr);
|
||||||
ObIOFd fd;
|
ObIOFd fd;
|
||||||
|
|||||||
Reference in New Issue
Block a user