311 lines
13 KiB
C++
311 lines
13 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.
|
|
*/
|
|
#define USING_LOG_PREFIX STORAGETEST
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/vfs.h>
|
|
#include <sys/types.h>
|
|
#include <gmock/gmock.h>
|
|
#define protected public
|
|
#define private public
|
|
#include "mittest/mtlenv/mock_tenant_module_env.h"
|
|
#include "mittest/shared_storage/clean_residual_data.h"
|
|
#include "storage/shared_storage/ob_ss_reader_writer.h"
|
|
#include "storage/shared_storage/ob_file_manager.h"
|
|
#include "storage/tmp_file/ob_tmp_file_manager.h"
|
|
#undef private
|
|
#undef protected
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace storage
|
|
{
|
|
using namespace oceanbase::blocksstable;
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::storage;
|
|
using namespace oceanbase::share;
|
|
|
|
class TestCalibrateDisk : public ::testing::Test
|
|
{
|
|
public:
|
|
TestCalibrateDisk() {}
|
|
virtual ~TestCalibrateDisk() = default;
|
|
static void SetUpTestCase();
|
|
static void TearDownTestCase();
|
|
virtual void SetUp();
|
|
virtual void TearDown();
|
|
static void prepare(const int64_t segment_id_pos);
|
|
static void write_dir();
|
|
public:
|
|
class TestThread : public Threads
|
|
{
|
|
public:
|
|
TestThread(ObTenantBase *tenant_base)
|
|
: tenant_base_(tenant_base), is_gc_tmp_file_(false), is_delete_dir_(false)
|
|
{}
|
|
|
|
virtual void run(int64_t idx) final
|
|
{
|
|
ObTenantEnv::set_tenant(tenant_base_);
|
|
ObTenantFileManager* tenant_file_mgr = MTL(ObTenantFileManager*);
|
|
ASSERT_NE(nullptr, tenant_file_mgr);
|
|
if (idx % 2 == 0) {
|
|
if (is_delete_dir_) {
|
|
const int64_t start_calc_size_time_s = ObTimeUtility::current_time_s();
|
|
ob_usleep(1L * 1000L * 1000L); //1s
|
|
LOG_INFO("start to calibrate tmp file alloc disk size");
|
|
ASSERT_EQ(OB_NO_SUCH_FILE_OR_DIRECTORY, tenant_file_mgr->calibrate_disk_space_task_.calibrate_alloc_disk_size(
|
|
ObStorageObjectType::TMP_FILE, start_calc_size_time_s, 0, 0));
|
|
LOG_INFO("finish to calibrate tmp file alloc disk size");
|
|
} else {
|
|
if (is_gc_tmp_file_) {
|
|
//because delete remote files need 9ms, delete local files need 5s
|
|
ob_usleep(3L * 1000L * 1000L); //3s
|
|
} else {
|
|
// because write 10w files need 10s
|
|
ob_usleep(5L * 1000L * 1000L); //5s
|
|
}
|
|
LOG_INFO("start to calibrate tmp file");
|
|
int64_t start_us = ObTimeUtility::current_time();
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->calibrate_disk_space_task_.calibrate_disk_space());
|
|
const int64_t cost_us = ObTimeUtility::current_time() - start_us;
|
|
LOG_INFO("finish to calibrate tmp file", K(cost_us));
|
|
}
|
|
} else {
|
|
if (is_delete_dir_) {
|
|
LOG_INFO("start to delete tmp file dir");
|
|
int64_t start_us = ObTimeUtility::current_time();
|
|
for (int64_t i = dir_num_; i >= 0; --i) {
|
|
MacroBlockId tmp_file;
|
|
tmp_file.set_id_mode((uint64_t)ObMacroBlockIdMode::ID_MODE_SHARE);
|
|
tmp_file.set_storage_object_type((uint64_t)ObStorageObjectType::TMP_FILE);
|
|
tmp_file.set_second_id(i);
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->delete_local_tmp_file(tmp_file));
|
|
}
|
|
const int64_t cost_us = ObTimeUtility::current_time() - start_us;
|
|
LOG_INFO("finish to delete tmp file dir", K(cost_us));
|
|
} else {
|
|
if (is_gc_tmp_file_) {
|
|
LOG_INFO("start to delete tmp file");
|
|
int64_t start_us = ObTimeUtility::current_time();
|
|
const int64_t DELETE_FILE_TIMEOUT = 10L * 1000L * 1000L;
|
|
MacroBlockId tmp_file;
|
|
tmp_file.set_id_mode((uint64_t)ObMacroBlockIdMode::ID_MODE_SHARE);
|
|
tmp_file.set_storage_object_type((uint64_t)ObStorageObjectType::TMP_FILE);
|
|
tmp_file.set_second_id(tmp_file_id_); // tmp_file_id
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->delete_tmp_file(tmp_file));
|
|
const int64_t cost_us = ObTimeUtility::current_time() - start_us;
|
|
LOG_INFO("finish to delete tmp file", K(cost_us));
|
|
} else {
|
|
LOG_INFO("start to write tmp file");
|
|
int64_t start_us = ObTimeUtility::current_time();
|
|
const int64_t segment_id_pos = file_num_;
|
|
TestCalibrateDisk::prepare(segment_id_pos);
|
|
const int64_t cost_us = ObTimeUtility::current_time() - start_us;
|
|
LOG_INFO("finish to write tmp file", K(cost_us));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void set_is_gc_tmp_file(const bool is_gc_tmp_file) { is_gc_tmp_file_ = is_gc_tmp_file; }
|
|
void set_is_delete_dir(const bool is_delete_dir) { is_delete_dir_ = is_delete_dir; }
|
|
|
|
private:
|
|
ObTenantBase *tenant_base_;
|
|
bool is_gc_tmp_file_;
|
|
bool is_delete_dir_;
|
|
};
|
|
|
|
public:
|
|
static const uint64_t tmp_file_id_ = 1001;
|
|
static const int64_t file_num_ = 100000; // 10w
|
|
static const int64_t dir_num_ = 30000; // 3w
|
|
static const int64_t file_size_ = 8 * 1024L; // 8KB
|
|
static const int64_t thread_cnt_ = 2;
|
|
};
|
|
|
|
void TestCalibrateDisk::SetUpTestCase()
|
|
{
|
|
GCTX.startup_mode_ = observer::ObServerMode::SHARED_STORAGE_MODE;
|
|
EXPECT_EQ(OB_SUCCESS, MockTenantModuleEnv::get_instance().init());
|
|
MTL(tmp_file::ObTenantTmpFileManager *)->stop();
|
|
MTL(tmp_file::ObTenantTmpFileManager *)->wait();
|
|
MTL(tmp_file::ObTenantTmpFileManager *)->destroy();
|
|
}
|
|
|
|
void TestCalibrateDisk::TearDownTestCase()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(ResidualDataCleanerHelper::clean_in_mock_env())) {
|
|
LOG_WARN("failed to clean residual data", KR(ret));
|
|
}
|
|
MockTenantModuleEnv::get_instance().destroy();
|
|
}
|
|
|
|
void TestCalibrateDisk::SetUp()
|
|
{
|
|
}
|
|
|
|
void TestCalibrateDisk::TearDown()
|
|
{
|
|
}
|
|
|
|
void TestCalibrateDisk::prepare(const int64_t segment_id_pos)
|
|
{
|
|
char write_buf[file_size_];
|
|
MEMSET(write_buf, 0, file_size_);
|
|
ObStorageObjectWriteInfo write_info;
|
|
write_info.io_desc_.set_wait_event(1);
|
|
write_info.io_desc_.set_unsealed();
|
|
write_info.buffer_ = write_buf;
|
|
write_info.offset_ = 0;
|
|
write_info.size_ = file_size_;
|
|
write_info.tmp_file_valid_length_ = file_size_;
|
|
write_info.io_timeout_ms_ = DEFAULT_IO_WAIT_TIME_MS;
|
|
write_info.mtl_tenant_id_ = MTL_ID();
|
|
|
|
for (int64_t i = segment_id_pos; i < segment_id_pos + file_num_; ++i) {
|
|
MacroBlockId macro_id;
|
|
macro_id.set_id_mode((uint64_t)ObMacroBlockIdMode::ID_MODE_SHARE);
|
|
macro_id.set_storage_object_type((uint64_t)ObStorageObjectType::TMP_FILE);
|
|
macro_id.set_second_id(tmp_file_id_); // tmp_file_id
|
|
macro_id.set_third_id(i); // segment_file_id
|
|
ASSERT_TRUE(macro_id.is_valid());
|
|
ObStorageObjectHandle write_object_handle;
|
|
ASSERT_EQ(OB_SUCCESS, write_object_handle.set_macro_block_id(macro_id));
|
|
ObTenantFileManager* tenant_file_mgr = MTL(ObTenantFileManager*);
|
|
ASSERT_NE(nullptr, tenant_file_mgr);
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->append_file(write_info, write_object_handle));
|
|
}
|
|
}
|
|
|
|
void TestCalibrateDisk::write_dir()
|
|
{
|
|
char write_buf[file_size_];
|
|
MEMSET(write_buf, 0, file_size_);
|
|
ObStorageObjectWriteInfo write_info;
|
|
write_info.io_desc_.set_wait_event(1);
|
|
write_info.io_desc_.set_unsealed();
|
|
write_info.buffer_ = write_buf;
|
|
write_info.offset_ = 0;
|
|
write_info.size_ = file_size_;
|
|
write_info.io_timeout_ms_ = DEFAULT_IO_WAIT_TIME_MS;
|
|
write_info.mtl_tenant_id_ = MTL_ID();
|
|
|
|
for (int64_t i = 0; i < dir_num_; ++i) {
|
|
MacroBlockId macro_id;
|
|
macro_id.set_id_mode((uint64_t)ObMacroBlockIdMode::ID_MODE_SHARE);
|
|
macro_id.set_storage_object_type((uint64_t)ObStorageObjectType::TMP_FILE);
|
|
macro_id.set_second_id(i); // tmp_file_id
|
|
macro_id.set_third_id(0); // segment_file_id
|
|
ASSERT_TRUE(macro_id.is_valid());
|
|
ObStorageObjectHandle write_object_handle;
|
|
ASSERT_EQ(OB_SUCCESS, write_object_handle.set_macro_block_id(macro_id));
|
|
ObTenantFileManager* tenant_file_mgr = MTL(ObTenantFileManager*);
|
|
ASSERT_NE(nullptr, tenant_file_mgr);
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->append_file(write_info, write_object_handle));
|
|
}
|
|
}
|
|
|
|
TEST_F(TestCalibrateDisk, calibrate_and_write_file)
|
|
{
|
|
ObTenantDiskSpaceManager* tenant_disk_space_mgr = MTL(ObTenantDiskSpaceManager*);
|
|
int64_t total_disk_size = 20L * 1024L * 1024L * 1024L; // 20GB
|
|
ASSERT_EQ(OB_SUCCESS, tenant_disk_space_mgr->resize_total_disk_size(total_disk_size));
|
|
ASSERT_EQ(total_disk_size, tenant_disk_space_mgr->get_total_disk_size());
|
|
|
|
// prepare file
|
|
const int64_t segment_id_pos = 0;
|
|
TestCalibrateDisk::prepare(segment_id_pos);
|
|
// test write files and calibrate
|
|
TestCalibrateDisk::TestThread calibrate_write_threads(ObTenantEnv::get_tenant());
|
|
calibrate_write_threads.set_is_gc_tmp_file(false);
|
|
calibrate_write_threads.set_thread_count(thread_cnt_);
|
|
calibrate_write_threads.start();
|
|
calibrate_write_threads.wait();
|
|
calibrate_write_threads.destroy();
|
|
int64_t tmp_file_write_cache_alloc_size = tenant_disk_space_mgr->get_tmp_file_write_cache_alloc_size();
|
|
const int64_t delta_alloc_size = std::abs(tmp_file_write_cache_alloc_size - TestCalibrateDisk::file_num_ * 2 * TestCalibrateDisk::file_size_);
|
|
// because statbuf.mtime_s_ is second level, maybe at start_calc_time_s has written some files
|
|
// ASSERT_EQ(TestCalibrateDisk::file_num_ * 2 * TestCalibrateDisk::file_size_, tmp_file_write_cache_alloc_size);
|
|
ASSERT_TRUE(delta_alloc_size < tmp_file_write_cache_alloc_size * 0.05);
|
|
}
|
|
|
|
TEST_F(TestCalibrateDisk, calibrate_and_delete_file)
|
|
{
|
|
ObTenantDiskSpaceManager* tenant_disk_space_mgr = MTL(ObTenantDiskSpaceManager*);
|
|
int64_t total_disk_size = 20L * 1024L * 1024L * 1024L; // 20GB
|
|
ASSERT_EQ(OB_SUCCESS, tenant_disk_space_mgr->resize_total_disk_size(total_disk_size));
|
|
ASSERT_EQ(total_disk_size, tenant_disk_space_mgr->get_total_disk_size());
|
|
|
|
// need calibrate disk space before calibrate_and_delete_file test,
|
|
// because calibrate_and_write_file statbuf.mtime_s_ is second level, maybe at start_calc_time_s has written some files,
|
|
// lead to calibrate disk size is inaccurate
|
|
ObTenantFileManager* tenant_file_mgr = MTL(ObTenantFileManager*);
|
|
ASSERT_NE(nullptr, tenant_file_mgr);
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->calibrate_disk_space_task_.calibrate_disk_space());
|
|
int64_t tmp_file_write_cache_alloc_size = tenant_disk_space_mgr->get_tmp_file_write_cache_alloc_size();
|
|
int64_t expected_disk_size = TestCalibrateDisk::file_num_ * 2 * TestCalibrateDisk::file_size_;
|
|
ObIODFileStat statbuf;
|
|
char dir_path[ObBaseFileManager::OB_MAX_FILE_PATH_LENGTH] = {0};
|
|
ASSERT_EQ(OB_SUCCESS, OB_DIR_MGR.get_local_tmp_file_dir(dir_path, sizeof(dir_path), MTL_ID(), MTL_EPOCH_ID(), tmp_file_id_));
|
|
ASSERT_EQ(OB_SUCCESS, ObIODeviceLocalFileOp::stat(dir_path, statbuf));
|
|
expected_disk_size += statbuf.size_;
|
|
LOG_INFO("local tmp file dir size", K(statbuf.size_), K(expected_disk_size), K(tmp_file_write_cache_alloc_size));
|
|
ASSERT_EQ(expected_disk_size, tmp_file_write_cache_alloc_size);
|
|
|
|
// test gc files and calibrate
|
|
TestCalibrateDisk::TestThread calibrate_gc_threads(ObTenantEnv::get_tenant());
|
|
calibrate_gc_threads.set_is_gc_tmp_file(true);
|
|
calibrate_gc_threads.set_thread_count(thread_cnt_);
|
|
calibrate_gc_threads.start();
|
|
calibrate_gc_threads.wait();
|
|
calibrate_gc_threads.destroy();
|
|
// because xfs dir size will become smaller as sub_files are deleted, so need calibrate disk size, otherwise tmp_file_write_cache_alloc_size is not 0, maybe dir size
|
|
ASSERT_EQ(OB_SUCCESS, tenant_file_mgr->calibrate_disk_space_task_.calibrate_disk_space());
|
|
tmp_file_write_cache_alloc_size = tenant_disk_space_mgr->get_tmp_file_write_cache_alloc_size();
|
|
ASSERT_EQ(0, tmp_file_write_cache_alloc_size);
|
|
}
|
|
|
|
TEST_F(TestCalibrateDisk, calibrate_and_delete_dir)
|
|
{
|
|
ObTenantDiskSpaceManager* tenant_disk_space_mgr = MTL(ObTenantDiskSpaceManager*);
|
|
int64_t total_disk_size = 20L * 1024L * 1024L * 1024L; // 20GB
|
|
ASSERT_EQ(OB_SUCCESS, tenant_disk_space_mgr->resize_total_disk_size(total_disk_size));
|
|
ASSERT_EQ(total_disk_size, tenant_disk_space_mgr->get_total_disk_size());
|
|
|
|
// prepare file
|
|
TestCalibrateDisk::write_dir();
|
|
// test write files and calibrate
|
|
TestCalibrateDisk::TestThread calibrate_delete_threads(ObTenantEnv::get_tenant());
|
|
calibrate_delete_threads.set_is_delete_dir(true);
|
|
calibrate_delete_threads.set_thread_count(thread_cnt_);
|
|
calibrate_delete_threads.start();
|
|
calibrate_delete_threads.wait();
|
|
calibrate_delete_threads.destroy();
|
|
}
|
|
|
|
|
|
} // namespace storage
|
|
} // namespace oceanbase
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int ret = 0;
|
|
system("rm -f ./test_calibrate_disk_space.log*");
|
|
OB_LOGGER.set_file_name("test_calibrate_disk_space.log", true);
|
|
OB_LOGGER.set_log_level("INFO");
|
|
testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|