585 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			585 lines
		
	
	
		
			23 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 {
 | |
|         //this->log_block_mgr_.abort_create_tenant(size);
 | |
|       }
 | |
|     }
 | |
|     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 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];
 | |
|       ret = this->log_block_mgr_.update_tenant(old_size, new_size);
 | |
|       if (OB_SUCCESS != ret) {
 | |
|         map_[key] = old_size;
 | |
|       } else {
 | |
|         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));
 | |
|   EXPECT_EQ(OB_SUCCESS, delete_blocks_at(ls_id, tenant_ls_fd_map_[ls_id], 0, 10));
 | |
| }
 | |
| 
 | |
| 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);
 | |
|   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_);
 | |
| }
 | |
| 
 | |
| 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_);
 | |
| }
 | |
| 
 | |
| 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();
 | |
| }
 | 
