177 lines
6.5 KiB
C++
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_
|