/** * 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 #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 #include #define private public #include "logservice/ob_server_log_block_mgr.h" #undef private #include #include 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 tenant_ls_fd_map_; static std::vector tenant_1_ls_fd_; ObServerLogBlockMgr log_block_mgr_; ObSpinLock lock_; std::map map_; }; const char *TestServerLogBlockMgr::log_pool_base_path_ = "clog_disk/clog"; const char *TestServerLogBlockMgr::tenant_string_ = "clog_disk/clog/tenant_1"; std::map TestServerLogBlockMgr::tenant_ls_fd_map_; std::vector 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 threads; std::atomic 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 > 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_ERR_UNEXPECTED, 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); system("rm -rf clog_disk/clog/tenant_0111"); EXPECT_EQ(OB_SUCCESS, log_block_mgr_.init(log_pool_base_path_)); } 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(); }