fix the overflow check of AObject
This commit is contained in:
		
							
								
								
									
										1
									
								
								deps/oblib/src/lib/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								deps/oblib/src/lib/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							@ -319,7 +319,6 @@ ob_set_subtarget(ob_malloc_object_list common_alloc
 | 
				
			|||||||
  alloc/alloc_struct.cpp
 | 
					  alloc/alloc_struct.cpp
 | 
				
			||||||
  alloc/block_set.cpp
 | 
					  alloc/block_set.cpp
 | 
				
			||||||
  alloc/memory_dump.cpp
 | 
					  alloc/memory_dump.cpp
 | 
				
			||||||
  alloc/ob_free_log_printer.cpp
 | 
					 | 
				
			||||||
  alloc/ob_malloc_allocator.cpp
 | 
					  alloc/ob_malloc_allocator.cpp
 | 
				
			||||||
  alloc/ob_malloc_callback.cpp
 | 
					  alloc/ob_malloc_callback.cpp
 | 
				
			||||||
  alloc/ob_malloc_sample_struct.cpp
 | 
					  alloc/ob_malloc_sample_struct.cpp
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								deps/oblib/src/lib/alloc/alloc_struct.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								deps/oblib/src/lib/alloc/alloc_struct.h
									
									
									
									
										vendored
									
									
								
							@ -150,13 +150,14 @@ struct ObMemAttr
 | 
				
			|||||||
        prio_(prio),
 | 
					        prio_(prio),
 | 
				
			||||||
        use_500_(false),
 | 
					        use_500_(false),
 | 
				
			||||||
        expect_500_(true),
 | 
					        expect_500_(true),
 | 
				
			||||||
        ignore_version_(ObMemVersionNode::tl_ignore_node)
 | 
					        ignore_version_(ObMemVersionNode::tl_ignore_node),
 | 
				
			||||||
 | 
					        alloc_extra_info_(false)
 | 
				
			||||||
  {}
 | 
					  {}
 | 
				
			||||||
  int64_t to_string(char* buf, const int64_t buf_len) const;
 | 
					  int64_t to_string(char* buf, const int64_t buf_len) const;
 | 
				
			||||||
  bool use_500() const { return use_500_; }
 | 
					  bool use_500() const { return use_500_; }
 | 
				
			||||||
  bool expect_500() const { return expect_500_; }
 | 
					  bool expect_500() const { return expect_500_; }
 | 
				
			||||||
  bool ignore_version() const { return ignore_version_; }
 | 
					  bool ignore_version() const { return ignore_version_; }
 | 
				
			||||||
private:
 | 
					public:
 | 
				
			||||||
  union {
 | 
					  union {
 | 
				
			||||||
    char padding__[4];
 | 
					    char padding__[4];
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
@ -164,6 +165,7 @@ private:
 | 
				
			|||||||
        uint8_t use_500_ : 1;
 | 
					        uint8_t use_500_ : 1;
 | 
				
			||||||
        uint8_t expect_500_ : 1;
 | 
					        uint8_t expect_500_ : 1;
 | 
				
			||||||
        uint8_t ignore_version_ : 1;
 | 
					        uint8_t ignore_version_ : 1;
 | 
				
			||||||
 | 
					        uint8_t alloc_extra_info_ : 1;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@ -300,6 +302,7 @@ struct AObject {
 | 
				
			|||||||
  OB_INLINE ABlock *block() const;
 | 
					  OB_INLINE ABlock *block() const;
 | 
				
			||||||
  OB_INLINE uint64_t hold(uint32_t cells_per_block) const;
 | 
					  OB_INLINE uint64_t hold(uint32_t cells_per_block) const;
 | 
				
			||||||
  OB_INLINE ObLabel label() const;
 | 
					  OB_INLINE ObLabel label() const;
 | 
				
			||||||
 | 
					  OB_INLINE char *bt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // members
 | 
					  // members
 | 
				
			||||||
  union {
 | 
					  union {
 | 
				
			||||||
@ -357,6 +360,7 @@ static const uint32_t INTACT_MIDDLE_AOBJECT_SIZE = 64L << 10;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const int32_t AOBJECT_BACKTRACE_COUNT = 16;
 | 
					static const int32_t AOBJECT_BACKTRACE_COUNT = 16;
 | 
				
			||||||
static const int32_t AOBJECT_BACKTRACE_SIZE = sizeof(void*) * AOBJECT_BACKTRACE_COUNT;
 | 
					static const int32_t AOBJECT_BACKTRACE_SIZE = sizeof(void*) * AOBJECT_BACKTRACE_COUNT;
 | 
				
			||||||
 | 
					static const int32_t AOBJECT_EXTRA_INFO_SIZE = AOBJECT_BACKTRACE_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const int32_t MAX_BACKTRACE_LENGTH = 512;
 | 
					static const int32_t MAX_BACKTRACE_LENGTH = 512;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -614,6 +618,10 @@ ObLabel AObject::label() const
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  return ObLabel(label_);
 | 
					  return ObLabel(label_);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					char *AObject::bt()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return &data_[alloc_bytes_ + AOBJECT_TAIL_SIZE];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Label
 | 
					class Label
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								deps/oblib/src/lib/alloc/memory_dump.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								deps/oblib/src/lib/alloc/memory_dump.cpp
									
									
									
									
										vendored
									
									
								
							@ -431,12 +431,11 @@ int label_stat(AChunk *chunk, ABlock *block, AObject *object,
 | 
				
			|||||||
    LabelItem *litem = nullptr;
 | 
					    LabelItem *litem = nullptr;
 | 
				
			||||||
    auto key = std::make_pair(*(uint64_t*)object->label_, *((uint64_t*)object->label_ + 1));
 | 
					    auto key = std::make_pair(*(uint64_t*)object->label_, *((uint64_t*)object->label_ + 1));
 | 
				
			||||||
    LabelInfoItem *linfoitem = lmap.get(key);
 | 
					    LabelInfoItem *linfoitem = lmap.get(key);
 | 
				
			||||||
    int64_t bt_size = object->on_malloc_sample_ ? AOBJECT_BACKTRACE_SIZE : 0;
 | 
					 | 
				
			||||||
    if (NULL != linfoitem) {
 | 
					    if (NULL != linfoitem) {
 | 
				
			||||||
      // exist
 | 
					      // exist
 | 
				
			||||||
      litem = linfoitem->litem_;
 | 
					      litem = linfoitem->litem_;
 | 
				
			||||||
      litem->hold_ += hold;
 | 
					      litem->hold_ += hold;
 | 
				
			||||||
      litem->used_ += (object->alloc_bytes_ - bt_size);
 | 
					      litem->used_ += object->alloc_bytes_;
 | 
				
			||||||
      litem->count_++;
 | 
					      litem->count_++;
 | 
				
			||||||
      if (chunk != linfoitem->chunk_) {
 | 
					      if (chunk != linfoitem->chunk_) {
 | 
				
			||||||
        litem->chunk_cnt_ += 1;
 | 
					        litem->chunk_cnt_ += 1;
 | 
				
			||||||
@ -456,7 +455,7 @@ int label_stat(AChunk *chunk, ABlock *block, AObject *object,
 | 
				
			|||||||
        litem->str_[sizeof(litem->str_) - 1] = '\0';
 | 
					        litem->str_[sizeof(litem->str_) - 1] = '\0';
 | 
				
			||||||
        litem->str_len_ = strlen(litem->str_);
 | 
					        litem->str_len_ = strlen(litem->str_);
 | 
				
			||||||
        litem->hold_ = hold;
 | 
					        litem->hold_ = hold;
 | 
				
			||||||
        litem->used_ = (object->alloc_bytes_ - bt_size);
 | 
					        litem->used_ = object->alloc_bytes_;
 | 
				
			||||||
        litem->count_ = 1;
 | 
					        litem->count_ = 1;
 | 
				
			||||||
        litem->block_cnt_ = 1;
 | 
					        litem->block_cnt_ = 1;
 | 
				
			||||||
        litem->chunk_cnt_ = 1;
 | 
					        litem->chunk_cnt_ = 1;
 | 
				
			||||||
@ -473,20 +472,19 @@ int malloc_sample_stat(uint64_t tenant_id, uint64_t ctx_id,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  int ret = OB_SUCCESS;
 | 
					  int ret = OB_SUCCESS;
 | 
				
			||||||
  if (object->in_use_ && object->on_malloc_sample_) {
 | 
					  if (object->in_use_ && object->on_malloc_sample_) {
 | 
				
			||||||
    int64_t offset = object->alloc_bytes_ - AOBJECT_BACKTRACE_SIZE;
 | 
					 | 
				
			||||||
    ObMallocSampleKey key;
 | 
					    ObMallocSampleKey key;
 | 
				
			||||||
    key.tenant_id_ = tenant_id;
 | 
					    key.tenant_id_ = tenant_id;
 | 
				
			||||||
    key.ctx_id_ = ctx_id;
 | 
					    key.ctx_id_ = ctx_id;
 | 
				
			||||||
    MEMCPY((char*)key.bt_, &object->data_[offset], AOBJECT_BACKTRACE_SIZE);
 | 
					    MEMCPY((char*)key.bt_, object->bt(), AOBJECT_BACKTRACE_SIZE);
 | 
				
			||||||
    STRNCPY(key.label_, object->label_, sizeof(key.label_));
 | 
					    STRNCPY(key.label_, object->label_, sizeof(key.label_));
 | 
				
			||||||
    key.label_[sizeof(key.label_) - 1] = '\0';
 | 
					    key.label_[sizeof(key.label_) - 1] = '\0';
 | 
				
			||||||
    ObMallocSampleValue *item = malloc_sample_map.get(key);
 | 
					    ObMallocSampleValue *item = malloc_sample_map.get(key);
 | 
				
			||||||
    if (NULL != item) {
 | 
					    if (NULL != item) {
 | 
				
			||||||
      item->alloc_count_ += 1;
 | 
					      item->alloc_count_ += 1;
 | 
				
			||||||
      item->alloc_bytes_ += offset;
 | 
					      item->alloc_bytes_ += object->alloc_bytes_;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      ObSignalHandlerGuard guard(ob_signal_handler);
 | 
					      ObSignalHandlerGuard guard(ob_signal_handler);
 | 
				
			||||||
      ret = malloc_sample_map.set_refactored(key, ObMallocSampleValue(1, offset));
 | 
					      ret = malloc_sample_map.set_refactored(key, ObMallocSampleValue(1, object->alloc_bytes_));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return ret;
 | 
					  return ret;
 | 
				
			||||||
@ -572,7 +570,7 @@ void ObMemoryDump::handle(void *task)
 | 
				
			|||||||
                        has_memory_leak = true;
 | 
					                        has_memory_leak = true;
 | 
				
			||||||
                        char bt[MAX_BACKTRACE_LENGTH] = {'\0'};
 | 
					                        char bt[MAX_BACKTRACE_LENGTH] = {'\0'};
 | 
				
			||||||
                        if (object->on_malloc_sample_) {
 | 
					                        if (object->on_malloc_sample_) {
 | 
				
			||||||
                          parray(bt, sizeof(bt), (int64_t*)&object->data_[object->alloc_bytes_ - AOBJECT_BACKTRACE_SIZE], AOBJECT_BACKTRACE_COUNT);
 | 
					                          parray(bt, sizeof(bt), (int64_t*)object->bt(), AOBJECT_BACKTRACE_COUNT);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        allow_next_syslog();
 | 
					                        allow_next_syslog();
 | 
				
			||||||
                        LOG_WARN("SQL_MEMORY_LEAK", KP(object), K(tenant_id), K(ctx_id), K(object->version_), K(object->label_), K(bt));
 | 
					                        LOG_WARN("SQL_MEMORY_LEAK", KP(object), K(tenant_id), K(ctx_id), K(object->version_), K(object->label_), K(bt));
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										118
									
								
								deps/oblib/src/lib/alloc/ob_free_log_printer.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										118
									
								
								deps/oblib/src/lib/alloc/ob_free_log_printer.cpp
									
									
									
									
										vendored
									
									
								
							@ -1,118 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * 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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "lib/alloc/ob_free_log_printer.h"
 | 
					 | 
				
			||||||
#include "lib/alloc/alloc_struct.h"
 | 
					 | 
				
			||||||
#include "lib/alloc/ob_malloc_sample_struct.h"
 | 
					 | 
				
			||||||
#include "lib/time/ob_time_utility.h"
 | 
					 | 
				
			||||||
#include "lib/utility/utility.h"
 | 
					 | 
				
			||||||
using namespace oceanbase::lib;
 | 
					 | 
				
			||||||
using namespace oceanbase::common;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ObFreeLogPrinter::ObFreeLogPrinter() : level_(DEFAULT), lock_()
 | 
					 | 
				
			||||||
{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ObFreeLogPrinter& ObFreeLogPrinter::get_instance()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  static ObFreeLogPrinter free_log_print;
 | 
					 | 
				
			||||||
  return free_log_print;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int ObFreeLogPrinter::get_level()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  int ret = DEFAULT;
 | 
					 | 
				
			||||||
  int reason = g_alloc_failed_ctx().reason_;
 | 
					 | 
				
			||||||
  switch (reason) {
 | 
					 | 
				
			||||||
  case CTX_HOLD_REACH_LIMIT : {
 | 
					 | 
				
			||||||
      ret = CTX;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  case TENANT_HOLD_REACH_LIMIT: {
 | 
					 | 
				
			||||||
      ret = TENANT;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  case SERVER_HOLD_REACH_LIMIT: {
 | 
					 | 
				
			||||||
      ret = SERVER;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  case PHYSICAL_MEMORY_EXHAUST: {
 | 
					 | 
				
			||||||
      ret = SERVER;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ObFreeLogPrinter::enable_free_log(int64_t tenant_id, int64_t ctx_id, int level)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool has_lock = false;
 | 
					 | 
				
			||||||
  if (DEFAULT == level_ && OB_SUCCESS == lock_.trylock()) {
 | 
					 | 
				
			||||||
    DEFER(lock_.unlock());
 | 
					 | 
				
			||||||
    last_enable_time_ = ObTimeUtility::current_time();
 | 
					 | 
				
			||||||
    tenant_id_ = tenant_id;
 | 
					 | 
				
			||||||
    ctx_id_ = ctx_id;
 | 
					 | 
				
			||||||
    level_ = level;
 | 
					 | 
				
			||||||
    has_lock = true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (has_lock) {
 | 
					 | 
				
			||||||
    _OB_LOG(INFO, "start to print free log");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ObFreeLogPrinter::disable_free_log()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool has_lock = false;
 | 
					 | 
				
			||||||
  if (DEFAULT != level_ && OB_SUCCESS == lock_.trylock()) {
 | 
					 | 
				
			||||||
    DEFER(lock_.unlock());
 | 
					 | 
				
			||||||
    level_ = DEFAULT;
 | 
					 | 
				
			||||||
    has_lock = true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (has_lock) {
 | 
					 | 
				
			||||||
    _OB_LOG(INFO, "finish to print free log");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ObFreeLogPrinter::print_free_log(int64_t tenant_id, int64_t ctx_id, AObject *obj)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (DEFAULT != level_ && obj->on_malloc_sample_) {
 | 
					 | 
				
			||||||
    if (ObTimeUtility::current_time() - last_enable_time_ > MAX_FREE_LOG_TIME) {
 | 
					 | 
				
			||||||
      disable_free_log();
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      bool allowed = false;
 | 
					 | 
				
			||||||
      switch (level_) {
 | 
					 | 
				
			||||||
        case CTX: {
 | 
					 | 
				
			||||||
          allowed = tenant_id == tenant_id_ && ctx_id == ctx_id_;
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        case TENANT: {
 | 
					 | 
				
			||||||
          allowed = tenant_id == tenant_id_;
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        case SERVER: {
 | 
					 | 
				
			||||||
          allowed = true;
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (allowed) {
 | 
					 | 
				
			||||||
        char buf[MAX_BACKTRACE_LENGTH];
 | 
					 | 
				
			||||||
        int64_t addrs[AOBJECT_BACKTRACE_COUNT];
 | 
					 | 
				
			||||||
        int64_t offset = obj->alloc_bytes_ - AOBJECT_BACKTRACE_SIZE;
 | 
					 | 
				
			||||||
        MEMCPY((char*)addrs, &obj->data_[offset], sizeof(addrs));
 | 
					 | 
				
			||||||
        IGNORE_RETURN parray(buf, sizeof(buf), addrs, ARRAYSIZEOF(addrs));
 | 
					 | 
				
			||||||
        allow_next_syslog();
 | 
					 | 
				
			||||||
        _OB_LOG(INFO, "[MEM_FREE_LOG] tenant_id=%ld, ctx_name=%s, mod=%s, alloc_bytes=%u, malloc_bt=%s\n",
 | 
					 | 
				
			||||||
                tenant_id, get_global_ctx_info().get_ctx_name(ctx_id),
 | 
					 | 
				
			||||||
                obj->label_, obj->alloc_bytes_, buf);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										48
									
								
								deps/oblib/src/lib/alloc/ob_free_log_printer.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								deps/oblib/src/lib/alloc/ob_free_log_printer.h
									
									
									
									
										vendored
									
									
								
							@ -1,48 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * 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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef _OB_FREE_LOG_PRINTER_H_
 | 
					 | 
				
			||||||
#define _OB_FREE_LOG_PRINTER_H_
 | 
					 | 
				
			||||||
#include "lib/lock/ob_mutex.h"
 | 
					 | 
				
			||||||
namespace oceanbase
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
namespace lib
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
class AObject;
 | 
					 | 
				
			||||||
class ObFreeLogPrinter
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  const int64_t MAX_FREE_LOG_TIME = 30 * 1000 * 1000; //30s
 | 
					 | 
				
			||||||
  enum Level
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    DEFAULT = 0,
 | 
					 | 
				
			||||||
    CTX = 1,
 | 
					 | 
				
			||||||
    TENANT = 2,
 | 
					 | 
				
			||||||
    SERVER = 3,
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  ObFreeLogPrinter();
 | 
					 | 
				
			||||||
  static ObFreeLogPrinter& get_instance();
 | 
					 | 
				
			||||||
  static int get_level();
 | 
					 | 
				
			||||||
  void enable_free_log(int64_t tenant_id , int64_t ctx_id, int level);
 | 
					 | 
				
			||||||
  void disable_free_log();
 | 
					 | 
				
			||||||
  void print_free_log(int64_t tenant_id, int64_t ctx_id, AObject *obj);
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  int64_t last_enable_time_;
 | 
					 | 
				
			||||||
  int64_t tenant_id_;
 | 
					 | 
				
			||||||
  int64_t ctx_id_;
 | 
					 | 
				
			||||||
  int level_;
 | 
					 | 
				
			||||||
  ObMutex lock_;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@ -159,15 +159,6 @@ inline bool ObMallocSampleKey::operator==(const ObMallocSampleKey &other) const
 | 
				
			|||||||
  return ret;
 | 
					  return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ob_malloc_sample_backtrace(obj, size)                                                                  \
 | 
					 | 
				
			||||||
  {                                                                                                            \
 | 
					 | 
				
			||||||
    if (OB_UNLIKELY(obj->on_malloc_sample_)) {                                                                 \
 | 
					 | 
				
			||||||
      void *addrs[100] = {nullptr};                                                                            \
 | 
					 | 
				
			||||||
      int bt_len = ob_backtrace(addrs, ARRAYSIZEOF(addrs));                                                    \
 | 
					 | 
				
			||||||
      STATIC_ASSERT(AOBJECT_BACKTRACE_SIZE < sizeof(addrs), "AOBJECT_BACKTRACE_SIZE must be less than addrs!");\
 | 
					 | 
				
			||||||
      MEMCPY(&obj->data_[size], (char*)addrs, AOBJECT_BACKTRACE_SIZE);                                         \
 | 
					 | 
				
			||||||
    }                                                                                                          \
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
} // end of namespace lib
 | 
					} // end of namespace lib
 | 
				
			||||||
} // end of namespace oceanbase
 | 
					} // end of namespace oceanbase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -413,7 +413,6 @@ void* ObTenantCtxAllocator::common_realloc(const void *ptr, const int64_t size,
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  AObject *obj = NULL;
 | 
					  AObject *obj = NULL;
 | 
				
			||||||
  int64_t alloc_size = 0;
 | 
					 | 
				
			||||||
  bool sample_allowed = false;
 | 
					  bool sample_allowed = false;
 | 
				
			||||||
  bool is_errsim = false;
 | 
					  bool is_errsim = false;
 | 
				
			||||||
  if (NULL != ptr) {
 | 
					  if (NULL != ptr) {
 | 
				
			||||||
@ -436,13 +435,14 @@ void* ObTenantCtxAllocator::common_realloc(const void *ptr, const int64_t size,
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
  ObLightBacktraceGuard light_backtrace_guard(is_memleak_light_backtrace_enabled()
 | 
					  ObLightBacktraceGuard light_backtrace_guard(is_memleak_light_backtrace_enabled()
 | 
				
			||||||
      && ObCtxIds::GLIBC != attr.ctx_id_);
 | 
					      && ObCtxIds::GLIBC != attr.ctx_id_);
 | 
				
			||||||
 | 
					  ObMemAttr inner_attr = attr;
 | 
				
			||||||
  if (OB_UNLIKELY(is_errsim)) {
 | 
					  if (OB_UNLIKELY(is_errsim)) {
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    BASIC_TIME_GUARD(time_guard, "ObMalloc");
 | 
					    BASIC_TIME_GUARD(time_guard, "ObMalloc");
 | 
				
			||||||
    DEFER(ObMallocTimeMonitor::get_instance().record_malloc_time(time_guard, size, attr));
 | 
					    DEFER(ObMallocTimeMonitor::get_instance().record_malloc_time(time_guard, size, inner_attr));
 | 
				
			||||||
    sample_allowed = ObMallocSampleLimiter::malloc_sample_allowed(size, attr);
 | 
					    sample_allowed = ObMallocSampleLimiter::malloc_sample_allowed(size, inner_attr);
 | 
				
			||||||
    alloc_size = sample_allowed ? (size + AOBJECT_BACKTRACE_SIZE) : size;
 | 
					    inner_attr.alloc_extra_info_ = sample_allowed;
 | 
				
			||||||
    obj = allocator.realloc_object(obj, alloc_size, attr);
 | 
					    obj = allocator.realloc_object(obj, size, inner_attr);
 | 
				
			||||||
    if(OB_ISNULL(obj)) {
 | 
					    if(OB_ISNULL(obj)) {
 | 
				
			||||||
      int64_t total_size = 0;
 | 
					      int64_t total_size = 0;
 | 
				
			||||||
      if (g_alloc_failed_ctx().need_wash_block()) {
 | 
					      if (g_alloc_failed_ctx().need_wash_block()) {
 | 
				
			||||||
@ -453,31 +453,40 @@ void* ObTenantCtxAllocator::common_realloc(const void *ptr, const int64_t size,
 | 
				
			|||||||
        BASIC_TIME_GUARD_CLICK("WASH_CHUNK_END");
 | 
					        BASIC_TIME_GUARD_CLICK("WASH_CHUNK_END");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (total_size > 0) {
 | 
					      if (total_size > 0) {
 | 
				
			||||||
        obj = allocator.realloc_object(obj, alloc_size, attr);
 | 
					        obj = allocator.realloc_object(obj, size, inner_attr);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (obj != NULL) {
 | 
					  if (obj != NULL) {
 | 
				
			||||||
    obj->on_malloc_sample_ = sample_allowed;
 | 
					    if (inner_attr.label_.str_ != nullptr) {
 | 
				
			||||||
    ob_malloc_sample_backtrace(obj, size);
 | 
					      STRNCPY(obj->label_, inner_attr.label_.str_, sizeof(obj->label_));
 | 
				
			||||||
    obj->ignore_version_ = attr.ignore_version() || ObMemVersionNode::tl_ignore_node;
 | 
					      obj->label_[sizeof(obj->label_) - 1] = '\0';
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      MEMSET(obj->label_, '\0', sizeof(obj->label_));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (sample_allowed) {
 | 
				
			||||||
 | 
					      void *addrs[100] = {nullptr};
 | 
				
			||||||
 | 
					      ob_backtrace(addrs, ARRAYSIZEOF(addrs));
 | 
				
			||||||
 | 
					      STATIC_ASSERT(AOBJECT_BACKTRACE_SIZE < sizeof(addrs), "AOBJECT_BACKTRACE_SIZE must be less than addrs!");
 | 
				
			||||||
 | 
					      MEMCPY(obj->bt(), (char*)addrs, AOBJECT_BACKTRACE_SIZE);
 | 
				
			||||||
 | 
					      obj->on_malloc_sample_ = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    obj->ignore_version_ = inner_attr.ignore_version() || ObMemVersionNode::tl_ignore_node;
 | 
				
			||||||
    if (!obj->ignore_version_) {
 | 
					    if (!obj->ignore_version_) {
 | 
				
			||||||
      obj->version_ = ObMemVersionNode::tl_node->version_;
 | 
					      obj->version_ = ObMemVersionNode::tl_node->version_;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    nptr = obj->data_;
 | 
					    nptr = obj->data_;
 | 
				
			||||||
    get_mem_leak_checker().on_alloc(*obj, attr);
 | 
					    get_mem_leak_checker().on_alloc(*obj, inner_attr);
 | 
				
			||||||
    SANITY_POISON(obj, AOBJECT_HEADER_SIZE);
 | 
					    SANITY_POISON(obj, obj->nobjs_ * AOBJECT_CELL_BYTES);
 | 
				
			||||||
    SANITY_UNPOISON(obj->data_, size);
 | 
					    SANITY_UNPOISON(obj->data_, size);
 | 
				
			||||||
    SANITY_POISON((void*)upper_align((int64_t)obj->data_ + size, 8),
 | 
					 | 
				
			||||||
                                     alloc_size - size + sizeof(AOBJECT_TAIL_MAGIC_CODE));
 | 
					 | 
				
			||||||
  } else if (TC_REACH_TIME_INTERVAL(1 * 1000 * 1000)) {
 | 
					  } else if (TC_REACH_TIME_INTERVAL(1 * 1000 * 1000)) {
 | 
				
			||||||
    const char *msg = is_errsim ? "[ERRSIM] errsim inject memory error" : alloc_failed_msg();
 | 
					    const char *msg = is_errsim ? "[ERRSIM] errsim inject memory error" : alloc_failed_msg();
 | 
				
			||||||
    LOG_DBA_WARN(OB_ALLOCATE_MEMORY_FAILED, "[OOPS]", "alloc failed reason", KCSTRING(msg));
 | 
					    LOG_DBA_WARN(OB_ALLOCATE_MEMORY_FAILED, "[OOPS]", "alloc failed reason", KCSTRING(msg));
 | 
				
			||||||
    _OB_LOG_RET(WARN, OB_ALLOCATE_MEMORY_FAILED, "oops, alloc failed, tenant_id=%ld, ctx_id=%ld, ctx_name=%s, ctx_hold=%ld, "
 | 
					    _OB_LOG_RET(WARN, OB_ALLOCATE_MEMORY_FAILED, "oops, alloc failed, tenant_id=%ld, ctx_id=%ld, ctx_name=%s, ctx_hold=%ld, "
 | 
				
			||||||
                "ctx_limit=%ld, tenant_hold=%ld, tenant_limit=%ld",
 | 
					                "ctx_limit=%ld, tenant_hold=%ld, tenant_limit=%ld",
 | 
				
			||||||
                attr.tenant_id_, attr.ctx_id_,
 | 
					                inner_attr.tenant_id_, inner_attr.ctx_id_,
 | 
				
			||||||
                get_global_ctx_info().get_ctx_name(attr.ctx_id_),
 | 
					                get_global_ctx_info().get_ctx_name(inner_attr.ctx_id_),
 | 
				
			||||||
                ta.get_hold(), ta.get_limit(), ta.get_tenant_hold(), ta.get_tenant_limit());
 | 
					                ta.get_hold(), ta.get_limit(), ta.get_tenant_hold(), ta.get_tenant_limit());
 | 
				
			||||||
    // 49 is the user defined signal to dump memory
 | 
					    // 49 is the user defined signal to dump memory
 | 
				
			||||||
    raise(49);
 | 
					    raise(49);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								deps/oblib/src/lib/alloc/object_mgr.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								deps/oblib/src/lib/alloc/object_mgr.cpp
									
									
									
									
										vendored
									
									
								
							@ -14,6 +14,7 @@
 | 
				
			|||||||
#include "lib/allocator/ob_ctx_define.h"
 | 
					#include "lib/allocator/ob_ctx_define.h"
 | 
				
			||||||
#include "lib/alloc/ob_malloc_allocator.h"
 | 
					#include "lib/alloc/ob_malloc_allocator.h"
 | 
				
			||||||
#include "lib/alloc/memory_sanity.h"
 | 
					#include "lib/alloc/memory_sanity.h"
 | 
				
			||||||
 | 
					#include "lib/alloc/ob_tenant_ctx_allocator.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace oceanbase;
 | 
					using namespace oceanbase;
 | 
				
			||||||
using namespace lib;
 | 
					using namespace lib;
 | 
				
			||||||
@ -243,15 +244,13 @@ SubObjectMgr *ObjectMgr::create_sub_mgr()
 | 
				
			|||||||
  attr.tenant_id_ = OB_SERVER_TENANT_ID;
 | 
					  attr.tenant_id_ = OB_SERVER_TENANT_ID;
 | 
				
			||||||
  attr.label_ = common::ObModIds::OB_TENANT_CTX_ALLOCATOR;
 | 
					  attr.label_ = common::ObModIds::OB_TENANT_CTX_ALLOCATOR;
 | 
				
			||||||
  attr.ctx_id_ = ObCtxIds::DEFAULT_CTX_ID;
 | 
					  attr.ctx_id_ = ObCtxIds::DEFAULT_CTX_ID;
 | 
				
			||||||
 | 
					  attr.ignore_version_ = true;
 | 
				
			||||||
  root_mgr.lock();
 | 
					  root_mgr.lock();
 | 
				
			||||||
  auto *obj = root_mgr.alloc_object(sizeof(SubObjectMgr), attr);
 | 
					  void *ptr = ObTenantCtxAllocator::common_realloc(NULL, sizeof(SubObjectMgr), attr, *(ta.ref_allocator()), root_mgr);
 | 
				
			||||||
  root_mgr.unlock();
 | 
					  root_mgr.unlock();
 | 
				
			||||||
  if (OB_NOT_NULL(obj)) {
 | 
					  if (OB_NOT_NULL(ptr)) {
 | 
				
			||||||
    obj->ignore_version_ = true;
 | 
					    sub_mgr = new (ptr) SubObjectMgr(ta_, enable_no_log_,
 | 
				
			||||||
    SANITY_UNPOISON(obj->data_, obj->alloc_bytes_);
 | 
					        ablock_size_, enable_dirty_list_, blk_mgr_);
 | 
				
			||||||
    sub_mgr = new (obj->data_) SubObjectMgr(ta_,
 | 
					 | 
				
			||||||
                                            enable_no_log_,
 | 
					 | 
				
			||||||
                                            ablock_size_, enable_dirty_list_, blk_mgr_);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return sub_mgr;
 | 
					  return sub_mgr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -263,11 +262,7 @@ void ObjectMgr::destroy_sub_mgr(SubObjectMgr *sub_mgr)
 | 
				
			|||||||
                                                                          ObCtxIds::DEFAULT_CTX_ID);
 | 
					                                                                          ObCtxIds::DEFAULT_CTX_ID);
 | 
				
			||||||
    auto &root_mgr = static_cast<ObjectMgr&>(ta->get_block_mgr()).root_mgr_;
 | 
					    auto &root_mgr = static_cast<ObjectMgr&>(ta->get_block_mgr()).root_mgr_;
 | 
				
			||||||
    sub_mgr->~SubObjectMgr();
 | 
					    sub_mgr->~SubObjectMgr();
 | 
				
			||||||
    auto *obj = reinterpret_cast<AObject*>((char*)sub_mgr - AOBJECT_HEADER_SIZE);
 | 
					    ObTenantCtxAllocator::common_free(sub_mgr);
 | 
				
			||||||
    abort_unless(obj->MAGIC_CODE_ == AOBJECT_MAGIC_CODE
 | 
					 | 
				
			||||||
                 || obj->MAGIC_CODE_ == BIG_AOBJECT_MAGIC_CODE);
 | 
					 | 
				
			||||||
    SANITY_POISON(obj->data_, obj->alloc_bytes_);
 | 
					 | 
				
			||||||
    root_mgr.free_object(obj);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								deps/oblib/src/lib/alloc/object_mgr.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								deps/oblib/src/lib/alloc/object_mgr.h
									
									
									
									
										vendored
									
									
								
							@ -49,6 +49,10 @@ public:
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    return os_.alloc_object(size, attr);
 | 
					    return os_.alloc_object(size, attr);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  OB_INLINE AObject *realloc_object(AObject *obj,  const uint64_t size, const ObMemAttr &attr)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    return os_.realloc_object(obj, size, attr);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  void free_object(AObject *object);
 | 
					  void free_object(AObject *object);
 | 
				
			||||||
  OB_INLINE ABlock *alloc_block(uint64_t size, const ObMemAttr &attr) override
 | 
					  OB_INLINE ABlock *alloc_block(uint64_t size, const ObMemAttr &attr) override
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								deps/oblib/src/lib/alloc/object_set.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								deps/oblib/src/lib/alloc/object_set.cpp
									
									
									
									
										vendored
									
									
								
							@ -55,7 +55,8 @@ AObject *ObjectSet::alloc_object(
 | 
				
			|||||||
    const uint64_t size, const ObMemAttr &attr)
 | 
					    const uint64_t size, const ObMemAttr &attr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const uint64_t adj_size = MAX(size, MIN_AOBJECT_SIZE);
 | 
					  const uint64_t adj_size = MAX(size, MIN_AOBJECT_SIZE);
 | 
				
			||||||
  const uint64_t all_size = align_up2(adj_size + AOBJECT_META_SIZE, 16);
 | 
					  const uint64_t meta_size = AOBJECT_META_SIZE + (attr.alloc_extra_info_ ? AOBJECT_EXTRA_INFO_SIZE : 0);
 | 
				
			||||||
 | 
					  const uint64_t all_size = align_up2(adj_size + meta_size, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const int64_t ctx_id = blk_mgr_->get_ctx_id();
 | 
					  const int64_t ctx_id = blk_mgr_->get_ctx_id();
 | 
				
			||||||
  abort_unless(ctx_id == attr.ctx_id_);
 | 
					  abort_unless(ctx_id == attr.ctx_id_);
 | 
				
			||||||
@ -77,7 +78,7 @@ AObject *ObjectSet::alloc_object(
 | 
				
			|||||||
      normal_used_bytes_ += obj->nobjs_ * AOBJECT_CELL_BYTES;
 | 
					      normal_used_bytes_ += obj->nobjs_ * AOBJECT_CELL_BYTES;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    obj = alloc_big_object(adj_size, attr);
 | 
					    obj = alloc_big_object(all_size, attr);
 | 
				
			||||||
    abort_unless(NULL == obj || obj->in_use_);
 | 
					    abort_unless(NULL == obj || obj->in_use_);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -86,12 +87,6 @@ AObject *ObjectSet::alloc_object(
 | 
				
			|||||||
    abort_unless(obj->is_valid());
 | 
					    abort_unless(obj->is_valid());
 | 
				
			||||||
    reinterpret_cast<uint64_t&>(obj->data_[size]) = AOBJECT_TAIL_MAGIC_CODE;
 | 
					    reinterpret_cast<uint64_t&>(obj->data_[size]) = AOBJECT_TAIL_MAGIC_CODE;
 | 
				
			||||||
    obj->alloc_bytes_ = static_cast<uint32_t>(size);
 | 
					    obj->alloc_bytes_ = static_cast<uint32_t>(size);
 | 
				
			||||||
    if (attr.label_.str_ != nullptr) {
 | 
					 | 
				
			||||||
      STRNCPY(&obj->label_[0], attr.label_.str_, sizeof(obj->label_));
 | 
					 | 
				
			||||||
      obj->label_[sizeof(obj->label_) - 1] = '\0';
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      MEMSET(obj->label_, '\0', sizeof(obj->label_));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    allocs_++;
 | 
					    allocs_++;
 | 
				
			||||||
    alloc_bytes_ += size;
 | 
					    alloc_bytes_ += size;
 | 
				
			||||||
    used_bytes_ += obj->hold(cells_per_block_);
 | 
					    used_bytes_ += obj->hold(cells_per_block_);
 | 
				
			||||||
@ -104,19 +99,12 @@ AObject *ObjectSet::realloc_object(
 | 
				
			|||||||
    AObject *obj, const uint64_t size, const ObMemAttr &attr)
 | 
					    AObject *obj, const uint64_t size, const ObMemAttr &attr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  AObject *new_obj = NULL;
 | 
					  AObject *new_obj = NULL;
 | 
				
			||||||
  uint64_t copy_size = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (NULL == obj) {
 | 
					  if (NULL == obj) {
 | 
				
			||||||
    new_obj = alloc_object(size, attr);
 | 
					    new_obj = alloc_object(size, attr);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    abort_unless(obj->is_valid());
 | 
					    abort_unless(obj->is_valid());
 | 
				
			||||||
    if (obj->is_large_ != 0) {
 | 
					    uint64_t copy_size = MIN(obj->alloc_bytes_, size);
 | 
				
			||||||
      copy_size = MIN(obj->alloc_bytes_, size);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      copy_size = MIN(
 | 
					 | 
				
			||||||
          size, (obj->nobjs_ - META_CELLS) * AOBJECT_CELL_BYTES);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    new_obj = alloc_object(size, attr);
 | 
					    new_obj = alloc_object(size, attr);
 | 
				
			||||||
    if (NULL != new_obj && copy_size != 0) {
 | 
					    if (NULL != new_obj && copy_size != 0) {
 | 
				
			||||||
      memmove(new_obj->data_, obj->data_, copy_size);
 | 
					      memmove(new_obj->data_, obj->data_, copy_size);
 | 
				
			||||||
@ -336,13 +324,12 @@ void ObjectSet::free_block(ABlock *block)
 | 
				
			|||||||
AObject *ObjectSet::alloc_big_object(const uint64_t size, const ObMemAttr &attr)
 | 
					AObject *ObjectSet::alloc_big_object(const uint64_t size, const ObMemAttr &attr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  AObject *obj = NULL;
 | 
					  AObject *obj = NULL;
 | 
				
			||||||
  ABlock *block = alloc_block(size + AOBJECT_META_SIZE, attr);
 | 
					  ABlock *block = alloc_block(size, attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (NULL != block) {
 | 
					  if (NULL != block) {
 | 
				
			||||||
    obj = new (block->data()) AObject();
 | 
					    obj = new (block->data()) AObject();
 | 
				
			||||||
    obj->is_large_ = true;
 | 
					    obj->is_large_ = true;
 | 
				
			||||||
    obj->in_use_ = true;
 | 
					    obj->in_use_ = true;
 | 
				
			||||||
    obj->alloc_bytes_ = static_cast<uint32_t>(size);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return obj;
 | 
					  return obj;
 | 
				
			||||||
@ -491,8 +478,7 @@ bool ObjectSet::check_has_unfree(char *first_label, char *first_bt)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            if (obj->on_malloc_sample_ && '\0' == first_bt[0]) {
 | 
					            if (obj->on_malloc_sample_ && '\0' == first_bt[0]) {
 | 
				
			||||||
              void *addrs[AOBJECT_BACKTRACE_COUNT];
 | 
					              void *addrs[AOBJECT_BACKTRACE_COUNT];
 | 
				
			||||||
              int64_t offset = obj->alloc_bytes_ - AOBJECT_BACKTRACE_SIZE;
 | 
					              MEMCPY((char*)addrs, obj->bt(), AOBJECT_BACKTRACE_SIZE);
 | 
				
			||||||
              MEMCPY((char*)addrs, &obj->data_[offset], AOBJECT_BACKTRACE_SIZE);
 | 
					 | 
				
			||||||
              IGNORE_RETURN parray(first_bt, MAX_BACKTRACE_LENGTH, (int64_t*)addrs, AOBJECT_BACKTRACE_COUNT);
 | 
					              IGNORE_RETURN parray(first_bt, MAX_BACKTRACE_LENGTH, (int64_t*)addrs, AOBJECT_BACKTRACE_COUNT);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (!has_unfree) {
 | 
					            if (!has_unfree) {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user