/** * 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 "share/backup/ob_backup_io_adapter.h" #include "task_executor.h" #include "../dumpsst/ob_admin_dumpsst_print_helper.h" using namespace oceanbase::share; using namespace oceanbase::common; namespace oceanbase { namespace tools { /*--------------------------------TaskConfig--------------------------------*/ TaskConfig::TaskConfig() : thread_num_(-1), max_task_runs_(-1), time_limit_s_(-1), obj_size_(-1), obj_num_(-1), fragment_size_(-1), is_adaptive_(false), type_(BenchmarkTaskType::BENCHMARK_TASK_MAX_TYPE) { } int TaskConfig::assign(const TaskConfig &other) { int ret = OB_SUCCESS; thread_num_ = other.thread_num_; max_task_runs_ = other.max_task_runs_; time_limit_s_ = other.time_limit_s_; obj_size_ = other.obj_size_; obj_num_ = other.obj_num_; fragment_size_ = other.fragment_size_; is_adaptive_ = other.is_adaptive_; type_ = other.type_; return ret; } /*--------------------------------Metrics--------------------------------*/ TimeMap::TimeMap() : total_entry_(0) { } int TimeMap::log_entry(const int64_t start_time_us) { int ret = OB_SUCCESS; const int64_t cost_time_ms = (ObTimeUtility::current_time() - start_time_us) / 1000; time_ms_map_[cost_time_ms]++; total_entry_++; return ret; } int TimeMap::add(const TimeMap &other) { int ret = OB_SUCCESS; std::map::const_iterator it = other.time_ms_map_.begin(); while (OB_SUCC(ret) && it != other.time_ms_map_.end()) { time_ms_map_[it->first] += it->second; ++it; } if (OB_SUCC(ret)) { total_entry_ += other.total_entry_; } return ret; } void TimeMap::summary(const char *map_name_str) { const char *map_name = "Anonymous Time Map"; if (OB_NOT_NULL(map_name_str)) { map_name = map_name_str; } if (total_entry_ <= 0) { PrintHelper::print_dump_line(map_name, "Empty Time Map"); } else { const int64_t th_50_count = total_entry_ * 0.5; const int64_t th_90_count = total_entry_ * 0.9; const int64_t th_99_count = total_entry_ * 0.99; const int64_t th_999_count = total_entry_ * 0.999; int64_t min_ms = 0; int64_t th_50_ms = 0; int64_t th_90_ms = 0; int64_t th_99_ms = 0; int64_t th_999_ms = 0; int64_t cur_count = 0; int64_t max_ms = 0; std::map::const_iterator it = time_ms_map_.begin(); min_ms = it->first; while (it != time_ms_map_.end()) { cur_count += it->second; if (th_50_ms == 0 && cur_count >= th_50_count) { th_50_ms = it->first; } if (th_90_ms == 0 && cur_count >= th_90_count) { th_90_ms = it->first; } if (th_99_ms == 0 && cur_count >= th_99_count) { th_99_ms = it->first; } if (th_999_ms == 0 && cur_count >= th_999_count) { th_999_ms = it->first; } if (max_ms == 0 && cur_count == total_entry_) { max_ms = it->first; } ++it; } char buf[2048]; int ret = OB_SUCCESS; if (OB_FAIL(databuff_printf(buf, sizeof(buf), "total_entry=%ld, min_ms=%ld, th_50_ms=%ld, th_90_ms=%ld, th_99_ms=%ld, th_999_ms=%ld, max_ms=%ld", total_entry_, min_ms, th_50_ms, th_90_ms,th_99_ms, th_999_ms, max_ms))) { OB_LOG(WARN, "fail to set log str", K(ret), K_(total_entry), K(min_ms), K(th_50_ms), K(th_90_ms), K(th_99_ms), K(th_999_ms), K(max_ms)); } else { OB_LOG(INFO, "time map status", K(ret), K_(total_entry), K(min_ms), K(th_50_ms), K(th_90_ms), K(th_99_ms), K(th_999_ms), K(max_ms)); PrintHelper::print_dump_line(map_name, buf); } } } int TimeMap::assign(const TimeMap &other) { int ret = OB_SUCCESS; total_entry_ = other.total_entry_; time_ms_map_ = other.time_ms_map_; return ret; } Metrics::Metrics() : status_(OB_SUCCESS), throughput_bytes_(0), operation_num_(0), total_op_time_ms_map_(), open_time_ms_map_(), close_time_ms_map_() { } int Metrics::assign(const Metrics &other) { int ret = OB_SUCCESS; if (OB_FAIL(total_op_time_ms_map_.assign(other.total_op_time_ms_map_))) { OB_LOG(WARN, "fail to assign total_op_time_ms_map", K(ret)); } else if (OB_FAIL(open_time_ms_map_.assign(other.open_time_ms_map_))) { OB_LOG(WARN, "fail to assign open_time_ms_map", K(ret)); } else if (OB_FAIL(close_time_ms_map_.assign(other.close_time_ms_map_))) { OB_LOG(WARN, "fail to assign close_time_ms_map", K(ret)); } else { status_ = other.status_; throughput_bytes_ = other.throughput_bytes_; operation_num_ = other.operation_num_; } return ret; } int Metrics::add(const Metrics &other) { int ret = OB_SUCCESS; if (OB_SUCC(status_)) { if (OB_SUCC(other.status_)) { if (OB_FAIL(total_op_time_ms_map_.add(other.total_op_time_ms_map_))) { OB_LOG(WARN, "fail to add total_op_time_ms_map", K(ret)); } else if (OB_FAIL(open_time_ms_map_.add(other.open_time_ms_map_))) { OB_LOG(WARN, "fail to add open_time_ms_map", K(ret)); } else if (OB_FAIL(close_time_ms_map_.add(other.close_time_ms_map_))) { OB_LOG(WARN, "fail to add close_time_ms_map", K(ret)); } else { throughput_bytes_ += other.throughput_bytes_; operation_num_ += other.operation_num_; } } else { status_ = other.status_; } } return ret; } static double cal_time_diff(const timeval& start, const timeval& end) { return (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1e6; } void Metrics::summary( const struct timeval &start_real_time, const struct rusage &start_usage, const int64_t thread_num) { PrintHelper::print_dump_line("Status", status_ == OB_SUCCESS ? "SUCCESS" : "FAIL"); if (OB_LIKELY(status_ == OB_SUCCESS)) { if (OB_UNLIKELY(operation_num_ <= 0)) { PrintHelper::print_dump_line("Operation num is unexpected", operation_num_); } else { struct rusage end_usage; struct timeval end_real_time; getrusage(RUSAGE_SELF, &end_usage); gettimeofday(&end_real_time, nullptr); const double cost_time_s = cal_time_diff(start_real_time, end_real_time); const double user_cpu_time_s = cal_time_diff(start_usage.ru_utime, end_usage.ru_utime); const double sys_cpu_time_s = cal_time_diff(start_usage.ru_stime, end_usage.ru_stime); const double cpu_usage = (user_cpu_time_s + sys_cpu_time_s) / (cost_time_s) * 100.0; const double QPS = ((double)operation_num_) / cost_time_s; const double BW = ( ((double)throughput_bytes_) / 1024.0 / 1024.0 ) / cost_time_s; PrintHelper::print_dump_line("Total operation num", operation_num_); PrintHelper::print_dump_line("Total execution time", (std::to_string(cost_time_s) + " s").c_str()); PrintHelper::print_dump_line("Total user time", (std::to_string(user_cpu_time_s) + " s").c_str()); PrintHelper::print_dump_line("Total system time", (std::to_string(sys_cpu_time_s) + " s").c_str()); if (BW > 1e-6) { const double cpu_usage_for_100MB_bw = (100.0 / BW) * cpu_usage; PrintHelper::print_dump_line("CPU usage for 100MB/s BW", (std::to_string(cpu_usage_for_100MB_bw) + "% per 100MB/s").c_str()); } else { PrintHelper::print_dump_line("Total CPU usage", (std::to_string(cpu_usage) + "%").c_str()); } PrintHelper::print_dump_line("Total throughput bytes", throughput_bytes_); PrintHelper::print_dump_line("Total QPS", std::to_string(QPS).c_str()); PrintHelper::print_dump_line("Per Thread QPS", std::to_string(QPS / thread_num).c_str()); PrintHelper::print_dump_line("Total BW", (std::to_string(BW) + " MB/s").c_str()); PrintHelper::print_dump_line("Per Thread BW", (std::to_string(BW / thread_num) + " MB/s").c_str()); total_op_time_ms_map_.summary("Total Op Time Map"); open_time_ms_map_.summary("Open Time Map"); close_time_ms_map_.summary("Close Op Time Map"); } } } /*--------------------------------ITaskExecutor--------------------------------*/ ITaskExecutor::ITaskExecutor() : is_inited_(false), base_uri_len_(-1), storage_info_(nullptr), metrics_() { base_uri_[0] = '\0'; } void ITaskExecutor::reset() { is_inited_ = false; base_uri_len_ = -1; storage_info_ = nullptr; base_uri_[0] = '\0'; } int ITaskExecutor::init(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config) { int ret = OB_SUCCESS; if (OB_UNLIKELY(is_inited_)) { ret = OB_INIT_TWICE; OB_LOG(WARN, "Task Executor init twice", K(ret)); } else if (OB_ISNULL(base_uri) || OB_ISNULL(storage_info) || OB_UNLIKELY(!storage_info->is_valid())) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid arguments", K(ret), K(base_uri), KPC(storage_info)); } else if (OB_FAIL(databuff_printf(base_uri_, sizeof(base_uri_), "%s", base_uri))) { OB_LOG(WARN, "fail to deep copy base uri", K(ret), K(base_uri)); } else { base_uri_len_ = strlen(base_uri_); storage_info_ = storage_info; is_inited_ = true; } return ret; } int ITaskExecutor::prepare_(const int64_t object_id) { int ret = OB_SUCCESS; int64_t pos = base_uri_len_; if (OB_FAIL(databuff_printf(base_uri_, sizeof(base_uri_), pos, "/%ld", object_id))) { OB_LOG(WARN, "fail to construct object name", K(ret), K_(base_uri), K(object_id)); } return ret; } void ITaskExecutor::finish_(const int64_t ob_errcode) { metrics_.status_ = ob_errcode; base_uri_[base_uri_len_] = '\0'; } template typename std::enable_if::value, int>::type alloc_executor(ITaskExecutor *&executor, ObMemAttr &attr) { int ret = OB_SUCCESS; void *buf = nullptr; if (OB_ISNULL(buf = ob_malloc(sizeof(Executor), attr))) { ret = OB_ALLOCATE_MEMORY_FAILED; OB_LOG(WARN,"fail to alloc buf for task executor", K(ret)); } else { executor = new(buf) Executor(); } return ret; } int init_task_executor(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config, ITaskExecutor *&executor) { int ret = OB_SUCCESS; executor = nullptr; void *buf = nullptr; ObMemAttr attr; attr.label_ = "TMPSTR"; if (OB_ISNULL(base_uri) || OB_ISNULL(storage_info) || OB_UNLIKELY(!storage_info->is_valid() || config.type_ == BenchmarkTaskType::BENCHMARK_TASK_MAX_TYPE)) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid arguments", K(ret), K(base_uri), KPC(storage_info), K(config)); } else if (config.type_ == BenchmarkTaskType::BENCHMARK_TASK_NORMAL_WRITE) { if (OB_FAIL(alloc_executor(executor, attr))) { OB_LOG(WARN, "fail to alloc and construct executor", K(ret), K(config)); } } else if (config.type_ == BenchmarkTaskType::BENCHMARK_TASK_READ) { if (OB_FAIL(alloc_executor(executor, attr))) { OB_LOG(WARN, "fail to alloc and construct executor", K(ret), K(config)); } } else if (config.type_ == BenchmarkTaskType::BENCHMARK_TASK_APPEND_WRITE) { if (OB_FAIL(alloc_executor(executor, attr))) { OB_LOG(WARN, "fail to alloc and construct executor", K(ret), K(config)); } } else if (config.type_ == BenchmarkTaskType::BENCHMARK_TASK_MULTIPART_WRITE) { if (OB_FAIL(alloc_executor(executor, attr))) { OB_LOG(WARN, "fail to alloc and construct executor", K(ret), K(config)); } } else if (config.type_ == BenchmarkTaskType::BENCHMARK_TASK_DEL) { if (OB_FAIL(alloc_executor(executor, attr))) { OB_LOG(WARN, "fail to alloc and construct executor", K(ret), K(config)); } } else { ret = OB_ERR_UNEXPECTED; OB_LOG(WARN, "unknown benchmark task type", K(ret), K(config)); } if (FAILEDx(executor->init(base_uri, storage_info, config))) { OB_LOG(WARN, "fail to init executor", K(ret), K(base_uri), KPC(storage_info), K(config)); } if (OB_FAIL(ret)) { if (OB_NOT_NULL(executor)) { executor->~ITaskExecutor(); ob_free(executor); executor = nullptr; } } return ret; } /*--------------------------------Write Task Executor--------------------------------*/ static const int64_t MAX_RANDOM_CONTENT_LEN = 128 * 1024 * 1024L; static char RANDOM_CONTENT[MAX_RANDOM_CONTENT_LEN + 1]; void init_random_content() { static bool is_inited = false; if (!is_inited) { static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; for (int64_t i = 0; i < MAX_RANDOM_CONTENT_LEN; i++) { RANDOM_CONTENT[i] = alphanum[ObRandom::rand(0, sizeof(alphanum) - 2)]; } RANDOM_CONTENT[MAX_RANDOM_CONTENT_LEN] = '\0'; is_inited = true; } } WriteTaskExecutor::WriteTaskExecutor() : ITaskExecutor(), obj_size_(-1), write_buf_(nullptr), allocator_() { } void WriteTaskExecutor::reset() { obj_size_ = -1; write_buf_ = nullptr; allocator_.clear(); ITaskExecutor::reset(); } int WriteTaskExecutor::init(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config) { int ret = OB_SUCCESS; if (OB_FAIL(ITaskExecutor::init(base_uri, storage_info, config))) { OB_LOG(WARN, "fail to init ITaskExecutor", K(ret), K(base_uri), KPC(storage_info), K(config)); } else if (OB_UNLIKELY(config.obj_size_ <= 0 || config.obj_size_ >= MAX_RANDOM_CONTENT_LEN)) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid arguments", K(ret), K(config)); } else if (FALSE_IT(obj_size_ = config.obj_size_)) { } else if (OB_ISNULL(write_buf_ = (char *)allocator_.alloc(obj_size_ + 1))) { ret = OB_ALLOCATE_MEMORY_FAILED; OB_LOG(WARN, "fail to alloc memory for write buf", K(ret), K_(obj_size)); } else { is_inited_ = true; } if (OB_FAIL(ret)) { reset(); } return ret; } int WriteTaskExecutor::execute() { int ret = OB_SUCCESS; const int64_t object_id = metrics_.operation_num_; const int64_t start_time_us = ObTimeUtility::current_time(); if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; OB_LOG(WARN, "WriteTaskExecutor not init", K(ret), K_(base_uri)); } else if (OB_FAIL(prepare_(object_id))) { OB_LOG(WARN, "fail to prepare", K(ret), K_(base_uri), K(object_id)); } else { ObBackupIoAdapter adapter; MEMCPY(write_buf_, RANDOM_CONTENT + ObRandom::rand(0, MAX_RANDOM_CONTENT_LEN - obj_size_), obj_size_); write_buf_[obj_size_] = '\0'; if (OB_FAIL(adapter.write_single_file(base_uri_, storage_info_, write_buf_, obj_size_))) { OB_LOG(WARN, "fail to write file", K(ret), K_(base_uri), KPC_(storage_info), K_(obj_size), K(object_id)); } else { metrics_.operation_num_++; metrics_.throughput_bytes_ += obj_size_; metrics_.total_op_time_ms_map_.log_entry(start_time_us); } } finish_(ret); return ret; } AppendWriteTaskExecutor::AppendWriteTaskExecutor() : ITaskExecutor(), obj_size_(-1), fragment_size_(-1), write_buf_(nullptr), allocator_() { } void AppendWriteTaskExecutor::reset() { obj_size_ = -1; fragment_size_ = -1; write_buf_ = nullptr; allocator_.clear(); ITaskExecutor::reset(); } int AppendWriteTaskExecutor::init(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config) { int ret = OB_SUCCESS; if (OB_FAIL(ITaskExecutor::init(base_uri, storage_info, config))) { OB_LOG(WARN, "fail to init ITaskExecutor", K(ret), K(base_uri), KPC(storage_info), K(config)); } else if (OB_UNLIKELY(config.fragment_size_ <= 0 || config.fragment_size_ > config.obj_size_ || config.fragment_size_ >= MAX_RANDOM_CONTENT_LEN)) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid arguments", K(ret), K(config)); } else if (FALSE_IT(obj_size_ = config.obj_size_)) { } else if (FALSE_IT(fragment_size_ = config.fragment_size_)) { } else if (OB_ISNULL(write_buf_ = (char *)allocator_.alloc(fragment_size_ + 1))) { ret = OB_ALLOCATE_MEMORY_FAILED; OB_LOG(WARN, "fail to alloc memory for write buf", K(ret), K_(fragment_size)); } else { is_inited_ = true; } if (OB_FAIL(ret)) { reset(); } return ret; } int AppendWriteTaskExecutor::execute() { int ret = OB_SUCCESS; const int64_t object_id = metrics_.operation_num_; const int64_t start_time_us = ObTimeUtility::current_time(); if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; OB_LOG(WARN, "AppendWriteTaskExecutor not init", K(ret), K_(base_uri)); } else if (OB_FAIL(prepare_(object_id))) { OB_LOG(WARN, "fail to prepare", K(ret), K_(base_uri), K(object_id)); } else { ObBackupIoAdapter adapter; ObIOFd fd; ObIODevice *device_handle = nullptr; ObStorageAccessType access_type = OB_STORAGE_ACCESS_RANDOMWRITER; const int64_t open_start_time_us = ObTimeUtility::current_time(); if (OB_FAIL(adapter.open_with_access_type( device_handle, fd, storage_info_, base_uri_, access_type))) { OB_LOG(WARN, "failed to open device with access type", K(ret), K_(base_uri), KPC_(storage_info), K(access_type)); } else if (OB_ISNULL(device_handle)) { ret = OB_ERR_UNEXPECTED; OB_LOG(WARN, "device handle is NULL", K(ret), KP(device_handle), K_(base_uri)); } else { metrics_.open_time_ms_map_.log_entry(open_start_time_us); } int64_t cur_offset = 0; int64_t actual_write_size = -1; int64_t cur_append_size = -1; while (OB_SUCC(ret) && cur_offset < obj_size_) { cur_append_size = MIN(obj_size_ - cur_offset, fragment_size_); MEMCPY(write_buf_, RANDOM_CONTENT + ObRandom::rand(0, MAX_RANDOM_CONTENT_LEN - cur_append_size), cur_append_size); write_buf_[cur_append_size] = '\0'; if (OB_FAIL(device_handle->pwrite(fd, cur_offset, cur_append_size, write_buf_, actual_write_size))) { OB_LOG(WARN, "fail to append object", K(ret), K_(base_uri), K(cur_offset), K(cur_append_size)); } else { cur_offset += cur_append_size; } } const int64_t close_start_time_us = ObTimeUtility::current_time(); if (FAILEDx(device_handle->seal_file(fd))) { OB_LOG(WARN, "fail to seal file", K(ret), K_(base_uri)); } else if (OB_FAIL(adapter.close_device_and_fd(device_handle, fd))) { OB_LOG(WARN, "fail to close device handle", K(ret), K_(base_uri)); } else { metrics_.close_time_ms_map_.log_entry(close_start_time_us); } if (OB_SUCC(ret)) { metrics_.operation_num_++; metrics_.throughput_bytes_ += obj_size_; metrics_.total_op_time_ms_map_.log_entry(start_time_us); } } finish_(ret); return ret; } MultipartWriteTaskExecutor::MultipartWriteTaskExecutor() : ITaskExecutor(), obj_size_(-1), part_size_(-1), write_buf_(nullptr), allocator_() { } void MultipartWriteTaskExecutor::reset() { obj_size_ = -1; part_size_ = -1; write_buf_ = nullptr; allocator_.clear(); ITaskExecutor::reset(); } int MultipartWriteTaskExecutor::init(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config) { int ret = OB_SUCCESS; if (OB_FAIL(ITaskExecutor::init(base_uri, storage_info, config))) { OB_LOG(WARN, "fail to init ITaskExecutor", K(ret), K(base_uri), KPC(storage_info), K(config)); } else if (OB_UNLIKELY(config.fragment_size_ <= 0 || config.fragment_size_ > config.obj_size_ || config.fragment_size_ >= MAX_RANDOM_CONTENT_LEN)) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid arguments", K(ret), K(config)); } else if (FALSE_IT(obj_size_ = config.obj_size_)) { } else if (FALSE_IT(part_size_ = config.fragment_size_)) { } else if (OB_ISNULL(write_buf_ = (char *)allocator_.alloc(part_size_ + 1))) { ret = OB_ALLOCATE_MEMORY_FAILED; OB_LOG(WARN, "fail to alloc memory for write buf", K(ret), K_(part_size)); } else { is_inited_ = true; } if (OB_FAIL(ret)) { reset(); } return ret; } int MultipartWriteTaskExecutor::execute() { int ret = OB_SUCCESS; const int64_t object_id = metrics_.operation_num_; const int64_t start_time_us = ObTimeUtility::current_time(); if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; OB_LOG(WARN, "MultipartWriteTaskExecutor not init", K(ret), K_(base_uri)); } else if (OB_FAIL(prepare_(object_id))) { OB_LOG(WARN, "fail to prepare", K(ret), K_(base_uri), K(object_id)); } else { ObBackupIoAdapter adapter; ObIOFd fd; ObIODevice *device_handle = nullptr; ObStorageAccessType access_type = OB_STORAGE_ACCESS_MULTIPART_WRITER; const int64_t open_start_time_us = ObTimeUtility::current_time(); if (OB_FAIL(adapter.open_with_access_type( device_handle, fd, storage_info_, base_uri_, access_type))) { OB_LOG(WARN, "failed to open device with access type", K(ret), K_(base_uri), KPC_(storage_info), K(access_type)); } else if (OB_ISNULL(device_handle)) { ret = OB_ERR_UNEXPECTED; OB_LOG(WARN, "device handle is NULL", K(ret), KP(device_handle), K_(base_uri)); } else { metrics_.open_time_ms_map_.log_entry(open_start_time_us); } int64_t cur_offset = 0; int64_t actual_write_size = -1; int64_t cur_part_size = -1; while (OB_SUCC(ret) && cur_offset < obj_size_) { cur_part_size = MIN(obj_size_ - cur_offset, part_size_); MEMCPY(write_buf_, RANDOM_CONTENT + ObRandom::rand(0, MAX_RANDOM_CONTENT_LEN - cur_part_size), cur_part_size); write_buf_[cur_part_size] = '\0'; if (OB_FAIL(device_handle->pwrite(fd, cur_offset, cur_part_size, write_buf_, actual_write_size))) { OB_LOG(WARN, "fail to upload part", K(ret), K_(base_uri), K(cur_offset), K(cur_part_size)); } else { cur_offset += cur_part_size; } } const int64_t close_start_time_us = ObTimeUtility::current_time(); if (FAILEDx(adapter.close_device_and_fd(device_handle, fd))) { OB_LOG(WARN, "fail to close device handle", K(ret), K_(base_uri)); } else { metrics_.close_time_ms_map_.log_entry(close_start_time_us); } if (OB_SUCC(ret)) { metrics_.operation_num_++; metrics_.throughput_bytes_ += obj_size_; metrics_.total_op_time_ms_map_.log_entry(start_time_us); } } finish_(ret); return ret; } /*--------------------------------Read Task Executor--------------------------------*/ ReadTaskExecutor::ReadTaskExecutor() : ITaskExecutor(), obj_size_(-1), obj_num_(-1), is_adaptive_(false), expected_read_size_(-1), read_buf_(nullptr), allocator_() { } void ReadTaskExecutor::reset() { obj_size_ = -1; obj_num_ = -1; is_adaptive_ = false; expected_read_size_ = -1; read_buf_ = nullptr; allocator_.clear(); ITaskExecutor::reset(); } int ReadTaskExecutor::init(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config) { int ret = OB_SUCCESS; if (OB_FAIL(ITaskExecutor::init(base_uri, storage_info, config))) { OB_LOG(WARN, "fail to init ITaskExecutor", K(ret), K(base_uri), KPC(storage_info), K(config)); } else if (OB_UNLIKELY(config.fragment_size_ <= 0 || config.fragment_size_ > config.obj_size_ || config.obj_num_ <= 0)) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid arguments", K(ret), K(config)); } else if (FALSE_IT(obj_size_ = config.obj_size_)) { } else if (FALSE_IT(expected_read_size_ = config.fragment_size_)) { } else if (OB_ISNULL(read_buf_ = (char *)allocator_.alloc(expected_read_size_ + 1))) { ret = OB_ALLOCATE_MEMORY_FAILED; OB_LOG(WARN, "fail to alloc memory for read buf", K(ret), K_(obj_size), K_(expected_read_size)); } else { obj_num_ = config.obj_num_; is_adaptive_ = config.is_adaptive_; is_inited_ = true; } if (OB_FAIL(ret)) { reset(); } return ret; } int ReadTaskExecutor::execute() { int ret = OB_SUCCESS; const int64_t object_id = ObRandom::rand(0, obj_num_ - 1); const int64_t start_time_us = ObTimeUtility::current_time(); if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; OB_LOG(WARN, "ReadTaskExecutor not init", K(ret), K_(base_uri)); } else if (OB_FAIL(prepare_(object_id))) { OB_LOG(WARN, "fail to prepare", K(ret), K_(base_uri), K(object_id)); } else { ObBackupIoAdapter adapter; const int64_t offset = (ObRandom::rand(0, obj_size_ - expected_read_size_) / ALIGNMENT) * ALIGNMENT; int64_t read_size = -1; if (is_adaptive_ && OB_FAIL(adapter.adaptively_read_part_file(base_uri_, storage_info_, read_buf_, expected_read_size_, offset, read_size))) { OB_LOG(WARN, "fail to read adaptive file", K(ret), K_(base_uri), KPC_(storage_info), K_(expected_read_size), K_(obj_size), K(offset), K(object_id)); } else if (!is_adaptive_ && OB_FAIL(adapter.read_part_file(base_uri_, storage_info_, read_buf_, expected_read_size_, offset, read_size))) { OB_LOG(WARN, "fail to read file", K(ret), K_(base_uri), KPC_(storage_info), K_(expected_read_size), K_(obj_size), K(offset), K(object_id)); } else { metrics_.operation_num_++; metrics_.throughput_bytes_ += read_size; metrics_.total_op_time_ms_map_.log_entry(start_time_us); } } finish_(ret); return ret; } /*--------------------------------Del Task Executor--------------------------------*/ DelTaskExecutor::DelTaskExecutor() : ITaskExecutor(), is_adaptive_(false) { } int DelTaskExecutor::init(const char *base_uri, share::ObBackupStorageInfo *storage_info, const TaskConfig &config) { int ret = OB_SUCCESS; if (OB_FAIL(ITaskExecutor::init(base_uri, storage_info, config))) { OB_LOG(WARN, "fail to init ITaskExecutor", K(ret), K(base_uri), KPC(storage_info), K(config)); } else { is_adaptive_ = config.is_adaptive_; is_inited_ = true; } if (OB_FAIL(ret)) { reset(); } return ret; } int DelTaskExecutor::execute() { int ret = OB_SUCCESS; const int64_t object_id = metrics_.operation_num_; const int64_t start_time_us = ObTimeUtility::current_time(); if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; OB_LOG(WARN, "DelTaskExecutor not init", K(ret), K_(base_uri)); } else if (OB_FAIL(prepare_(object_id))) { OB_LOG(WARN, "fail to prepare", K(ret), K_(base_uri), K(object_id)); } else { ObBackupIoAdapter adapter; if (is_adaptive_ && OB_FAIL(adapter.adaptively_del_file(base_uri_, storage_info_))) { OB_LOG(WARN, "fail to delete adaptive file", K(ret), K_(base_uri), KPC_(storage_info), K(object_id)); } else if (!is_adaptive_ && OB_FAIL(adapter.del_file(base_uri_, storage_info_))) { OB_LOG(WARN, "fail to delete file", K(ret), K_(base_uri), KPC_(storage_info), K(object_id)); } else { metrics_.operation_num_++; metrics_.total_op_time_ms_map_.log_entry(start_time_us); } } finish_(ret); return ret; } } //tools } //oceanbase