oceanbase/deps/oblib/src/lib/restore/ob_storage.cpp

2302 lines
80 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 "ob_storage.h"
#include "lib/restore/ob_i_storage.h"
#include "lib/utility/ob_tracepoint.h"
#include "lib/stat/ob_diagnose_info.h"
#include "lib/container/ob_array_iterator.h"
#include "common/ob_smart_var.h"
#include "common/storage/ob_device_common.h"
#include "lib/atomic/ob_atomic.h"
namespace oceanbase
{
namespace common
{
const char *OB_STORAGE_TYPES_STR[] = {"OSS", "FILE", "COS", "LOCAL", "S3"};
void print_access_storage_log(
const char *msg,
const common::ObString &uri,
const int64_t start_ts,
const int64_t size,
bool *is_slow)
{
if (NULL != is_slow) {
*is_slow = false;
}
if (NULL != msg) {
int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
const int64_t warn_cost_time = 1000 * 1000;
double speed = 0;
if (cost_ts > warn_cost_time) {
if (NULL != is_slow) {
*is_slow = true;
}
speed = 1.0 * (double)size / 1024 / 1024 * 1000 * 1000 / (double)cost_ts;
_STORAGE_LOG_RET(WARN, OB_SUCCESS, "access storage op=%s uri=%.*s size=%ld Byte cost_ts=%ld us speed=%.2f MB/s",
msg, uri.length(), uri.ptr(), size, cost_ts, speed);
}
}
}
int validate_uri_type(const common::ObString &uri)
{
int ret = OB_SUCCESS;
if (!uri.prefix_match(OB_OSS_PREFIX) &&
!uri.prefix_match(OB_COS_PREFIX) &&
!uri.prefix_match(OB_S3_PREFIX) &&
!uri.prefix_match(OB_FILE_PREFIX)) {
ret = OB_INVALID_BACKUP_DEST;
STORAGE_LOG(ERROR, "invalid backup uri", K(ret), K(uri));
}
return ret;
}
int get_storage_type_from_path(const common::ObString &uri, ObStorageType &type)
{
int ret = OB_SUCCESS;
type = OB_STORAGE_MAX_TYPE;
if (uri.prefix_match(OB_OSS_PREFIX)) {
type = OB_STORAGE_OSS;
} else if (uri.prefix_match(OB_COS_PREFIX)) {
type = OB_STORAGE_COS;
} else if (uri.prefix_match(OB_S3_PREFIX)) {
type = OB_STORAGE_S3;
} else if (uri.prefix_match(OB_FILE_PREFIX)) {
type = OB_STORAGE_FILE;
} else {
ret = OB_INVALID_BACKUP_DEST;
STORAGE_LOG(ERROR, "invalid backup uri", K(ret), K(uri));
}
return ret;
}
const char *get_storage_type_str(const ObStorageType &type)
{
const char *str = "UNKNOWN";
STATIC_ASSERT(static_cast<int64_t>(OB_STORAGE_MAX_TYPE) == ARRAYSIZEOF(OB_STORAGE_TYPES_STR), "ObStorageType count mismatch");
if (type >= 0 && type < OB_STORAGE_MAX_TYPE) {
str = OB_STORAGE_TYPES_STR[type];
}
return str;
}
bool is_io_error(const int result)
{
return OB_IO_ERROR == result || OB_OSS_ERROR == result || OB_COS_ERROR == result || OB_S3_ERROR == result;
}
int get_storage_type_from_name(const char *type_str, ObStorageType &type)
{
int ret = OB_SUCCESS;
type = ObStorageType::OB_STORAGE_MAX_TYPE;
const int64_t count = ARRAYSIZEOF(OB_STORAGE_TYPES_STR);
STATIC_ASSERT(static_cast<int64_t>(ObStorageType::OB_STORAGE_MAX_TYPE) == count, "status count mismatch");
for (int64_t i = 0; i < count; ++i) {
if (0 == strcmp(type_str, OB_STORAGE_TYPES_STR[i])) {
type = static_cast<ObStorageType>(i);
break;
}
}
return ret;
}
// let path end with '/'
int build_full_dir_path(const char *dir_path, char *dir_path_buf, const int64_t dir_path_buf_len)
{
int ret = OB_SUCCESS;
int64_t pos = 0;
if (OB_ISNULL(dir_path) || OB_ISNULL(dir_path_buf) ||
OB_UNLIKELY(strlen(dir_path) <= 0 || dir_path_buf_len <= 0)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid arguments", K(ret), K(dir_path), KP(dir_path_buf), K(dir_path_buf_len));
} else if (OB_FAIL(databuff_printf(dir_path_buf, dir_path_buf_len, pos, "%s", dir_path))) {
OB_LOG(WARN, "failed to deep copy dir path", K(ret), K(dir_path), K(dir_path_buf_len));
} else if (!is_end_with_slash(dir_path)
&& OB_FAIL(databuff_printf(dir_path_buf, dir_path_buf_len, pos, "/"))) {
OB_LOG(WARN, "failed to make path end with '/'", K(ret), K(dir_path), K(dir_path_buf_len));
}
return ret;
}
/**
* ------------------------------ListAppendableObjectFragmentOp------------------------------
*/
int ListAppendableObjectFragmentOp::func(const dirent *entry)
{
int ret = OB_SUCCESS;
ObString fragment_name(entry->d_name);
ObAppendableFragmentMeta fragment_meta;
if (OB_FAIL(fragment_meta.parse_from(fragment_name))) {
OB_LOG(WARN, "fail to parse fragment name", K(ret), K(entry->d_name));
} else if (OB_LIKELY(fragment_meta.is_valid())) {
if (fragment_meta.is_format_meta()) {
exist_format_meta_ = true;
} else if (fragment_meta.is_seal_meta()) {
exist_seal_meta_ = true;
} else if (fragment_meta.is_data()) {
if (need_get_file_size()) {
if (get_size() != fragment_meta.get_length()) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "fragment file size is not equal to the fragment name range", K(ret), "file_size",
get_size(), K(fragment_meta));
}
}
if (FAILEDx(meta_arr_.push_back(fragment_meta))) {
OB_LOG(WARN, "fail to push back fragment meta", K(ret), K(fragment_meta));
}
} else {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "unknown fragment meta type", K(ret), K(fragment_meta));
}
} else {
// just skip this invalid fragment, continue next one.
OB_LOG(WARN, "invalid fragment name", K(ret), K(entry->d_name));
}
return ret;
}
int ListAppendableObjectFragmentOp::gen_object_meta(ObStorageObjectMeta &obj_meta)
{
int ret = OB_SUCCESS;
int64_t i = 0;
int64_t last_end_offset = 0;
obj_meta.reset();
obj_meta.type_ = ObStorageObjectMetaType::OB_OBJ_SIMULATE_APPEND;
std::sort(meta_arr_.begin(), meta_arr_.end(), ObStorageObjectMeta::fragment_meta_cmp_func);
while (OB_SUCC(ret) && i < meta_arr_.size()) {
ObAppendableFragmentMeta &tmp_meta = meta_arr_[i];
last_end_offset = tmp_meta.end_;
if (OB_FAIL(obj_meta.fragment_metas_.push_back(tmp_meta))) {
OB_LOG(WARN, "failed to push back fragment meta", K(ret), K(obj_meta.fragment_metas_));
}
// find a fragment that intersects with the current fragment(and not covered by the current fragment)
// and can maximize the coverage of the file contents
int64_t j = i + 1;
int64_t selected_idx = i;
int64_t max_end_offset = tmp_meta.end_;
while (OB_SUCC(ret) && j < meta_arr_.size() && meta_arr_[j].start_ <= tmp_meta.end_) {
if (meta_arr_[j].end_ > max_end_offset) {
selected_idx = j;
max_end_offset = meta_arr_[j].end_;
}
j++;
}
if (OB_FAIL(ret)) {
} else if (selected_idx == i) {
if (i < meta_arr_.size() - 1) {
// do not return error
OB_LOG(WARN, "cannot find a fragment that intersects with the current fragment",
K(i), K(j), K(tmp_meta));
}
i = j;
} else {
i = selected_idx;
}
}
if (OB_SUCC(ret)) {
obj_meta.is_exist_ = true;
obj_meta.length_ = last_end_offset;
}
return ret;
}
/**
* ------------------------------DelAppendableObjectFragmentOp------------------------------
*/
DelAppendableObjectFragmentOp::DelAppendableObjectFragmentOp(
const common::ObString &uri, ObStorageUtil &util)
: uri_(uri), util_(util)
{}
int DelAppendableObjectFragmentOp::func(const dirent *entry)
{
int ret = OB_SUCCESS;
char obj_fragment_path[OB_MAX_URI_LENGTH] = {0};
const char *delemiter_str = is_end_with_slash(uri_.ptr()) ? "" : "/";
if (OB_ISNULL(entry)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid argument", K(ret));
} else if (OB_FAIL(databuff_printf(obj_fragment_path, sizeof(obj_fragment_path),
"%s%s%s", uri_.ptr(), delemiter_str, entry->d_name))) {
OB_LOG(WARN, "fail to construct appendable obj fragment path", K(ret), K_(uri), K(delemiter_str), K(entry->d_name));
} else if (OB_FAIL(util_.del_file(obj_fragment_path))) {
OB_LOG(WARN, "fail to del appendable object fragment", K(ret), K(obj_fragment_path));
} else {
OB_LOG(DEBUG, "succ to del appendable object fragment", K(obj_fragment_path));
}
return ret;
}
/**
* ------------------------------ObStorageGlobalIns------------------------------
*/
ObStorageGlobalIns::ObStorageGlobalIns()
:io_prohibited_(false)
{}
ObStorageGlobalIns& ObStorageGlobalIns::get_instance()
{
static ObStorageGlobalIns instance;
return instance;
}
int ObStorageGlobalIns::init()
{
int ret = OB_SUCCESS;
io_prohibited_ = false;
return ret;
}
void ObStorageGlobalIns::fin()
{
}
void ObStorageGlobalIns::set_io_prohibited(bool prohibited)
{
STORAGE_LOG_RET(WARN, OB_SUCCESS, "set_io_prohibited", K_(io_prohibited), K(prohibited));
io_prohibited_ = prohibited;
}
bool ObStorageGlobalIns::is_io_prohibited() const
{
return io_prohibited_;
}
/**
* ------------------------------ObExternalIOCounter------------------------------
*/
int64_t ObExternalIOCounter::flying_io_cnt_ = 0;
void ObExternalIOCounter::inc_flying_io()
{
ATOMIC_INC(&ObExternalIOCounter::flying_io_cnt_);
}
void ObExternalIOCounter::dec_flying_io()
{
ATOMIC_DEC(&ObExternalIOCounter::flying_io_cnt_);
}
int64_t ObExternalIOCounter::get_flying_io_cnt()
{
return ATOMIC_LOAD(&ObExternalIOCounter::flying_io_cnt_);
}
/**
* ------------------------------ObExternalIOCounterGuard------------------------------
*/
ObExternalIOCounterGuard::ObExternalIOCounterGuard()
{
io_counter_.inc_flying_io();
}
ObExternalIOCounterGuard::~ObExternalIOCounterGuard()
{
io_counter_.dec_flying_io();
}
/**
* ------------------------------ObStorageUtil------------------------------
*/
ObStorageUtil::ObStorageUtil()
: file_util_(),
oss_util_(),
cos_util_(),
s3_util_(),
util_(NULL),
storage_info_(NULL),
init_state(false),
device_type_(ObStorageType::OB_STORAGE_MAX_TYPE)
{
}
/*this fun just like the get_util*/
int ObStorageUtil::open(common::ObObjectStorageInfo *storage_info)
{
int ret = OB_SUCCESS;
if (is_init()) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "double init the storage util", K(ret));
} else if (OB_ISNULL(storage_info) || OB_UNLIKELY(!storage_info->is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), KP(storage_info));
} else if (OB_FALSE_IT(device_type_ = storage_info->get_type())) {
} else if (OB_STORAGE_OSS == device_type_) {
util_ = &oss_util_;
} else if (OB_STORAGE_COS == device_type_) {
util_ = &cos_util_;
} else if (OB_STORAGE_S3 == device_type_) {
util_ = &s3_util_;
} else if (OB_STORAGE_FILE == device_type_) {
util_ = &file_util_;
} else {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid device type", K(ret), K_(device_type));
}
if (OB_SUCC(ret) && NULL != util_) {
if (OB_FAIL(util_->open(storage_info))) {
STORAGE_LOG(WARN, "failed to open util", K(ret), K_(device_type));
util_ = NULL;
} else {
storage_info_ = storage_info;
init_state = true;
}
}
return ret;
}
void ObStorageUtil::close()
{
if (NULL != util_) {
util_->close();
util_ = NULL;
storage_info_ = NULL;
init_state = false;
device_type_ = OB_STORAGE_MAX_TYPE;
}
}
/*---------------------------------- NEW ADAPTIVE INTERFACE ----------------------------------*/
int ObStorageUtil::detect_storage_obj_meta(
const common::ObString &uri,
const bool is_adaptive,
const bool need_fragment_meta,
ObStorageObjectMeta &obj_meta)
{
int ret = OB_SUCCESS;
obj_meta.reset();
bool need_detect_appendable = is_adaptive;
if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(util_->head_object_meta(uri, obj_meta))) {
STORAGE_LOG(WARN, "fail to head object meta", K(ret), K(uri));
} else if (obj_meta.is_exist_) {
if (ObStorageObjectMetaType::OB_FS_DIR != obj_meta.type_) {
// just return directly
need_detect_appendable = false;
obj_meta.type_ = ObStorageObjectMetaType::OB_OBJ_NORMAL;
}
}
if (OB_SUCC(ret) && need_detect_appendable) {
obj_meta.reset();
int64_t pos = 0;
// if need_fragment_meta is TRUE, we need to obtain fragment meta from seal_meta or list_info
if (need_fragment_meta) {
if (OB_FAIL(read_seal_meta_if_needed(uri, obj_meta))) {
OB_LOG(WARN, "fail to read seal meta if needed", K(ret), K(uri));
}
// If not exist seal meta, we need to list all files and check format meta exist or not.
// format meta must exist, otherwise need to return error.
if (OB_SUCC(ret) && !obj_meta.is_exist_) {
if (OB_FAIL(list_appendable_file_fragments(uri, obj_meta))) {
OB_LOG(WARN, "fail to list appendable file fragments", K(ret), K(uri));
}
}
} else {
// if need_fragment_meta is FALSE, just check format_meta exist or not
char format_meta_uri[OB_MAX_URI_LENGTH] = { 0 };
if (OB_FAIL(construct_fragment_full_name(uri, OB_S3_APPENDABLE_FORMAT_META,
format_meta_uri, sizeof(format_meta_uri)))) {
OB_LOG(WARN, "fail to construct s3 format_meta name", K(ret), K(uri));
} else if (OB_FAIL(util_->head_object_meta(format_meta_uri, obj_meta))) {
STORAGE_LOG(WARN, "fail to head object meta", K(ret), K(format_meta_uri));
} else if (obj_meta.is_exist_) {
obj_meta.type_ = ObStorageObjectMetaType::OB_OBJ_SIMULATE_APPEND;
} else {
if (ObStorageObjectMetaType::OB_FS_DIR == obj_meta.type_) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "please set is_adaptive as false when want to check a common dir exist or not",
K(ret), K(uri), K(is_adaptive));
}
}
}
}
return ret;
}
int ObStorageUtil::read_seal_meta_if_needed(
const common::ObString &uri,
ObStorageObjectMeta &obj_meta)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObArenaAllocator allocator(APPENDABLE_OBJECT_ALLOCATOR);
int64_t pos = 0;
char *seal_meta_uri = NULL;
if (OB_ISNULL(seal_meta_uri = static_cast<char *>(allocator.alloc(OB_MAX_URI_LENGTH)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
OB_LOG(WARN, "fail to alloc buf for reading seal meta file", K(ret));
} else if (FALSE_IT(memset(seal_meta_uri, 0, OB_MAX_URI_LENGTH))) {
} else if (OB_FAIL(construct_fragment_full_name(uri, OB_S3_APPENDABLE_SEAL_META,
seal_meta_uri, OB_MAX_URI_LENGTH))) {
OB_LOG(WARN, "fail to construct s3 seal_meta name", K(ret), K(uri));
} else {
ObStorageReader reader;
int64_t seal_meta_len = 0;
if (OB_FAIL(reader.open(seal_meta_uri, storage_info_))) {
if (OB_BACKUP_FILE_NOT_EXIST == ret) {
obj_meta.is_exist_ = false;
ret = OB_SUCCESS;
}
} else {
// If exist seal meta, directly read it content.
seal_meta_len = reader.get_length();
if (seal_meta_len > 0) {
int64_t read_size = 0;
char *buf = NULL;
pos = 0;
if (OB_ISNULL(buf = static_cast<char *>(allocator.alloc(seal_meta_len + 1)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
OB_LOG(WARN, "fail to alloc buf for reading seal meta file", K(ret), K(seal_meta_uri), K(seal_meta_len));
} else if (OB_FAIL(reader.pread(buf, seal_meta_len, 0/*offset*/, read_size))) {
OB_LOG(WARN, "failed to read seal meta file content", K(ret), K(seal_meta_uri), K(seal_meta_len));
} else if (OB_UNLIKELY(seal_meta_len != read_size)) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "fail to read seal meta file entire content",
K(ret), K(seal_meta_uri), K(seal_meta_len), K(read_size));
} else if (OB_FAIL(obj_meta.deserialize(buf, read_size, pos))) {
OB_LOG(WARN, "fail to deserialize storage object meta", K(ret), K(seal_meta_uri), K(read_size), KP(buf));
} else {
obj_meta.is_exist_ = true;
}
} else {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "the seal meta file is empty", K(ret), K(seal_meta_uri));
}
if (OB_TMP_FAIL(reader.close())) {
OB_LOG(WARN, "fail to close reader", K(ret), K(tmp_ret), K(seal_meta_uri));
}
}
}
return ret;
}
int ObStorageUtil::list_appendable_file_fragments(
const ObString &uri,
ObStorageObjectMeta &obj_meta)
{
int ret = OB_SUCCESS;
int64_t appendable_file_length = -1;
ListAppendableObjectFragmentOp op;
obj_meta.reset();
if (OB_FAIL(list_files(uri, false, op))) {
OB_LOG(WARN, "failed to list appendable object fragments", K(ret), K(uri));
} else if (OB_UNLIKELY(!op.exist_format_meta())) {
ret = OB_BACKUP_FILE_NOT_EXIST;
OB_LOG(WARN, "not exist valid appendable file, cuz lack of format_meta", K(ret), K(uri));
} else if (FALSE_IT(obj_meta.is_exist_ = true)) {
} else if (FALSE_IT(obj_meta.type_ = ObStorageObjectMetaType::OB_OBJ_SIMULATE_APPEND)) {
} else if (OB_FAIL(op.gen_object_meta(obj_meta))) {
OB_LOG(WARN, "fail to gen object meta based on the listed meta info", K(ret), K(uri));
}
return ret;
}
int ObStorageUtil::is_exist(const common::ObString &uri, const bool is_adaptive, bool &exist)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
exist = false;
ObStorageObjectMeta obj_meta;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_IS_EXIST) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
//do nothing
} else if (OB_FAIL(validate_uri_type(uri))) {
OB_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(detect_storage_obj_meta(uri, is_adaptive, false/*need_fragment_meta*/, obj_meta))) {
OB_LOG(WARN, "fail to detect storage obj type", K(ret), K(uri), K(is_adaptive));
} else {
exist = obj_meta.is_exist_;
}
print_access_storage_log("is_exist", uri, start_ts);
return ret;
}
int ObStorageUtil::get_file_length(const common::ObString &uri, const bool is_adaptive, int64_t &file_length)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
file_length = -1;
ObStorageObjectMeta obj_meta;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_GET_FILE_LENGTH) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_FAIL(validate_uri_type(uri))) {
OB_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(detect_storage_obj_meta(uri, is_adaptive, true/*need_fragment_meta*/, obj_meta))) {
OB_LOG(WARN, "fail to detect storage obj type", K(ret), K(uri), K(is_adaptive));
} else if (!obj_meta.is_exist_) {
ret = OB_BACKUP_FILE_NOT_EXIST;
OB_LOG(INFO, "cannot get file length for not exist file", K(ret), K(uri));
} else {
file_length = obj_meta.length_;
}
if (OB_SUCC(ret)) {
if (file_length == 0) {
OB_LOG(INFO, "this file is empty", K(ret), K(uri), K(file_length));
} else if (file_length < 0) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "this file length is invalid", K(ret), K(uri), K(file_length));
}
}
print_access_storage_log("get_file_length", uri, start_ts);
return ret;
}
int ObStorageUtil::del_file(const common::ObString &uri, const bool is_adaptive)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
ObStorageObjectMeta obj_meta;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_BEFORE_DEL_FILE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(detect_storage_obj_meta(uri, is_adaptive, false/*need_fragment_meta*/, obj_meta))) {
OB_LOG(WARN, "fail to detect storage obj type", K(ret), K(uri), K(is_adaptive));
} else if (obj_meta.is_simulate_append_type()) {
if (OB_FAIL(del_appendable_file(uri))) {
OB_LOG(WARN, "fail to delete appendable file", K(ret), K(uri));
}
} else {
const int max_try_cnt = 5;
int try_cnt = 0;
while (try_cnt < max_try_cnt) {
if (OB_FAIL(util_->del_file(uri))) {
try_cnt++;
OB_LOG(WARN, "fail to delete file", K(ret), K(try_cnt), K(uri));
} else {
break;
}
}
}
if (OB_SUCC(ret)) {
OB_LOG(DEBUG, "succ to delete file", K(ret), K(uri));
} else {
OB_LOG(WARN, "fail to delete file", K(ret), K(uri));
}
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = OB_E(EventTable::EN_BACKUP_IO_AFTER_DEL_FILE) OB_SUCCESS;
}
#endif
print_access_storage_log("del_file", uri, start_ts);
if (OB_FAIL(ret)) {
EVENT_INC(ObStatEventIds::BACKUP_IO_DEL_FAIL_COUNT);
}
EVENT_INC(ObStatEventIds::BACKUP_DELETE_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_DELETE_DELAY, ObTimeUtility::current_time() - start_ts);
return ret;
}
int ObStorageUtil::del_appendable_file(const ObString &uri)
{
int ret = OB_SUCCESS;
ObExternalIOCounterGuard io_guard;
if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else {
DelAppendableObjectFragmentOp op(uri, *this);
if (OB_FAIL(list_files(uri, false/*is_adaptive*/, op))) {
OB_LOG(WARN, "fail to list appendable object fragments", K(ret), K(uri));
}
}
return ret;
}
int ObStorageUtil::list_files(
const common::ObString &uri,
const bool is_adaptive,
common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
char uri_buf[OB_MAX_URI_LENGTH] = {0};
if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(build_full_dir_path(uri.ptr(), uri_buf, sizeof(uri_buf)))) {
OB_LOG(WARN, "fail to make uri end with '/'", K(ret), K(uri));
} else if (is_adaptive && OB_FAIL(list_adaptive_files(uri_buf, op))) {
STORAGE_LOG(WARN, "fail to list adaptive files", K(ret), K(uri));
} else if (!is_adaptive && OB_FAIL(util_->list_files(uri_buf, op))) {
STORAGE_LOG(WARN, "fail to list files", K(ret), K(uri));
}
print_access_storage_log("list_files", uri, start_ts, 0);
if (OB_FAIL(ret)) {
EVENT_INC(ObStatEventIds::BACKUP_IO_LS_FAIL_COUNT);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_LS_COUNT);
return ret;
}
int ObStorageUtil::list_adaptive_files(
const common::ObString &uri,
common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
ObArenaAllocator allocator(APPENDABLE_OBJECT_ALLOCATOR);
ObStorageListObjectsCtx list_obj_ctx;
ObStorageListFilesCtx list_file_ctx;
ObStorageListCtxBase *list_ctx = NULL;
bool is_obj_storage = (OB_STORAGE_FILE != device_type_);
const bool need_get_size = op.need_get_file_size();
if (is_obj_storage) {
if (OB_FAIL(list_obj_ctx.init(allocator, OB_STORAGE_LIST_MAX_NUM, need_get_size))) {
OB_LOG(WARN, "fail to init list_obj_ctx", K(ret), K(need_get_size));
} else {
list_ctx = &list_obj_ctx;
}
} else {
if (OB_FAIL(list_file_ctx.init(allocator, OB_STORAGE_LIST_MAX_NUM, need_get_size))) {
OB_LOG(WARN, "fail to init list_file_ctx", K(ret), K(need_get_size));
} else {
list_ctx = &list_file_ctx;
}
}
ObString bucket;
ObString dir_path;
if (OB_SUCC(ret)) {
if (OB_FAIL(build_bucket_and_object_name(allocator, uri, bucket, dir_path))) {
OB_LOG(WARN, "fail to build bucket and object name", K(ret), K(uri));
}
}
if (OB_SUCC(ret)) {
do {
list_ctx->rsp_num_ = 0;
list_ctx->has_next_ = false;
if (OB_FAIL(util_->list_files(uri, *list_ctx))) {
OB_LOG(WARN, "fail to list files", K(ret), K(uri), K(list_ctx));
} else if (list_ctx->rsp_num_ > 0) {
if (is_obj_storage) {
if (OB_FAIL(handle_listed_objs(list_ctx, uri, dir_path, op))) {
OB_LOG(WARN, "fail to handle listed objs", K(ret), K(uri), K(dir_path), K(list_ctx));
}
} else {
if (OB_FAIL(handle_listed_fs(list_ctx, uri, dir_path, op))) {
OB_LOG(WARN, "fail to handle listed fs", K(ret), K(uri), K(dir_path), K(list_ctx));
}
}
}
} while (OB_SUCC(ret) && list_ctx->has_next_);
}
return ret;
}
int ObStorageUtil::handle_listed_objs(
ObStorageListCtxBase *ctx_base,
const common::ObString &uri,
const common::ObString &dir_path,
common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(ctx_base)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid argument", K(ret));
} else {
ObStorageListObjectsCtx *list_ctx = static_cast<ObStorageListObjectsCtx *>(ctx_base);
int64_t dir_path_len = dir_path.length();
int64_t full_dir_path_len = (is_end_with_slash(dir_path.ptr()) ? dir_path_len : (dir_path_len + 1));
char cur_appendable_full_path[OB_MAX_URI_LENGTH] = {0};
bool already_exist_fragment = (strlen(list_ctx->cur_appendable_full_obj_path_) > 0);
for (int64_t i = 0; OB_SUCC(ret) && (i < list_ctx->rsp_num_); ++i) {
ObString cur_obj_path(strlen(list_ctx->name_arr_[i]), list_ctx->name_arr_[i]);
char *contain_idx_ptr = strstr(cur_obj_path.ptr(), OB_S3_APPENDABLE_FRAGMENT_PREFIX);
bool is_fragment_obj = (nullptr != contain_idx_ptr);
if (is_fragment_obj) {
const int64_t appendable_full_path_len = (contain_idx_ptr - cur_obj_path.ptr());
if (OB_UNLIKELY(appendable_full_path_len <= full_dir_path_len ||
appendable_full_path_len >= OB_MAX_URI_LENGTH)) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "appendable obj full path len is invalid", K(ret), K(appendable_full_path_len),
K(full_dir_path_len), K(OB_MAX_URI_LENGTH), K(dir_path), K(cur_obj_path));
} else {
if (!already_exist_fragment) {
MEMCPY(list_ctx->cur_appendable_full_obj_path_, cur_obj_path.ptr(), appendable_full_path_len);
list_ctx->cur_appendable_full_obj_path_[appendable_full_path_len] = '\0';
already_exist_fragment = true;
} else {
// check current fragment's parent dir is same with the previous one
// if not, we need to handle previous one, and then save current one into list_ctx
MEMCPY(cur_appendable_full_path, cur_obj_path.ptr(), appendable_full_path_len);
cur_appendable_full_path[appendable_full_path_len] = '\0';
if (0 != STRCMP(list_ctx->cur_appendable_full_obj_path_, cur_appendable_full_path)) {
if (OB_FAIL(handle_listed_appendable_obj(list_ctx, uri, dir_path, op))) {
OB_LOG(WARN, "fail to handle listed appendable obj", K(ret), K(uri), K(dir_path),
K(cur_appendable_full_path), K(list_ctx->cur_appendable_full_obj_path_));
} else {
MEMCPY(list_ctx->cur_appendable_full_obj_path_, cur_obj_path.ptr(), appendable_full_path_len);
list_ctx->cur_appendable_full_obj_path_[appendable_full_path_len] = '\0';
}
}
}
}
} else {
// use @op to handle previous appendable object name
if (already_exist_fragment) {
if (OB_FAIL(handle_listed_appendable_obj(list_ctx, uri, dir_path, op))) {
OB_LOG(WARN, "fail to handle listed appendable obj", K(ret), K(uri), K(dir_path));
} else {
already_exist_fragment = false;
}
}
// use @op to handle current normal object name
if (OB_SUCC(ret)) {
const int64_t size = op.need_get_file_size() ? list_ctx->size_arr_[i] : -1;
if (OB_FAIL(handle_listed_object(op, cur_obj_path.ptr() + full_dir_path_len,
cur_obj_path.length() - full_dir_path_len,
size))) {
OB_LOG(WARN, "fail to handle listed object", K(ret), K(cur_obj_path),
K(cur_obj_path.length()), K(full_dir_path_len), K(dir_path), K(size));
}
}
}
}
if (OB_SUCC(ret)) {
if (already_exist_fragment && strlen(list_ctx->cur_appendable_full_obj_path_) > 0 && !list_ctx->has_next_) {
if (OB_FAIL(handle_listed_appendable_obj(list_ctx, uri, dir_path, op))) {
OB_LOG(WARN, "fail to handle listed appendable obj", K(ret), K(uri), K(dir_path));
} else {
already_exist_fragment = false;
}
}
}
}
return ret;
}
int ObStorageUtil::handle_listed_appendable_obj(
ObStorageListObjectsCtx *list_ctx,
const common::ObString &uri,
const common::ObString &dir_path,
common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
bool need_handle_file = true;
int64_t dir_path_len = dir_path.length();
int64_t full_dir_path_len = (is_end_with_slash(dir_path.ptr()) ? dir_path_len : (dir_path_len + 1));
const int64_t appendable_full_path_len = strlen(list_ctx->cur_appendable_full_obj_path_);
int64_t appendable_file_len = 0;
if (op.need_get_file_size()) {
char append_obj_uri[OB_MAX_URI_LENGTH] = {0};
// uri is equal to "prefix + bucket + '/' + dir_path"
const int64_t uri_prefix_len = uri.length() - dir_path_len;
MEMCPY(append_obj_uri, uri.ptr(), uri_prefix_len); // now append_obj_uri == prefix + bucket + '/'
// cur_appendable_full_obj_path_ == full_dir_path + logic_apendable_obj_name + '/'
// not copy the last character '/'
MEMCPY(append_obj_uri + uri_prefix_len, list_ctx->cur_appendable_full_obj_path_, appendable_full_path_len - 1);
append_obj_uri[uri_prefix_len + appendable_full_path_len - 1] = '\0';
// after above operation, append_obj_uri is equal to "prefix + bucket + '/' + full_dir_path + apendable_obj_name"
if (OB_FAIL(get_adaptive_file_length(append_obj_uri, appendable_file_len))) {
OB_LOG(WARN, "fail to get adaptive file length", K(ret), KP(append_obj_uri));
} else if (appendable_file_len == 0) {
// For appendable file, if its length is 0, we think that this file should not exist in the listed result,
// thus we will not handle this file.
need_handle_file = false;
} else if (appendable_file_len < 0) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "appendable file len should not be less than 0",
K(ret), K(appendable_file_len), K(append_obj_uri));
}
}
if (OB_SUCC(ret) && need_handle_file) {
if (OB_FAIL(handle_listed_object(op, list_ctx->cur_appendable_full_obj_path_ + full_dir_path_len,
appendable_full_path_len - full_dir_path_len - 1,
appendable_file_len))) {
OB_LOG(WARN, "fail to handle listed object",
K(ret), K(full_dir_path_len), K(appendable_full_path_len));
} else {
list_ctx->cur_appendable_full_obj_path_[0] = '\0';
}
}
return ret;
}
int ObStorageUtil::handle_listed_fs(
ObStorageListCtxBase *ctx_base,
const common::ObString &uri,
const common::ObString &dir_path,
common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(ctx_base)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid argument", K(ret));
} else {
ObStorageListFilesCtx *list_ctx = static_cast<ObStorageListFilesCtx *>(ctx_base);
const bool is_slash_end = is_end_with_slash(uri.ptr());
const char *slash_delimiter = is_slash_end ? "" : "/";
char tmp_uri[OB_MAX_URI_LENGTH] = { 0 };
int64_t size = 0;
// When handling file system list_files, the result will only save file's name(not include dir path)
for (int64_t i = 0; OB_SUCC(ret) && (i < list_ctx->rsp_num_); ++i) {
const int64_t name_len = strlen(list_ctx->name_arr_[i]);
// if the file's suffix is '/', that means this is a 'appendable' file. otherwise it is a normal file
if (list_ctx->name_arr_[i][name_len - 1] == '/') {
list_ctx->name_arr_[i][name_len - 1] = '\0';
if (op.need_get_file_size()) {
if (OB_FAIL(databuff_printf(tmp_uri, OB_MAX_URI_LENGTH, "%s%s%s", uri.ptr(), slash_delimiter,
list_ctx->name_arr_[i]))) {
STORAGE_LOG(WARN, "fail to build appendable file uri", K(ret), K(i), K(uri), K(is_slash_end),
KP(list_ctx->name_arr_[i]));
} else if (OB_FAIL(get_adaptive_file_length(tmp_uri, size))) {
OB_LOG(WARN, "fail to get adaptive file length", K(ret), KP(tmp_uri));
}
}
} else {
if (op.need_get_file_size()) {
size = list_ctx->size_arr_[i];
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(handle_listed_object(op, list_ctx->name_arr_[i],
strlen(list_ctx->name_arr_[i]),
size))) {
OB_LOG(WARN, "fail to handle listed object",
K(ret), K(list_ctx->name_arr_[i]), K(dir_path), K(size));
}
}
}
}
return ret;
}
int ObStorageUtil::list_directories(
const common::ObString &uri,
const bool is_adaptive,
common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
char uri_buf[OB_MAX_URI_LENGTH] = {0};
const int64_t start_ts = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_LIST_FILE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(is_adaptive)) {
ret = OB_NOT_SUPPORTED;
OB_LOG(WARN, "not support list directories for adaptive mode", K(ret), K(uri), K(is_adaptive));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(build_full_dir_path(uri.ptr(), uri_buf, sizeof(uri_buf)))) {
OB_LOG(WARN, "fail to make uri end with '/'", K(ret), K(uri));
} else if (OB_FAIL(util_->list_directories(uri_buf, op))) {
STORAGE_LOG(WARN, "failed to list_files", K(ret), K(uri), K(uri_buf));
}
print_access_storage_log("list_files", uri, start_ts, 0);
return ret;
}
/*---------------------------------- NEW ADAPTIVE INTERFACE ----------------------------------*/
int ObStorageUtil::is_exist(const common::ObString &uri, bool &exist)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
exist = false;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_IS_EXIST) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
//do nothing
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(util_->is_exist(uri, exist))) {
STORAGE_LOG(WARN, "failed to check is exist", K(ret), K(uri));
}
print_access_storage_log("is_exist", uri, start_ts);
return ret;
}
int ObStorageUtil::get_file_length(const common::ObString &uri, int64_t &file_length)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
file_length = -1;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_GET_FILE_LENGTH) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(util_->get_file_length(uri, file_length))) {
if (OB_BACKUP_FILE_NOT_EXIST == ret) {
STORAGE_LOG(INFO, "cannot get file length for not exist file", K(ret), K(uri));
} else {
STORAGE_LOG(WARN, "failed to get_file_length", K(ret), K(uri));
}
}
if (OB_SUCC(ret)) {
if (file_length == 0) {
STORAGE_LOG(INFO, "this file is empty", K(ret), K(uri), K(file_length));
} else if (file_length < 0) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "this file length is invalid", K(ret), K(uri), K(file_length));
}
}
print_access_storage_log("get_file_length", uri, start_ts);
return ret;
}
int ObStorageUtil::get_adaptive_file_length(const common::ObString &uri, int64_t &file_length)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
file_length = 0;
ObStorageObjectMeta obj_meta;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_GET_FILE_LENGTH) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else {
if (OB_FAIL(read_seal_meta_if_needed(uri, obj_meta))) {
OB_LOG(WARN, "fail to read seal meta if needed", K(ret), K(uri));
}
// If not exist seal meta, we need to list all files and check format meta exist or not.
// format meta must exist, otherwise need to return error.
if (OB_SUCC(ret) && !obj_meta.is_exist_) {
if (OB_FAIL(list_appendable_file_fragments(uri, obj_meta))) {
OB_LOG(WARN, "fail to list appendable file fragments", K(ret), K(uri));
}
}
if (OB_SUCC(ret) && obj_meta.is_exist_) {
file_length = obj_meta.length_;
}
}
if (OB_SUCC(ret)) {
if (file_length == 0) {
STORAGE_LOG(INFO, "this file is empty", K(ret), K(uri), K(file_length));
} else if (file_length < 0) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "this file length is invalid", K(ret), K(uri), K(file_length));
}
}
print_access_storage_log("get_adaptive_file_length", uri, start_ts);
return ret;
}
int ObStorageUtil::del_file(const common::ObString &uri)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_BEFORE_DEL_FILE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else {
const int max_try_cnt = 5;
int try_cnt = 0;
while (try_cnt < max_try_cnt) {
if (OB_FAIL(util_->del_file(uri))) {
try_cnt++;
OB_LOG(WARN, "failed to delete file", K(ret), K(try_cnt), K(uri));
} else {
break;
}
}
if (OB_SUCC(ret)) {
OB_LOG(DEBUG, "succeed to delete file", K(ret), K(uri));
} else {
OB_LOG(WARN, "failed to delete file", K(ret), K(uri));
}
}
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = OB_E(EventTable::EN_BACKUP_IO_AFTER_DEL_FILE) OB_SUCCESS;
}
#endif
print_access_storage_log("del_file", uri, start_ts);
if (OB_FAIL(ret)) {
EVENT_INC(ObStatEventIds::BACKUP_IO_DEL_FAIL_COUNT);
}
EVENT_INC(ObStatEventIds::BACKUP_DELETE_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_DELETE_DELAY, ObTimeUtility::current_time() - start_ts);
return ret;
}
int ObStorageUtil::mkdir(const common::ObString &uri)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
STORAGE_LOG(DEBUG, "mkdir", K(uri));
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_BEFORE_MKDIR) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(util_->mkdir(uri))) {
STORAGE_LOG(WARN, "failed to mkdir", K(ret), K(uri));
}
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = OB_E(EventTable::EN_BACKUP_IO_AFTER_MKDIR) OB_SUCCESS;
}
#endif
print_access_storage_log("mkdir", uri, start_ts);
return ret;
}
int ObStorageUtil::list_files(const common::ObString &uri, common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
char uri_buf[OB_MAX_URI_LENGTH] = {0};
const int64_t start_ts = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_LIST_FILE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(build_full_dir_path(uri.ptr(), uri_buf, sizeof(uri_buf)))) {
OB_LOG(WARN, "fail to make dir path end with '/'", K(ret), K(uri));
} else if (OB_FAIL(util_->list_files(uri_buf, op))) {
STORAGE_LOG(WARN, "failed to list_files", K(ret), K(uri), K(uri_buf));
}
print_access_storage_log("list_files", uri, start_ts, 0);
if (OB_FAIL(ret)) {
EVENT_INC(ObStatEventIds::BACKUP_IO_LS_FAIL_COUNT);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_LS_COUNT);
return ret;
}
int ObStorageUtil::write_single_file(const common::ObString &uri, const char *buf, const int64_t size)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_BEFORE_WRITE_SINGLE_FILE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(util_->write_single_file(uri, buf, size))) {
STORAGE_LOG(WARN, "failed to write single file", K(ret), K(uri));
} else {
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_BYTES, size);
}
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = OB_E(EventTable::EN_BACKUP_IO_AFTER_WRITE_SINGLE_FILE) OB_SUCCESS;
}
#endif
print_access_storage_log("write_single_file", uri, start_ts, size);
if (OB_FAIL(ret)) {
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_FAIL_COUNT);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_DELAY, ObTimeUtility::current_time() - start_ts);
return ret;
}
int ObStorageUtil::del_dir(const common::ObString &uri)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(util_->del_dir(uri))) {
STORAGE_LOG(WARN, "failed to del_file", K(ret), K(uri));
}
print_access_storage_log("del_file", uri, start_ts);
return ret;
}
int ObStorageUtil::list_directories(const common::ObString &uri, common::ObBaseDirEntryOperator &op)
{
int ret = OB_SUCCESS;
char uri_buf[OB_MAX_URI_LENGTH] = {0};
const int64_t start_ts = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_LIST_FILE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(build_full_dir_path(uri.ptr(), uri_buf, sizeof(uri_buf)))) {
OB_LOG(WARN, "fail to make dir path end with '/'", K(ret), K(uri));
} else if (OB_FAIL(util_->list_directories(uri_buf, op))) {
STORAGE_LOG(WARN, "failed to list_directories", K(ret), K(uri), K(uri_buf));
}
print_access_storage_log("list_directories", uri, start_ts, 0);
return ret;
}
int ObStorageUtil::is_tagging(const common::ObString &uri, bool &is_tagging)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
is_tagging = false;
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(!is_init())) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (OB_FAIL(validate_uri_type(uri))) {
STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
} else if (OB_FAIL(util_->is_tagging(uri, is_tagging))) {
STORAGE_LOG(WARN, "failed to check is tagging", K(ret), K(uri));
}
print_access_storage_log("is_tagging", uri, start_ts, 0);
return ret;
}
int ObStorageUtil::del_unmerged_parts(const common::ObString &uri)
{
int ret = OB_NOT_SUPPORTED;
OB_LOG(WARN, "del_unmerged_parts is not supported yet", K(ret), K(uri));
// const int64_t start_ts = ObTimeUtility::current_time();
// if (OB_FAIL(ret)) {
// } else if (OB_UNLIKELY(!is_init())) {
// ret = OB_NOT_INIT;
// STORAGE_LOG(WARN, "util is not inited", K(ret), K(uri));
// } else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
// ret = OB_BACKUP_IO_PROHIBITED;
// STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
// } else if (OB_FAIL(validate_uri_type(uri))) {
// STORAGE_LOG(WARN, "fail to validate uri!", K(ret), K(uri));
// } else if (OB_FAIL(util_->del_unmerged_parts(uri))) {
// STORAGE_LOG(WARN, "fail to del unmerged parts!", K(ret), K(uri));
// }
// print_access_storage_log("del_unmerged_parts", uri, start_ts, 0);
return ret;
}
/**
* ------------------------------ObStorageReader------------------------------
*/
ObStorageReader::ObStorageReader()
: file_length_(-1),
reader_(NULL),
file_reader_(),
oss_reader_(),
cos_reader_(),
s3_reader_(),
start_ts_(0)
{
uri_[0] = '\0';
}
ObStorageReader::~ObStorageReader()
{
if (NULL != reader_) {
STORAGE_LOG_RET(ERROR, common::OB_ERR_UNEXPECTED, "reader not closed", KCSTRING(uri_));
}
}
int ObStorageReader::open(const common::ObString &uri, common::ObObjectStorageInfo *storage_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObStorageType type = OB_STORAGE_MAX_TYPE;
start_ts_ = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_READER_OPEN) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (NULL != reader_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "cannot open twice", K(ret), K(uri));
} else if (OB_FAIL(databuff_printf(uri_, sizeof(uri_), "%.*s", uri.length(), uri.ptr()))) {
STORAGE_LOG(WARN, "failed to fill uri", K(ret), K(uri));
} else if (OB_FAIL(get_storage_type_from_path(uri, type))) {
STORAGE_LOG(WARN, "failed to get type", K(ret), K(uri));
} else if (OB_STORAGE_OSS == type) {
reader_ = &oss_reader_;
} else if (OB_STORAGE_COS == type) {
reader_ = &cos_reader_;
} else if (OB_STORAGE_S3 == type) {
reader_ = &s3_reader_;
} else if (OB_STORAGE_FILE == type) {
reader_ = &file_reader_;
} else {
ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "unkown storage type", K(ret), K(uri));
}
if (OB_SUCC(ret)) {
if (OB_ISNULL(reader_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "reader_ is null", K(ret), K(uri));
} else if (OB_FAIL(reader_->open(uri, storage_info))) {
STORAGE_LOG(WARN, "failed to open reader", K(ret), K(uri));
} else {
file_length_ = reader_->get_length();
}
}
if(OB_FAIL(ret)) {
if (OB_SUCCESS != (tmp_ret = close())) {
STORAGE_LOG(WARN, "failed to close read file", K(ret), K(tmp_ret), K(uri));
}
}
print_access_storage_log("ObStorageReader::open", uri_, start_ts_, 0);
return ret;
}
int ObStorageReader::pread(char *buf,const int64_t buf_size, int64_t offset, int64_t &read_size)
{
int ret = OB_SUCCESS;
read_size = 0;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_READER_PREAD) OB_SUCCESS;
#endif
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(offset), K(buf_size));
} else if (OB_ISNULL(reader_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_ISNULL(buf) || offset < 0 || offset > file_length_) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid args", K(ret), KP(buf), K(offset), K(file_length_));
} else if (OB_FAIL(reader_->pread(buf, buf_size, offset, read_size))) {
EVENT_INC(ObStatEventIds::BACKUP_IO_READ_FAIL_COUNT);
STORAGE_LOG(WARN, "failed to read file", K(ret));
} else {
EVENT_ADD(ObStatEventIds::BACKUP_IO_READ_BYTES, read_size);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_READ_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_IO_READ_DELAY, ObTimeUtility::current_time() - start_ts);
print_access_storage_log("ObStorageReader::pread", uri_, start_ts, read_size);
return ret;
}
int ObStorageReader::close()
{
int ret = OB_SUCCESS;
if (NULL != reader_) {
print_access_storage_log("storage reader", uri_, start_ts_, file_length_);
}
if (OB_ISNULL(reader_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(reader_->close())) {
STORAGE_LOG(WARN, "failed to close reader", K(ret));
}
reader_ = NULL;
file_length_ = -1;
start_ts_ = 0;
uri_[0] = '\0';
return ret;
}
ObStorageAdaptiveReader::ObStorageAdaptiveReader()
: allocator_(APPENDABLE_OBJECT_ALLOCATOR),
meta_(),
bucket_(),
object_(),
reader_(NULL),
file_reader_(),
oss_reader_(),
cos_reader_(),
s3_reader_(),
start_ts_(0),
storage_info_(NULL)
{
uri_[0] = '\0';
}
ObStorageAdaptiveReader::~ObStorageAdaptiveReader()
{
if (NULL != reader_) {
STORAGE_LOG_RET(ERROR, common::OB_ERR_UNEXPECTED, "adaptive reader not closed", KCSTRING(uri_));
}
}
int ObStorageAdaptiveReader::open(const common::ObString &uri,
common::ObObjectStorageInfo *storage_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObStorageType type = OB_STORAGE_MAX_TYPE;
start_ts_ = ObTimeUtility::current_time();
ObStorageUtil util;
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (NULL != reader_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "cannot open twice", K(ret), K(uri));
} else if (OB_FAIL(databuff_printf(uri_, sizeof(uri_), "%.*s", uri.length(), uri.ptr()))) {
STORAGE_LOG(WARN, "failed to fill uri", K(ret), K(uri));
} else if (OB_FAIL(get_storage_type_from_path(uri, type))) {
STORAGE_LOG(WARN, "failed to get type", K(ret), K(uri));
} else if (OB_STORAGE_OSS == type) {
reader_ = &oss_reader_;
} else if (OB_STORAGE_COS == type) {
reader_ = &cos_reader_;
} else if (OB_STORAGE_S3 == type) {
reader_ = &s3_reader_;
} else if (OB_STORAGE_FILE == type) {
reader_ = &file_reader_;
} else {
ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "unkown storage type", K(ret), K(uri));
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(reader_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "reader_ is null", K(ret), K(uri));
} else if (OB_FAIL(util.open(storage_info))) {
OB_LOG(WARN, "fail to open util", K(ret), K(uri), KPC(storage_info));
} else if (OB_FAIL(util.detect_storage_obj_meta(uri, true/*is_adaptive*/,
true/*need_fragment_meta*/, meta_))) {
OB_LOG(WARN, "fail to detect obejct meta", K(ret), K(uri), KPC(storage_info));
} else if (meta_.is_simulate_append_type()) {
// no need to open reader
} else if (meta_.is_object_file_type()) {
if (OB_FAIL(reader_->open(uri, storage_info))) {
OB_LOG(WARN, "fail to open reader", K(ret), K(uri), KPC(storage_info));
}
} else {
ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "invalid storage object type", K(ret), K(uri), KPC(storage_info), K_(meta));
}
if(OB_FAIL(ret)) {
if (OB_SUCCESS != (tmp_ret = close())) {
STORAGE_LOG(WARN, "failed to close read file", K(ret), K(tmp_ret), K(uri));
}
} else {
storage_info_ = storage_info;
}
print_access_storage_log("ObStorageAdaptiveReader::open", uri_, start_ts_, 0);
return ret;
}
int ObStorageAdaptiveReader::pread(char *buf,
const int64_t buf_size, const int64_t offset, int64_t &read_size)
{
int ret = OB_SUCCESS;
read_size = 0;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
OB_LOG(WARN, "current observer backup io is prohibited", K(ret), K(offset), K(buf_size));
} else if (OB_ISNULL(reader_)) {
ret = OB_NOT_INIT;
OB_LOG(WARN, "adaptive reader not opened", K(ret));
} else if (OB_ISNULL(buf) || OB_UNLIKELY(buf_size <= 0 || offset < 0)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid args", K(ret), KP(buf), K(buf_size), K(offset), K_(meta));
} else if (OB_UNLIKELY(offset > meta_.length_)) {
ret = OB_FILE_LENGTH_INVALID;
OB_LOG(WARN, "offset is larger than file length", K(ret), K(offset), K_(meta));
} else if (offset == meta_.length_) {
ret = OB_SUCCESS;
read_size = 0;
} else if (meta_.is_object_file_type()) {
if (OB_FAIL(reader_->pread(buf, buf_size, offset, read_size))) {
OB_LOG(WARN, "fail to read object", K(ret), K_(meta));
}
} else if (meta_.is_simulate_append_type()) {
char uri[OB_MAX_URI_LENGTH] = { 0 };
ObArray<ObAppendableFragmentMeta> fragments_need_to_read;
if (OB_FAIL(meta_.get_needed_fragments(offset, offset + buf_size,
fragments_need_to_read))) {
OB_LOG(WARN, "failed to get fragments need to read",
K(ret), K_(bucket), K_(object), K(offset), K(buf_size), K_(meta));
} else if (fragments_need_to_read.empty()) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "the subsequent data that is anticipated to be read may not be present",
K(ret), K(offset), K(buf_size));
} else {
int64_t cur_read_size = 0;
int64_t actual_read_size = -1;
int64_t expected_read_size = -1;
for (int64_t i = 0; OB_SUCC(ret) && i < fragments_need_to_read.size(); i++) {
actual_read_size = -1;
const ObAppendableFragmentMeta &fragment_meta = fragments_need_to_read[i];
expected_read_size =
std::min({meta_.length_, fragment_meta.end_, offset + buf_size})
- (offset + cur_read_size);
if (OB_UNLIKELY(!fragment_meta.is_valid())) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "invalid fragment meta",
K(ret), K(fragment_meta), K(cur_read_size));
} else if (OB_FAIL(construct_fragment_full_name(uri_,
fragment_meta.start_, fragment_meta.end_,
uri, sizeof(uri)))) {
OB_LOG(WARN, "failed to construct fragment name", K(ret),
K(fragment_meta), K(cur_read_size));
} else if (OB_FAIL(reader_->open(uri, storage_info_, false/*head_meta*/))) {
OB_LOG(WARN, "fail to open reader for fragment",
K(ret), K(uri), K(fragment_meta), K(cur_read_size), K(offset));
} else if (OB_FAIL(reader_->pread(buf + cur_read_size,
expected_read_size,
(offset + cur_read_size) - fragment_meta.start_,
actual_read_size))) {
OB_LOG(WARN, "failed to read fragment content", K(ret),
K(uri), K(fragment_meta), K(cur_read_size), K(offset), K(expected_read_size));
} else if (OB_FAIL(reader_->close())) {
OB_LOG(WARN, "fail to close reader", K(ret), K(uri), K(fragment_meta), K(cur_read_size));
} else if (actual_read_size != expected_read_size) {
ret = OB_IO_ERROR;
OB_LOG(WARN, "failed to read expected size from fragment", K(ret),
K(uri), K(fragment_meta),
K(cur_read_size), K(offset), K(actual_read_size), K(expected_read_size));
} else {
cur_read_size += actual_read_size;
}
}
if (OB_SUCC(ret)) {
read_size = cur_read_size;
}
}
} else {
ret = OB_ERR_SYS;
OB_LOG(ERROR, "unkown object type", K(ret), K_(meta));
}
// TODO @fangdan: add event
EVENT_ADD(ObStatEventIds::BACKUP_IO_READ_DELAY, ObTimeUtility::current_time() - start_ts);
print_access_storage_log("ObStorageAdaptiveReader::pread", uri_, start_ts, read_size);
return ret;
}
int ObStorageAdaptiveReader::close()
{
int ret = OB_SUCCESS;
if (NULL != reader_) {
print_access_storage_log("storage adaptive reader", uri_, start_ts_, meta_.length_);
}
if (OB_ISNULL(reader_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(reader_->close())) {
STORAGE_LOG(WARN, "failed to close reader", K(ret));
}
reader_ = NULL;
start_ts_ = 0;
uri_[0] = '\0';
allocator_.clear();
meta_.reset();
storage_info_ = NULL;
return ret;
}
ObStorageWriter::ObStorageWriter()
: writer_(NULL),
file_writer_(),
oss_writer_(),
cos_writer_(),
s3_writer_(),
start_ts_(0)
{
uri_[0] = '\0';
}
ObStorageWriter::~ObStorageWriter()
{
if (NULL != writer_) {
STORAGE_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "writer not close");
}
}
int ObStorageWriter::open(const common::ObString &uri, common::ObObjectStorageInfo *storage_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObStorageType type = OB_STORAGE_MAX_TYPE;
start_ts_ = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_WRITE_OPEN) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (NULL != writer_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "cannot open twice", K(ret), K(uri));
} else if (OB_FAIL(databuff_printf(uri_, sizeof(uri_), "%.*s", uri.length(), uri.ptr()))) {
STORAGE_LOG(WARN, "failed to fill uri", K(ret), K(uri));
} else if (OB_FAIL(get_storage_type_from_path(uri, type))) {
STORAGE_LOG(WARN, "failed to get type", K(ret), K(uri));
} else if (OB_STORAGE_OSS == type) {
writer_ = &oss_writer_;
} else if (OB_STORAGE_COS == type) {
writer_ = &cos_writer_;
} else if (OB_STORAGE_S3 == type) {
writer_ = &s3_writer_;
} else if (OB_STORAGE_FILE == type) {
writer_ = &file_writer_;
} else {
ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "unkown storage type", K(ret), K(uri));
}
if (OB_SUCC(ret)) {
if (OB_ISNULL(writer_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "writer_ is null", K(ret), K(uri));
} else if (OB_FAIL(writer_->open(uri, storage_info))) {
STORAGE_LOG(WARN, "failed to open writer", K(ret), K(uri));
}
}
if (OB_FAIL(ret)) {
if (OB_SUCCESS != (tmp_ret = close())) {
STORAGE_LOG(WARN, "failed close write file", K(ret), K(tmp_ret), K(uri));
}
}
print_access_storage_log("ObStorageWriter::open", uri_, start_ts_, 0);
return ret;
}
int ObStorageWriter::write(const char *buf,const int64_t size)
{
int ret = OB_SUCCESS;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_WRITE_WRITE) OB_SUCCESS;
#endif
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(size));
} else if (OB_ISNULL(writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if(OB_FAIL(writer_->write(buf, size))) {
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_FAIL_COUNT);
STORAGE_LOG(WARN, "failed to write", K(ret));
} else {
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_BYTES, size);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_DELAY, ObTimeUtility::current_time() - start_ts);
print_access_storage_log("ObStorageWriter::write", uri_, start_ts, size);
return ret;
}
int ObStorageWriter::close()
{
int ret = OB_SUCCESS;
if (NULL != writer_) {
print_access_storage_log("storage writer", uri_, start_ts_, writer_->get_length());
}
if (OB_ISNULL(writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(writer_->close())) {
STORAGE_LOG(WARN, "failed to close writer", K(ret));
}
writer_ = NULL;
start_ts_ = 0;
uri_[0] = '\0';
return ret;
}
ObStorageAppender::ObStorageAppender()
: appender_(NULL),
file_appender_(),
oss_appender_(),
cos_appender_(),
s3_appender_(),
start_ts_(0),
is_opened_(false),
storage_info_(),
allocator_(APPENDABLE_OBJECT_ALLOCATOR),
type_(OB_STORAGE_MAX_TYPE)
{
uri_[0] = '\0';
}
ObStorageAppender::ObStorageAppender(StorageOpenMode mode)
: appender_(NULL),
file_appender_(mode),
oss_appender_(),
cos_appender_(),
s3_appender_(),
start_ts_(0),
is_opened_(false),
storage_info_(),
allocator_(APPENDABLE_OBJECT_ALLOCATOR),
type_(OB_STORAGE_MAX_TYPE)
{
uri_[0] = '\0';
}
ObStorageAppender::~ObStorageAppender()
{
if (is_opened_ && NULL != appender_) {
STORAGE_LOG_RET(ERROR, common::OB_ERR_UNEXPECTED, "appender not close");
}
}
int ObStorageAppender::open(
const common::ObString &uri,
common::ObObjectStorageInfo *storage_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
start_ts_ = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_APPENDER_OPEN) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (NULL != appender_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "cannot open twice", K(ret), K(uri));
} else if (OB_UNLIKELY(uri.empty()) || OB_ISNULL(storage_info)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(uri), KP(storage_info));
} else if (OB_FAIL(databuff_printf(uri_, sizeof(uri_), "%.*s", uri.length(), uri.ptr()))) {
STORAGE_LOG(WARN, "failed to fill uri", K(ret), K(uri));
} else if (OB_FAIL(get_storage_type_from_path(uri, type_))) {
STORAGE_LOG(WARN, "failed to get type", K(ret), K(uri));
} else if (OB_STORAGE_OSS == type_ || OB_STORAGE_COS == type_ || OB_STORAGE_S3 == type_) {
if (OB_FAIL(storage_info_.assign(*storage_info))) {
STORAGE_LOG(WARN, "failed to copy storage info", K(ret));
} else if (OB_STORAGE_OSS == type_) {
appender_ = &oss_appender_;
} else if (OB_STORAGE_COS == type_) {
appender_ = &cos_appender_;
} else if (OB_STORAGE_S3 == type_) {
appender_ = &s3_appender_;
}
} else if (OB_STORAGE_FILE == type_) {
appender_ = &file_appender_;
} else {
ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "unkown storage type", K(ret), K(uri));
}
if (OB_SUCC(ret)) {
if (OB_ISNULL(appender_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "appender_ is null", K(ret), K(uri));
} else if (OB_FAIL(appender_->open(uri, storage_info))) {
STORAGE_LOG(WARN, "failed to open writer", K(ret), K(uri));
} else {
is_opened_ = true;
}
}
if (OB_FAIL(ret)) {
if (OB_SUCCESS != (tmp_ret = close())) {
STORAGE_LOG(WARN, "failed close write file", K(ret), K(tmp_ret), K(uri));
}
}
print_access_storage_log("ObStorageAppender::open", uri_, start_ts_, 0);
return ret;
}
int ObStorageAppender::write(const char *buf,const int64_t size)
{
int ret = OB_SUCCESS;
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_APPENDER_WRITE) OB_SUCCESS;
#endif
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(size));
} else if (OB_ISNULL(appender_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if(OB_FAIL(appender_->write(buf, size))) {
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_FAIL_COUNT);
STORAGE_LOG(WARN, "failed to write", K(ret));
} else {
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_BYTES, size);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_DELAY, ObTimeUtility::current_time() - start_ts);
print_access_storage_log("ObStorageAppender::write", uri_, start_ts, size);
return ret;
}
int ObStorageAppender::repeatable_pwrite_(const char *buf, const int64_t size, const int64_t offset)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
int64_t read_size = 0;
int64_t read_buf_size = 0;
int64_t actual_write_offset = 0;
char *read_buffer = nullptr;
ObStorageReader reader;
ObArenaAllocator allocator;
if (OB_ISNULL(appender_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(reader.open(uri_, &storage_info_))) {
STORAGE_LOG(WARN, "failed to open reader", K(ret));
} else if (reader.get_length() <= offset) {
// This situation also has concurrency issues.
// The length read by the reader may be old, so offset not match needs to be returned for retry.
ret = OB_BACKUP_PWRITE_OFFSET_NOT_MATCH;
STORAGE_LOG(WARN, "offset is invalid", K(offset), "length", reader.get_length(), K(ret));
} else if (OB_FALSE_IT(actual_write_offset = reader.get_length() - offset)) {
} else if (OB_FALSE_IT(read_buf_size = std::min(actual_write_offset, size))) {
} else if (OB_ISNULL(read_buffer = static_cast<char *>(allocator.alloc(read_buf_size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
OB_LOG(WARN, "failed to allocate memory", K(ret), K(size));
} else if (OB_FAIL(reader.pread(read_buffer, read_buf_size, offset, read_size))) {
STORAGE_LOG(WARN, "failed to pread", K(ret));
} else if (0 != MEMCMP(buf, read_buffer, read_buf_size)) {
ret = OB_BACKUP_PWRITE_CONTENT_NOT_MATCH;
STORAGE_LOG(WARN, "data inconsistent", K(ret));
} else if (offset + size > reader.get_length()) {
if (OB_FAIL(appender_->pwrite(buf + actual_write_offset, size - actual_write_offset, reader.get_length()))) {
if (OB_BACKUP_PWRITE_OFFSET_NOT_MATCH == ret) {
ret = OB_IO_ERROR;
STORAGE_LOG(WARN, "There may be concurrency problems that require the caller to retry", K(ret));
}
}
}
if (OB_SUCCESS != (tmp_ret = reader.close())) {
STORAGE_LOG(WARN, "failed to close reader", K(tmp_ret));
}
return ret;
}
int ObStorageAppender::pwrite(const char *buf, const int64_t size, const int64_t offset)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
#ifdef ERRSIM
ret = OB_E(EventTable::EN_BACKUP_IO_APPENDER_WRITE) OB_SUCCESS;
#endif
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(offset), K(size));
} else if (OB_ISNULL(appender_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(appender_->pwrite(buf, size, offset))) {
STORAGE_LOG(WARN, "failed to write", K(ret));
}
// no need to adjust the function repeatable_pwrite_
// because S3 will not return OB_BACKUP_PWRITE_OFFSET_NOT_MATCH
if (OB_BACKUP_PWRITE_OFFSET_NOT_MATCH == ret && appender_ != &s3_appender_) {
if (OB_FAIL(repeatable_pwrite_(buf, size, offset))) {
STORAGE_LOG(WARN, "failed to repeatable_pwrite", K(ret));
} else {
STORAGE_LOG(DEBUG, "repeatable pwrite success", K(ret));
}
}
print_access_storage_log("ObStorageAppender::pwrite", uri_, start_ts, size);
return ret;
}
int64_t ObStorageAppender::get_length()
{
int64_t ret_int = -1;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_ISNULL(appender_)) {
STORAGE_LOG_RET(WARN, common::OB_ERR_UNEXPECTED, "appender not opened");
} else if (OB_STORAGE_S3 != type_) {
ret_int = appender_->get_length();
} else {
int ret = OB_SUCCESS;
ObStorageUtil util;
ObStorageObjectMeta meta;
ObExternalIOCounterGuard io_guard;
char uri[OB_MAX_URI_LENGTH] = { 0 };
if (OB_FAIL(util.open(&storage_info_))) {
OB_LOG(WARN, "failed to open util", K(ret));
} else if (OB_FAIL(util.list_appendable_file_fragments(uri_, meta))) {
OB_LOG(WARN, "failed to list appendable object fragments", K(ret), K_(uri));
} else {
ret_int = meta.length_;
}
util.close();
}
print_access_storage_log("ObStorageAppender::get_length", uri_, start_ts, 0);
return ret_int;
}
int ObStorageAppender::close()
{
int ret = OB_SUCCESS;
if (NULL != appender_) {
print_access_storage_log("storage appender_", uri_, start_ts_, appender_->get_length());
}
if (OB_ISNULL(appender_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(appender_->close())) {
STORAGE_LOG(WARN, "failed to close writer", K(ret));
}
appender_ = NULL;
start_ts_ = 0;
uri_[0] = '\0';
is_opened_ = false;
return ret;
}
int ObStorageAppender::seal_for_adaptive()
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
int64_t handled_size = 0;
if (OB_NOT_NULL(appender_)) {
print_access_storage_log("storage appender_", uri_, start_ts_, appender_->get_length());
}
if (OB_ISNULL(appender_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_STORAGE_S3 != type_) {
} else {
char *buf = NULL;
char seal_meta_uri[OB_MAX_URI_LENGTH] = { 0 };
ObStorageUtil util;
ListAppendableObjectFragmentOp op;
ObStorageObjectMeta appendable_obj_meta;
int64_t pos = 0; // for serializing appendable_obj_meta
int64_t serialize_size = -1; // for serializing appendable_obj_meta
ObExternalIOCounterGuard io_guard;
if (OB_FAIL(util.open(&storage_info_))) {
OB_LOG(WARN, "failed to open util", K(ret), K_(uri), K_(storage_info));
} else if (OB_FAIL(util.list_appendable_file_fragments(uri_, appendable_obj_meta))) {
OB_LOG(WARN, "failed to list appendable object fragments", K(ret), K_(uri));
} else if (FALSE_IT(serialize_size = appendable_obj_meta.get_serialize_size() + 1)) {
} else if (OB_ISNULL(buf = static_cast<char *>(allocator_.alloc(serialize_size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
OB_LOG(WARN, "failed to alloc memory for appendable object seal meta buf",
K(ret), K(serialize_size), K_(uri), K(appendable_obj_meta));
} else if (OB_FAIL(appendable_obj_meta.serialize(buf, serialize_size, pos))) {
OB_LOG(WARN, "failed to serialize s3 appendable object meta",
K(ret), K(serialize_size), K_(uri), K(appendable_obj_meta));
} else if (OB_FAIL(construct_fragment_full_name(uri_, OB_S3_APPENDABLE_SEAL_META,
seal_meta_uri, sizeof(seal_meta_uri)))) {
OB_LOG(WARN, "failed to construct s3 appendable object name for writing seal meta file",
K(ret), K_(uri), K(appendable_obj_meta));
} else if (OB_FAIL(util.write_single_file(seal_meta_uri, buf, pos))) {
OB_LOG(WARN, "fail to write seal meta file", K(ret), K(seal_meta_uri), K(appendable_obj_meta));
} else {
// The seal operation includes listing fragments and writing this data to a meta file.
// Here, 'serialize_size' is used as an approximation of the data throughput of the list operation.
handled_size = serialize_size + pos;
OB_LOG(DEBUG, "succeed to write seal meta file",
K_(uri), K(seal_meta_uri), KP(buf), K(pos), K(appendable_obj_meta));
}
util.close();
}
print_access_storage_log("ObStorageAppender::seal_for_adaptive", uri_, start_ts, handled_size);
return ret;
}
ObStorageMultiPartWriter::ObStorageMultiPartWriter()
: multipart_writer_(NULL),
file_multipart_writer_(),
cos_multipart_writer_(),
oss_multipart_writer_(),
s3_multipart_writer_(),
start_ts_(0),
is_opened_(false),
storage_info_()
{
uri_[0] = '\0';
}
ObStorageMultiPartWriter::~ObStorageMultiPartWriter()
{
if (is_opened_ && NULL != multipart_writer_) {
STORAGE_LOG_RET(ERROR, common::OB_ERR_UNEXPECTED, "multipart_writer not close");
}
}
int ObStorageMultiPartWriter::open(
const common::ObString &uri,
common::ObObjectStorageInfo *storage_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObStorageType type = OB_STORAGE_MAX_TYPE;
start_ts_ = ObTimeUtility::current_time();
if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(uri));
} else if (NULL != multipart_writer_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "multipart writer cannot open twice", K(ret), K(uri));
} else if (OB_UNLIKELY(uri.empty()) || OB_ISNULL(storage_info)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(uri), KPC(storage_info));
} else if (OB_FAIL(databuff_printf(uri_, sizeof(uri_), "%.*s", uri.length(), uri.ptr()))) {
STORAGE_LOG(WARN, "failed to fill uri", K(ret), K(uri));
} else if (OB_FAIL(get_storage_type_from_path(uri, type))) {
STORAGE_LOG(WARN, "failed to get type", K(ret), K(uri));
} else if (OB_STORAGE_OSS == type || OB_STORAGE_COS == type || OB_STORAGE_S3 == type) {
if (OB_FAIL(storage_info_.assign(*storage_info))) {
STORAGE_LOG(WARN, "failed to copy storage info", K(ret), KPC(storage_info));
} else if (OB_STORAGE_OSS == type) {
multipart_writer_ = &oss_multipart_writer_;
} else if (OB_STORAGE_COS == type) {
multipart_writer_ = &cos_multipart_writer_;
} else if (OB_STORAGE_S3 == type) {
multipart_writer_ = &s3_multipart_writer_;
}
} else if (OB_STORAGE_FILE == type) {
multipart_writer_ = &file_multipart_writer_;
} else {
ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "unkown storage type", K(ret), K(uri));
}
if (OB_SUCC(ret)) {
if (OB_ISNULL(multipart_writer_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "multipart_writer is null", K(ret), K(uri));
} else if (OB_FAIL(multipart_writer_->open(uri, storage_info))) {
STORAGE_LOG(WARN, "failed to open multipart writer", K(ret), K(uri), K(storage_info));
} else {
is_opened_ = true;
}
}
if (OB_FAIL(ret)) {
if (OB_SUCCESS != (tmp_ret = close())) {
STORAGE_LOG(WARN, "failed close multipart writer", K(ret), K(tmp_ret), K(uri));
}
}
print_access_storage_log("ObStorageMultiPartWriter::open", uri_, start_ts_, 0);
return ret;
}
int ObStorageMultiPartWriter::write(const char *buf, const int64_t size)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(size));
} else if (OB_ISNULL(multipart_writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "multipart writer not opened", K(ret));
} else if(OB_FAIL(multipart_writer_->write(buf, size))) {
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_FAIL_COUNT);
STORAGE_LOG(WARN, "failed to write", K(ret));
} else {
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_BYTES, size);
}
EVENT_INC(ObStatEventIds::BACKUP_IO_WRITE_COUNT);
EVENT_ADD(ObStatEventIds::BACKUP_IO_WRITE_DELAY, ObTimeUtility::current_time() - start_ts);
print_access_storage_log("ObStorageMultiPartWriter::write", uri_, start_ts, size);
return ret;
}
int ObStorageMultiPartWriter::pwrite(const char *buf, const int64_t size, const int64_t offset)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret), K(offset), K(size));
} else if (OB_ISNULL(multipart_writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "multipart writer not opened", K(ret));
} else if (OB_FAIL(multipart_writer_->pwrite(buf, size, offset))) {
STORAGE_LOG(WARN, "failed to write", K(ret));
}
print_access_storage_log("ObStorageMultiPartWriter::pwrite", uri_, start_ts, size);
return ret;
}
int64_t ObStorageMultiPartWriter::get_length()
{
int64_t ret_int = -1;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_ISNULL(multipart_writer_)) {
STORAGE_LOG_RET(WARN, common::OB_ERR_UNEXPECTED, "multipart_writer_ not opened");
} else {
ret_int = multipart_writer_->get_length();
}
print_access_storage_log("ObStorageMultiPartWriter::get_length", uri_, start_ts, 0);
return ret_int;
}
int ObStorageMultiPartWriter::complete()
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited", K(ret));
} else if (OB_ISNULL(multipart_writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "multipart writer not opened", K(ret));
} else if (OB_FAIL(multipart_writer_->complete())) {
STORAGE_LOG(WARN, "failed to complete", K(ret));
}
print_access_storage_log("ObStorageMultiPartWriter::complete", uri_, start_ts, 0);
return ret;
}
int ObStorageMultiPartWriter::abort()
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ret)) {
} else if (ObStorageGlobalIns::get_instance().is_io_prohibited()) {
ret = OB_BACKUP_IO_PROHIBITED;
STORAGE_LOG(WARN, "current observer backup io is prohibited");
} else if (OB_ISNULL(multipart_writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "multipart writer not opened", K(ret));
} else if (OB_FAIL(multipart_writer_->abort())) {
STORAGE_LOG(WARN, "failed to abort", K(ret));
}
print_access_storage_log("ObStorageMultiPartWriter::abort", uri_, start_ts, 0);
return ret;
}
int ObStorageMultiPartWriter::close()
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (NULL != multipart_writer_) {
print_access_storage_log("storage multipart writer", uri_, start_ts_, multipart_writer_->get_length());
}
if (OB_ISNULL(multipart_writer_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not opened", K(ret));
} else if (OB_FAIL(multipart_writer_->close())) {
STORAGE_LOG(WARN, "failed to close multipart writer", K(ret));
}
multipart_writer_ = NULL;
start_ts_ = 0;
uri_[0] = '\0';
is_opened_ = false;
print_access_storage_log("ObStorageMultiPartWriter::close", uri_, start_ts, 0);
return ret;
}
}
}//oceanbase