Files
oceanbase/unittest/logservice/test_server_log_block_mgr.cpp
2023-07-18 08:18:25 +00:00

630 lines
25 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/file/file_directory_utils.h"
#include "lib/list/ob_dlist.h"
#include "lib/ob_abort.h"
#include "lib/ob_define.h"
#include "lib/ob_errno.h"
#include "lib/oblog/ob_log.h"
#include "lib/time/ob_time_utility.h"
#include "lib/utility/ob_utility.h"
#include "logservice/palf/log_block_pool_interface.h"
#include "logservice/palf/log_define.h"
#include "share/ob_errno.h"
#include <thread>
#include <functional>
#define private public
#include "logservice/ob_server_log_block_mgr.h"
#undef private
#include <gtest/gtest.h>
#include <regex>
namespace oceanbase
{
using namespace logservice;
using namespace common;
using namespace palf;
namespace unittest
{
static const int64_t DEFAULT_LS_COUNT = 10;
static int ls_id_array_[DEFAULT_LS_COUNT] = {1, 1001, 1002, 1003, 1004,
1005, 1006, 1007, 1008, 1009};
static const char *log_or_meta_[2] = {"log", "meta"};
class TestServerLogBlockMgr : public ::testing::Test
{
public:
static void SetUpTestCase();
static void TearDownTestCase();
TestServerLogBlockMgr()
{}
virtual ~TestServerLogBlockMgr()
{}
static int create_ls_in_tenant(const int ls_count, const char *tenant_dir);
static int remove_ls_in_tenant(const char *tenant_dir);
int create_new_blocks_at(const int64_t ls_id, const palf::FileDesc &fd,
const palf::block_id_t start_block_id, const int64_t block_cnt)
{
int ret = OB_SUCCESS;
char block_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
for (int i = 0; i < block_cnt && OB_SUCC(ret); i++) {
char create_block_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
int64_t pos = 0;
bool result = false;
const palf::block_id_t block_id = start_block_id + i;
databuff_printf(block_path, OB_MAX_FILE_NAME_LENGTH, pos, "%s/%lu/%s/%lu",
tenant_string_, ls_id, log_or_meta_[ls_id % 2], block_id);
if (OB_FAIL(block_id_to_string(block_id, create_block_path, OB_MAX_FILE_NAME_LENGTH))) {
CLOG_LOG(ERROR, "block_id_to_string failed", K(ret));
} else if (OB_FAIL(log_block_mgr_.create_block_at(fd, create_block_path,
ObServerLogBlockMgr::BLOCK_SIZE))) {
CLOG_LOG(ERROR, "create_block_at failed", K(ret), K(ls_id), K(fd),
K(start_block_id), K(block_id));
} else if (OB_FAIL(FileDirectoryUtils::is_exists(block_path, result))) {
CLOG_LOG(ERROR, "is_exists failed", K(ret), K(block_path), K(result), K(i),
K(start_block_id));
} else if (false == result) {
ret = OB_ERR_UNEXPECTED;
CLOG_LOG(ERROR, "file not exist, unexpected error", K(ret), K(block_path),
K(start_block_id), K(i));
} else {
}
}
return ret;
}
int delete_blocks_at(const int64_t ls_id, const palf::FileDesc &fd,
const palf::block_id_t start_block_id, const int64_t block_cnt)
{
int ret = OB_SUCCESS;
char block_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
for (int i = 0; i < block_cnt && OB_SUCC(ret); i++) {
char remove_block_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
int64_t pos = 0;
bool result = false;
const palf::block_id_t block_id = start_block_id + i;
databuff_printf(block_path, OB_MAX_FILE_NAME_LENGTH, pos, "%s/%lu/%s/%lu",
tenant_string_, ls_id, log_or_meta_[ls_id % 2], block_id);
if (OB_FAIL(block_id_to_string(block_id, remove_block_path, OB_MAX_FILE_NAME_LENGTH))) {
CLOG_LOG(ERROR, "block_id_to_string failed", K(ret));
} else if (OB_FAIL(log_block_mgr_.remove_block_at(fd, remove_block_path))) {
CLOG_LOG(ERROR, "delete_new_block_at failed", K(ret), K(ls_id), K(fd),
K(start_block_id), K(i));
} else if (OB_FAIL(FileDirectoryUtils::is_exists(block_path, result))) {
CLOG_LOG(ERROR, "is_exists failed", K(ret), K(block_path), K(result), K(i),
K(start_block_id));
} else if (true == result) {
ret = OB_ERR_UNEXPECTED;
CLOG_LOG(ERROR, "file exist, unexpected error", K(ret), K(block_path),
K(start_block_id), K(start_block_id), K(i));
} else {
}
}
return ret;
}
static constexpr int64_t GB = 1024 * 1024 * 1024ul;
int create_tenant(int key, int64_t size) {
ObSpinLockGuard guard(this->lock_);
int ret = OB_SUCCESS;
if (map_.end() != map_.find(key)) {
ret = OB_ENTRY_EXIST;
} else {
ret = this->log_block_mgr_.create_tenant(size);
if (OB_SUCC(ret)) {
map_[key] = size;
} else {
}
}
return ret;
};
int remove_tenant(int key) {
ObSpinLockGuard guard(this->lock_);
int ret = OB_SUCCESS;
if (map_.end() == map_.find(key)) {
ret = OB_ENTRY_NOT_EXIST;
} else {
int64_t size = map_[key];
map_.erase(key);
this->log_block_mgr_.remove_tenant(size);
}
return ret;
};
int update_tenant(int key, int64_t new_size) {
ObSpinLockGuard guard(this->lock_);
int ret = OB_SUCCESS;
if (map_.end() == map_.find(key)) {
ret = OB_ENTRY_NOT_EXIST;
} else {
int64_t old_size = map_[key];
int64_t tmp_min_log_disk_size_for_all_tenants = this->log_block_mgr_.min_log_disk_size_for_all_tenants_;
tmp_min_log_disk_size_for_all_tenants -= old_size;
tmp_min_log_disk_size_for_all_tenants += new_size;
if (tmp_min_log_disk_size_for_all_tenants > this->log_block_mgr_.get_total_size_guarded_by_lock_()) {
ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
}
if (OB_SUCCESS != ret) {
map_[key] = old_size;
} else {
this->log_block_mgr_.min_log_disk_size_for_all_tenants_ = tmp_min_log_disk_size_for_all_tenants;
map_[key] = new_size;
}
}
return ret;
};
public:
virtual void SetUp();
virtual void TearDown();
static const char *log_pool_base_path_;
static const char *log_disk_path_;
static const char *tenant_string_;
static std::map<int64_t, int> tenant_ls_fd_map_;
static std::vector<int> tenant_1_ls_fd_;
ObServerLogBlockMgr log_block_mgr_;
ObSpinLock lock_;
std::map<int, int64_t> map_;
};
const char *TestServerLogBlockMgr::log_pool_base_path_ = "clog_disk/clog";
const char *TestServerLogBlockMgr::tenant_string_ = "clog_disk/clog/tenant_1";
std::map<int64_t, int> TestServerLogBlockMgr::tenant_ls_fd_map_;
std::vector<int> TestServerLogBlockMgr::tenant_1_ls_fd_;
void TestServerLogBlockMgr::SetUpTestCase()
{
bool result = false;
int ret = OB_SUCCESS;
if (OB_FAIL(FileDirectoryUtils::create_directory(tenant_string_))) {
CLOG_LOG(ERROR, "FileDirectoryUtils create_directory failed", K(ret),
K(tenant_string_));
} else if (OB_FAIL(create_ls_in_tenant(DEFAULT_LS_COUNT, tenant_string_))) {
CLOG_LOG(ERROR, "create_ls_in_tenant failed", K(ret));
} else {
CLOG_LOG(INFO, "SetUpTestSuite success", K(log_pool_base_path_));
}
}
void TestServerLogBlockMgr::TearDownTestCase()
{
remove_ls_in_tenant(tenant_string_);
system("rm -rf clog_disk");
}
int TestServerLogBlockMgr::create_ls_in_tenant(const int ls_count, const char *tenant_dir)
{
int ret = OB_SUCCESS;
for (int i = 0; i < ls_count && OB_SUCC(ret); i++) {
char ls_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
int fd = -1;
snprintf(ls_path, OB_MAX_FILE_NAME_LENGTH, "%s/%d", tenant_dir, ls_id_array_[i]);
if (-1 == ::mkdir(ls_path, ObServerLogBlockMgr::CREATE_DIR_MODE)) {
ret = palf::convert_sys_errno();
CLOG_LOG(ERROR, "::mkdir failed", K(ret));
} else if (FALSE_IT(snprintf(ls_path, OB_MAX_FILE_NAME_LENGTH, "%s/%d/%s", tenant_dir,
ls_id_array_[i], log_or_meta_[ls_id_array_[i] % 2]))
|| -1 == ::mkdir(ls_path, ObServerLogBlockMgr::CREATE_DIR_MODE)) {
ret = palf::convert_sys_errno();
CLOG_LOG(ERROR, "::mkdir failed", K(ret));
} else if (-1 == (fd = ::open(ls_path, ObServerLogBlockMgr::OPEN_DIR_FLAG))) {
ret = palf::convert_sys_errno();
CLOG_LOG(ERROR, "::open failed", K(ret));
} else {
tenant_ls_fd_map_.insert(std::make_pair(ls_id_array_[i], fd));
}
}
return ret;
}
int TestServerLogBlockMgr::remove_ls_in_tenant(const char *tenant_dir)
{
int ret = OB_SUCCESS;
for (auto iter = tenant_ls_fd_map_.begin(); iter != tenant_ls_fd_map_.end(); iter++) {
char ls_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
snprintf(ls_path, OB_MAX_FILE_NAME_LENGTH, "%s/%lu", tenant_dir, iter->first);
if (-1 == FileDirectoryUtils::delete_directory_rec(ls_path)) {
ret = palf::convert_sys_errno();
CLOG_LOG(ERROR, "::rmdir failed", K(ret), K(ls_path));
} else if (-1 == ::close(iter->second)) {
ret = palf::convert_sys_errno();
CLOG_LOG(ERROR, "::close failed", K(ret), K(ls_path));
} else {
}
}
return ret;
}
void TestServerLogBlockMgr::SetUp()
{
OB_ASSERT(OB_SUCCESS == log_block_mgr_.init(log_pool_base_path_));
log_block_mgr_.get_tenants_log_disk_size_func_ = [this](int64_t &out) -> int
{
for(auto pair : map_)
{
out += pair.second;
CLOG_LOG(INFO, "current pair", K(pair.first), K(pair.second));
}
CLOG_LOG(INFO, "get_tenants_log_disk_size_func_ success", K(out), K(log_block_mgr_));
return OB_SUCCESS;
};
}
void TestServerLogBlockMgr::TearDown()
{
log_block_mgr_.destroy();
}
using namespace palf;
TEST_F(TestServerLogBlockMgr, basic_func)
{
const int64_t reserved_size = 2 * ObServerLogBlockMgr::GB;
const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
// resize
EXPECT_EQ(0, log_block_mgr_.log_pool_meta_.curr_total_size_);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.start(aligned_reserved_size));
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(2 * aligned_reserved_size));
EXPECT_EQ(2 * aligned_reserved_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(aligned_reserved_size));
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
const int64_t ls_id = 1;
EXPECT_EQ(OB_SUCCESS, create_new_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, 10));
int64_t in_use_size_byte, total_size_byte;
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.get_disk_usage(in_use_size_byte, total_size_byte));
EXPECT_EQ(10*ObServerLogBlockMgr::BLOCK_SIZE, in_use_size_byte);
EXPECT_EQ(OB_SUCCESS, delete_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, 10));
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.get_disk_usage(in_use_size_byte, total_size_byte));
EXPECT_EQ(0, in_use_size_byte);
}
TEST_F(TestServerLogBlockMgr, restart_for_empty_log_disk)
{
log_block_mgr_.destroy();
const int64_t reserved_size = 2 * ObServerLogBlockMgr::GB;
const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
int64_t in_use_size_byte, total_size_byte;
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.init(log_pool_base_path_));
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.next_total_size_);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.get_disk_usage(in_use_size_byte, total_size_byte));
EXPECT_EQ(0, in_use_size_byte);
EXPECT_EQ(0, log_block_mgr_.log_pool_meta_.status_);
}
TEST_F(TestServerLogBlockMgr, allocate_blocks_in_tenant)
{
const int64_t ls_id = 1001;
EXPECT_EQ(OB_SUCCESS, create_new_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, 10));
EXPECT_EQ(OB_SUCCESS,
create_new_blocks_at(ls_id + 1, tenant_ls_fd_map_[ls_id + 1], 0, 5));
EXPECT_EQ(OB_SUCCESS, delete_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, 3));
EXPECT_EQ(OB_SUCCESS, delete_blocks_at(ls_id + 1, tenant_ls_fd_map_[ls_id + 1], 0, 3));
}
TEST_F(TestServerLogBlockMgr, restart_for_non_empty_log_disk)
{
log_block_mgr_.destroy();
const int64_t reserved_size = 2 * ObServerLogBlockMgr::GB;
const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.init(log_pool_base_path_));
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.next_total_size_);
EXPECT_EQ(0, log_block_mgr_.log_pool_meta_.status_);
const int64_t ls_id = 1001;
EXPECT_EQ(OB_SUCCESS, delete_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 3, 7));
EXPECT_EQ(OB_SUCCESS, delete_blocks_at(ls_id + 1, tenant_ls_fd_map_[ls_id + 1], 3, 2));
}
TEST_F(TestServerLogBlockMgr, concurrent_create_delete_resize)
{
const int64_t reserved_size = 4 * ObServerLogBlockMgr::GB;
const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(aligned_reserved_size));
const int64_t free_block_size = log_block_mgr_.get_free_size_guarded_by_lock_();
std::vector<std::thread> threads;
std::atomic<int64_t> total_allocate_block_count(0);
auto create_func = [&](int64_t ls_id) -> int {
int64_t block_cnt = 6;
total_allocate_block_count += block_cnt;
return create_new_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, block_cnt);
};
auto delete_func = [&](int64_t ls_id) -> int {
int64_t block_cnt = 6;
create_new_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, block_cnt);
total_allocate_block_count += 2;
return delete_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, block_cnt-2);
};
std::vector< std::function<int(int64_t) > > funcs;
funcs.push_back(create_func);
funcs.push_back(delete_func);
std::thread resize_thread([&]() -> int
{
const int64_t reserved_size = 10 * ObServerLogBlockMgr::GB;
const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
return log_block_mgr_.resize_(reserved_size);
});
for (int i = 0; i < DEFAULT_LS_COUNT; i++) {
threads.emplace_back(std::thread(funcs[i%2], ls_id_array_[i]));
}
for (int i = 0; i < DEFAULT_LS_COUNT; i++) {
threads[i].join();
}
resize_thread.join();
const int64_t curr_free_zie = log_block_mgr_.get_free_size_guarded_by_lock_();
int64_t total_allocate_block_count_int = total_allocate_block_count;
const int64_t total_block_size = log_block_mgr_.log_pool_meta_.curr_total_size_;
EXPECT_EQ(total_allocate_block_count_int*ObServerLogBlockMgr::BLOCK_SIZE + curr_free_zie, total_block_size);
int64_t ls_id = ls_id_array_[0];
EXPECT_EQ(OB_SUCCESS, create_new_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 6, 3));
}
TEST_F(TestServerLogBlockMgr, dirty_ls_dir_and_log_pool_file)
{
system("mkdir clog_disk/clog/tenant_0111");
system("mkdir clog_disk/clog/tenant_0111/log");
system("touch clog_disk/clog/tenant_0111/log/0");
system("touch clog_disk/clog/tenant_0111/log/1");
system("touch clog_disk/clog/log_pool/0.tmp");
system("touch clog_disk/clog/tenant_1/1/meta/10000.tmp");
system("fallocate -l 67108863 clog_disk/clog/tenant_1/1/meta/10000.tmp ");
system("mkdir clog_disk/clog/log_pool/1.tmp");
log_block_mgr_.destroy();
bool result = false;
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.init(log_pool_base_path_));
EXPECT_EQ(OB_SUCCESS, FileDirectoryUtils::is_exists("clog_disk/clog/tenant_1/1/meta/10000.tmp",result));
EXPECT_EQ(false, result);
}
TEST_F(TestServerLogBlockMgr, resize_failed_and_restar)
{
const int64_t reserved_size = 15 * ObServerLogBlockMgr::GB;
const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
ObServerLogBlockMgr::LogPoolMeta meta = log_block_mgr_.get_log_pool_meta_guarded_by_lock_();
meta.status_ = ObServerLogBlockMgr::EXPANDING_STATUS;
meta.next_total_size_ = aligned_reserved_size;
log_block_mgr_.update_log_pool_meta_guarded_by_lock_(meta);
// 触发trim
system("touch clog_disk/clog/log_pool/100050");
system("touch clog_disk/clog/log_pool/100000");
log_block_mgr_.destroy();
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.init(log_pool_base_path_));
EXPECT_EQ(false, log_block_mgr_.log_pool_meta_.resizing());
EXPECT_EQ(aligned_reserved_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
}
// This case will cause disk space not enough, ignore it.
//TEST_F(TestServerLogBlockMgr, expand_when_disk_space_not_enough)
//{
// const int64_t reserved_size = 100 * 1024 * ObServerLogBlockMgr::GB;
// const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
// ObServerLogBlockMgr::LogPoolMeta origin_meta = log_block_mgr_.get_log_pool_meta_guarded_by_lock_();
// EXPECT_EQ(OB_ALLOCATE_DISK_SPACE_FAILED, log_block_mgr_.resize_(aligned_reserved_size));
// EXPECT_EQ(origin_meta, log_block_mgr_.get_log_pool_meta_guarded_by_lock_());
//}
// TEST_F(TestServerLogBlockMgr, performance)
// {
// const int64_t reserved_size = 2 * ObServerLogBlockMgr::GB;
// const int64_t free_size = log_block_mgr_.get_free_size_guarded_by_lock_();
// const int64_t aligned_reserved_size = log_block_mgr_.lower_align_(reserved_size);
// EXPECT_EQ(OB_NOT_SUPPORTED, log_block_mgr_.resize_(aligned_reserved_size));
// EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(log_block_mgr_.get_total_size_guarded_by_lock_() - free_size));
// EXPECT_EQ(OB_ENTRY_NOT_EXIST, create_new_blocks_at(1, tenant_ls_fd_map_[1], 100000, 10));
//
// system("mkdir clog_disk/tmp.dir");
// const int64_t reserved_size1 = 1024 * ObServerLogBlockMgr::GB;
// const int64_t aligned_reserved_size1 = log_block_mgr_.lower_align_(reserved_size1);
// int64_t start_ts = ObTimeUtility::current_time();
// int fd = ::open("clog_disk/tmp.dir", ObServerLogBlockMgr::OPEN_DIR_FLAG);
// EXPECT_EQ(OB_SUCCESS, log_block_mgr_.allocate_blocks_at_tmp_dir_(fd, 0, aligned_reserved_size1/ObServerLogBlockMgr::BLOCK_SIZE));
// int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
// ::close(fd);
// EXPECT_EQ(OB_SUCCESS, FileDirectoryUtils::delete_directory_rec("clog_disk/tmp.dir"));
// CLOG_LOG(INFO, "allocate cost", K(cost_ts));
// EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(aligned_reserved_size1));
// }
TEST_F(TestServerLogBlockMgr, check_dir_is_empty)
{
system("mkdir clog_disk/test");
system("mkdir clog_disk/test/log_pool");
bool result = false;
EXPECT_EQ(OB_SUCCESS, ObServerLogBlockMgr::check_clog_directory_is_empty("clog_disk/test", result));
EXPECT_EQ(true, result);
system("mkdir clog_disk/test/log_pool1");
EXPECT_EQ(OB_SUCCESS, ObServerLogBlockMgr::check_clog_directory_is_empty("clog_disk/test", result));
EXPECT_EQ(false, result);
}
TEST_F(TestServerLogBlockMgr, create_tenant_resize)
{
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(4 * GB));
EXPECT_EQ(0, log_block_mgr_.min_log_disk_size_for_all_tenants_);
EXPECT_EQ(OB_SUCCESS, create_tenant(OB_MAX_RESERVED_TENANT_ID + 1, 2 * GB));
EXPECT_EQ(OB_SUCCESS, create_tenant(OB_MAX_RESERVED_TENANT_ID + 2, 2 * GB));
EXPECT_EQ(OB_MACHINE_RESOURCE_NOT_ENOUGH, create_tenant(OB_MAX_RESERVED_TENANT_ID + 3, 2 * GB));
EXPECT_EQ(OB_SUCCESS, remove_tenant(OB_MAX_RESERVED_TENANT_ID + 1));
EXPECT_EQ(2 * GB, log_block_mgr_.min_log_disk_size_for_all_tenants_);
EXPECT_EQ(OB_SUCCESS, update_tenant(OB_MAX_RESERVED_TENANT_ID + 2, 3 * GB));
EXPECT_EQ(3 * GB, log_block_mgr_.min_log_disk_size_for_all_tenants_);
EXPECT_EQ(OB_ENTRY_NOT_EXIST, update_tenant(OB_MAX_RESERVED_TENANT_ID + 1, 3 * GB));
EXPECT_EQ(OB_MACHINE_RESOURCE_NOT_ENOUGH, update_tenant(OB_MAX_RESERVED_TENANT_ID + 2, 5 * GB));
EXPECT_EQ(3 * GB, log_block_mgr_.min_log_disk_size_for_all_tenants_);
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.resize_(10 * GB));
EXPECT_EQ(3 * GB, log_block_mgr_.min_log_disk_size_for_all_tenants_);
EXPECT_EQ(10 * GB, log_block_mgr_.get_total_size_guarded_by_lock_());
constexpr int64_t MB = 1024*1024;
std::thread t_create1(
[&](){
for (int i = 4+OB_MAX_RESERVED_TENANT_ID; i < 1000+OB_MAX_RESERVED_TENANT_ID; i++) {
create_tenant(i, 32*MB);
};
}
);
std::thread t_create2(
[&](){
for (int i = 4+OB_MAX_RESERVED_TENANT_ID; i < 1000+OB_MAX_RESERVED_TENANT_ID; i++) {
create_tenant(i, 32*MB);
};
}
);
std::thread t_update1(
[&](){
usleep(10);
for (int i = 4+OB_MAX_RESERVED_TENANT_ID; i < 1000+OB_MAX_RESERVED_TENANT_ID; i++) {
update_tenant(i, 128*MB);
};
}
);
std::thread t_update2(
[&](){
usleep(10);
for (int i = 4+OB_MAX_RESERVED_TENANT_ID; i < 1000+OB_MAX_RESERVED_TENANT_ID; i++) {
update_tenant(i, 128*MB);
};
}
);
t_create1.join();
t_create2.join();
t_update1.join();
t_update2.join();
EXPECT_EQ(10*GB, log_block_mgr_.min_log_disk_size_for_all_tenants_);
std::thread t_remove1(
[&](){
for (int i = 4+OB_MAX_RESERVED_TENANT_ID; i < 1000+OB_MAX_RESERVED_TENANT_ID; i++) {
remove_tenant(i);
};
}
);
std::thread t_remove2(
[&](){
for (int i = 4+OB_MAX_RESERVED_TENANT_ID; i < 1000+OB_MAX_RESERVED_TENANT_ID; i++) {
remove_tenant(i);
};
}
);
t_remove1.join();
t_remove2.join();
EXPECT_EQ(3*GB, log_block_mgr_.min_log_disk_size_for_all_tenants_);
}
TEST_F(TestServerLogBlockMgr, resize_log_loop_and_restart)
{
ObServerLogBlockMgr::LogPoolMeta meta;
meta.curr_total_size_ = log_block_mgr_.log_pool_meta_.curr_total_size_;
int64_t next_total_size = meta.next_total_size_ = meta.curr_total_size_ + 1*1024*1024*1024;
meta.status_ = ObServerLogBlockMgr::EXPANDING_STATUS;
log_block_mgr_.update_log_pool_meta_guarded_by_lock_(meta);
char tmp_dir_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
snprintf(tmp_dir_path, OB_MAX_FILE_NAME_LENGTH, "%s/expanding.tmp", log_block_mgr_.log_pool_path_);
int tmp_dir_fd = -1;
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.make_resizing_tmp_dir_(tmp_dir_path, tmp_dir_fd));
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.remove_resizing_tmp_dir_(tmp_dir_path, tmp_dir_fd));
char file_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
auto touch_file_in_log_pool = [](const char *file_path) {
char cmd_touch[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
char cmd_fallocate[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
snprintf(cmd_touch, OB_MAX_FILE_NAME_LENGTH, "touch %s", file_path);
snprintf(cmd_fallocate, OB_MAX_FILE_NAME_LENGTH, "fallocate -l %lu %s", PALF_PHY_BLOCK_SIZE, file_path);
system(cmd_touch);
system(cmd_fallocate);
};
for (int i = 0; i < 10; i++) {
int64_t file_id = i + 10000;
snprintf(file_path, OB_MAX_FILE_NAME_LENGTH, "%s/%ld", log_block_mgr_.log_pool_path_, file_id);
touch_file_in_log_pool(file_path);
}
log_block_mgr_.destroy();
EXPECT_EQ(OB_SUCCESS, log_block_mgr_.init(log_pool_base_path_));
EXPECT_EQ(ObServerLogBlockMgr::NORMAL_STATUS, log_block_mgr_.log_pool_meta_.status_);
EXPECT_EQ(next_total_size, log_block_mgr_.log_pool_meta_.curr_total_size_);
}
class DummyBlockPool : public palf::ILogBlockPool {
public:
virtual int create_block_at(const palf::FileDesc &dir_fd,
const char *block_path,
const int64_t block_size)
{
if (-1 == ::openat(dir_fd, block_path, palf::LOG_WRITE_FLAG | O_CREAT)) {
return OB_IO_ERROR;
}
return OB_SUCCESS;
}
virtual int remove_block_at(const palf::FileDesc &dir_fd,
const char *block_path)
{
if (-1 == ::unlinkat(dir_fd, block_path, 0)) {
return OB_IO_ERROR;
}
return OB_SUCCESS;
}
};
TEST_F(TestServerLogBlockMgr, basic_func_test)
{
const char *test_path = "clog_disk/basic_func_test";
const char *file_path_obs= "1.tmp";
const char *file_path = "clog_disk/basic_func_test/1.tmp";
char cmd_mkdir[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
char cmd_touch[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
char cmd_fallocate[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
snprintf(cmd_mkdir, OB_MAX_FILE_NAME_LENGTH, "mkdir %s", test_path);
snprintf(cmd_touch, OB_MAX_FILE_NAME_LENGTH, "touch %s", file_path);
snprintf(cmd_fallocate, OB_MAX_FILE_NAME_LENGTH, "fallocate -l %lu %s", PALF_PHY_BLOCK_SIZE, file_path);
system(cmd_mkdir);
system(cmd_touch);
int dir_fd = ::open(test_path, O_DIRECTORY | O_RDONLY);
bool result = false;
EXPECT_EQ(OB_SUCCESS, is_block_used_for_palf(dir_fd, file_path_obs, result));
EXPECT_EQ(false, result);
system(cmd_fallocate);
EXPECT_EQ(OB_SUCCESS, is_block_used_for_palf(dir_fd, file_path_obs, result));
EXPECT_EQ(true, result);
DummyBlockPool block_pool;
EXPECT_EQ(OB_SUCCESS, remove_tmp_file_or_directory_at(test_path, &block_pool));
EXPECT_EQ(OB_SUCCESS, FileDirectoryUtils::is_empty_directory(test_path, result));
EXPECT_EQ(true, result);
EXPECT_EQ(OB_SUCCESS, remove_directory_rec("clog_disk", &block_pool));
EXPECT_EQ(OB_SUCCESS, FileDirectoryUtils::is_exists("clog_disk", result));
EXPECT_EQ(false, result);
}
} // namespace unittest
} // namespace oceanbase
int main(int argc, char **argv)
{
system("rm -f test_server_log_block_mgr.log");
system("rm -rf clog_disk");
system("rm -rf clog_disk/clog");
system("mkdir clog_disk");
system("mkdir clog_disk/clog");
OB_LOGGER.set_file_name("test_server_log_block_mgr.log", true);
OB_LOGGER.set_log_level("INFO");
PALF_LOG(INFO, "begin unittest::test_server_log_block_mgr");
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}