Files
oceanbase/deps/oblib/unittest/common/test_memfrag_recycle_allocator.cpp
gm 4a92b6d7df reformat source code
according to code styles, 'AccessModifierOffset' should be -2.
2021-06-17 10:40:36 +08:00

291 lines
7.3 KiB
C++

/**
* 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 <gtest/gtest.h>
#include "lib/oblog/ob_log.h"
#include "lib/allocator/ob_memfrag_recycle_allocator.h"
#include "lib/random/ob_random.h"
using namespace oceanbase::common;
namespace oceanbase {
namespace common {
class TestObMetaImage : public ObIRewritable, public lib::ThreadPool {
public:
TestObMetaImage();
virtual ~TestObMetaImage();
int init(const int64_t expire_duration);
void destroy();
virtual int rewrite_switch();
void run1() final;
private:
static const int64_t MAX_META_COUNT = 1024L * 1024L * 2L;
struct TestObMeta {
int64_t size_;
char data_[0];
};
int do_work();
inline void* alloc(const int64_t size)
{
return allocator_.alloc(size);
}
inline void free(void* ptr)
{
allocator_.free(ptr);
}
inline int need_rewrite(void* ptr, bool& is_need)
{
return allocator_.need_rewrite(ptr, is_need);
}
ObMemfragRecycleAllocator allocator_;
TestObMeta** meta_array_;
};
TestObMetaImage::TestObMetaImage()
{
meta_array_ = (TestObMeta**)ob_malloc(sizeof(TestObMeta*) * MAX_META_COUNT);
memset(meta_array_, 0, sizeof(TestObMeta*) * MAX_META_COUNT);
}
TestObMetaImage::~TestObMetaImage()
{
ob_free(meta_array_);
}
int TestObMetaImage::init(const int64_t expire_duration)
{
return allocator_.init(ObModIds::OB_MACRO_BLOCK_META, this, expire_duration);
}
void TestObMetaImage::destroy()
{
for (int64_t i = 0; i < MAX_META_COUNT; i++) {
if (NULL != meta_array_[i]) {
free(meta_array_[i]);
}
}
allocator_.destroy();
}
void TestObMetaImage::run1()
{
int ret = OB_SUCCESS;
if (OB_SUCCESS != (ret = do_work())) {
LIB_ALLOC_LOG(WARN, "do work failed, ", "ret", ret);
}
}
int TestObMetaImage::do_work()
{
int ret = OB_SUCCESS;
int64_t loc = 0;
int64_t size = 0;
TestObMeta* old_meta = NULL;
TestObMeta* new_meta = NULL;
while (!has_set_stop()) {
loc = ObRandom::rand(0, MAX_META_COUNT - 1);
size = ObRandom::rand(128, 1000);
new_meta = (TestObMeta*)alloc(size);
if (NULL == new_meta) {
ret = OB_ALLOCATE_MEMORY_FAILED;
break;
} else {
new_meta->size_ = size;
}
old_meta = (TestObMeta*)ATOMIC_TAS(reinterpret_cast<volatile uint64_t*>(&meta_array_[loc]), (uint64_t)new_meta);
if (NULL != old_meta) {
free(old_meta);
}
}
return ret;
}
int TestObMetaImage::rewrite_switch()
{
int ret = OB_SUCCESS;
TestObMeta* old_meta = NULL;
TestObMeta* new_meta = NULL;
TestObMeta* tmp_meta = NULL;
bool is_need = false;
for (int64_t i = 0; OB_SUCC(ret) && i < MAX_META_COUNT; i++) {
old_meta = meta_array_[i];
if (OB_SUCCESS != (ret = need_rewrite(old_meta, is_need))) {
LIB_ALLOC_LOG(WARN, "fail to decide if need rewrite, ", "ret", ret);
} else if (is_need) {
new_meta = (TestObMeta*)alloc(old_meta->size_);
if (NULL == new_meta) {
ret = OB_ALLOCATE_MEMORY_FAILED;
break;
} else {
new_meta->size_ = old_meta->size_;
tmp_meta = (TestObMeta*)ATOMIC_VCAS(
reinterpret_cast<volatile uint64_t*>(&meta_array_[i]), (uint64_t)old_meta, (uint64_t)new_meta);
if (old_meta == tmp_meta) {
free(old_meta);
} else {
// retry
free(new_meta);
i--;
}
}
}
}
return ret;
}
TEST(ObMRAllocatorRecycler, test_recycle)
{
int ret = OB_SUCCESS;
ObMemfragRecycleAllocator allocator[100];
// test null argument
ret = ObMRAllocatorRecycler::get_instance().register_allocator(NULL);
EXPECT_NE(OB_SUCCESS, ret);
// test normal register
ret = ObMRAllocatorRecycler::get_instance().register_allocator(&allocator[0]);
EXPECT_EQ(OB_SUCCESS, ret);
// test repeatly register
ret = ObMRAllocatorRecycler::get_instance().register_allocator(&allocator[0]);
EXPECT_NE(OB_SUCCESS, ret);
// test normal deregister
ret = ObMRAllocatorRecycler::get_instance().deregister_allocator(&allocator[0]);
EXPECT_EQ(OB_SUCCESS, ret);
// test repeatly deregister
ret = ObMRAllocatorRecycler::get_instance().deregister_allocator(&allocator[0]);
EXPECT_NE(OB_SUCCESS, ret);
// test invalid_deregister
ret = ObMRAllocatorRecycler::get_instance().deregister_allocator(NULL);
EXPECT_NE(OB_SUCCESS, ret);
// test invalid_deregister
ret = ObMRAllocatorRecycler::get_instance().deregister_allocator(&allocator[1]);
EXPECT_NE(OB_SUCCESS, ret);
// test register limit count
ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < 100; i++) {
ret = ObMRAllocatorRecycler::get_instance().register_allocator(&allocator[i]);
}
EXPECT_NE(OB_SUCCESS, ret);
ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < 100; i++) {
ret = ObMRAllocatorRecycler::get_instance().deregister_allocator(&allocator[i]);
}
}
TEST(ObMemfragRecycleAllocator, test_allocator)
{
int ret = OB_SUCCESS;
ObMemfragRecycleAllocator allocator;
TestObMetaImage image1;
TestObMetaImage image2;
void* data = NULL;
// test invalid argument
ret = allocator.init(-1, NULL, -1);
EXPECT_NE(OB_SUCCESS, ret);
// test invalid alloc, free ...
data = allocator.alloc(100);
EXPECT_TRUE(NULL == data);
allocator.free(data);
// test invalid switch
ret = allocator.switch_state();
EXPECT_NE(OB_SUCCESS, ret);
// test thread unsafe init
ret = allocator.init(ObModIds::OB_MACRO_BLOCK_META, NULL, 0);
EXPECT_EQ(OB_SUCCESS, ret);
// test invalid switch
ret = allocator.switch_state();
EXPECT_NE(OB_SUCCESS, ret);
// test destroy
allocator.destroy();
// test normal init
ret = allocator.init(ObModIds::OB_MACRO_BLOCK_META, &image1, 0);
EXPECT_EQ(OB_SUCCESS, ret);
// test repeatly init
ret = allocator.init(ObModIds::OB_MACRO_BLOCK_META, &image2, 0);
EXPECT_NE(OB_SUCCESS, ret);
// test normal alloc
data = allocator.alloc(100);
EXPECT_TRUE(data != NULL);
// test normal free
allocator.free(data);
// test invalid free
allocator.free(&image1);
// test invalid need_rewrite
bool is_need = false;
ret = allocator.need_rewrite(NULL, is_need);
EXPECT_EQ(OB_SUCCESS, ret);
EXPECT_TRUE(!is_need);
// test normal need_rewrite
data = allocator.alloc(100);
ret = allocator.need_rewrite(data, is_need);
EXPECT_EQ(OB_SUCCESS, ret);
EXPECT_TRUE(!is_need);
allocator.destroy();
}
TEST(ObMetaImage, test_image)
{
const int64_t THREAD_COUNT = 9;
int ret = OB_SUCCESS;
TestObMetaImage image;
ret = image.init(1000 * 1000);
EXPECT_EQ(OB_SUCCESS, ret);
ObMRAllocatorRecycler::get_instance().set_schedule_interval_us(1000 * 1000);
image.set_thread_count(THREAD_COUNT);
image.start();
sleep(60);
image.stop();
image.wait();
image.destroy();
}
} // namespace common
} // namespace oceanbase
int main(int argc, char** argv)
{
oceanbase::common::ObLogger::get_logger().set_log_level("DEBUG");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}