diff --git a/deps/oblib/src/lib/allocator/ob_slice_alloc.h b/deps/oblib/src/lib/allocator/ob_slice_alloc.h index 87b0cc2c2f..613e88dafc 100644 --- a/deps/oblib/src/lib/allocator/ob_slice_alloc.h +++ b/deps/oblib/src/lib/allocator/ob_slice_alloc.h @@ -257,6 +257,33 @@ private: FList flist_ CACHE_ALIGNED; }; + +/******************************************** debug code *********************************************/ + +#ifdef ENABLE_DEBUG_LOG +#define OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG +// #define OB_RECORD_ALL_LBT_IN_THIS_ALLOCATOR +#endif + +#ifdef OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG +#define OB_SLICE_LBT_BUFF_LENGTH 128 +#endif + +#ifdef OB_RECORD_ALL_LBT_IN_THIS_ALLOCATOR +#define GEN_RECORD_ALL_LBT_IN_THIS_ALLOCATOR_CODE \ + do { \ + if (is_leak_debug_ && OB_NOT_NULL(ret)) { \ + void *slice_ptr = (void *)(ret + 1); \ + char *lbt_buf = (char *)slice_ptr + isize_ - OB_SLICE_LBT_BUFF_LENGTH; \ + lbt(lbt_buf, OB_SLICE_LBT_BUFF_LENGTH); \ + } \ + } while (0); +#else +#define GEN_RECORD_ALL_LBT_IN_THIS_ALLOCATOR_CODE +#endif + +/******************************************** debug code *********************************************/ + class ObSliceAlloc { public: @@ -354,6 +381,7 @@ public: } } + GEN_RECORD_ALL_LBT_IN_THIS_ALLOCATOR_CODE return NULL == ret? NULL: (void*)(ret + 1); #endif } @@ -462,7 +490,42 @@ protected: Sync blk_ref_[MAX_REF_NUM]; BlockAlloc &blk_alloc_; void* tmallocator_; + +/******************************************** debug code *********************************************/ + +#ifdef OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG + +public: + // use this function after initiating slice allocator + void enable_leak_debug() + { + new (this) ObSliceAlloc(isize_ + 128, attr_, bsize_, blk_alloc_, NULL); + is_leak_debug_ = true; + LIB_LOG(INFO, "leak debug mode! allocate extra 128 bytes memory for lbt record", K(is_leak_debug_)); + } + + void *alloc(const bool record_alloc_lbt) + { + void *ret = alloc(); + if (record_alloc_lbt && is_leak_debug_ && OB_NOT_NULL(ret)) { + char *lbt_buf = (char *)ret + isize_ - OB_SLICE_LBT_BUFF_LENGTH; + lbt(lbt_buf, OB_SLICE_LBT_BUFF_LENGTH); + } + return ret; + } + +private: + bool is_leak_debug_ = false; + +#endif + +#undef OB_SLICE_LBT_BUFF_LENGTH +#undef OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG +/******************************************** debug code *********************************************/ + }; + + }; // end namespace common }; // end namespace oceanbase #endif /* OCEANBASE_ALLOCATOR_OB_SLICE_ALLOC_H_ */ diff --git a/src/storage/tx/ob_tx_data_define.cpp b/src/storage/tx/ob_tx_data_define.cpp index 4ddb41d0a2..68a6ab52ea 100644 --- a/src/storage/tx/ob_tx_data_define.cpp +++ b/src/storage/tx/ob_tx_data_define.cpp @@ -113,7 +113,11 @@ int ObUndoStatusList::deserialize_(const char *buf, // allcate new undo status node if needed if (OB_ISNULL(cur_node) || cur_node->size_ >= TX_DATA_UNDO_ACT_MAX_NUM_PER_NODE) { void *undo_node_buf = nullptr; +#ifdef OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG + if (OB_ISNULL(undo_node_buf = slice_allocator.alloc(true /*record_alloc_lbt*/))) { +#else if (OB_ISNULL(undo_node_buf = slice_allocator.alloc())) { +#endif ret = OB_ALLOCATE_MEMORY_FAILED; STORAGE_LOG(WARN, "allocate memory when deserialize ObTxData failed.", KR(ret)); } else { diff --git a/src/storage/tx_table/ob_tx_data_table.cpp b/src/storage/tx_table/ob_tx_data_table.cpp index e7ec59ccc4..c1856f7008 100644 --- a/src/storage/tx_table/ob_tx_data_table.cpp +++ b/src/storage/tx_table/ob_tx_data_table.cpp @@ -36,6 +36,14 @@ using namespace oceanbase::share; namespace storage { +#ifdef OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG +#define TX_DATA_MEM_LEAK_DEBUG_CODE slice_allocator_.enable_leak_debug(); +#else +#define TX_DATA_MEM_LEAK_DEBUG_CODE +#endif + + + int ObTxDataTable::init(ObLS *ls, ObTxCtxTable *tx_ctx_table) { int ret = OB_SUCCESS; @@ -58,6 +66,7 @@ int ObTxDataTable::init(ObLS *ls, ObTxCtxTable *tx_ctx_table) STORAGE_LOG(WARN, "init tx data read ctx failed.", KR(ret), K(tablet_id_)); } else { slice_allocator_.set_nway(ObTxDataTable::TX_DATA_MAX_CONCURRENCY); + TX_DATA_MEM_LEAK_DEBUG_CODE ls_ = ls; memtable_mgr_ = static_cast(memtable_mgr_handle.get_memtable_mgr()); @@ -318,7 +327,11 @@ int ObTxDataTable::alloc_undo_status_node(ObUndoStatusNode *&undo_status_node) { int ret = OB_SUCCESS; void *slice_ptr = nullptr; +#ifdef OB_ENABLE_SLICE_ALLOC_LEAK_DEBUG + if (OB_ISNULL(slice_ptr = slice_allocator_.alloc(true /*record_alloc_lbt*/))) { +#else if (OB_ISNULL(slice_ptr = slice_allocator_.alloc())) { +#endif ret = OB_ALLOCATE_MEMORY_FAILED; STORAGE_LOG(WARN, "allocate memory fail.", KR(ret), KP(this), K(tablet_id_)); } else {