init push
This commit is contained in:
273
unittest/share/schema/test_schema_mem_mgr.cpp
Normal file
273
unittest/share/schema/test_schema_mem_mgr.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SHARE
|
||||
#include <gtest/gtest.h>
|
||||
#define private public
|
||||
#include "lib/oblog/ob_log.h"
|
||||
#include "lib/time/ob_time_utility.h"
|
||||
#include "lib/random/ob_random.h"
|
||||
#define private public
|
||||
#include "share/schema/ob_schema_mgr.h"
|
||||
#include "share/schema/ob_schema_mem_mgr.h"
|
||||
|
||||
namespace oceanbase {
|
||||
using namespace share::schema;
|
||||
|
||||
namespace common {
|
||||
|
||||
class TestSchemaMemMgr : public ::testing::Test {};
|
||||
|
||||
TEST_F(TestSchemaMemMgr, basic_test)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSchemaMgr* mgr = NULL;
|
||||
int pos = -1;
|
||||
|
||||
void* ptr = NULL;
|
||||
ObIAllocator* allocator = NULL;
|
||||
ObSchemaMemMgr mem_mgr;
|
||||
// not init when alloc
|
||||
ret = mem_mgr.alloc(sizeof(ObSchemaMgr), ptr, &allocator);
|
||||
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
|
||||
ret = mem_mgr.init(ObModIds::OB_SCHEMA_MGR);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
// invalid arg when alloc
|
||||
ret = mem_mgr.alloc(-1, ptr, &allocator);
|
||||
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
|
||||
ret = mem_mgr.alloc(0, ptr, &allocator);
|
||||
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
|
||||
|
||||
ret = mem_mgr.alloc(sizeof(ObSchemaMgr), ptr, &allocator);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_TRUE(NULL != ptr && NULL != allocator);
|
||||
pos = mem_mgr.pos_;
|
||||
ASSERT_EQ(1, mem_mgr.ptrs_[pos].count());
|
||||
ASSERT_EQ(0, mem_mgr.ptrs_[1 - pos].count());
|
||||
ASSERT_EQ(ptr, mem_mgr.ptrs_[pos].at(0));
|
||||
ASSERT_EQ(allocator, &mem_mgr.allocer_[pos]);
|
||||
mgr = new (ptr) ObSchemaMgr(*allocator);
|
||||
mgr->dump();
|
||||
|
||||
// not init when free
|
||||
mem_mgr.is_inited_ = false;
|
||||
ret = mem_mgr.free(static_cast<void*>(mgr));
|
||||
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
|
||||
mem_mgr.is_inited_ = true;
|
||||
// invalid arg when free
|
||||
ret = mem_mgr.free(NULL);
|
||||
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
|
||||
|
||||
ret = mem_mgr.free(static_cast<void*>(mgr));
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_EQ(0, mem_mgr.ptrs_[pos].count());
|
||||
int64_t alloc_cnt = 0;
|
||||
ret = mem_mgr.get_cur_alloc_cnt(alloc_cnt);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_EQ(1, alloc_cnt);
|
||||
ret = mem_mgr.free(static_cast<void*>(mgr));
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_EQ(0, mem_mgr.ptrs_[pos].count());
|
||||
ret = mem_mgr.get_cur_alloc_cnt(alloc_cnt);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_EQ(1, alloc_cnt);
|
||||
ASSERT_TRUE(0 != mem_mgr.allocer_[pos].used());
|
||||
bool can_switch = false;
|
||||
ret = mem_mgr.check_can_switch_allocer(can_switch);
|
||||
ASSERT_TRUE(can_switch);
|
||||
ret = mem_mgr.switch_allocer();
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_TRUE(0 != mem_mgr.allocer_[pos].used());
|
||||
ret = mem_mgr.check_can_switch_allocer(can_switch);
|
||||
ASSERT_TRUE(can_switch);
|
||||
ret = mem_mgr.switch_allocer();
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_TRUE(0 == mem_mgr.allocer_[pos].used());
|
||||
mem_mgr.dump();
|
||||
}
|
||||
|
||||
TEST_F(TestSchemaMemMgr, NULL_ptr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
ObSchemaMemMgr mem_mgr;
|
||||
ret = mem_mgr.init(ObModIds::OB_SCHEMA_MGR);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
|
||||
// free when ptrs array contains NULL ptr.
|
||||
mem_mgr.ptrs_[0].push_back(NULL);
|
||||
ret = mem_mgr.free(static_cast<void*>(this));
|
||||
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
|
||||
mem_mgr.ptrs_[0].reset();
|
||||
|
||||
// free when two ptrs array have the same ptr.
|
||||
mem_mgr.ptrs_[0].push_back(static_cast<void*>(this));
|
||||
mem_mgr.ptrs_[1].push_back(static_cast<void*>(this));
|
||||
ret = mem_mgr.free(static_cast<void*>(this));
|
||||
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
|
||||
}
|
||||
|
||||
TEST_F(TestSchemaMemMgr, check_can_switch_allocer)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
ObSchemaMemMgr mem_mgr;
|
||||
bool can_switch = false;
|
||||
// not init
|
||||
ret = mem_mgr.check_can_switch_allocer(can_switch);
|
||||
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
|
||||
ret = mem_mgr.init(ObModIds::OB_SCHEMA_MGR);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
// can switch
|
||||
ret = mem_mgr.check_can_switch_allocer(can_switch);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_TRUE(can_switch);
|
||||
// cannot switch
|
||||
mem_mgr.ptrs_[1].push_back(static_cast<void*>(this));
|
||||
ret = mem_mgr.check_can_switch_allocer(can_switch);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_FALSE(can_switch);
|
||||
}
|
||||
|
||||
TEST_F(TestSchemaMemMgr, switch_allocer)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
ObSchemaMemMgr mem_mgr;
|
||||
ret = mem_mgr.switch_allocer();
|
||||
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
|
||||
// not init
|
||||
ret = mem_mgr.init(ObModIds::OB_SCHEMA_MGR);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
|
||||
mem_mgr.ptrs_[1].push_back(static_cast<void*>(this));
|
||||
mem_mgr.all_ptrs_[1].push_back(static_cast<void*>(this));
|
||||
ret = mem_mgr.switch_allocer();
|
||||
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
|
||||
mem_mgr.ptrs_[1].reset();
|
||||
ret = mem_mgr.switch_allocer();
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ASSERT_EQ(0, mem_mgr.all_ptrs_[1].count());
|
||||
|
||||
// free when two ptrs array have the same ptr.
|
||||
mem_mgr.ptrs_[0].push_back(static_cast<void*>(this));
|
||||
mem_mgr.ptrs_[1].push_back(static_cast<void*>(this));
|
||||
ret = mem_mgr.free(static_cast<void*>(this));
|
||||
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
|
||||
}
|
||||
|
||||
// It's not matched with the real elimination strategy of increment schema refresh.
|
||||
// Eliminate a random ObSchemaMgr at a time.
|
||||
TEST_F(TestSchemaMemMgr, simulate_increment_refresh_schema)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
static const int min_switch_alloc_cnt = 32;
|
||||
static const int cache_size = 8;
|
||||
ObSchemaMgr* schema_mgr_for_cache = NULL;
|
||||
ObSchemaMgr* mgr_cache[cache_size];
|
||||
memset(mgr_cache, 0, sizeof(ObSchemaMgr*) * cache_size);
|
||||
ObSchemaMemMgr mem_mgr;
|
||||
ret = mem_mgr.init(ObModIds::OB_SCHEMA_MGR);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
const int alloc_size = sizeof(ObSchemaMgr);
|
||||
ObSchemaMgr* mgr = NULL;
|
||||
// init schema_mgr_for_cache
|
||||
void* tmp_ptr = NULL;
|
||||
ObIAllocator* allocator = NULL;
|
||||
ret = mem_mgr.alloc(alloc_size, tmp_ptr, &allocator);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
schema_mgr_for_cache = new (tmp_ptr) ObSchemaMgr(*allocator);
|
||||
|
||||
static const int refresh_times = 1024;
|
||||
int64_t switch_cnt = 0;
|
||||
for (int64_t i = 0; i < refresh_times; ++i) {
|
||||
schema_mgr_for_cache->set_schema_version(1);
|
||||
// eliminate randomly
|
||||
int64_t eli_pos = ObRandom::rand(0, cache_size - 1);
|
||||
void* eli_ptr = static_cast<void*>(mgr_cache[eli_pos]);
|
||||
ret = mem_mgr.alloc(alloc_size, tmp_ptr);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
mgr = new (tmp_ptr) ObSchemaMgr;
|
||||
mgr->assign(*schema_mgr_for_cache);
|
||||
mgr_cache[eli_pos] = mgr;
|
||||
if (NULL != eli_ptr) {
|
||||
bool can_switch = false;
|
||||
int64_t alloc_cnt = 0;
|
||||
ret = mem_mgr.free(eli_ptr);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ret = mem_mgr.check_can_switch_allocer(can_switch);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ret = mem_mgr.get_cur_alloc_cnt(alloc_cnt);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
LOG_INFO("debug",
|
||||
K(tmp_ptr),
|
||||
K(eli_pos),
|
||||
K(eli_ptr),
|
||||
K(alloc_cnt),
|
||||
K(mem_mgr.ptrs_[0].count()),
|
||||
K(mem_mgr.ptrs_[1].count()));
|
||||
if (can_switch && alloc_cnt > min_switch_alloc_cnt) {
|
||||
LOG_INFO("switch allocator");
|
||||
++switch_cnt;
|
||||
// overwrite schema_mgr_for_cache
|
||||
void* tmp_ptr = NULL;
|
||||
ObIAllocator* allocator = NULL;
|
||||
ObSchemaMgr* old_mgr = schema_mgr_for_cache;
|
||||
ObSchemaMgr* new_mgr = NULL;
|
||||
ret = mem_mgr.switch_allocer();
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
ret = mem_mgr.alloc(alloc_size, tmp_ptr, &allocator);
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
new_mgr = new (tmp_ptr) ObSchemaMgr(*allocator);
|
||||
new_mgr->deep_copy(*old_mgr);
|
||||
ret = mem_mgr.free(static_cast<void*>(old_mgr));
|
||||
ASSERT_EQ(OB_SUCCESS, ret);
|
||||
schema_mgr_for_cache = new_mgr;
|
||||
// expect no core
|
||||
schema_mgr_for_cache->dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
// check
|
||||
for (int64_t i = 0; i < cache_size; ++i) {
|
||||
ObSchemaMgr* mgr = mgr_cache[i];
|
||||
bool exist = false;
|
||||
for (int64_t j = 0; j < mem_mgr.ptrs_[0].count() && !exist; ++j) {
|
||||
exist = mgr == mem_mgr.ptrs_[0].at(j);
|
||||
}
|
||||
for (int64_t j = 0; j < mem_mgr.ptrs_[1].count() && !exist; ++j) {
|
||||
exist = mgr == mem_mgr.ptrs_[1].at(j);
|
||||
}
|
||||
ASSERT_TRUE(exist);
|
||||
}
|
||||
bool exist = false;
|
||||
for (int64_t j = 0; j < mem_mgr.ptrs_[0].count() && !exist; ++j) {
|
||||
exist = schema_mgr_for_cache == mem_mgr.ptrs_[0].at(j);
|
||||
}
|
||||
for (int64_t j = 0; j < mem_mgr.ptrs_[1].count() && !exist; ++j) {
|
||||
exist = schema_mgr_for_cache == mem_mgr.ptrs_[1].at(j);
|
||||
}
|
||||
ASSERT_TRUE(exist);
|
||||
ASSERT_TRUE(switch_cnt > 10);
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace oceanbase
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
|
||||
OB_LOGGER.set_file_name("test_schema_mem_mgr.log", true);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user