From 9064421f66663e0c703fd402b8b70c82b8138c9e Mon Sep 17 00:00:00 2001 From: Jack Drogon Date: Tue, 21 Nov 2023 20:30:27 +0800 Subject: [PATCH] [fix](clone) Fix engine_clone file exist (#27361) Signed-off-by: Jack Drogon --- be/src/common/status.h | 2 + be/src/olap/task/engine_clone_task.cpp | 79 +++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/be/src/common/status.h b/be/src/common/status.h index b11642371303e7..88981fe808b329 100644 --- a/be/src/common/status.h +++ b/be/src/common/status.h @@ -595,6 +595,8 @@ inline std::string Status::to_string() const { template using Result = expected; +using ResultError = unexpected; + #define RETURN_IF_ERROR_RESULT(stmt) \ do { \ Status _status_ = (stmt); \ diff --git a/be/src/olap/task/engine_clone_task.cpp b/be/src/olap/task/engine_clone_task.cpp index 3621a958eff80c..86ba6ac2b9f364 100644 --- a/be/src/olap/task/engine_clone_task.cpp +++ b/be/src/olap/task/engine_clone_task.cpp @@ -74,6 +74,58 @@ using strings::SkipWhitespace; namespace doris { using namespace ErrorCode; +namespace { +/// if binlog file exist, then check if binlog file md5sum equal +/// if equal, then skip link file +/// if not equal, then return error +/// return value: if binlog file not exist, then return to binlog file path +Result check_dest_binlog_valid(const std::string& tablet_dir, + const std::string& clone_file, bool* skip_link_file) { + // change clone_file suffix .binlog to .dat + std::string new_clone_file = clone_file; + new_clone_file.replace(clone_file.size() - 7, 7, ".dat"); + auto to = fmt::format("{}/_binlog/{}", tablet_dir, new_clone_file); + + // check to to file exist + bool exists = true; + auto status = io::global_local_filesystem()->exists(to, &exists); + if (!status.ok()) { + return ResultError(std::move(status)); + } + + if (!exists) { + return to; + } + + LOG(WARNING) << "binlog file already exist. " + << "tablet_dir=" << tablet_dir << ", clone_file=" << clone_file; + + std::string clone_file_md5sum; + status = io::global_local_filesystem()->md5sum(clone_file, &clone_file_md5sum); + if (!status.ok()) { + return ResultError(std::move(status)); + } + std::string to_file_md5sum; + status = io::global_local_filesystem()->md5sum(to, &to_file_md5sum); + if (!status.ok()) { + return ResultError(std::move(status)); + } + + if (clone_file_md5sum == to_file_md5sum) { + // if md5sum equal, then skip link file + *skip_link_file = true; + return to; + } else { + auto err_msg = fmt::format( + "binlog file already exist, but md5sum not equal. " + "tablet_dir={}, clone_file={}", + tablet_dir, clone_file); + LOG(WARNING) << err_msg; + return ResultError(Status::InternalError(std::move(err_msg))); + } +} +} // namespace + #define RETURN_IF_ERROR_(status, stmt) \ do { \ status = (stmt); \ @@ -603,6 +655,8 @@ Status EngineCloneTask::_finish_clone(Tablet* tablet, const std::string& clone_d /// Traverse all downloaded clone files in CLONE dir. /// If it does not exist in local tablet dir, link the file to local tablet dir /// And save all linked files in linked_success_files. + /// if binlog exist in clone dir and md5sum equal, then skip link file + bool skip_link_file = false; for (const string& clone_file : clone_file_names) { if (local_file_names.find(clone_file) != local_file_names.end()) { VLOG_NOTICE << "find same file when clone, skip it. " @@ -619,19 +673,30 @@ Status EngineCloneTask::_finish_clone(Tablet* tablet, const std::string& clone_d break; } - // change clone_file suffix .binlog to .dat - std::string new_clone_file = clone_file; - new_clone_file.replace(clone_file.size() - 7, 7, ".dat"); - to = fmt::format("{}/_binlog/{}", tablet_dir, new_clone_file); + if (auto&& result = check_dest_binlog_valid(tablet_dir, clone_file, &skip_link_file); + result) { + to = std::move(result.value()); + } else { + status = std::move(result.error()); + return status; + } } else { to = fmt::format("{}/{}", tablet_dir, clone_file); } - RETURN_IF_ERROR(io::global_local_filesystem()->link_file(from, to)); - linked_success_files.emplace_back(std::move(to)); + if (!skip_link_file) { + status = io::global_local_filesystem()->link_file(from, to); + if (!status.ok()) { + return status; + } + linked_success_files.emplace_back(std::move(to)); + } } if (contain_binlog) { - RETURN_IF_ERROR(tablet->ingest_binlog_metas(&rowset_binlog_metas_pb)); + status = tablet->ingest_binlog_metas(&rowset_binlog_metas_pb); + if (!status.ok()) { + return status; + } } // clone and compaction operation should be performed sequentially