Files
oceanbase/mittest/shared_storage/clean_residual_data.h
2024-11-27 17:16:17 +00:00

177 lines
6.5 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.
*/
#ifndef OCEANBASE_SENSITIVE_TEST_SHARED_STORAGE_CLEAN_RESIDUAL_DATA_H_
#define OCEANBASE_SENSITIVE_TEST_SHARED_STORAGE_CLEAN_RESIDUAL_DATA_H_
#include <gtest/gtest.h>
#include "share/backup/ob_backup_struct.h" // ObBackupStorageInfo
#include "share/backup/ob_backup_io_adapter.h" // ObBackupIoAdapter
#include "share/backup/ob_backup_path.h" // ObBackupPath
#include "share/object_storage/ob_device_config_mgr.h" // ObDeviceConfigMgr
namespace oceanbase {
namespace storage {
// `TestDelOp` is used to perform deletion operations on files while listing files.
class TestDelOp : public ObBaseDirEntryOperator
{
public:
TestDelOp(const share::ObBackupPath &path, const share::ObBackupStorageInfo *storage_info)
: path_(path), storage_info_(storage_info)
{}
virtual ~TestDelOp()
{}
int func(const dirent *entry) override;
private:
const share::ObBackupPath path_;
const share::ObBackupStorageInfo *storage_info_;
};
int TestDelOp::func(const dirent *entry)
{
int ret = OB_SUCCESS;
common::ObBackupIoAdapter io_adapter;
share::ObBackupPath tmp_path;
if (OB_ISNULL(entry)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid list entry, entry is null", KR(ret));
} else if (OB_ISNULL(entry->d_name)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid list entry, d_name is null", KR(ret));
} else if (OB_FAIL(tmp_path.init(path_.get_obstr()))) {
OB_LOG(WARN, "failed to init tmp_path", KR(ret), K_(path));
} else if (OB_FAIL(tmp_path.join(entry->d_name, share::ObBackupFileSuffix::NONE))) {
OB_LOG(WARN, "failed to join file name", KR(ret), KCSTRING(entry->d_name));
} else if (OB_FAIL(io_adapter.del_file(tmp_path.get_ptr(), storage_info_))) {
// File does not exist should be considered successful
if (OB_OBJECT_NOT_EXIST == ret) {
OB_LOG(INFO, "object is not exist", KR(ret), K(tmp_path));
ret = OB_SUCCESS;
} else {
OB_LOG(WARN, "failed to delete file", KR(ret), K(tmp_path));
}
} else {
OB_LOG(INFO, "success to delete file", K(tmp_path));
}
return ret;
}
class ResidualDataCleaner
{
public:
ResidualDataCleaner() : is_inited_(false), path_(), storage_info_()
{}
virtual ~ResidualDataCleaner()
{}
// Directly retrieve the device_config from the mock environment
// in the test and perform initialization.
int init_in_mock_env();
int clean_residual_data();
private:
int init(const char *path, const char *endpoint, const char *access_info, const char *extension);
bool is_inited_;
share::ObBackupPath path_;
share::ObBackupStorageInfo storage_info_;
};
int ResidualDataCleaner::init(const char *path, const char *endpoint, const char *access_info, const char *extension)
{
int ret = OB_SUCCESS;
common::ObStorageType type = common::ObStorageType::OB_STORAGE_MAX_TYPE;
if (OB_ISNULL(path) || OB_ISNULL(endpoint) || OB_ISNULL(access_info) || OB_ISNULL(extension)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid initialization argument", KR(ret), KP(path), KP(endpoint), KP(access_info), KP(extension));
} else if (OB_FAIL(path_.init(path))) {
OB_LOG(WARN, "failed to set path when initiating residual data cleaner", KR(ret), KCSTRING(path));
} else if (OB_FAIL(get_storage_type_from_path(path, type))) {
OB_LOG(WARN, "failed to get storage type when initiating residual data cleaner", KR(ret), KCSTRING(path));
} else if (OB_FAIL(storage_info_.set(type, endpoint, access_info, extension))) {
OB_LOG(WARN, "failed to set storage info when initiating residual data cleaner", KR(ret), KCSTRING(path), KCSTRING(endpoint));
} else {
is_inited_ = true;
OB_LOG(INFO, "success to initiate residual data cleaner", KCSTRING(path), KCSTRING(endpoint));
}
return ret;
};
int ResidualDataCleaner::init_in_mock_env()
{
int ret = OB_SUCCESS;
share::ObDeviceConfig device_config;
if (OB_FAIL(share::ObDeviceConfigMgr::get_instance().get_device_config(
share::ObStorageUsedType::TYPE::USED_TYPE_DATA, device_config))) {
OB_LOG(WARN, "failed to get device config when initiating residual data cleaner", KR(ret));
} else if (OB_FAIL(init(
device_config.path_, device_config.endpoint_, device_config.access_info_, device_config.extension_))) {
OB_LOG(WARN, "failed to init residual data cleaner", KR(ret));
}
return ret;
};
int ResidualDataCleaner::clean_residual_data()
{
int ret = OB_SUCCESS;
common::ObBackupIoAdapter io_adapter;
TestDelOp del_op(path_, &storage_info_);
if (OB_FAIL(io_adapter.list_files(path_.get_obstr(), &storage_info_, del_op))) {
if (OB_DIR_NOT_EXIST == ret) {
OB_LOG(INFO, "dir is not exist when cleaning residual data", KR(ret));
ret = OB_SUCCESS;
} else {
OB_LOG(WARN, "failed to del dir when cleaning residual data", KR(ret));
}
} else {
OB_LOG(INFO, "success to clean residual data");
}
return ret;
};
class ResidualDataCleanerHelper
{
public:
ResidualDataCleanerHelper()
{}
virtual ~ResidualDataCleanerHelper()
{}
static int clean_in_mock_env();
};
int ResidualDataCleanerHelper::clean_in_mock_env()
{
int ret = OB_SUCCESS;
const int failed_count = ::testing::UnitTest::GetInstance()->failed_test_count();
const ::testing::TestCase *test_case = ::testing::UnitTest::GetInstance()->current_test_case();
// When all test cases are passed, clean residual data
if (OB_ISNULL(test_case)) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "test case is null when try to clean residual data", KR(ret));
} else if (failed_count == 0) {
int ret = OB_SUCCESS;
ResidualDataCleaner cleaner;
if (OB_FAIL(cleaner.init_in_mock_env())) {
OB_LOG(WARN, "failed to init residual data cleaner", KR(ret));
} else if (OB_FAIL(cleaner.clean_residual_data())) {
OB_LOG(WARN, "failed to clean residual data", KR(ret), K(test_case->name()));
} else {
OB_LOG(INFO, "success to clean residual data after test", K(test_case->name()));
}
}
return ret;
};
} // namespace storage
} // namespace oceanbase
#endif // OCEANBASE_SENSITIVE_TEST_SHARED_STORAGE_CLEAN_RESIDUAL_DATA_H_