1580 lines
66 KiB
C++
1580 lines
66 KiB
C++
/**log_engine.cpp
|
|
* 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.
|
|
*/
|
|
|
|
#define USING_LOG_PREFIX PALF
|
|
#include "log_engine.h"
|
|
#include "lib/lock/ob_spin_lock.h"
|
|
#include "lib/ob_define.h"
|
|
#include "lib/ob_errno.h"
|
|
#include "lib/utility/ob_macro_utils.h" // For UNUSED
|
|
#include "lib/oblog/ob_log_module.h" // PALF_LOG
|
|
#include "share/ob_errno.h" // ERRNO
|
|
#include "share/rc/ob_tenant_base.h" // mtl_malloc
|
|
#include "share/allocator/ob_tenant_mutil_allocator.h" // ObILogAllocator
|
|
#include "log_io_task_cb_utils.h" // LogFlushCbCtx...
|
|
#include "log_io_task.h" // LogIOTask
|
|
#include "log_io_worker.h" // LogIOWorker
|
|
#include "log_reader_utils.h" // ReadBuf
|
|
#include "log_writer_utils.h" // LogWriteBuf
|
|
#include "lsn.h" // LSN
|
|
#include "log_meta_entry.h" // LogMetaEntry
|
|
#include "log_group_entry_header.h" // LogGroupEntryHeader
|
|
#include "log_define.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
using namespace share;
|
|
namespace palf
|
|
{
|
|
|
|
// ===================== LogEngine start =======================
|
|
LogEngine::LogEngine() :
|
|
block_gc_lock_(common::ObLatchIds::PALF_LOG_ENGINE_LOCK),
|
|
min_block_max_scn_(),
|
|
min_block_id_(LOG_INVALID_BLOCK_ID),
|
|
base_lsn_for_block_gc_(PALF_INITIAL_LSN_VAL),
|
|
log_meta_lock_(common::ObLatchIds::PALF_LOG_ENGINE_LOCK),
|
|
log_meta_(),
|
|
log_meta_storage_(),
|
|
log_storage_(),
|
|
log_net_service_(),
|
|
alloc_mgr_(NULL),
|
|
log_io_worker_(NULL),
|
|
plugins_(NULL),
|
|
palf_id_(INVALID_PALF_ID),
|
|
palf_epoch_(-1),
|
|
last_purge_throttling_ts_(OB_INVALID_TIMESTAMP),
|
|
is_inited_(false)
|
|
{}
|
|
|
|
LogEngine::~LogEngine() { destroy(); }
|
|
|
|
|
|
int LogEngine::append_log_meta_(const LogMeta &log_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t pos = 0;
|
|
char *buf = NULL;
|
|
const int64_t buf_len = MAX_META_ENTRY_SIZE;
|
|
if (NULL == (buf = reinterpret_cast<char *>(mtl_malloc(buf_len,
|
|
"LogEngine")))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "allocate memory failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(serialize_log_meta_(log_meta, buf, buf_len))) {
|
|
PALF_LOG(ERROR, "serialize_log_meta_ failed", K(ret), K_(palf_id), K_(is_inited), K(log_meta));
|
|
} else if (OB_FAIL(log_meta_storage_.append_meta(buf, buf_len))) {
|
|
PALF_LOG(ERROR, "log_meta_storage_ append failed", K(ret), K_(palf_id), K_(is_inited));
|
|
}
|
|
if (NULL != buf) {
|
|
mtl_free(buf);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::init(const int64_t palf_id,
|
|
const char *base_dir,
|
|
const LogMeta &log_meta,
|
|
ObILogAllocator *alloc_mgr,
|
|
ILogBlockPool *log_block_pool,
|
|
LogHotCache *hot_cache,
|
|
LogRpc *log_rpc,
|
|
LogIOWorker *log_io_worker,
|
|
LogPlugins *plugins,
|
|
const int64_t palf_epoch,
|
|
const int64_t log_storage_block_size,
|
|
const int64_t log_meta_storage_block_ize)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
auto log_meta_storage_update_manifest_cb = [](const block_id_t max_block_id, const bool in_restart) {
|
|
// do nothing
|
|
return OB_SUCCESS;
|
|
};
|
|
auto log_storage_update_manifest_cb = [this](const block_id_t max_block_id, const bool in_restart) {
|
|
return this->update_manifest(max_block_id);
|
|
};
|
|
if (IS_INIT) {
|
|
ret = OB_INIT_TWICE;
|
|
PALF_LOG(ERROR, "LogEngine has inited!!!", K(ret), K(palf_id));
|
|
} else if (false == is_valid_palf_id(palf_id) || OB_ISNULL(base_dir) || OB_ISNULL(alloc_mgr)
|
|
|| OB_ISNULL(log_rpc) || OB_ISNULL(log_io_worker) || OB_ISNULL(plugins)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR,
|
|
"Invalid argument!!!",
|
|
K(ret),
|
|
K(palf_id),
|
|
K(base_dir),
|
|
K(log_meta),
|
|
K(hot_cache),
|
|
K(alloc_mgr),
|
|
K(log_io_worker),
|
|
K(plugins));
|
|
// NB: Nowday, LSN is strongly dependent on physical block,
|
|
} else if (OB_FAIL(log_meta_storage_.init(base_dir,
|
|
"meta",
|
|
LSN(PALF_INITIAL_LSN_VAL),
|
|
palf_id,
|
|
log_meta_storage_block_ize,
|
|
LOG_DIO_ALIGN_SIZE,
|
|
LOG_DIO_ALIGNED_BUF_SIZE_META,
|
|
log_meta_storage_update_manifest_cb,
|
|
log_block_pool,
|
|
plugins,
|
|
NULL /*set hot_cache to NULL for meta storage*/))) {
|
|
PALF_LOG(ERROR, "LogMetaStorage init failed", K(ret), K(palf_id), K(base_dir));
|
|
} else if(0 != log_storage_block_size
|
|
&& OB_FAIL(log_storage_.init(base_dir,
|
|
"log",
|
|
log_meta.get_log_snapshot_meta().base_lsn_,
|
|
palf_id,
|
|
log_storage_block_size,
|
|
LOG_DIO_ALIGN_SIZE,
|
|
LOG_DIO_ALIGNED_BUF_SIZE_REDO,
|
|
log_storage_update_manifest_cb,
|
|
log_block_pool,
|
|
plugins,
|
|
hot_cache))) {
|
|
PALF_LOG(ERROR, "LogStorage init failed!!!", K(ret), K(palf_id), K(base_dir), K(log_meta));
|
|
} else if (OB_FAIL(log_net_service_.init(palf_id, log_rpc))) {
|
|
PALF_LOG(ERROR, "LogNetService init failed", K(ret), K(palf_id));
|
|
} else if (OB_FAIL(append_log_meta_(log_meta))) {
|
|
PALF_LOG(ERROR, "append_log_meta_ failed", K(ret));
|
|
} else {
|
|
palf_id_ = palf_id;
|
|
log_meta_ = log_meta;
|
|
alloc_mgr_ = alloc_mgr;
|
|
log_io_worker_ = log_io_worker;
|
|
plugins_ = plugins;
|
|
palf_epoch_ = palf_epoch;
|
|
base_lsn_for_block_gc_ = log_meta.get_log_snapshot_meta().base_lsn_;
|
|
is_inited_ = true;
|
|
PALF_LOG(INFO, "LogEngine init success", K(ret), K(palf_id), K(base_dir), K(palf_epoch));
|
|
}
|
|
if (OB_FAIL(ret) && OB_INIT_TWICE != ret) {
|
|
destroy();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void LogEngine::destroy()
|
|
{
|
|
if (IS_INIT) {
|
|
PALF_LOG(INFO, "LogEngine destroy", K_(palf_id), K_(is_inited));
|
|
is_inited_ = false;
|
|
palf_id_ = INVALID_PALF_ID;
|
|
log_io_worker_ = NULL;
|
|
alloc_mgr_ = NULL;
|
|
log_net_service_.destroy();
|
|
log_meta_storage_.destroy();
|
|
log_meta_.reset();
|
|
log_storage_.destroy();
|
|
base_lsn_for_block_gc_.reset();
|
|
min_block_id_ = LOG_INVALID_BLOCK_ID;
|
|
min_block_max_scn_.reset();
|
|
last_purge_throttling_ts_ = OB_INVALID_TIMESTAMP;
|
|
}
|
|
}
|
|
|
|
int LogEngine::load(const int64_t palf_id,
|
|
const char *base_dir,
|
|
common::ObILogAllocator *alloc_mgr,
|
|
ILogBlockPool *log_block_pool,
|
|
LogHotCache *hot_cache,
|
|
LogRpc *log_rpc,
|
|
LogIOWorker *log_io_worker,
|
|
LogPlugins *plugins,
|
|
LogGroupEntryHeader &entry_header,
|
|
const int64_t palf_epoch,
|
|
bool &is_integrity,
|
|
const int64_t log_storage_block_size,
|
|
const int64_t log_meta_storage_block_ize)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObTimeGuard guard("load", 0);
|
|
block_id_t expected_next_block_id = LOG_INVALID_BLOCK_ID;
|
|
auto log_meta_storage_update_manifest_cb = [](const block_id_t new_expected_next_block_id, const bool in_restart) {
|
|
// do nothing
|
|
return OB_SUCCESS;
|
|
};
|
|
auto log_storage_update_manifest_cb = [&expected_next_block_id, this](const block_id_t new_expected_next_block_id, const bool in_restart) {
|
|
int ret = OB_SUCCESS;
|
|
if (in_restart) {
|
|
if (new_expected_next_block_id == expected_next_block_id + 1) {
|
|
PALF_LOG(INFO, "need update_manifest in restart", K(in_restart), K(new_expected_next_block_id), K(expected_next_block_id));
|
|
ret = this->update_manifest(new_expected_next_block_id);
|
|
} else {
|
|
PALF_LOG(INFO, "no need update_manifest in restart", K(in_restart), K(new_expected_next_block_id), K(expected_next_block_id));
|
|
}
|
|
} else {
|
|
ret = this->update_manifest(new_expected_next_block_id);
|
|
}
|
|
return ret;
|
|
};
|
|
LSN last_group_entry_header_lsn;
|
|
LSN last_meta_entry_start_lsn;
|
|
LogMetaEntryHeader unused_meta_entry_header;
|
|
if (IS_INIT) {
|
|
ret = OB_INIT_TWICE;
|
|
PALF_LOG(ERROR, "LogEngine has initted!!!", K(ret), K(palf_id));
|
|
} else if (false == is_valid_palf_id(palf_id) || OB_ISNULL(base_dir)
|
|
|| OB_ISNULL(alloc_mgr) || OB_ISNULL(log_rpc) || OB_ISNULL(log_io_worker)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(palf_id), K(base_dir), K(hot_cache), K(alloc_mgr),
|
|
K(log_io_worker));
|
|
} else if (OB_FAIL(log_meta_storage_.load(base_dir,
|
|
"meta",
|
|
LSN(PALF_INITIAL_LSN_VAL),
|
|
palf_id,
|
|
log_meta_storage_block_ize,
|
|
LOG_DIO_ALIGN_SIZE,
|
|
LOG_DIO_ALIGNED_BUF_SIZE_META,
|
|
log_meta_storage_update_manifest_cb,
|
|
log_block_pool,
|
|
plugins,
|
|
NULL, /*set hot_cache to NULL for meta storage*/
|
|
unused_meta_entry_header,
|
|
last_meta_entry_start_lsn))) {
|
|
PALF_LOG(ERROR, "LogMetaStorage load failed", K(ret), K(palf_id));
|
|
} else if (OB_FAIL(construct_log_meta_(last_meta_entry_start_lsn, expected_next_block_id))) {
|
|
PALF_LOG(ERROR, "construct_log_meta_ failed", K(ret));
|
|
} else if (FALSE_IT(guard.click("load log_meta_storage"))
|
|
|| (0 != log_storage_block_size
|
|
&& OB_FAIL(log_storage_.load(base_dir, "log",
|
|
log_meta_.get_log_snapshot_meta().base_lsn_, palf_id,
|
|
log_storage_block_size, LOG_DIO_ALIGN_SIZE,
|
|
LOG_DIO_ALIGNED_BUF_SIZE_REDO,
|
|
log_storage_update_manifest_cb, log_block_pool, plugins,
|
|
hot_cache, entry_header, last_group_entry_header_lsn)))) {
|
|
PALF_LOG(ERROR, "LogStorage load failed", K(ret), K(palf_id), K(base_dir));
|
|
} else if (FALSE_IT(guard.click("load log_storage"))
|
|
|| (0 != log_storage_block_size
|
|
&& OB_FAIL(try_clear_up_holes_and_check_storage_integrity_(
|
|
last_group_entry_header_lsn, expected_next_block_id, entry_header)))) {
|
|
PALF_LOG(ERROR, "the last block may be deleted by human, restart failed!!!", K(ret),
|
|
K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(integrity_verify_(last_meta_entry_start_lsn, last_group_entry_header_lsn, is_integrity))) {
|
|
PALF_LOG(ERROR, "integrity_verify_ failed, unexpected error", K(ret), KPC(this));
|
|
} else if (OB_FAIL(log_net_service_.init(palf_id, log_rpc))) {
|
|
PALF_LOG(ERROR, "LogNetService init failed", K(ret), K(palf_id));
|
|
} else {
|
|
palf_id_ = palf_id;
|
|
palf_epoch_ = palf_epoch;
|
|
alloc_mgr_ = alloc_mgr;
|
|
log_io_worker_ = log_io_worker;
|
|
base_lsn_for_block_gc_ = log_meta_.get_log_snapshot_meta().base_lsn_;
|
|
is_inited_ = true;
|
|
PALF_LOG(INFO,
|
|
"LogEngine load success",
|
|
K_(palf_id), K_(is_inited),
|
|
K(entry_header),
|
|
K(log_storage_),
|
|
K(log_meta_storage_),
|
|
K(guard),
|
|
K_(palf_epoch));
|
|
}
|
|
|
|
if (OB_FAIL(ret) && OB_INIT_TWICE != ret) {
|
|
destroy();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::integrity_verify_(const LSN &last_meta_entry_start_lsn,
|
|
const LSN &last_group_entry_header_lsn,
|
|
bool &is_integrity)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_integrity = true;
|
|
bool meta_is_valid = last_meta_entry_start_lsn.is_valid();
|
|
bool redo_is_valid = last_group_entry_header_lsn.is_valid();
|
|
// 1. meta is empty, but redo is not empty, unexpected error
|
|
// 2. meta and redo are both empty, move this directory to another place, and remove this from PalfEnvImpl
|
|
// 3. meta is not empty, but redo is empty, normal case
|
|
// 4. meta and redo are not empty, normal case
|
|
// In case2, we will load LogEngine success, and remove PalfHandleImpl in PalfEnvImpl.
|
|
if (false == meta_is_valid && true == redo_is_valid) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
PALF_LOG(ERROR, "meta dir is empty, but redo is not empty, unexpected error", K(ret), KPC(this));
|
|
} else if (false == meta_is_valid && false == redo_is_valid) {
|
|
is_integrity = false;
|
|
PALF_LOG(WARN, "log engine is not integrity", KPC(this));
|
|
} else {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flush_log_task(const FlushLogCbCtx &flush_log_cb_ctx,
|
|
const LogWriteBuf &write_buf)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogIOFlushLogTask *flush_log_task = NULL;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == flush_log_cb_ctx.is_valid() || false == write_buf.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flush_log_cb_ctx), K(write_buf));
|
|
} else if (OB_FAIL(generate_flush_log_task_(flush_log_cb_ctx, write_buf, flush_log_task))) {
|
|
PALF_LOG(ERROR, "generate_flush_log_task failed", K(ret), K(flush_log_cb_ctx));
|
|
} else if (OB_FAIL(log_io_worker_->submit_io_task(flush_log_task))) {
|
|
PALF_LOG(ERROR, "submit_io_task failed", K(ret));
|
|
} else {
|
|
PALF_LOG(TRACE, "submit_flush_log_task success", K(ret), K(flush_log_cb_ctx), K(write_buf));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flush_prepare_meta_task(const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogPrepareMeta &prepare_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == flush_meta_cb_ctx.is_valid() || false == prepare_meta.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flush_meta_cb_ctx), K(prepare_meta));
|
|
} else if (OB_FAIL(log_meta_.update_log_prepare_meta(prepare_meta))) {
|
|
PALF_LOG(ERROR, "LogMeta update_log_prepare_meta failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(submit_flush_meta_task_(flush_meta_cb_ctx, log_meta_))) {
|
|
PALF_LOG(ERROR, "submit_flush_meta_task_ failed", K(ret));
|
|
} else {
|
|
PALF_LOG(INFO, "submit_flush_prepare_meta_task success", K(ret), K(flush_meta_cb_ctx), K(prepare_meta));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flush_change_config_meta_task(const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogConfigMeta &config_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEnginenot inited!!!", K(ret));
|
|
} else if (false == flush_meta_cb_ctx.is_valid() || false == config_meta.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flush_meta_cb_ctx), K(config_meta));
|
|
} else if (OB_FAIL(log_meta_.update_log_config_meta(config_meta))) {
|
|
PALF_LOG(ERROR, "LogMeta update_log_config_meta failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(submit_flush_meta_task_(flush_meta_cb_ctx, log_meta_))) {
|
|
PALF_LOG(ERROR, "submit_flush_meta_task_ failed", K(ret));
|
|
} else {
|
|
PALF_LOG(INFO, "submit_flush_change_config_meta_task success", K(ret), K(flush_meta_cb_ctx), K(config_meta));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flush_mode_meta_task(const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogModeMeta &mode_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEnginenot inited!!!", K(ret));
|
|
} else if (false == flush_meta_cb_ctx.is_valid() || false == mode_meta.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flush_meta_cb_ctx), K(mode_meta));
|
|
} else if (OB_FAIL(log_meta_.update_log_mode_meta(mode_meta))) {
|
|
PALF_LOG(ERROR, "LogMeta update_log_mode_meta failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(submit_flush_meta_task_(flush_meta_cb_ctx, log_meta_))) {
|
|
PALF_LOG(ERROR, "submit_flush_meta_task_ failed", K(ret));
|
|
} else {
|
|
PALF_LOG(INFO, "submit_flush_mode_meta_task success", K(ret), K(flush_meta_cb_ctx), K(mode_meta));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flush_snapshot_meta_task(const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogSnapshotMeta &log_snapshot_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
const LSN &curr_base_lsn = log_meta_.get_log_snapshot_meta().base_lsn_;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == flush_meta_cb_ctx.is_valid() || false == log_snapshot_meta.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flush_meta_cb_ctx), K(log_snapshot_meta));
|
|
} else if (log_snapshot_meta.base_lsn_ != curr_base_lsn &&
|
|
OB_FAIL(log_meta_.update_log_snapshot_meta(log_snapshot_meta))) {
|
|
PALF_LOG(WARN, "update_log_snapshot_meta failed", K(log_snapshot_meta));
|
|
} else if (OB_FAIL(submit_flush_meta_task_(flush_meta_cb_ctx, log_meta_))) {
|
|
PALF_LOG(
|
|
WARN, "submit_flush_snapshot_meta_task_ failed", K(ret), K(flush_meta_cb_ctx), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
PALF_LOG(TRACE, "submit_flush_snapshot_meta_task success", K(ret), K(flush_meta_cb_ctx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flush_replica_property_meta_task(
|
|
const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogReplicaPropertyMeta &log_replica_property_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == flush_meta_cb_ctx.is_valid()
|
|
|| false == log_replica_property_meta.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flush_meta_cb_ctx),
|
|
K(log_replica_property_meta));
|
|
} else if (OB_FAIL(log_meta_.update_log_replica_property_meta(log_replica_property_meta))) {
|
|
PALF_LOG(WARN, "update_log_replica_property_meta failed", K(log_replica_property_meta));
|
|
} else if (OB_FAIL(submit_flush_meta_task_(flush_meta_cb_ctx, log_meta_))) {
|
|
PALF_LOG(WARN, "submit_flush_replica_property_meta_task_ failed", K(ret), K(flush_meta_cb_ctx), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
PALF_LOG(TRACE, "submit_flush_replica_property_meta_task_ success", K(ret), K(flush_meta_cb_ctx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_truncate_log_task(const TruncateLogCbCtx &truncate_log_cb_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogIOTruncateLogTask *truncate_log_task = NULL;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == truncate_log_cb_ctx.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(truncate_log_cb_ctx));
|
|
} else if (OB_FAIL(generate_truncate_log_task_(truncate_log_cb_ctx, truncate_log_task))) {
|
|
PALF_LOG(ERROR, "generate_truncate_log_task_ failed", K(ret), K(truncate_log_cb_ctx));
|
|
} else if (OB_FAIL(log_io_worker_->submit_io_task(truncate_log_task))) {
|
|
PALF_LOG(ERROR, "submit_io_task failed", K(ret));
|
|
} else {
|
|
PALF_LOG(INFO, "submit_truncate_log_task success", K(ret), K(truncate_log_cb_ctx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_truncate_prefix_blocks_task(
|
|
const TruncatePrefixBlocksCbCtx &truncate_prefix_blocks_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogIOTruncatePrefixBlocksTask *truncate_prefix_blocks_task = NULL;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == truncate_prefix_blocks_ctx.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(truncate_prefix_blocks_ctx));
|
|
} else if (OB_FAIL(generate_truncate_prefix_blocks_task_(truncate_prefix_blocks_ctx,
|
|
truncate_prefix_blocks_task))) {
|
|
PALF_LOG(ERROR, "generate_truncate_log_task_ failed", K(ret), K(truncate_prefix_blocks_ctx));
|
|
} else if (OB_FAIL(log_io_worker_->submit_io_task(truncate_prefix_blocks_task))) {
|
|
PALF_LOG(ERROR, "submit_io_task failed", K(ret));
|
|
} else {
|
|
PALF_LOG(
|
|
INFO, "submit_truncate_prefix_blocks_task success", K(ret), K(truncate_prefix_blocks_ctx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_flashback_task(const FlashbackCbCtx &flashback_cb_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogIOFlashbackTask *flashback_task = NULL;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (false == flashback_cb_ctx.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K(flashback_cb_ctx));
|
|
} else if (OB_FAIL(generate_flashback_task_(flashback_cb_ctx, flashback_task))) {
|
|
PALF_LOG(ERROR, "generate_flashback_task_ failed", K(ret), K(flashback_cb_ctx));
|
|
} else if (OB_FAIL(log_io_worker_->submit_io_task(flashback_task))) {
|
|
PALF_LOG(ERROR, "submit_io_task failed", K(ret));
|
|
} else {
|
|
PALF_LOG(INFO, "submit_flashback_task success", K(ret), K(flashback_cb_ctx));
|
|
}
|
|
return ret;
|
|
}
|
|
int LogEngine::submit_purge_throttling_task(const PurgeThrottlingType purge_type)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
PurgeThrottlingCbCtx purge_cb_ctx(purge_type);
|
|
LogIOPurgeThrottlingTask *purge_task = NULL;
|
|
const int64_t cur_ts = ObClockGenerator::getClock();
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret));
|
|
} else if (OB_UNLIKELY(!purge_cb_ctx.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(purge_cb_ctx));
|
|
} else if ((!need_force_purge(purge_type)) &&
|
|
(cur_ts - last_purge_throttling_ts_ <= PURGE_THROTTLING_INTERVAL)) {
|
|
PALF_LOG(INFO, "no need to purge throttling according to PURGE_THROTTLING_INTERVAL",
|
|
K(purge_cb_ctx), K(last_purge_throttling_ts_), K(cur_ts), K(PURGE_THROTTLING_INTERVAL));
|
|
} else if (OB_FAIL(generate_purge_throttling_task_(purge_cb_ctx, purge_task))) {
|
|
PALF_LOG(ERROR, "generate_purge_throttling_ failed", K(purge_cb_ctx));
|
|
} else if (OB_FAIL(log_io_worker_->submit_io_task(purge_task))) {
|
|
PALF_LOG(ERROR, "submit_io_task failed", K(purge_cb_ctx));
|
|
} else {
|
|
last_purge_throttling_ts_ = cur_ts;
|
|
PALF_LOG(INFO, "submit_purge_throttling success", K(last_purge_throttling_ts_), "purge_type",
|
|
get_purge_throttling_type_str(purge_type));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// ====================== LogStorage start =====================
|
|
int LogEngine::append_log(const LSN &lsn, const LogWriteBuf &write_buf, const SCN &scn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (false == lsn.is_valid() || false == write_buf.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(lsn), K(write_buf));
|
|
} else if (OB_FAIL(log_storage_.writev(lsn, write_buf, scn))) {
|
|
PALF_LOG(ERROR, "LogStorage append_log failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
PALF_LOG(
|
|
TRACE, "LogEngine append_log success", K(ret), K_(palf_id), K_(is_inited), K(lsn), K(write_buf), K(scn));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::append_log(const LSNArray &lsn_array, const LogWriteBufArray &write_buf_array,
|
|
const SCNArray &scn_array)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(log_storage_.writev(lsn_array, write_buf_array, scn_array))) {
|
|
PALF_LOG(ERROR, "LogStorage writev failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::read_log(const LSN &lsn,
|
|
const int64_t in_read_size,
|
|
ReadBuf &read_buf,
|
|
int64_t &out_read_size)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (false == lsn.is_valid() || 0 >= in_read_size || false == read_buf.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(lsn), K(in_read_size), K(read_buf));
|
|
} else if (OB_FAIL(log_storage_.pread(lsn, in_read_size, read_buf, out_read_size))) {
|
|
PALF_LOG(ERROR, "LogEngine read_log failed", K(ret), K(lsn), K(in_read_size), K(read_buf));
|
|
} else {
|
|
PALF_LOG(TRACE, "LogEngine read_log success", K(ret), K(lsn), K(read_buf), K(out_read_size));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::read_group_entry_header(const LSN &lsn, LogGroupEntryHeader &log_group_entry_header)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// 4K is enough to read log_group_entry_header;
|
|
const int64_t in_read_size = MAX_LOG_HEADER_SIZE;
|
|
ReadBufGuard read_buf_guard("LogEngine", in_read_size);
|
|
ReadBuf &read_buf = read_buf_guard.read_buf_;
|
|
int64_t out_read_size = 0;
|
|
int64_t pos = 0;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else if (false == lsn.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else if (!read_buf.is_valid()) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(WARN, "allocate memory failed", KPC(this), K(lsn));
|
|
} else if (OB_FAIL(log_storage_.pread_without_block_header(lsn, in_read_size, read_buf, out_read_size))) {
|
|
PALF_LOG(WARN, "LogStorage pread failed", K(ret));
|
|
} else if (OB_FAIL(log_group_entry_header.deserialize(read_buf.buf_, in_read_size, pos))) {
|
|
PALF_LOG(WARN,
|
|
"deserialize log_group_entry_header failed",
|
|
K(ret),
|
|
K(read_buf),
|
|
K(in_read_size),
|
|
K(pos),
|
|
K(out_read_size));
|
|
} else if (false == log_group_entry_header.check_header_integrity()) {
|
|
ret = OB_INVALID_DATA;
|
|
PALF_LOG(ERROR, "the data has been corrupted!!!", K(ret), K(lsn), K(log_group_entry_header));
|
|
} else {
|
|
PALF_LOG(TRACE, "read_group_entry_header success", K(ret), K(lsn), K(log_group_entry_header));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::truncate(const LSN &lsn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogGroupEntryHeader log_group_entry_header;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (false == lsn.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(lsn));
|
|
} else if (OB_FAIL(read_group_entry_header(lsn, log_group_entry_header))
|
|
&& OB_ERR_OUT_OF_UPPER_BOUND != ret) {
|
|
PALF_LOG(ERROR, "read_group_entry_header failed, unexpected error, lsn must be the start position"
|
|
"of one LogGroupEntry", K(ret), K(lsn), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(log_storage_.truncate(lsn))) {
|
|
PALF_LOG(ERROR, "LogStorage truncate failed", K(ret), K(lsn));
|
|
} else {
|
|
PALF_LOG(INFO, "truncate success", K(lsn));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::truncate_prefix_blocks(const LSN &lsn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (false == lsn.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(lsn));
|
|
} else if (OB_FAIL(log_storage_.truncate_prefix_blocks(lsn))) {
|
|
PALF_LOG(WARN, "truncate_prefix_blocks failed", K(ret), K_(palf_id), K_(is_inited), K(lsn));
|
|
} else {
|
|
PALF_LOG(INFO, "truncate_prefix_blocks success", K(ret), K_(palf_id), K_(is_inited), K(lsn)); }
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::begin_flashback(const LSN &start_lsn_of_block)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(log_storage_.begin_flashback(start_lsn_of_block))) {
|
|
PALF_LOG(ERROR, "LogStorage begin_flashback failed", K(ret), KPC(this), K(start_lsn_of_block));
|
|
} else {
|
|
PALF_LOG(INFO, "LogEngine begin_flashback success", KPC(this), K(start_lsn_of_block));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::end_flashback(const LSN &start_lsn_of_block)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(log_storage_.end_flashback(start_lsn_of_block))) {
|
|
PALF_LOG(ERROR, "LogStorege end_flashback failed", K(ret), KPC(this), K(start_lsn_of_block));
|
|
} else {
|
|
PALF_LOG(INFO, "LogEngine end_flashback success", KPC(this), K(start_lsn_of_block));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// NB: delete_block only called by GC
|
|
//
|
|
// Nowdays, may be concurrently executed with 'truncate_prefix_blocks', need handle follow cases:
|
|
// 1. delete block may be failed;
|
|
// 2. get_block_min_scn may be failed, and then, we need reset 'min_block_scn' which used by GC.
|
|
int LogEngine::delete_block(const block_id_t &block_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
block_id_t next_block_id = block_id + 1;
|
|
SCN next_block_max_scn;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (false == is_valid_block_id(block_id)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(block_id));
|
|
} else if (OB_FAIL(log_storage_.delete_block(block_id)) && OB_NO_SUCH_FILE_OR_DIRECTORY != ret) {
|
|
PALF_LOG(ERROR, "LogStorage delete block failed, unexpected error", K(ret), K(block_id));
|
|
} else if (OB_NO_SUCH_FILE_OR_DIRECTORY == ret) {
|
|
PALF_LOG(INFO, "file not exist, may be concurrently delete by others module", K(ret), K(block_id));
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
PALF_LOG(INFO, "delete success", K(block_id), K_(palf_id), K_(is_inited));
|
|
}
|
|
|
|
int tmp_ret = OB_SUCCESS;
|
|
if (OB_SUCC(ret) && OB_SUCCESS != (tmp_ret = get_block_min_scn(next_block_id + 1, next_block_max_scn))) {
|
|
PALF_LOG(WARN, "get the max ts of next block failed", K(tmp_ret), K(next_block_id));
|
|
}
|
|
// If 'delete_block' or 'get_block_min_scn' failed, need reset 'min_block_scn_' to be invalid.
|
|
reset_min_block_info_guarded_by_lock_(next_block_id, next_block_max_scn);
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::get_block_min_scn(const block_id_t &block_id, SCN &min_scn) const
|
|
{
|
|
return log_storage_.get_block_min_scn(block_id, min_scn);
|
|
}
|
|
|
|
const LSN LogEngine::get_begin_lsn() const { return log_storage_.get_begin_lsn(); }
|
|
|
|
int LogEngine::get_block_id_range(block_id_t &min_block_id, block_id_t &max_block_id) const
|
|
{
|
|
return log_storage_.get_block_id_range(min_block_id, max_block_id);
|
|
}
|
|
|
|
int LogEngine::get_min_block_info_for_gc(block_id_t &block_id, SCN &max_scn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
block_id_t max_block_id = LOG_INVALID_BLOCK_ID;
|
|
block_id_t min_block_id = LOG_INVALID_BLOCK_ID;
|
|
SCN min_block_max_scn;
|
|
|
|
do {
|
|
ObSpinLockGuard guard(block_gc_lock_);
|
|
min_block_id = min_block_id_;
|
|
min_block_max_scn = min_block_max_scn_;
|
|
} while (0);
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(WARN, "LogEngine is not inited", K(ret), KPC(this));
|
|
} else if (min_block_max_scn.is_valid()) {
|
|
block_id = min_block_id;
|
|
max_scn = min_block_max_scn;
|
|
} else if (OB_FAIL(get_block_id_range(min_block_id, max_block_id))) {
|
|
PALF_LOG(WARN, "get_block_id_range failed", K(ret));
|
|
// NB: used next block min_block_ts as the max_scn of current block
|
|
} else if (OB_FAIL(get_block_min_scn(min_block_id+1, min_block_max_scn))) {
|
|
PALF_LOG(TRACE, "get_block_min_scn failed", K(ret));
|
|
} else {
|
|
reset_min_block_info_guarded_by_lock_(min_block_id, min_block_max_scn);
|
|
block_id = min_block_id;
|
|
max_scn = min_block_max_scn;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::get_min_block_info(block_id_t &min_block_id, SCN &min_block_scn) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
block_id_t max_block_id;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(WARN, "LogEngine is not inited", K(ret), KPC(this));
|
|
} else if (OB_FAIL(get_block_id_range(min_block_id, max_block_id))) {
|
|
PALF_LOG(WARN, "get_block_id_range failed", K(ret), KPC(this));
|
|
} else if (OB_FAIL(get_block_min_scn(min_block_id, min_block_scn))) {
|
|
PALF_LOG(WARN, "get_block_min_scn failed", K(ret), KPC(this));
|
|
} else {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::get_total_used_disk_space(int64_t &total_used_size_byte,
|
|
int64_t &unrecyclable_disk_space) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
block_id_t min_block_id = LOG_INVALID_BLOCK_ID;
|
|
block_id_t max_block_id = LOG_INVALID_BLOCK_ID;
|
|
int64_t log_storage_used = 0;
|
|
int64_t meta_storage_used = 0;
|
|
int64_t log_storage_logical_block_size = 0;
|
|
int64_t meta_storage_logical_block_size = 0;
|
|
// calc log storage used
|
|
if (OB_FAIL(get_block_id_range(min_block_id, max_block_id))
|
|
&& OB_ENTRY_NOT_EXIST != ret) {
|
|
PALF_LOG(WARN, "get_block_id_range failed", K(ret), KPC(this));
|
|
} else if (OB_ENTRY_NOT_EXIST == ret) {
|
|
log_storage_used = 0;
|
|
ret = OB_SUCCESS;
|
|
} else if (OB_FAIL(log_storage_.get_logical_block_size(log_storage_logical_block_size))) {
|
|
PALF_LOG(WARN, "LogStorage get_logical_block_size failed", KPC(this));
|
|
} else if (OB_FAIL(log_meta_storage_.get_logical_block_size(meta_storage_logical_block_size))) {
|
|
PALF_LOG(WARN, "MetaStorage get_logical_block_size failed", KPC(this));
|
|
} else {
|
|
//usage calculation should be precise to avoid stopping writing when actually no need
|
|
log_storage_used = (max_block_id - min_block_id) * (log_storage_logical_block_size + MAX_INFO_BLOCK_SIZE)
|
|
+ lsn_2_offset(log_storage_.get_end_lsn(), log_storage_logical_block_size) + MAX_INFO_BLOCK_SIZE;
|
|
PALF_LOG(TRACE, "log_storage_used size", K(min_block_id), K(max_block_id), K(log_storage_used));
|
|
}
|
|
// calc meta storage used
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(log_meta_storage_.get_block_id_range(min_block_id, max_block_id))) {
|
|
PALF_LOG(WARN, "get_block_id_range failed", K(ret), KPC(this));
|
|
} else {
|
|
meta_storage_used = meta_storage_logical_block_size + MAX_INFO_BLOCK_SIZE;
|
|
total_used_size_byte = log_storage_used + meta_storage_used;
|
|
|
|
const int64_t unrecyclable_meta_size = meta_storage_used;
|
|
unrecyclable_disk_space = log_storage_.get_end_lsn() - get_base_lsn_used_for_block_gc() + unrecyclable_meta_size;
|
|
PALF_LOG(TRACE, "get_total_used_disk_space", K(meta_storage_used), K(log_storage_used), K(total_used_size_byte));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// ====================== LogStorage end =======================
|
|
|
|
// ===================== MetaStorage start =====================
|
|
// NB: need update snapshot_meta inc.
|
|
int LogEngine::update_base_lsn_used_for_gc(const LSN &lsn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
if (true == base_lsn_for_block_gc_.is_valid() && lsn < base_lsn_for_block_gc_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
PALF_LOG(WARN,
|
|
"lsn is smaller than base_lsn_for_block_gc_",
|
|
K(ret),
|
|
K(lsn),
|
|
K(base_lsn_for_block_gc_));
|
|
} else {
|
|
base_lsn_for_block_gc_ = lsn;
|
|
PALF_LOG(INFO, "update_base_lsn_used_for_gc success", K(ret), K(lsn), K_(palf_id), K_(is_inited));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::update_manifest(const block_id_t block_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_valid_block_id(block_id)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "invalid argument!!!", KPC(this), K(block_id));
|
|
} else if (OB_FAIL(log_meta_storage_.update_manifest_used_for_meta_storage(block_id))) {
|
|
PALF_LOG(WARN, "update_manifest_used_for_meta_storage failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
PALF_LOG(INFO,
|
|
"update_max_block_id_for_switch_block_cb success",
|
|
K(ret),
|
|
K_(palf_id), K_(is_inited),
|
|
K(block_id));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::append_meta(const char *buf, const int64_t buf_len)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_UNLIKELY(NULL == buf || 0 >= buf_len)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
PALF_LOG(ERROR, "Invalid argumnt!!!", K(ret), K_(palf_id), K_(is_inited), K(buf), K(buf_len));
|
|
} else if (OB_FAIL(log_meta_storage_.append_meta(buf, buf_len))) {
|
|
PALF_LOG(ERROR, "LogMetaStorage pwrite failed", K(ret), K(buf), K(buf_len));
|
|
} else {
|
|
PALF_LOG(TRACE, "LogEngine append_meta success", K(ret), K(buf), K(buf_len));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::update_log_snapshot_meta_for_flashback(const LogInfo &log_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogSnapshotMeta snapshot_meta = log_meta_.get_log_snapshot_meta();
|
|
snapshot_meta.prev_log_info_ = log_info;
|
|
if (OB_FAIL(log_meta_.update_log_snapshot_meta(snapshot_meta))) {
|
|
PALF_LOG(WARN, "update_log_snapshot_meta failed", K(ret), KPC(this), K(log_info), K(snapshot_meta));
|
|
} else if (OB_FAIL(append_log_meta_(log_meta_))) {
|
|
PALF_LOG(WARN, "append_log_meta failed", K(ret), KPC(this), K(log_info), K(snapshot_meta));
|
|
} else {
|
|
PALF_LOG(INFO, "update_log_snapshot_meta_for_flashback success", K(ret), KPC(this), K(log_info),
|
|
K(snapshot_meta));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// ===================== MetaStorage end =======================
|
|
|
|
// ===================== NetService start ======================
|
|
int LogEngine::submit_push_log_req(const common::ObAddr &server,
|
|
const PushLogType &push_log_type,
|
|
const int64_t &msg_proposal_id,
|
|
const int64_t &prev_log_proposal_id,
|
|
const LSN &prev_lsn,
|
|
const LSN &curr_lsn,
|
|
const LogWriteBuf &write_buf)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not init", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(log_net_service_.submit_push_log_req(server,
|
|
push_log_type,
|
|
msg_proposal_id,
|
|
prev_log_proposal_id,
|
|
prev_lsn,
|
|
curr_lsn,
|
|
write_buf))) {
|
|
PALF_LOG(ERROR,
|
|
"LogNetService submit_group_entry_to_server failed",
|
|
K(ret),
|
|
K_(palf_id), K_(is_inited),
|
|
K(server),
|
|
K(prev_log_proposal_id),
|
|
K(prev_lsn),
|
|
K(curr_lsn),
|
|
K(write_buf));
|
|
} else {
|
|
PALF_LOG(TRACE,
|
|
"submit_group_entry_to_server success",
|
|
K(ret),
|
|
K_(palf_id), K_(is_inited),
|
|
K(server),
|
|
K(prev_log_proposal_id),
|
|
K(prev_lsn),
|
|
K(curr_lsn));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_push_log_resp(const ObAddr &server,
|
|
const int64_t &msg_proposal_id,
|
|
const LSN &lsn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_push_log_resp(server, msg_proposal_id, lsn);
|
|
PALF_LOG(TRACE, "submit_push_log_resp success", K(ret), K(server));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_prepare_meta_resp(const common::ObAddr &server,
|
|
const int64_t &msg_proposal_id,
|
|
const bool vote_granted,
|
|
const int64_t &log_proposal_id,
|
|
const LSN &max_flushed_lsn,
|
|
const LSN &committed_end_lsn,
|
|
const LogModeMeta &mode_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_prepare_meta_resp(
|
|
server, msg_proposal_id, vote_granted, log_proposal_id, max_flushed_lsn, committed_end_lsn, mode_meta);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_change_config_meta_resp(const common::ObAddr &server,
|
|
const int64_t msg_proposal_id,
|
|
const LogConfigVersion &config_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_change_config_meta_resp(server, msg_proposal_id, config_version);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_change_mode_meta_resp(const common::ObAddr &server,
|
|
const int64_t &msg_proposal_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_change_mode_meta_resp(server, msg_proposal_id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_config_change_pre_check_req(const common::ObAddr &server,
|
|
const LogConfigVersion &config_version,
|
|
const bool need_purge_throttling,
|
|
const int64_t timeout_us,
|
|
LogGetMCStResp &resp)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_config_change_pre_check_req(
|
|
server, config_version, need_purge_throttling, timeout_us, resp);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int LogEngine::submit_fetch_log_req(const ObAddr &server,
|
|
const FetchLogType fetch_type,
|
|
const int64_t msg_proposal_id,
|
|
const LSN &prev_lsn,
|
|
const LSN &lsn,
|
|
const int64_t fetch_log_size,
|
|
const int64_t fetch_log_count,
|
|
const int64_t accepted_mode_pid)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_fetch_log_req(
|
|
server, fetch_type, msg_proposal_id, prev_lsn, lsn,
|
|
fetch_log_size, fetch_log_count, accepted_mode_pid);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_batch_fetch_log_resp(const common::ObAddr &server,
|
|
const int64_t msg_proposal_id,
|
|
const int64_t prev_log_proposal_id,
|
|
const LSN &prev_lsn,
|
|
const LSN &curr_lsn,
|
|
const LogWriteBuf &write_buf)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_batch_fetch_log_resp(
|
|
server, msg_proposal_id, prev_log_proposal_id,
|
|
prev_lsn, curr_lsn, write_buf);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_notify_rebuild_req(const ObAddr &server,
|
|
const LSN &base_lsn,
|
|
const LogInfo &base_prev_log_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_notify_rebuild_req(server, base_lsn, base_prev_log_info);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_notify_fetch_log_req(const ObMemberList &dst_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_notify_fetch_log_req(dst_list);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_register_parent_req(const common::ObAddr &server,
|
|
const LogLearner &child_itself,
|
|
const bool is_to_leader)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_register_parent_req(server, child_itself, is_to_leader);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_register_parent_resp(const common::ObAddr &server,
|
|
const LogLearner &parent_itself,
|
|
const LogCandidateList &candidate_list,
|
|
const RegisterReturn reg_ret)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_register_parent_resp(
|
|
server, parent_itself, candidate_list, reg_ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_retire_parent_req(const common::ObAddr &server,
|
|
const LogLearner &child_itself)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_retire_parent_req(server, child_itself);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_retire_child_req(const common::ObAddr &server,
|
|
const LogLearner &parent_itself)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_retire_child_req(server, parent_itself);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_learner_keepalive_req(const common::ObAddr &server,
|
|
const LogLearner &sender_itself)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_learner_keepalive_req(server, sender_itself);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_learner_keepalive_resp(const common::ObAddr &server,
|
|
const LogLearner &sender_itself)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_learner_keepalive_resp(server, sender_itself);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_committed_info_req(
|
|
const common::ObAddr &server,
|
|
const int64_t &msg_proposal_id,
|
|
const int64_t prev_log_id,
|
|
const int64_t &prev_log_proposal_id,
|
|
const LSN &committed_end_lsn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
PALF_LOG(ERROR, "LogEngine not init", K(ret), KPC(this));
|
|
} else if (OB_FAIL(log_net_service_.submit_committed_info_req(
|
|
server, msg_proposal_id,
|
|
prev_log_id, prev_log_proposal_id, committed_end_lsn))) {
|
|
PALF_LOG(ERROR, "LogNetService submit_committed_info_req failed", K(ret),
|
|
KPC(this), K(server),
|
|
K(prev_log_id), K(prev_log_proposal_id), K(committed_end_lsn));
|
|
} else {
|
|
PALF_LOG(TRACE, "submit_committed_info_req success", K(ret), KPC(this),
|
|
K(server), K(msg_proposal_id), K(prev_log_id),
|
|
K(prev_log_proposal_id), K(committed_end_lsn));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::submit_get_stat_req(const common::ObAddr &server,
|
|
const int64_t timeout_us,
|
|
const LogGetStatReq &req,
|
|
LogGetStatResp &resp)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ret = log_net_service_.submit_get_stat_req(server, timeout_us, req, resp);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
LogMeta LogEngine::get_log_meta() const
|
|
{
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
return log_meta_;
|
|
}
|
|
|
|
const LSN &LogEngine::get_base_lsn_used_for_block_gc() const
|
|
{
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
return base_lsn_for_block_gc_;
|
|
}
|
|
|
|
int LogEngine::submit_flush_meta_task_(const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogMeta &log_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogIOFlushMetaTask *flush_meta_task = NULL;
|
|
if (OB_FAIL(generate_flush_meta_task_(flush_meta_cb_ctx, log_meta, flush_meta_task))) {
|
|
PALF_LOG(ERROR, "generate_flush_meta_task_ failed", K(ret), K(flush_meta_cb_ctx), K(log_meta_));
|
|
} else if (OB_FAIL(log_io_worker_->submit_io_task(flush_meta_task))) {
|
|
PALF_LOG(ERROR, "submit_io_task failed", K(ret));
|
|
} else {
|
|
PALF_LOG(INFO, "submit_flush_meta_task_ success", K(flush_meta_cb_ctx), K(log_meta));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::construct_log_meta_(const LSN &lsn, block_id_t &expected_next_block_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t out_read_size = 0;
|
|
int64_t pos = 0;
|
|
const int64_t buf_len = MAX_META_ENTRY_SIZE;
|
|
ReadBufGuard guard("LogEngine", buf_len);
|
|
ReadBuf &read_buf = guard.read_buf_;
|
|
LogMetaEntry meta_entry;
|
|
if (false == lsn.is_valid()) {
|
|
PALF_LOG(INFO, "there is no meta entry, maybe create palf failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (!read_buf.is_valid()) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(WARN, "allocate memory failed", KPC(this), K(lsn));
|
|
} else if (OB_FAIL(log_meta_storage_.pread(lsn, buf_len, read_buf, out_read_size))) {
|
|
PALF_LOG(WARN, "ObLogMetaStorage pread failed", K(ret), K_(palf_id), K_(is_inited));
|
|
// NB: when lsn is invalid, means there is no data on disk.
|
|
} else if (OB_FAIL(meta_entry.deserialize(read_buf.buf_, buf_len, pos))) {
|
|
PALF_LOG(WARN, "LogMetaEntry deserialize failed", K(ret), K(pos));
|
|
} else if (false == meta_entry.check_integrity()) {
|
|
ret = OB_INVALID_DATA;
|
|
PALF_LOG(ERROR,
|
|
"the data of LogMeta has been corrupted, unexpected error!!!",
|
|
K(ret),
|
|
K(meta_entry),
|
|
K_(palf_id), K_(is_inited));
|
|
} else if (FALSE_IT(pos = 0)) {
|
|
} else if (OB_FAIL(log_meta_.deserialize(meta_entry.get_buf(), meta_entry.get_data_len(), pos))) {
|
|
PALF_LOG(WARN, "LogMeta deserialize failed");
|
|
} else if (OB_FAIL(log_meta_storage_.load_manifest_for_meta_storage(expected_next_block_id))) {
|
|
PALF_LOG(ERROR, "load_manifest_for_meta_storage failed", K(ret), KPC(this));
|
|
} else {
|
|
PALF_LOG(INFO, "construct_log_meta_ success", K(ret), K(log_meta_), K(meta_entry));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::generate_flush_log_task_(const FlushLogCbCtx &flush_log_cb_ctx,
|
|
const LogWriteBuf &write_buf,
|
|
LogIOFlushLogTask *&flush_log_task)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// Be careful to handle the duration of this pointer
|
|
flush_log_task = NULL;
|
|
if (false == flush_log_cb_ctx.is_valid() || false == write_buf.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else if (NULL == (flush_log_task = alloc_mgr_->alloc_log_io_flush_log_task(palf_id_, palf_epoch_))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "alloc_log_io_flush_log_task failed", K(ret));
|
|
} else if (OB_FAIL(flush_log_task->init(flush_log_cb_ctx, write_buf))) {
|
|
PALF_LOG(ERROR, "init LogIOFlushLogTask failed", K(ret));
|
|
} else {/*do nothing*/}
|
|
if (OB_FAIL(ret) && NULL != flush_log_task) {
|
|
alloc_mgr_->free_log_io_flush_log_task(flush_log_task);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::generate_truncate_log_task_(const TruncateLogCbCtx &truncate_log_cb_ctx,
|
|
LogIOTruncateLogTask *&truncate_log_task)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
truncate_log_task = NULL;
|
|
if (NULL == (truncate_log_task = alloc_mgr_->alloc_log_io_truncate_log_task(palf_id_, palf_epoch_))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "alloc_log_io_truncate_log_task failed", K(ret));
|
|
} else if (OB_FAIL(truncate_log_task->init(truncate_log_cb_ctx))) {
|
|
PALF_LOG(ERROR, "init LogIOTruncateLogTask failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
PALF_LOG(TRACE, "generate_truncate_log_task_ success", K(ret), K_(palf_id), K_(is_inited));
|
|
}
|
|
if (OB_FAIL(ret) && NULL != truncate_log_task) {
|
|
alloc_mgr_->free_log_io_truncate_log_task(truncate_log_task);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::generate_truncate_prefix_blocks_task_(
|
|
const TruncatePrefixBlocksCbCtx &truncate_prefix_blocks_ctx,
|
|
LogIOTruncatePrefixBlocksTask *&truncate_prefix_blocks_task)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL
|
|
== (truncate_prefix_blocks_task = alloc_mgr_->alloc_log_io_truncate_prefix_blocks_task(palf_id_, palf_epoch_))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "alloc_log_io_truncate_prefix_blocks_task failed", K(ret));
|
|
} else if (OB_FAIL(truncate_prefix_blocks_task->init(truncate_prefix_blocks_ctx))) {
|
|
PALF_LOG(ERROR, "init LogIOTruncatePrefixBlocksTask failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else {/*do nothing*/}
|
|
if (OB_FAIL(ret) && NULL != truncate_prefix_blocks_task) {
|
|
alloc_mgr_->free_log_io_truncate_prefix_blocks_task(truncate_prefix_blocks_task);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::generate_flush_meta_task_(const FlushMetaCbCtx &flush_meta_cb_ctx,
|
|
const LogMeta &log_meta,
|
|
LogIOFlushMetaTask *&flush_meta_task)
|
|
{
|
|
|
|
int ret = OB_SUCCESS;
|
|
char *buf = NULL;
|
|
const int64_t buf_len = MAX_META_ENTRY_SIZE;
|
|
flush_meta_task = NULL;
|
|
if (false == flush_meta_cb_ctx.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else if (NULL == (flush_meta_task = alloc_mgr_->alloc_log_io_flush_meta_task(palf_id_, palf_epoch_))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "alloc_log_io_flush_meta_task failed", K(ret));
|
|
} else if (NULL == (buf = reinterpret_cast<char *>(mtl_malloc(buf_len,
|
|
"LogEngine")))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "allocate memory failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(serialize_log_meta_(log_meta, buf, buf_len))) {
|
|
PALF_LOG(ERROR, "serialize_log_meta_ failed", K(ret), K_(palf_id), K_(is_inited), K(log_meta));
|
|
} else if (OB_FAIL(flush_meta_task->init(flush_meta_cb_ctx, buf, buf_len))) {
|
|
PALF_LOG(ERROR, "init LogIOFlushMetaTask failed", K(ret));
|
|
} else {
|
|
PALF_LOG(TRACE, "generate_flush_meta_task_ success", K(ret), K_(palf_id), K_(is_inited));
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
//free memory
|
|
if (NULL != buf) {
|
|
mtl_free(buf);
|
|
}
|
|
if (NULL != flush_meta_task) {
|
|
alloc_mgr_->free_log_io_flush_meta_task(flush_meta_task);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::generate_flashback_task_(const FlashbackCbCtx &flashback_cb_ctx,
|
|
LogIOFlashbackTask *&flashback_task)
|
|
{
|
|
|
|
int ret = OB_SUCCESS;
|
|
flashback_task = NULL;
|
|
if (false == flashback_cb_ctx.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else if (NULL == (flashback_task = alloc_mgr_->alloc_log_io_flashback_task(palf_id_, palf_epoch_))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "alloc_log_io_flush_log_task failed", K(ret));
|
|
} else if (OB_FAIL(flashback_task->init(flashback_cb_ctx,
|
|
palf_id_))) {
|
|
PALF_LOG(ERROR, "init LogIOFlashbackTask failed", K(ret));
|
|
} else {
|
|
PALF_LOG(TRACE, "generate_flashback_task_ hsuccess", K(ret), KPC(this));
|
|
}
|
|
if (OB_FAIL(ret) && NULL != flashback_task) {
|
|
alloc_mgr_->free_log_io_flashback_task(flashback_task);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::generate_purge_throttling_task_(const PurgeThrottlingCbCtx &purge_cb_ctx,
|
|
LogIOPurgeThrottlingTask *&purge_task) {
|
|
|
|
int ret = OB_SUCCESS;
|
|
purge_task = NULL;
|
|
if (!purge_cb_ctx.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else if (NULL == (purge_task = alloc_mgr_->alloc_log_io_purge_throttling_task(palf_id_, palf_epoch_))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
PALF_LOG(ERROR, "alloc_log_io_purge_throttling_task failed", KPC(this));
|
|
} else if (OB_FAIL(purge_task->init(purge_cb_ctx))) {
|
|
PALF_LOG(ERROR, "init LogIOPurgeThrottlingTask failed", KPC(this));
|
|
} else {
|
|
PALF_LOG(TRACE, "generate_purge_throttling_task_ hsuccess", KPC(this));
|
|
}
|
|
if (OB_FAIL(ret) && NULL != purge_task) {
|
|
alloc_mgr_->free_log_io_purge_throttling_task(purge_task);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::serialize_log_meta_(const LogMeta& log_meta, char *buf, int64_t buf_len)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LogMetaEntry log_meta_entry;
|
|
LogMetaEntryHeader log_meta_entry_header;
|
|
const int64_t log_meta_entry_header_len = log_meta_entry_header.get_serialize_size();
|
|
// ASSUME the real length of meta is smaller than 4K
|
|
const int64_t log_meta_entry_body_len = buf_len - log_meta_entry_header_len;
|
|
const int64_t log_meta_entry_len = log_meta_entry_header_len + log_meta_entry_body_len;
|
|
constexpr int64_t log_meta_body_serialize_buf_len = MAX_META_ENTRY_SIZE;
|
|
int64_t pos = 0;
|
|
char log_meta_body_serialize_buf[log_meta_body_serialize_buf_len] = {'\0'};
|
|
if (MAX_META_ENTRY_SIZE != buf_len) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
PALF_LOG(ERROR, "log_meta_entry_len must be smaller than or equal to LOG_DIO_ALIGN_SIZE",
|
|
K(ret), K_(palf_id), K_(is_inited), K(log_meta_entry_header_len), K(log_meta_entry_body_len), K(log_meta_entry_len),
|
|
K(buf_len));
|
|
} else if (FALSE_IT(memset(buf, '\0', buf_len))) {
|
|
// serialize log_meta_entry_body
|
|
} else if (OB_FAIL(log_meta.serialize(log_meta_body_serialize_buf, log_meta_body_serialize_buf_len, pos))) {
|
|
PALF_LOG(ERROR, "log_meta serialize failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_FAIL(log_meta_entry_header.generate(log_meta_body_serialize_buf, log_meta_entry_body_len))) {
|
|
PALF_LOG(ERROR, "generate LogMetaEntryHeader failed", K(ret), K(buf), K(log_meta_entry_body_len));
|
|
} else if (OB_FAIL(log_meta_entry.generate(log_meta_entry_header, log_meta_body_serialize_buf))) {
|
|
PALF_LOG(ERROR, "generate LogMetaEntry failed", K(ret), K(log_meta_entry_header));
|
|
} else if (FALSE_IT(pos = 0)) {
|
|
} else if (OB_FAIL(log_meta_entry.serialize(buf, buf_len, pos))) {
|
|
PALF_LOG(ERROR, "LogMetaEntry serialize failed", K(ret), K(buf), K(pos),
|
|
K(log_meta_entry_body_len), K(log_meta_entry_header_len), K(log_meta_entry_len));
|
|
} else {
|
|
PALF_LOG(INFO, "serialize_log_meta_ success", K(ret), K(log_meta),
|
|
K(log_meta_entry), K(log_meta_entry_header_len));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int LogEngine::update_config_meta_guarded_by_lock_(const LogConfigMeta &config_meta,
|
|
LogMeta &log_meta)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(log_meta_lock_);
|
|
if (OB_FAIL(log_meta_.update_log_config_meta(config_meta))) {
|
|
PALF_LOG(WARN, "update_log_config_meta failed", K(ret), K_(palf_id), K_(is_inited), K(config_meta));
|
|
} else {
|
|
log_meta = log_meta_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Background:
|
|
int LogEngine::try_clear_up_holes_and_check_storage_integrity_(
|
|
const LSN &last_entry_begin_lsn,
|
|
const block_id_t &expected_next_block_id,
|
|
LogGroupEntryHeader &last_group_entry_header)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const LSN base_lsn = log_meta_.get_log_snapshot_meta().base_lsn_;
|
|
const LogInfo prev_log_info = log_meta_.get_log_snapshot_meta().prev_log_info_;
|
|
const bool prev_log_info_is_valid = prev_log_info.is_valid();
|
|
// 'expected_next_block_id': ethier it's the empty block or not exist.
|
|
block_id_t base_block_id = LOG_INVALID_BLOCK_ID;
|
|
block_id_t min_block_id = LOG_INVALID_BLOCK_ID;
|
|
block_id_t max_block_id = LOG_INVALID_BLOCK_ID;
|
|
int64_t logical_block_size = 0;
|
|
const LSN log_storage_tail = log_storage_.get_end_lsn();
|
|
if (OB_FAIL(log_storage_.get_logical_block_size(logical_block_size))) {
|
|
PALF_LOG(WARN, "get_logical_block_size failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (FALSE_IT(base_block_id = lsn_2_block(base_lsn, logical_block_size))) {
|
|
} else if (OB_FAIL(log_storage_.get_block_id_range(min_block_id, max_block_id))
|
|
&& OB_ENTRY_NOT_EXIST != ret) {
|
|
PALF_LOG(ERROR, "get_block_id_range failed", K(ret), K_(palf_id), K_(is_inited));
|
|
} else if (OB_ENTRY_NOT_EXIST == ret) {
|
|
// For empty directory, ethier 'base_lsn' is initial lsn or 'prev_log_info(rebuild)' is valid,
|
|
// meanwhile, 'expected_next_block_id' must be smaller than or eaul to 'base_block_id'.
|
|
if (true == is_valid_block_id(expected_next_block_id)
|
|
&& expected_next_block_id > base_block_id) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
PALF_LOG(ERROR,
|
|
"the directory of log is empty, but expected_next_block_id is greater than "
|
|
"base_block_id, unexpected error!!!",
|
|
K(ret), K_(palf_id), K_(is_inited));
|
|
} else {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
// If log_storage_ is not empty but last_group_entry_header is invalid, unexpected error.
|
|
// For rebuild, the base_lsn may be greater than the log_tail of LogStorage because we
|
|
// update LogSnapshotMeta firstly.
|
|
} else if (log_storage_.get_end_lsn() != base_lsn && !last_group_entry_header.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
PALF_LOG(ERROR, "unexpected error, LogStorage are not empty bus last log entry is invalid",
|
|
K(last_entry_begin_lsn), K(expected_next_block_id), K(last_group_entry_header));
|
|
} else {
|
|
// NB: assume before 'truncate_prefix_blocks' finish, there is not any new write opt!!!
|
|
//
|
|
// For non-empty directory:
|
|
// 1. If 'base_block_id' is greater than 'expected_next_block_id', we need delete all blocks
|
|
// between ['min_block_id', 'base_block_id');
|
|
// 2. otherwise, check 'expected_next_block_id' whether is integrity.
|
|
//
|
|
// Ensure that:
|
|
// 1. check LogStorage integrity only when 'expected_next_block_id' is greater than
|
|
// 'base_block_id', consider rebuild, all blocks on disk may be deleted.;
|
|
// 2. 'min_block_id' must be smaller than or equal to 'base_block_id';
|
|
// 3. the last block is integral, means that 'max_block_id' is ethier equal to
|
|
// 'expected_next_block_id'(last block is
|
|
// empty) or 'expected_next_block_id' is equal to 'max_block_id' + 1.
|
|
LSN log_storage_tail = last_entry_begin_lsn + last_group_entry_header.get_serialize_size()
|
|
+ last_group_entry_header.get_data_len();
|
|
if (false == is_valid_block_id(expected_next_block_id)) {
|
|
PALF_LOG(INFO,
|
|
"expected_next_block_id is invalid, no need check_last_block_whether_is_integrity_",
|
|
K(ret), KPC(this), K(expected_next_block_id));
|
|
} else if (expected_next_block_id <= base_block_id) {
|
|
// do nothing
|
|
} else if (min_block_id > base_block_id
|
|
|| false
|
|
== check_last_block_whether_is_integrity_(expected_next_block_id,
|
|
max_block_id, log_storage_tail)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
PALF_LOG(ERROR,
|
|
"directory is not empty, but there are something unexpected!!!(may be min block is "
|
|
"less than base block "
|
|
"or last block is incorrect)",
|
|
K(min_block_id), K(base_block_id), K(expected_next_block_id), K(max_block_id));
|
|
// NB: If just advance 'base_lsn' in rebuild, we need handle holes for 'get_block_id_range',
|
|
// an easy way to do this is that, after advance 'base_lsn', the 'min_block_id_' of
|
|
// 'LogBlockMgr' is lsn_2_block('base_lsn', PALF_BLOCK_SIZE), meanwhile, we need make
|
|
// 'BlockGCTimerTask' can see the really 'min_block_id_' and 'max_block_id_'.
|
|
} else {
|
|
}
|
|
|
|
// Deleting holes before 'base_block_id'
|
|
// NB: deleting holes only when 'prev_log_info' is valid. 'prev_log_info' is valid means that
|
|
// the rebuild option has occured, and we can't known previous log which before 'base_lsn'
|
|
// whether has been confirmed, therefore, delete these blocks.
|
|
// if the tail of last entry (log_storage_tail) is smaller than or equal to base lsn, need
|
|
// reset last_group_entry_header, PalfHandleImpl will be inited with the prev log info saved
|
|
// snapshot meta.
|
|
if (OB_SUCC(ret) && true == prev_log_info_is_valid) {
|
|
if (OB_FAIL(log_storage_.truncate_prefix_blocks(base_lsn))) {
|
|
PALF_LOG(ERROR, "clear_up_holes_ failed", K(ret), K(min_block_id), K(max_block_id),
|
|
K(base_block_id), K_(palf_id), K_(is_inited));
|
|
} else if (base_lsn >= last_group_entry_header.get_committed_end_lsn()) {
|
|
PALF_LOG(WARN, "the max committed end lsn is smaller than or equal to base_lsn,"
|
|
" there is a rebuild operation before restart, and we will use prev_log_info"
|
|
" to construct PalfBaseInfo", K_(palf_id), K(base_lsn), K(last_group_entry_header),
|
|
K(prev_log_info));
|
|
last_group_entry_header.reset();
|
|
}
|
|
}
|
|
}
|
|
PALF_LOG(INFO, "try_clear_up_holes_and_check_storage_integrity_ finish", K(ret), K_(palf_id), K(min_block_id),
|
|
K(max_block_id), K(base_block_id), K(expected_next_block_id), K(prev_log_info));
|
|
return ret;
|
|
}
|
|
|
|
bool LogEngine::check_last_block_whether_is_integrity_(const block_id_t expected_next_block_id,
|
|
const block_id_t max_block_id,
|
|
const LSN &log_storage_tail)
|
|
{
|
|
// NB:
|
|
// 1. 'expected_next_block_id' == 'max_block_id' + 1, normal case
|
|
// 2. 'expected_next_block_id' <= 'max_block_id', means:
|
|
// 1. a 'truncate' or 'flashback' opt before stop palf, we need update manifest first,
|
|
// and stop palf before delete blocks on disk, 'expected_next_block_id' is smaller
|
|
// than or equal to 'max_block_id'.
|
|
// 2. a switch block opt before stop palf, and just create new block on disk success,
|
|
// expected_next_block_id is equal to 'max_block_id', and 'max_block_id' is empty,
|
|
// we need update manifest to max_block_id + 1 in process of restart.
|
|
return expected_next_block_id == max_block_id + 1
|
|
|| expected_next_block_id <= max_block_id;
|
|
}
|
|
|
|
void LogEngine::reset_min_block_info_guarded_by_lock_(const block_id_t min_block_id, const SCN &min_block_max_scn)
|
|
{
|
|
ObSpinLockGuard guard(block_gc_lock_);
|
|
min_block_id_ = min_block_id;
|
|
min_block_max_scn_ = min_block_max_scn;
|
|
}
|
|
|
|
LogNetService& LogEngine::get_net_service()
|
|
{
|
|
return log_net_service_;
|
|
}
|
|
} // end namespace palf
|
|
} // end namespace oceanbase
|