630 lines
25 KiB
C++
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();
|
|
}
|