/** * 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 "fetch_log_engine.h" #include "log_define.h" #include "palf_handle_impl.h" #include "palf_handle_impl_guard.h" #include "share/allocator/ob_tenant_mutil_allocator.h" #include "share/ob_thread_mgr.h" #include "share/ob_ls_id.h" #include "palf_env_impl.h" namespace oceanbase { using namespace common; namespace palf { int FetchLogTask::set(const int64_t id, const common::ObAddr &server, const FetchLogType fetch_type, const int64_t &proposal_id, const LSN &prev_lsn, const LSN &start_lsn, const int64_t log_size, const int64_t log_count, const int64_t accepted_mode_pid) { int ret = OB_SUCCESS; if (id < 0 || !server.is_valid() || INVALID_PROPOSAL_ID == proposal_id || !start_lsn.is_valid() || log_size < 0 || log_count < 0 || INVALID_PROPOSAL_ID == accepted_mode_pid) { ret = OB_INVALID_ARGUMENT; PALF_LOG(WARN, "invalid argument", K(id), K(server), K(proposal_id), K(prev_lsn), K(start_lsn), K(log_size), K(log_count), K(accepted_mode_pid)); } else { timestamp_us_ = ObTimeUtility::current_time(); id_ = id; server_ = server; fetch_type_ = fetch_type; proposal_id_ = proposal_id; prev_lsn_ = prev_lsn; start_lsn_ = start_lsn; log_size_ = log_size; log_count_ = log_count; accepted_mode_pid_ = accepted_mode_pid; } return ret; } void FetchLogTask::reset() { timestamp_us_ = common::OB_INVALID_TIMESTAMP; id_ = -1; server_.reset(); fetch_type_ = FETCH_LOG_FOLLOWER; proposal_id_ = INVALID_PROPOSAL_ID; prev_lsn_.reset(); start_lsn_.reset(); log_size_ = 0; accepted_mode_pid_ = INVALID_PROPOSAL_ID; } FetchLogEngine::FetchLogEngine() : tg_id_(-1), is_inited_(false), palf_env_impl_(NULL), allocator_(NULL), replayable_point_() {} int FetchLogEngine::init(IPalfEnvImpl *palf_env_impl, common::ObILogAllocator *alloc_mgr) { int ret = OB_SUCCESS; if (is_inited_) { PALF_LOG(WARN, "FetchLogEngine init twice"); ret = OB_INIT_TWICE; } else if (OB_ISNULL(palf_env_impl) || OB_ISNULL(alloc_mgr)) { PALF_LOG(WARN, "invalid argument", KP(palf_env_impl), K(alloc_mgr)); ret = OB_INVALID_ARGUMENT; } else if (OB_FAIL(TG_CREATE_TENANT(lib::TGDefIDs::LSFetchLogEngine, tg_id_))) { PALF_LOG(WARN, "ObSimpleThreadPool::init failed", K(ret)); } else if (OB_FAIL(MTL_REGISTER_THREAD_DYNAMIC(1, tg_id_))) { PALF_LOG(WARN, "MTL_REGISTER_THREAD_DYNAMIC failed", K(ret), K(tg_id_)); } else { palf_env_impl_ = palf_env_impl; allocator_ = alloc_mgr; is_inited_ = true; } if ((OB_FAIL(ret)) && (OB_INIT_TWICE != ret)) { PALF_LOG(WARN, "FetchLogEngine init failed", K(ret), KP(palf_env_impl)); destroy(); } return ret; } int FetchLogEngine::start() { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(ERROR, "FetchLogEngine not inited!!!", K(ret)); } else if (OB_FAIL(TG_SET_HANDLER_AND_START(tg_id_, *this))) { PALF_LOG(ERROR, "start FetchLogEngine failed", K(ret)); } else { PALF_LOG(INFO, "start FetchLogEngine success", K(ret), K(tg_id_)); } return ret; } int FetchLogEngine::stop() { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(WARN, "FetchLogEngine not inited!!!", K(ret)); } else { TG_STOP(tg_id_); PALF_LOG(INFO, "stop FetchLogEngine success", K(tg_id_)); } return ret; } int FetchLogEngine::wait() { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(WARN, "FetchLogEngine not inited!!!", K(ret)); } else { TG_WAIT(tg_id_); PALF_LOG(INFO, "wait FetchLogEngine success", K(tg_id_)); } return ret; } void FetchLogEngine::destroy() { stop(); wait(); is_inited_ = false; if (-1 != tg_id_) { MTL_UNREGISTER_THREAD_DYNAMIC(tg_id_); TG_DESTROY(tg_id_); } tg_id_ = -1; palf_env_impl_ = NULL; allocator_ = NULL; PALF_LOG(INFO, "destroy FetchLogEngine success", K(tg_id_)); } int FetchLogEngine::submit_fetch_log_task(FetchLogTask *fetch_log_task) { int ret = OB_SUCCESS; if (!is_inited_) { PALF_LOG(WARN, "FetchLogEngine not init"); ret = OB_NOT_INIT; } else if (OB_ISNULL(fetch_log_task)) { PALF_LOG(WARN, "invalid argument", KP(fetch_log_task)); ret = OB_INVALID_ARGUMENT; } else if (OB_FAIL(TG_PUSH_TASK(tg_id_, fetch_log_task))) { PALF_LOG(WARN, "push failed", K(ret), KPC(fetch_log_task)); } else { //do nothing } return ret; } void FetchLogEngine::handle(void *task) { int ret = OB_SUCCESS; IPalfHandleImpl *palf_handle_impl = NULL; if (!is_inited_) { PALF_LOG(WARN, "FetchLogEngine not init"); } else if (OB_ISNULL(task)) { PALF_LOG(WARN, "invalid argument", KP(task)); } else { int64_t handle_start_time_us = ObTimeUtility::current_time(); FetchLogTask *fetch_log_task = static_cast(task); int64_t palf_id = -1; if (OB_ISNULL(fetch_log_task)) { PALF_LOG(ERROR, "fetch_log_task is NULL"); } else if (is_task_queue_timeout_(fetch_log_task)) { PALF_LOG(WARN, "fetch log task wait timeout, ignore", K(ret), KPC(fetch_log_task)); } else { palf_id = fetch_log_task->get_id(); PALF_LOG(INFO, "handle fetch_log_task", KPC(fetch_log_task)); IPalfHandleImplGuard guard; if (OB_FAIL(palf_env_impl_->get_palf_handle_impl(palf_id, guard))) { if (OB_ENTRY_NOT_EXIST != ret) { PALF_LOG(ERROR, "PalfEnvImpl get_palf_handle_impl failed", K(ret), K(palf_id)); } else { PALF_LOG(WARN, "ObLogService has not existed!!!", K(ret), K(palf_id)); } } else if (OB_ISNULL(palf_handle_impl = guard.get_palf_handle_impl())) { ret = OB_ERR_UNEXPECTED; PALF_LOG(WARN, "invalid log service", K(ret), K(palf_id)); } else if (OB_FAIL(palf_handle_impl->fetch_log_from_storage(fetch_log_task->get_server(), fetch_log_task->get_fetch_type(), fetch_log_task->get_proposal_id(), fetch_log_task->get_prev_lsn(), fetch_log_task->get_start_lsn(), fetch_log_task->get_log_size(), fetch_log_task->get_log_count(), fetch_log_task->get_accepted_mode_meta(), replayable_point_.atomic_load()))) { PALF_LOG(WARN, "fetch_log_from_storage failed", K(ret), K(palf_id), KPC(fetch_log_task)); } else { // do nothing } } int64_t handle_finish_time_us = ObTimeUtility::current_time(); int64_t handle_cost_time_us = handle_finish_time_us - handle_start_time_us; if (REACH_TIME_INTERVAL(100 * 1000L)) { PALF_LOG(INFO, "handle fetch log task", K(ret), K(palf_id), K(handle_cost_time_us), KPC(fetch_log_task)); } else if (handle_cost_time_us > 200 * 1000L) { PALF_LOG(INFO, "handle fetch log task cost too much time", K(ret), K(palf_id), K(handle_cost_time_us), KPC(fetch_log_task)); } free_fetch_log_task(fetch_log_task); } } void FetchLogEngine::handle_drop(void *task) { int ret = OB_SUCCESS; IPalfHandleImpl *palf_handle_impl = NULL; if (!is_inited_) { PALF_LOG(WARN, "FetchLogEngine not init"); } else if (OB_ISNULL(task)) { PALF_LOG(WARN, "invalid argument", KP(task)); } else { FetchLogTask *fetch_log_task = static_cast(task); free_fetch_log_task(fetch_log_task); } } FetchLogTask *FetchLogEngine::alloc_fetch_log_task() { return allocator_->alloc_palf_fetch_log_task(); } void FetchLogEngine::free_fetch_log_task(FetchLogTask *task) { allocator_->free_palf_fetch_log_task(task); } bool FetchLogEngine::is_task_queue_timeout_(FetchLogTask *task) const { bool bool_ret = false; if (!is_inited_) { PALF_LOG_RET(WARN, OB_NOT_INIT, "FetchLogEngine not init"); } else if (OB_ISNULL(task)) { PALF_LOG_RET(WARN, OB_INVALID_ARGUMENT, "invalid argument", KP(task)); } else { bool_ret = (ObTimeUtility::current_time() - task->get_timestamp_us()) > PALF_FETCH_LOG_INTERVAL_US; } return bool_ret; } int FetchLogEngine::update_replayable_point(const share::SCN &replayable_scn) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; } else { replayable_point_.atomic_store(replayable_scn); } return ret; } } // namespace palf } // namespace oceanbase