1003 lines
34 KiB
C++
1003 lines
34 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#define USING_LOG_PREFIX STORAGE
|
|
#include "storage/tablet/ob_tablet_memtable_mgr.h"
|
|
#include "storage/memtable/ob_memtable.h"
|
|
#include "storage/memtable/ob_multi_source_data.h"
|
|
#include "storage/meta_mem/ob_tenant_meta_mem_mgr.h"
|
|
#include "storage/ls/ob_freezer.h"
|
|
#include "storage/tx_storage/ob_ls_service.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
using namespace rootserver;
|
|
using namespace blocksstable;
|
|
using namespace memtable;
|
|
using namespace transaction;
|
|
using namespace clog;
|
|
using namespace share::schema;
|
|
using namespace share;
|
|
using namespace obrpc;
|
|
namespace storage
|
|
{
|
|
|
|
ObTabletMemtableMgr::ObTabletMemtableMgr()
|
|
: ObIMemtableMgr(LockType::OB_SPIN_RWLOCK, &lock_def_),
|
|
ls_(NULL),
|
|
lock_def_(common::ObLatchIds::TABLET_MEMTABLE_LOCK),
|
|
schema_recorder_(),
|
|
medium_info_recorder_()
|
|
{
|
|
#if defined(__x86_64__)
|
|
static_assert(sizeof(ObTabletMemtableMgr) <= 448, "The size of ObTabletMemtableMgr will affect the meta memory manager, and the necessity of adding new fields needs to be considered.");
|
|
#endif
|
|
}
|
|
|
|
ObTabletMemtableMgr::~ObTabletMemtableMgr()
|
|
{
|
|
destroy();
|
|
}
|
|
|
|
void ObTabletMemtableMgr::destroy()
|
|
{
|
|
MemMgrWLockGuard lock_guard(lock_);
|
|
// release memtable
|
|
memtable::ObIMemtable *imemtable = nullptr;
|
|
int ret = OB_SUCCESS;
|
|
for (int64_t pos = memtable_head_; pos < memtable_tail_; ++pos) {
|
|
imemtable = tables_[get_memtable_idx(pos)];
|
|
if (OB_ISNULL(imemtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
STORAGE_LOG(WARN, "memtable is nullptr", K(ret), KP(imemtable), K(pos));
|
|
} else if (imemtable->is_data_memtable()) {
|
|
memtable::ObMemtable *memtable = static_cast<memtable::ObMemtable *>(imemtable);
|
|
memtable->remove_from_data_checkpoint();
|
|
}
|
|
}
|
|
reset_tables();
|
|
tablet_id_ = 0;
|
|
ls_ = NULL;
|
|
freezer_ = nullptr;
|
|
schema_recorder_.destroy();
|
|
medium_info_recorder_.destroy();
|
|
is_inited_ = false;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::init(const common::ObTabletID &tablet_id,
|
|
const ObLSID &ls_id,
|
|
ObFreezer *freezer,
|
|
ObTenantMetaMemMgr *t3m)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObLSService *ls_service = MTL(storage::ObLSService *);
|
|
ObLSHandle ls_handle;
|
|
|
|
if (OB_UNLIKELY(is_inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_WARN("this has been initialized, not init again", K(ret), K_(is_inited));
|
|
} else if (OB_UNLIKELY(!tablet_id.is_valid())
|
|
|| OB_ISNULL(t3m)
|
|
|| OB_ISNULL(freezer)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid arguments", K(ret), K(tablet_id), KP(freezer), KP(t3m));
|
|
} else if (OB_ISNULL(ls_service)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "ls service should not be NULL", K(ret), KP(ls_service));
|
|
} else if (OB_FAIL(ls_service->get_ls(ls_id,
|
|
ls_handle,
|
|
ObLSGetMod::TABLET_MOD))) {
|
|
TRANS_LOG(WARN, "failed to get ls", K(ret), K(MTL_ID()));
|
|
} else if (OB_ISNULL(ls_ = ls_handle.get_ls())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "ls should not be NULL", K(ret), KP(ls_));
|
|
} else {
|
|
tablet_id_ = tablet_id;
|
|
t3m_ = t3m;
|
|
table_type_ = ObITable::TableType::DATA_MEMTABLE;
|
|
freezer_ = freezer;
|
|
is_inited_ = true;
|
|
TRANS_LOG(DEBUG, "succeeded to init tablet memtable mgr", K(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
destroy();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::init_storage_recorder(
|
|
const ObTabletID &tablet_id,
|
|
const share::ObLSID &ls_id,
|
|
const int64_t max_saved_schema_version,
|
|
const int64_t max_saved_medium_scn,
|
|
const lib::Worker::CompatMode compat_mode,
|
|
logservice::ObLogHandler *log_handler)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(schema_recorder_.init(ls_id, tablet_id, max_saved_schema_version, compat_mode, log_handler))) {
|
|
TRANS_LOG(WARN, "failed to init schema recorder", K(ret), K(max_saved_schema_version), KP(log_handler));
|
|
} else if (OB_FAIL(medium_info_recorder_.init(ls_id, tablet_id, max_saved_medium_scn, log_handler))) {
|
|
TRANS_LOG(WARN, "failed to init medium info recorder", K(ret), K(max_saved_medium_scn), KP(log_handler));
|
|
} else {
|
|
TRANS_LOG(INFO, "success to init storage recorder", K(ret), K(ls_id), K(tablet_id), K(max_saved_schema_version),
|
|
K(max_saved_medium_scn), K(compat_mode));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::reset_storage_recorder()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!schema_recorder_.is_inited() || !medium_info_recorder_.is_inited())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("schema recorder or medium recorder is not init", K(ret), K_(schema_recorder),
|
|
K_(medium_info_recorder));
|
|
} else {
|
|
schema_recorder_.reset();
|
|
medium_info_recorder_.reset();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// There are two cases:
|
|
// 1. create the first memtable for tablet
|
|
// 2. create the new memtable after freezing the old memtable
|
|
int ObTabletMemtableMgr::create_memtable(const SCN clog_checkpoint_scn,
|
|
const int64_t schema_version,
|
|
const bool for_replay)
|
|
{
|
|
ObTimeGuard time_guard("ObTabletMemtableMgr::create_memtable", 10 * 1000);
|
|
// Write lock
|
|
MemMgrWLockGuard lock_guard(lock_);
|
|
time_guard.click("lock");
|
|
|
|
int ret = OB_SUCCESS;
|
|
ObTableHandleV2 memtable_handle;
|
|
const bool has_memtable = has_memtable_();
|
|
const uint32_t logstream_freeze_clock = freezer_->get_freeze_clock();
|
|
memtable::ObMemtable *active_memtable = nullptr;
|
|
uint32_t memtable_freeze_clock = UINT32_MAX;
|
|
const share::ObLSID ls_id = ls_->get_ls_id();
|
|
SCN new_clog_checkpoint_scn;
|
|
if (has_memtable && OB_NOT_NULL(active_memtable = get_active_memtable_())) {
|
|
memtable_freeze_clock = active_memtable->get_freeze_clock();
|
|
}
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (logstream_freeze_clock == memtable_freeze_clock) {
|
|
// new memtable has already existed
|
|
ret = OB_ENTRY_EXIST;
|
|
} else if (get_memtable_count_() >= MAX_MEMSTORE_CNT) {
|
|
ret = OB_MINOR_FREEZE_NOT_ALLOW;
|
|
if (TC_REACH_TIME_INTERVAL(1000 * 1000)) {
|
|
ObTableHandleV2 first_frozen_memtable;
|
|
get_first_frozen_memtable_(first_frozen_memtable);
|
|
LOG_WARN("cannot create more memtable", K(ret), K(ls_id), K(tablet_id_), K(MAX_MEMSTORE_CNT),
|
|
K(get_memtable_count_()),
|
|
KPC(first_frozen_memtable.get_table()));
|
|
}
|
|
} else if (OB_FAIL(get_newest_clog_checkpoint_scn(new_clog_checkpoint_scn))) {
|
|
LOG_WARN("failed to get newest clog_checkpoint_scn", K(ret), K(ls_id), K(tablet_id_), K(new_clog_checkpoint_scn));
|
|
} else if (for_replay && clog_checkpoint_scn != new_clog_checkpoint_scn) {
|
|
ret = OB_EAGAIN;
|
|
LOG_INFO("clog_checkpoint_scn changed, need retry to replay", K(ls_id), K(tablet_id_), K(clog_checkpoint_scn), K(new_clog_checkpoint_scn));
|
|
} else {
|
|
ObITable::TableKey table_key;
|
|
table_key.table_type_ = ObITable::DATA_MEMTABLE;
|
|
table_key.tablet_id_ = tablet_id_;
|
|
table_key.scn_range_.start_scn_ = clog_checkpoint_scn;
|
|
table_key.scn_range_.end_scn_.set_max();
|
|
memtable::ObMemtable *memtable = NULL;
|
|
ObLSHandle ls_handle;
|
|
|
|
if (OB_FAIL(t3m_->acquire_memtable(memtable_handle))) {
|
|
LOG_WARN("failed to create memtable", K(ret), K(ls_id), K(tablet_id_));
|
|
} else if (FALSE_IT(time_guard.click("acquire_memtable"))) {
|
|
} else if (OB_ISNULL(memtable = static_cast<memtable::ObMemtable *>(memtable_handle.get_table()))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to get memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle));
|
|
} else if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id, ls_handle, ObLSGetMod::DATA_MEMTABLE_MOD))) {
|
|
LOG_WARN("failed to get log stream", K(ret), K(ls_id), K(tablet_id_));
|
|
} else if (OB_UNLIKELY(!ls_handle.is_valid())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected error, invalid ls handle", K(ret), K(ls_handle), K(ls_id), K(tablet_id_));
|
|
} else if (OB_FAIL(memtable->init(table_key,
|
|
ls_handle,
|
|
freezer_,
|
|
this,
|
|
schema_version,
|
|
logstream_freeze_clock))) {
|
|
LOG_WARN("failed to init memtable", K(ret), K(ls_id), K(table_key), KP(freezer_), KP(this),
|
|
K(schema_version), K(logstream_freeze_clock));
|
|
} else {
|
|
ObTableHandleV2 last_frozen_memtable_handle;
|
|
memtable::ObMemtable *last_frozen_memtable = nullptr;
|
|
if (OB_FAIL(get_last_frozen_memtable_(last_frozen_memtable_handle))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("fail to get last frozen memtable", K(ret));
|
|
} else {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
} else if (OB_FAIL(last_frozen_memtable_handle.get_data_memtable(last_frozen_memtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret));
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_NOT_NULL(last_frozen_memtable)) {
|
|
// keep the check order: is_frozen, write_ref_cnt, then unsubmitted_cnt and unsynced_cnt
|
|
int64_t write_ref = last_frozen_memtable->get_write_ref();
|
|
int64_t unsubmitted_cnt = last_frozen_memtable->get_unsubmitted_cnt();
|
|
int64_t unsynced_cnt = last_frozen_memtable->get_unsynced_cnt();
|
|
if (write_ref > 0 || unsubmitted_cnt > 0) {
|
|
memtable->set_logging_blocked();
|
|
TRANS_LOG(INFO, "set logging_block", KPC(last_frozen_memtable), KPC(memtable));
|
|
}
|
|
if (write_ref > 0 || unsynced_cnt > 0) {
|
|
last_frozen_memtable->set_resolve_active_memtable_left_boundary(false);
|
|
}
|
|
// for follower, must decide the boundary of frozen memtable
|
|
// for leader, decide the boundary of frozen memtable that meets ready_for_flush
|
|
if (for_replay || (0 == write_ref &&
|
|
0 == unsubmitted_cnt &&
|
|
0 == unsynced_cnt)) {
|
|
last_frozen_memtable->resolve_right_boundary();
|
|
TRANS_LOG(INFO, "[resolve_right_boundary] last_frozen_memtable in create_memtable", K(for_replay), K(ls_id), KPC(last_frozen_memtable));
|
|
if (memtable != last_frozen_memtable) {
|
|
const SCN &new_start_scn = MAX(last_frozen_memtable->get_end_scn(), last_frozen_memtable->get_migration_clog_checkpoint_scn());
|
|
memtable->resolve_left_boundary(new_start_scn);
|
|
}
|
|
}
|
|
// there is no frozen memtable and new sstable will not be generated,
|
|
// meaning that clog_checkpoint_scn will not be updated now,
|
|
// so get newest clog_checkpoint_scn to set left boundary
|
|
} else {
|
|
memtable->resolve_left_boundary(new_clog_checkpoint_scn);
|
|
}
|
|
|
|
time_guard.click("init memtable");
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(add_memtable_(memtable_handle))) {
|
|
LOG_WARN("failed to add memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle));
|
|
} else if (FALSE_IT(time_guard.click("add memtable"))) {
|
|
} else if (OB_FAIL(memtable->add_to_data_checkpoint(freezer_->get_ls_data_checkpoint()))) {
|
|
LOG_WARN("add to data_checkpoint failed", K(ret), K(ls_id), KPC(memtable));
|
|
clean_tail_memtable_();
|
|
} else if (FALSE_IT(time_guard.click("add to data_checkpoint"))) {
|
|
} else if (FALSE_IT(memtable->set_freeze_clock(freezer_->get_freeze_clock()))) {
|
|
} else {
|
|
LOG_INFO("succeed to create memtable", K(ret), K(ls_id), KPC(memtable));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint32_t ObTabletMemtableMgr::get_ls_freeze_clock()
|
|
{
|
|
return freezer_->get_freeze_clock();
|
|
}
|
|
|
|
bool ObTabletMemtableMgr::has_active_memtable()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool bool_ret = false;
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else {
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
if (NULL != get_active_memtable_()) {
|
|
bool_ret = true;
|
|
}
|
|
}
|
|
return bool_ret;
|
|
}
|
|
|
|
int64_t ObTabletMemtableMgr::get_memtable_count() const
|
|
{
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
return get_memtable_count_();
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_boundary_memtable(ObTableHandleV2 &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
memtable::ObIMemtable *memtable = nullptr;
|
|
handle.reset();
|
|
|
|
if (OB_UNLIKELY(get_memtable_count_() == 0)) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
} else if (memtable_tail_ > memtable_head_) {
|
|
if (OB_FAIL(get_ith_memtable(memtable_tail_ - 1, handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(memtable_tail_));
|
|
} else if (OB_FAIL(handle.get_memtable(memtable))) {
|
|
handle.reset();
|
|
LOG_WARN("there is no boundary memtable", K(ret));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_active_memtable(ObTableHandleV2 &handle) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
handle.reset();
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_active_memtable_(handle))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("fail to get active memtable", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_active_memtable_(ObTableHandleV2 &handle) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(get_memtable_count_() == 0)) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_DEBUG("no memtable exists", K(ret));
|
|
} else if (memtable_tail_ > memtable_head_) {
|
|
memtable::ObMemtable *memtable = nullptr;
|
|
if (OB_FAIL(get_ith_memtable(memtable_tail_ - 1, handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(memtable_tail_));
|
|
} else if (OB_FAIL(handle.get_data_memtable(memtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret));
|
|
} else if (!memtable->is_active_memtable()) {
|
|
handle.reset();
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_last_frozen_memtable(ObTableHandleV2 &handle) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_last_frozen_memtable_(handle))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("fail to get last frozen memtable", K(ret));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_last_frozen_memtable_(ObTableHandleV2 &handle) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
handle.reset();
|
|
|
|
if (OB_UNLIKELY(get_memtable_count_() == 0)) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
} else if (memtable_tail_ > memtable_head_) {
|
|
for (int64_t i = memtable_tail_ - 1; OB_SUCC(ret) && i >= memtable_head_; --i) {
|
|
ObTableHandleV2 m_handle;
|
|
const ObMemtable *memtable = nullptr;
|
|
if (OB_FAIL(get_ith_memtable(i, m_handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i));
|
|
} else if (OB_UNLIKELY(!m_handle.is_valid())) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("memtable handle is invalid", K(ret), K(m_handle));
|
|
} else if (OB_FAIL(m_handle.get_data_memtable(memtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret), K(m_handle));
|
|
} else if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("memtable must not null", K(ret), K(m_handle));
|
|
} else if (memtable->is_frozen_memtable()) {
|
|
handle = m_handle;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!handle.is_valid()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::resolve_left_boundary_for_active_memtable(memtable::ObIMemtable *memtable,
|
|
SCN start_scn,
|
|
SCN snapshot_scn)
|
|
{
|
|
ObTableHandleV2 handle;
|
|
ObIMemtable *active_memtable = nullptr;
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_active_memtable(handle))) {
|
|
LOG_WARN( "fail to get active memtable", K(ret));
|
|
} else if (OB_FAIL(handle.get_memtable(active_memtable))) {
|
|
LOG_WARN("fail to get active memtable", K(ret));
|
|
} else {
|
|
// set the start_scn of the new memtable
|
|
static_cast<ObMemtable*>(active_memtable)->resolve_left_boundary(start_scn);
|
|
}
|
|
if (OB_ENTRY_NOT_EXIST== ret) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
static_cast<ObMemtable*>(memtable)->set_resolve_active_memtable_left_boundary(true);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::unset_logging_blocked_for_active_memtable(memtable::ObIMemtable *memtable)
|
|
{
|
|
ObTableHandleV2 handle;
|
|
ObIMemtable *active_memtable = nullptr;
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_active_memtable(handle))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("fail to get active memtable", K(ret));
|
|
}
|
|
} else if (OB_FAIL(handle.get_memtable(active_memtable))) {
|
|
LOG_WARN("fail to get active memtable", K(ret));
|
|
} else {
|
|
// allow the new memtable to submit log
|
|
static_cast<ObMemtable*>(active_memtable)->unset_logging_blocked();
|
|
}
|
|
if (OB_ENTRY_NOT_EXIST== ret) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
static_cast<ObMemtable*>(memtable)->unset_active_memtable_logging_blocked();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::set_is_tablet_freeze_for_active_memtable(ObTableHandleV2 &handle, bool is_force_freeze)
|
|
{
|
|
handle.reset();
|
|
memtable::ObIMemtable *active_memtable = nullptr;
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_active_memtable(handle))) {
|
|
LOG_WARN("fail to get active memtable", K(ret));
|
|
} else if (OB_FAIL(handle.get_memtable(active_memtable))) {
|
|
LOG_WARN("fail to get active memtable", K(ret));
|
|
if (ret == OB_NOT_INIT) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_WARN("active memtable is null", K(ret));
|
|
}
|
|
} else {
|
|
static_cast<ObMemtable*>(active_memtable)->set_is_tablet_freeze();
|
|
if (is_force_freeze) {
|
|
static_cast<ObMemtable*>(active_memtable)->set_is_force_freeze();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_memtable_for_replay(SCN replay_scn,
|
|
ObTableHandleV2 &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const share::ObLSID ls_id = ls_->get_ls_id();
|
|
ObMemtable *memtable = nullptr;
|
|
handle.reset();
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else {
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
int64_t i = 0;
|
|
for (i = memtable_tail_ - 1; OB_SUCC(ret) && i >= memtable_head_; --i) {
|
|
if (OB_FAIL(get_ith_memtable(i, handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i));
|
|
} else if (OB_FAIL(handle.get_data_memtable(memtable))) {
|
|
handle.reset();
|
|
LOG_WARN("fail to get data memtable", K(ret));
|
|
} else {
|
|
if (replay_scn > memtable->get_start_scn() && replay_scn <= memtable->get_end_scn()) {
|
|
break;
|
|
} else {
|
|
handle.reset();
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !handle.is_valid() && i < memtable_head_) {
|
|
SCN clog_checkpoint_scn;
|
|
if (OB_FAIL(get_newest_clog_checkpoint_scn(clog_checkpoint_scn))) {
|
|
} else if (replay_scn <= clog_checkpoint_scn) {
|
|
// no need to replay the log
|
|
ret = OB_NO_NEED_UPDATE;
|
|
LOG_INFO("no need to replay the log", K(ret), K(ls_id), K(tablet_id_), K(replay_scn), K(clog_checkpoint_scn));
|
|
} else {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_WARN("fail to get memtable for replay", K(ret), K(ls_id), K(tablet_id_), K(replay_scn), K(clog_checkpoint_scn), K(memtable_tail_ - memtable_head_));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_memtables(
|
|
ObTableHdlArray &handle,
|
|
const bool reset_handle,
|
|
const int64_t start_point,
|
|
const bool include_active_memtable)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else {
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
if (reset_handle) {
|
|
handle.reset();
|
|
}
|
|
if (OB_FAIL(get_memtables_(handle, start_point, include_active_memtable))) {
|
|
LOG_WARN("fail to get memtables", K(ret), K(start_point), K(include_active_memtable));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_memtables_nolock(ObTableHdlArray &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t start_point = -1;
|
|
const bool include_active_memtable = true;
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_memtables_(handle, start_point, include_active_memtable))) {
|
|
LOG_WARN("fail to get memtables", K(ret), K(start_point), K(include_active_memtable));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_all_memtables(ObTableHdlArray &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_memtables_nolock(handle))) {
|
|
LOG_WARN("failed to get all memtables", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable,
|
|
const bool force)
|
|
{
|
|
UNUSED(force);
|
|
int ret = OB_SUCCESS;
|
|
const share::ObLSID ls_id = ls_->get_ls_id();
|
|
memtable::ObMemtable *memtable = static_cast<memtable::ObMemtable *>(imemtable);
|
|
|
|
if (OB_UNLIKELY(get_memtable_count_() <= 0)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
} else {
|
|
const int64_t idx = get_memtable_idx(memtable_head_);
|
|
if (nullptr != tables_[idx] && memtable == tables_[idx]) {
|
|
LOG_INFO("release head memtable", K(ret), K(ls_id), KPC(memtable));
|
|
memtable::ObMtStat& mt_stat = memtable->get_mt_stat();
|
|
if (0 == mt_stat.release_time_) {
|
|
mt_stat.release_time_ = ObTimeUtility::current_time();
|
|
} else {
|
|
LOG_WARN("cannot set release_time twice", K(ls_id), KPC(memtable));
|
|
}
|
|
if (!memtable->is_empty()) {
|
|
memtable->set_read_barrier();
|
|
}
|
|
memtable->remove_from_data_checkpoint();
|
|
memtable->set_is_flushed();
|
|
memtable->set_freeze_state(ObMemtableFreezeState::RELEASED);
|
|
release_head_memtable();
|
|
FLOG_INFO("succeed to release head data memtable", K(ret), K(ls_id), K(tablet_id_));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_first_frozen_memtable(ObTableHandleV2 &handle) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
memtable::ObMemtable *memtable = NULL;
|
|
MemMgrRLockGuard guard(lock_);
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_FAIL(get_first_frozen_memtable_(handle))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("fail to get first frozen memtable", K(ret));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
memtable::ObMemtable *ObTabletMemtableMgr::get_active_memtable_()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
memtable::ObMemtable *memtable = nullptr;
|
|
if (memtable_tail_ > memtable_head_) {
|
|
memtable = static_cast<memtable::ObMemtable *>(tables_[get_memtable_idx(memtable_tail_ - 1)]);
|
|
if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
STORAGE_LOG(WARN, "memtable is nullptr", K(ret), KP(memtable), K(memtable_tail_));
|
|
} else if (!memtable->is_active_memtable()) {
|
|
memtable = NULL;
|
|
}
|
|
}
|
|
|
|
return memtable;
|
|
}
|
|
|
|
memtable::ObMemtable *ObTabletMemtableMgr::get_memtable_(const int64_t pos) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
memtable::ObMemtable *memtable = nullptr;
|
|
memtable::ObMemtable *table = static_cast<memtable::ObMemtable *>(tables_[get_memtable_idx(pos)]);
|
|
if (OB_ISNULL(table)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("table is nullptr", K(ret), KP(table), K(pos));
|
|
} else if (!table->is_data_memtable()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("not data memtable", K(ret), K(pos), K(table->get_key()));
|
|
} else {
|
|
memtable = table;
|
|
}
|
|
return const_cast<memtable::ObMemtable *>(memtable);
|
|
}
|
|
|
|
int64_t ObTabletMemtableMgr::get_unmerged_memtable_count_() const
|
|
{
|
|
int64_t cnt = 0;
|
|
|
|
for (int64_t i = memtable_head_; i < memtable_tail_; i++) {
|
|
ObMemtable *memtable = get_memtable_(i);
|
|
if (NULL == memtable) {
|
|
LOG_ERROR("memtable must not null");
|
|
} else if (0 == memtable->get_minor_merged_time()) {
|
|
cnt++;
|
|
}
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
void ObTabletMemtableMgr::clean_tail_memtable_()
|
|
{
|
|
ObIMemtableMgr::release_tail_memtable();
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_memtables_(ObTableHdlArray &handle, const int64_t start_point,
|
|
const bool include_active_memtable)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t start_pos = memtable_head_;
|
|
if (-1 != start_point) {
|
|
if (OB_FAIL(find_start_pos_(start_point, start_pos))) {
|
|
LOG_WARN("failed to find_start_pos_", K(ret), K(start_point));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && OB_FAIL(add_tables_(start_pos, include_active_memtable, handle))) {
|
|
LOG_WARN("failed to add tables", K(ret), K(start_point), K(include_active_memtable));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::add_tables_(
|
|
const int64_t start_pos,
|
|
const bool include_active_memtable,
|
|
ObTableHdlArray &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_LIKELY(start_pos > -1)) {
|
|
const int64_t last_pos = memtable_tail_ - 1;
|
|
for (int64_t pos = start_pos; OB_SUCC(ret) && pos < last_pos; ++pos) {
|
|
ObTableHandleV2 memtable_handle;
|
|
if (OB_FAIL(get_ith_memtable(pos, memtable_handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(pos));
|
|
} else if (OB_UNLIKELY(!memtable_handle.is_valid())) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("invalid memtable handle", K(ret), K(memtable_handle));
|
|
} else if (OB_FAIL(handle.push_back(memtable_handle))) {
|
|
LOG_WARN("failed to add memtable", K(ret), K(memtable_handle));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && memtable_tail_ > memtable_head_) {
|
|
ObTableHandleV2 last_memtable_handle;
|
|
if (OB_FAIL(get_ith_memtable(last_pos, last_memtable_handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(last_pos));
|
|
} else if (OB_UNLIKELY(!last_memtable_handle.is_valid())) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("invalid memtable handle", K(ret), K(last_memtable_handle));
|
|
} else if (include_active_memtable || last_memtable_handle.get_table()->is_frozen_memtable()) {
|
|
if (OB_FAIL(handle.push_back(last_memtable_handle))) {
|
|
LOG_WARN("failed to add last memtable to handle", K(ret), K(start_pos),
|
|
K(include_active_memtable), K(last_memtable_handle));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::find_start_pos_(const int64_t start_point, int64_t &start_pos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
start_pos = -1;
|
|
if (OB_UNLIKELY(start_point < 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid start_point", K(ret), K(start_point));
|
|
}
|
|
for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) {
|
|
ObMemtable *memtable = get_memtable_(i);
|
|
if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("memtable must not null", K(ret));
|
|
} else if (memtable->get_snapshot_version() > start_point) {
|
|
start_pos = i;
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int64_t ObTabletMemtableMgr::to_string(char *buf, const int64_t buf_len) const
|
|
{
|
|
int64_t pos = 0;
|
|
if (OB_ISNULL(buf) || buf_len <= 0) {
|
|
} else {
|
|
J_OBJ_START();
|
|
J_NAME("ObIMemtableMgr");
|
|
J_COLON();
|
|
pos += ObIMemtableMgr::to_string(buf + pos, buf_len - pos);
|
|
J_COMMA();
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
J_OBJ_START();
|
|
J_ARRAY_START();
|
|
for (int64_t i = memtable_head_; i < memtable_tail_; ++i) {
|
|
ObMemtable *memtable = get_memtable_(i);
|
|
if (nullptr != memtable) {
|
|
J_OBJ_START();
|
|
J_KV(K(i), "table_key", memtable->get_key(), "ref", memtable->get_ref());
|
|
J_OBJ_END();
|
|
J_COMMA();
|
|
}
|
|
}
|
|
J_KV("schema_recorder", schema_recorder_);
|
|
J_ARRAY_END();
|
|
J_OBJ_END();
|
|
J_OBJ_END();
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::find_start_pos_(const int64_t start_log_ts,
|
|
const int64_t start_snapshot_version,
|
|
int64_t &start_pos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
start_pos = -1;
|
|
if (OB_UNLIKELY(start_log_ts <= 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid start_snapshot_version", K(ret), K(start_snapshot_version), K(start_log_ts));
|
|
}
|
|
for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) {
|
|
ObMemtable *memtable = get_memtable_(i);
|
|
if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("memtable must not null", K(ret));
|
|
} else if (memtable->get_end_scn().get_val_for_tx() == start_log_ts) {
|
|
if (memtable->get_snapshot_version() > start_snapshot_version) {
|
|
start_pos = i;
|
|
break;
|
|
}
|
|
} else if (memtable->get_end_scn().get_val_for_tx() > start_log_ts) {
|
|
start_pos = i;
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_memtables_v2(
|
|
ObTableHdlArray &handle,
|
|
const int64_t start_log_ts,
|
|
const int64_t start_snapshot_version,
|
|
const bool reset_handle,
|
|
const bool include_active_memtable)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else {
|
|
MemMgrRLockGuard guard(lock_);
|
|
if (reset_handle) {
|
|
handle.reset();
|
|
}
|
|
int64_t start_pos = memtable_head_;
|
|
if (0 < start_log_ts) {
|
|
if (OB_FAIL(find_start_pos_(start_log_ts, start_snapshot_version, start_pos))) {
|
|
LOG_WARN("failed to find_start_pos_", K(ret), K(start_log_ts), K(start_snapshot_version));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && OB_FAIL(add_tables_(start_pos, include_active_memtable, handle))) {
|
|
LOG_WARN("failed to add_tables", K(ret), K(start_log_ts), K(start_snapshot_version),
|
|
K(include_active_memtable), K(reset_handle));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_first_frozen_memtable_(ObTableHandleV2 &handle) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; i++) {
|
|
ObTableHandleV2 m_handle;
|
|
const ObMemtable *memtable = nullptr;
|
|
if (OB_FAIL(get_ith_memtable(i, m_handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i));
|
|
} else if (OB_UNLIKELY(!m_handle.is_valid())) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("memtable handle is invalid", K(ret), K(m_handle));
|
|
} else if (OB_FAIL(m_handle.get_data_memtable(memtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret), K(m_handle));
|
|
} else if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("memtable is nullptr", K(ret), K(m_handle));
|
|
} else if (memtable->is_frozen_memtable()) {
|
|
handle = m_handle;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!handle.is_valid()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_multi_source_data_unit(
|
|
memtable::ObIMultiSourceDataUnit *const multi_source_data_unit,
|
|
ObIAllocator *allocator/*= nullptr*/) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
memtable::ObMemtable *memtable = nullptr;
|
|
multi_source_data_unit->reset();
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else if (OB_ISNULL(multi_source_data_unit)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid args", K(ret), KP(multi_source_data_unit));
|
|
} else {
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
|
|
if (!has_memtable_()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_DEBUG("memtable does not exist", K(ret), K(memtable_head_), K(memtable_tail_));
|
|
} else {
|
|
for (int64_t i = memtable_tail_ - 1; (OB_ENTRY_NOT_EXIST == ret || OB_SUCC(ret)) && i >= memtable_head_; --i) {
|
|
memtable = static_cast<ObMemtable*>(get_memtable_(i));
|
|
if (OB_FAIL(memtable->get_multi_source_data_unit(multi_source_data_unit, allocator))) {
|
|
if (OB_ENTRY_NOT_EXIST == ret) {
|
|
} else {
|
|
LOG_WARN("fail to get multi source data", K(ret), K(tablet_id_));
|
|
}
|
|
} else if (multi_source_data_unit->is_valid()) {
|
|
break;
|
|
}
|
|
memtable = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
if (nullptr != multi_source_data_unit) {
|
|
multi_source_data_unit->reset();
|
|
}
|
|
memtable = nullptr;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMemtableMgr::get_memtable_for_multi_source_data_unit(
|
|
ObTableHandleV2 &handle,
|
|
const memtable::MultiSourceDataUnitType type) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
handle.reset();
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not inited", K(ret), K_(is_inited));
|
|
} else {
|
|
MemMgrRLockGuard lock_guard(lock_);
|
|
|
|
if (!has_memtable_()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_DEBUG("memtable does not exist", K(ret), K(memtable_head_), K(memtable_tail_));
|
|
} else {
|
|
for (int64_t i = memtable_tail_ - 1; OB_SUCC(ret) && i >= memtable_head_; --i) {
|
|
ObTableHandleV2 m_handle;
|
|
const ObMemtable *memtable = nullptr;
|
|
if (OB_FAIL(get_ith_memtable(i, m_handle))) {
|
|
STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i));
|
|
} else if (OB_UNLIKELY(!m_handle.is_valid())) {
|
|
ret = OB_ERR_SYS;
|
|
LOG_ERROR("memtable handle is invalid", K(ret), K(m_handle));
|
|
} else if (OB_FAIL(m_handle.get_data_memtable(memtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret), K(m_handle));
|
|
} else if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("memtable is nullptr", K(ret), K(m_handle));
|
|
} else if (memtable->has_multi_source_data_unit(type)) {
|
|
handle = m_handle;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!handle.is_valid()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_WARN("failed to get memtable", K(ret), K(type));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // namespace storage
|
|
} // namespace oceanbase
|