/** * 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/ob_pg_memtable_mgr.h" #include "lib/lock/ob_spin_rwlock.h" #include "lib/allocator/ob_malloc.h" #include "lib/utility/ob_print_utils.h" #include "lib/utility/ob_tracepoint.h" #include "common/ob_partition_key.h" #include "storage/ob_partition_storage.h" #include "storage/ob_partition_service.h" #include "storage/memtable/ob_memtable.h" #include "storage/ob_table_mgr.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 { ObPGMemtableMgr::ObPGMemtableMgr() : memtable_head_(0), memtable_tail_(0), last_print_readable_info_ts_(0) { MEMSET(memtables_, 0, sizeof(memtables_)); } void ObPGMemtableMgr::reset() { memtable_head_ = 0; memtable_tail_ = 0; MEMSET(memtables_, 0, sizeof(memtables_)); new_active_memstore_handle_.reset(); last_print_readable_info_ts_ = 0; } void ObPGMemtableMgr::destroy() { TCWLockGuard lock_guard(lock_); // release memtable for (int64_t pos = memtable_head_; pos < memtable_tail_; ++pos) { if (OB_ISNULL(memtables_[get_memtable_idx_(pos)])) { STORAGE_LOG(ERROR, "memtable must not null", K(pos), K(get_memtable_idx_(pos))); } else { ObTableMgr::get_instance().release_table(memtables_[get_memtable_idx_(pos)]); memtables_[get_memtable_idx_(pos)] = NULL; } } memtable_head_ = 0; memtable_tail_ = 0; MEMSET(memtables_, 0, sizeof(memtables_)); new_active_memstore_handle_.reset(); } void ObPGMemtableMgr::invalidate_readable_info_() { LOG_INFO("invalid save safe slave read timestamp", K_(pkey), K(cur_readable_info_), K(tmp_readable_info_), K(last_readable_info_)); tmp_readable_info_.reset(); last_readable_info_.reset(); cur_readable_info_.reset(); } // create the first memtable of partition int ObPGMemtableMgr::create_memtable(const ObDataStorageInfo& info, const common::ObPartitionKey& pkey) { int ret = OB_SUCCESS; ObTableHandle memtable_handle; if (!info.is_valid() || !pkey.is_valid()) { ret = OB_INVALID_ARGUMENT; STORAGE_LOG(WARN, "invalid argument", K(ret), K(info), K(pkey)); } else { // Write lock TCWLockGuard lock_guard(lock_); const ObDataStorageInfo& data_info = info; ObITable::TableKey table_key; table_key.table_type_ = ObITable::MEMTABLE; table_key.pkey_ = pkey; table_key.table_id_ = pkey.table_id_; table_key.trans_version_range_.base_version_ = data_info.get_publish_version() == 0 ? 1 : data_info.get_publish_version(); table_key.trans_version_range_.multi_version_start_ = table_key.trans_version_range_.base_version_; table_key.trans_version_range_.snapshot_version_ = ObVersionRange::MAX_VERSION; table_key.log_ts_range_.start_log_ts_ = data_info.get_last_replay_log_ts(); table_key.log_ts_range_.end_log_ts_ = ObLogTsRange::MAX_TS; table_key.log_ts_range_.max_log_ts_ = 0; memtable::ObMemtable* memtable = NULL; if (OB_FAIL(ObTableMgr::get_instance().create_memtable(table_key, memtable_handle))) { STORAGE_LOG(WARN, "failed to create memtable", K(ret), K(pkey)); } else if (OB_FAIL(memtable_handle.get_memtable(memtable))) { STORAGE_LOG(WARN, "failed to get memtable", K(ret), K(info), K(pkey)); } else if (FALSE_IT(memtable->set_max_schema_version(data_info.get_schema_version()))) { // set initial schema version for memtable } else if (OB_FAIL(add_memtable_(memtable))) { STORAGE_LOG(WARN, "add memtable error", K(ret), K(info), K(pkey)); } else { memtable->set_with_accurate_log_ts_range(info.is_created_by_new_minor_freeze()); invalidate_readable_info_(); } } return ret; } int ObPGMemtableMgr::update_memtable_schema_version(const int64_t schema_version) { int ret = OB_SUCCESS; ObMemtable* active_memtable = get_active_memtable_(); if (NULL != active_memtable) { int64_t old_schema_version = active_memtable->get_max_schema_version(); active_memtable->set_max_schema_version(schema_version); TRANS_LOG(INFO, "update memtable schema version", K(*active_memtable), K(old_schema_version), K(schema_version)); } else { TRANS_LOG(INFO, "none active memtable", K(schema_version)); } return ret; } int ObPGMemtableMgr::new_active_memstore(const common::ObPartitionKey& pkey, int64_t& protection_clock) { int ret = OB_SUCCESS; ObITable::TableKey table_key; table_key.table_type_ = ObITable::MEMTABLE; table_key.pkey_ = pkey; table_key.table_id_ = pkey.table_id_; table_key.trans_version_range_.snapshot_version_ = ObVersionRange::MAX_VERSION; table_key.log_ts_range_.end_log_ts_ = ObLogTsRange::MAX_TS; table_key.log_ts_range_.max_log_ts_ = 0; memtable::ObMemtable* memtable = NULL; TCWLockGuard lock_guard(lock_); if (OB_ISNULL(get_active_memtable_())) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(ERROR, "no active memstore, unexpected error", K(ret), K(pkey)); } else if (get_unmerged_memtable_count_() >= MAX_FROZEN_MEMSTORE_CNT_IN_STORAGE || get_memtable_count_() >= MAX_MEMSTORE_CNT) { ret = OB_MINOR_FREEZE_NOT_ALLOW; STORAGE_LOG(WARN, "Too many frozen memtables", K(ret), K(get_unmerged_memtable_count_()), K(get_memtable_count_()), K(pkey)); new_active_memstore_handle_.reset(); } else if (NULL != new_active_memstore_handle_.get_table()) { ret = OB_ENTRY_EXIST; STORAGE_LOG(WARN, "new active memstore already exist", K(ret), K(get_memtable_count_()), K(pkey)); } else if (OB_FAIL(ObTableMgr::get_instance().create_memtable(table_key, new_active_memstore_handle_))) { STORAGE_LOG(WARN, "failed to create active memtable", K(ret), K(pkey)); } else if (OB_FAIL(new_active_memstore_handle_.get_memtable(memtable))) { STORAGE_LOG(WARN, "new active memstore handle get memtable error", K(ret), K_(new_active_memstore_handle)); } else if (OB_ISNULL(memtable)) { ret = OB_ERR_SYS; STORAGE_LOG(ERROR, "new_active_memstore must not null", K(ret), K(pkey)); } else { protection_clock = memtable->get_retire_clock(); STORAGE_LOG(INFO, "new active memstore success", K(pkey), K(*memtable), K(protection_clock)); } return ret; } int ObPGMemtableMgr::effect_new_active_memstore(const ObSavedStorageInfoV2& info, const common::ObPartitionKey& pkey, const common::ObReplicaType& replica_type, const bool emergency) { int ret = OB_SUCCESS; memtable::ObMemtable* active_mt = NULL; ObTimeGuard timeguard("effect new active memstore", 100L * 1000L); { TCWLockGuard lock_guard(lock_); if (OB_FAIL(new_active_memstore_handle_.get_memtable(active_mt))) { STORAGE_LOG(WARN, "no prepared memstore exist", K(ret), K(pkey)); } else if (OB_ISNULL(active_mt)) { ret = OB_ERR_SYS; STORAGE_LOG(ERROR, "active_mt must not null", K(ret), K(pkey)); } else if (OB_FAIL(active_mt->set_base_version(info.get_data_info().get_publish_version()))) { STORAGE_LOG(ERROR, "fail to set base version", K(ret), K(pkey)); } else if (OB_FAIL(active_mt->set_start_log_ts(info.get_data_info().get_last_replay_log_ts()))) { STORAGE_LOG(ERROR, "fail to set base version", K(ret), K(pkey)); } else if (OB_FAIL(save_frozen_base_storage_info_(info))) { STORAGE_LOG(ERROR, "fail to set frozen info", K(ret), K(pkey)); } else { active_mt->set_with_accurate_log_ts_range(info.get_data_info().is_created_by_new_minor_freeze()); timeguard.click(); if (OB_SUCC(ret) && OB_FAIL(freeze_and_add_memtable_(replica_type, active_mt, emergency))) { STORAGE_LOG(WARN, "effect new active memstore failed", K(ret), K(pkey)); } timeguard.click(); if (OB_SUCC(ret)) { new_active_memstore_handle_.reset(); } } } if (OB_FAIL(ret)) { // private method should not call publich method, otherwise K(*this) maybe deadlock; STORAGE_LOG(WARN, "effect new active memstore error", K(info), K(pkey), K(replica_type), K(*this)); } return ret; } int ObPGMemtableMgr::clean_new_active_memstore() { int ret = OB_SUCCESS; TCWLockGuard lock_guard(lock_); new_active_memstore_handle_.reset(); return ret; } int ObPGMemtableMgr::complete_active_memstore(const ObSavedStorageInfoV2& info) { int ret = OB_SUCCESS; memtable::ObMemtable* active_memstore = NULL; TCWLockGuard lock_guard(lock_); if (OB_UNLIKELY(NULL == (active_memstore = get_active_memtable_()))) { ret = OB_SUCCESS; STORAGE_LOG(WARN, "active memstore is NULL", K(ret), K(info)); } else if (OB_UNLIKELY(!active_memstore->is_active_memtable())) { ret = OB_SUCCESS; STORAGE_LOG(WARN, "can not freeze twice", K(ret), K(info)); } else if (OB_FAIL(save_frozen_base_storage_info_(info))) { STORAGE_LOG(ERROR, "fail to set frozen info", K(ret), K(info)); } else if (OB_FAIL(freeze_active_memtable_( info.get_data_info().get_last_replay_log_ts(), info.get_data_info().get_publish_version(), false))) { STORAGE_LOG(WARN, "freeze memstore failed", K(ret), K(info)); } else { active_memstore->mark_for_split(); new_active_memstore_handle_.reset(); } return ret; } bool ObPGMemtableMgr::has_active_memtable() { bool bool_ret = false; TCRLockGuard lock_guard(lock_); if (NULL != get_active_memtable_()) { bool_ret = true; } return bool_ret; } int ObPGMemtableMgr::get_active_memtable(ObTableHandle& handle) { int ret = OB_SUCCESS; memtable::ObMemtable* memtable = NULL; TCRLockGuard lock_guard(lock_); if (get_memtable_count_() == 0) { ret = OB_ENTRY_NOT_EXIST; } else if (OB_ISNULL(memtable = get_active_memtable_())) { ret = OB_ENTRY_NOT_EXIST; } else if (OB_FAIL(handle.set_table(memtable))) { STORAGE_LOG(WARN, "failed to set memtable", K(ret)); } return ret; } int ObPGMemtableMgr::get_memtables( ObTablesHandle& handle, const bool reset_handle, const int64_t start_point, const bool include_active_memtable) { TCRLockGuard lock_guard(lock_); if (reset_handle) { handle.reset(); } return get_memtables_(handle, start_point, include_active_memtable); } int ObPGMemtableMgr::get_memtables_nolock(ObTablesHandle& handle) { const int64_t start_point = -1; const bool include_active_memtable = true; return get_memtables_(handle, start_point, include_active_memtable); } int ObPGMemtableMgr::get_all_memtables(ObTablesHandle& handle) { int ret = OB_SUCCESS; TCRLockGuard lock_guard(lock_); if (OB_FAIL(get_memtables_nolock(handle))) { LOG_WARN("failed to get all memtables", K(ret)); } return ret; } void ObPGMemtableMgr::clean_memtables() { int tmp_ret = OB_SUCCESS; TCWLockGuard lock_guard(lock_); for (int64_t pos = memtable_head_; pos < memtable_tail_; ++pos) { const int64_t idx = get_memtable_idx_(pos); STORAGE_LOG(INFO, "succeed clear non reused memtable", K(idx), K(pos), K(memtable_head_), K(memtable_tail_), K(*memtables_[idx])); if (OB_ISNULL(memtables_[idx])) { tmp_ret = OB_ERR_SYS; STORAGE_LOG(ERROR, "memtable must not null", K(tmp_ret), K(idx)); } else if (OB_SUCCESS != (tmp_ret = ObTableMgr::get_instance().release_table(memtables_[idx]))) { STORAGE_LOG(WARN, "failed to release table", K(tmp_ret)); } memtables_[idx] = NULL; } memtable_head_ = memtable_tail_; invalidate_readable_info_(); } int ObPGMemtableMgr::release_head_memtable(memtable::ObMemtable* memtable) { int tmp_ret = OB_SUCCESS; TCWLockGuard lock_guard(lock_); if (get_memtable_count_() > 0) { const int64_t idx = get_memtable_idx_(memtable_head_); if (NULL != memtables_[idx] && memtable == memtables_[idx]) { memtable->set_read_barrier(); if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = ObTableMgr::get_instance().release_table(memtable)))) { STORAGE_LOG(WARN, "failed to release memtable", K(tmp_ret), K(memtable->get_key())); // defensive code : check slave_read_timestamp and the right bounded // of frozen_memstore when releasing memstore (20660486) } else if (cur_readable_info_.max_readable_ts_ <= memtable->get_snapshot_version()) { // rebuild scenario maybe exists // ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "unexpected slave read timestamp or frozen memstore snapshot version", K_(cur_readable_info), K(*memtable)); } else { // do nothing } memtables_[idx] = NULL; ++memtable_head_; } } return OB_SUCCESS; } bool ObPGMemtableMgr::has_memtable() { TCRLockGuard lock_guard(lock_); return get_memtable_count_() > 0; } int64_t ObPGMemtableMgr::get_memtable_count() const { TCRLockGuard lock_guard(lock_); return get_memtable_count_(); } int ObPGMemtableMgr::get_first_frozen_memtable(ObTableHandle& handle) { int ret = OB_SUCCESS; memtable::ObMemtable* memtable = NULL; TCRLockGuard guard(lock_); if (OB_ISNULL(memtable = get_first_frozen_memtable_())) { // do nothing } else if (OB_FAIL(handle.set_table(memtable))) { STORAGE_LOG(WARN, "failed to set table", K(ret)); } return ret; } int ObPGMemtableMgr::freeze_and_add_memtable_( const common::ObReplicaType& replica_type, memtable::ObMemtable* memtable, const bool emergency) { int ret = OB_SUCCESS; ObMemtable* old_memtable = NULL; ObTimeGuard timeguard("freeze and add memtable", 100L * 1000L); if (OB_ISNULL(memtable)) { ret = OB_INVALID_ARGUMENT; STORAGE_LOG(WARN, "invalid argument", K(ret), KP(memtable)); } else if (!ObReplicaTypeCheck::is_replica_with_memstore(replica_type)) { ret = OB_STATE_NOT_MATCH; STORAGE_LOG(WARN, "replica without memstore, cannot freeze memtable", K(ret)); } else if (get_memtable_count_() >= MAX_MEMSTORE_CNT) { ret = OB_SIZE_OVERFLOW; STORAGE_LOG(WARN, "memtable count is too much, cannot add more", K(ret), K(get_memtable_count_())); } else if (OB_UNLIKELY(NULL == (old_memtable = get_active_memtable_()))) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(ERROR, "no active memtable found", KP(old_memtable)); } else { if (OB_FAIL(wait_old_memtable_release_())) { STORAGE_LOG(WARN, "failed to wait_old_memtable_release", K(ret)); } timeguard.click(); if (OB_SUCC(ret) && OB_FAIL(freeze_active_memtable_(memtable->get_start_log_ts(), memtable->get_base_version(), emergency))) { STORAGE_LOG(WARN, "failed to freeze active memtable", K(ret)); } timeguard.click(); if (OB_SUCC(ret)) { memtable->inc_timestamp(old_memtable->get_timestamp()); memtable->set_max_schema_version(old_memtable->get_max_schema_version()); if (OB_FAIL(add_memtable_(memtable))) { STORAGE_LOG(ERROR, "failed to do add memtable", K(ret), K(*memtable)); ob_abort(); } } } return ret; } int ObPGMemtableMgr::freeze_active_memtable_(int64_t freeze_log_ts, int64_t snapshot_version, const bool emergency) { int ret = OB_SUCCESS; memtable::ObMemtable* frozen_memtable = get_active_memtable_(); if (OB_UNLIKELY(NULL == frozen_memtable || !frozen_memtable->is_active_memtable())) { ret = OB_CANCELED; STORAGE_LOG(WARN, "frozen memtable not found", K(ret)); } else if (OB_FAIL(frozen_memtable->minor_freeze(emergency))) { STORAGE_LOG(WARN, "memtable minor freeze failed", K(ret), K(*frozen_memtable)); } else if (ObVersionRange::MAX_VERSION != frozen_memtable->get_snapshot_version()) { ret = OB_STATE_NOT_MATCH; LOG_ERROR("memtable cannot frozen twice", K(ret), K(snapshot_version), K(*frozen_memtable)); } else if (OB_FAIL(frozen_memtable->set_snapshot_version(snapshot_version))) { LOG_ERROR("failed to set snapshot version", K(ret), K(*frozen_memtable)); } else if (OB_FAIL(frozen_memtable->set_end_log_ts(freeze_log_ts))) { LOG_ERROR("failed to set end_log_ts", K(ret), K(*frozen_memtable), K(freeze_log_ts)); } else if (OB_FAIL(frozen_memtable->update_max_log_ts(freeze_log_ts))) { LOG_ERROR("failed to update max log id", K(ret), K(*frozen_memtable), K(freeze_log_ts)); } return ret; } int ObPGMemtableMgr::wait_old_memtable_release_() { int ret = OB_SUCCESS; const int64_t SLEEP_US = 100; int64_t begin_time = common::ObTimeUtility::current_time(); memtable::ObMemtable* old_memtable = get_active_memtable_(); if (OB_UNLIKELY(NULL == old_memtable)) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(ERROR, "no active memtable found", KP(old_memtable)); } else { old_memtable->set_write_barrier(); MEM_BARRIER(); // need sequential consistency here while (old_memtable->get_write_ref() > 0) { if (REACH_TIME_INTERVAL(1 * 1000 * 1000)) { ObTaskController::get().allow_next_syslog(); STORAGE_LOG( WARN, "wait old memstore release cost too long", "time", ObTimeUtility::current_time() - begin_time); } usleep(SLEEP_US); } } return ret; } int ObPGMemtableMgr::save_frozen_base_storage_info_(const ObSavedStorageInfoV2& info) { int ret = OB_SUCCESS; ObTableHandle handle; memtable::ObMemtable* memtable = NULL; if (OB_ISNULL(memtable = get_active_memtable_())) { ret = OB_ACTIVE_MEMTBALE_NOT_EXSIT; STORAGE_LOG(WARN, "active memtable must not null", K(ret), K(get_memtable_count_())); } else if (OB_FAIL(memtable->save_base_storage_info(info))) { STORAGE_LOG(WARN, "failed to save base store info", K(ret)); } else { STORAGE_LOG(INFO, "succeed to save base store info", K(info)); } return ret; } memtable::ObMemtable* ObPGMemtableMgr::get_active_memtable_() { memtable::ObMemtable* memtable = NULL; if (memtable_tail_ > memtable_head_) { memtable = memtables_[get_memtable_idx_(memtable_tail_ - 1)]; if (NULL != memtable && !memtable->is_active_memtable()) { memtable = NULL; } } return memtable; } memtable::ObMemtable* ObPGMemtableMgr::get_memtable_(const int64_t pos) const { return memtables_[get_memtable_idx_(pos)]; } OB_INLINE int64_t ObPGMemtableMgr::get_memtable_idx_(const int64_t pos) const { return pos & (MAX_MEMSTORE_CNT - 1); } int64_t ObPGMemtableMgr::get_memtable_count_() const { return memtable_tail_ - memtable_head_; } int64_t ObPGMemtableMgr::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) { STORAGE_LOG(ERROR, "memtable must not null"); } else if (0 == memtable->get_minor_merged_time()) { cnt++; } } return cnt; } int ObPGMemtableMgr::add_memtable_(memtable::ObMemtable* memtable) { int ret = OB_SUCCESS; if (OB_ISNULL(memtable)) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "memtable is null, unexpected error", K(ret), KP(memtable)); } else { const int64_t idx = get_memtable_idx_(memtable_tail_); memtable_tail_++; memtables_[idx] = memtable; memtable->inc_ref(); ObTaskController::get().allow_next_syslog(); // TODO check if table continues and if has duplicates STORAGE_LOG(INFO, "succeed to add memtable", K(memtable_head_), K(memtable_tail_), K(get_memtable_count_()), K(*memtable), KP(memtable), K(lbt())); } return ret; } int ObPGMemtableMgr::get_memtables_( ObTablesHandle& 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 ObPGMemtableMgr::add_tables_(const int64_t start_pos, const bool include_active_memtable, ObTablesHandle& 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) { memtable::ObMemtable* memtable = get_memtable_(pos); if (OB_ISNULL(memtable)) { ret = OB_ERR_SYS; STORAGE_LOG(ERROR, "memtable must not null", K(ret)); } else if (OB_FAIL(handle.add_table(memtable))) { STORAGE_LOG(WARN, "failed to add memtable", K(ret)); } } if (OB_SUCC(ret) && memtable_tail_ > memtable_head_) { ObMemtable* last_memtable = get_memtable_(last_pos); if (include_active_memtable || last_memtable->is_frozen_memtable()) { if (OB_FAIL(handle.add_table(last_memtable))) { LOG_WARN("failed to add last memtable to handle", K(ret), K(start_pos), K(include_active_memtable), K(*last_memtable)); } } } } return ret; } int ObPGMemtableMgr::push_reference_tables(const ObTablesHandle& ref_memtables) { int ret = OB_SUCCESS; ObTablesHandle current_memtables; { TCWLockGuard lock_guard(lock_); if (OB_FAIL(get_memtables_nolock(current_memtables))) { LOG_WARN("failed to get memtables nolock", K(ret)); } else if (OB_FAIL(current_memtables.add_tables(ref_memtables))) { LOG_WARN("failed to add tables", K(ret)); } else { for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) { ObMemtable* memtable = get_memtable_(i); memtable->dec_ref(); } memtable_tail_ = memtable_head_ = 0; for (int64_t i = 0; OB_SUCC(ret) && i < current_memtables.get_count(); ++i) { ObMemtable* memtable = static_cast(current_memtables.get_table(i)); if (OB_FAIL(add_memtable_(memtable))) { LOG_WARN("failed to add memtable", K(ret), K(current_memtables), K(i)); } } if (OB_SUCC(ret)) { if (current_memtables.get_count() == 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition should have at least one memtable", K(ret)); } else { ObTableStore::ObITableSnapshotVersionCompare cmp(ret); std::sort(&memtables_[0], &memtables_[memtable_tail_], cmp); if (OB_FAIL(ret)) { LOG_WARN("failed to sort memtables", K(ret)); } } } } } if (OB_FAIL(ret)) { // private method should not call publich method, otherwise K(*this) maybe deadlock; LOG_WARN("push refrence tables error", K(ret), K(*this)); } return ret; } int ObPGMemtableMgr::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 ObPGMemtableMgr::to_string(char* buf, const int64_t buf_len) const { int64_t pos = 0; if (OB_ISNULL(buf) || buf_len <= 0) { } else { TCRLockGuard 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(), "version", memtable->get_version(), "ref", memtable->get_ref()); J_OBJ_END(); J_COMMA(); } } J_ARRAY_END(); J_OBJ_END(); } return pos; } int ObPGMemtableMgr::update_readable_info(const ObPartitionReadableInfo& readable_info) { int ret = OB_SUCCESS; if (readable_info.force_ || readable_info.max_readable_ts_ >= cur_readable_info_.max_readable_ts_) { last_readable_info_ = cur_readable_info_; cur_readable_info_ = readable_info; const int64_t cur_time = ObTimeUtility::current_time(); if (cur_time > last_print_readable_info_ts_ + PRINT_READABLE_INFO_DURATION_US) { STORAGE_LOG(TRACE, "update_readable_info", K_(pkey), K(readable_info)); last_print_readable_info_ts_ = cur_time; } } else { STORAGE_LOG(ERROR, "min slave read timestamp is smaller than the last, unexpected error", K_(pkey), K(cur_readable_info_), K(readable_info), K(last_readable_info_)); } return ret; } int ObPGMemtableMgr::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_log_ts() == start_log_ts) { if (memtable->get_snapshot_version() > start_snapshot_version) { start_pos = i; break; } } else if (memtable->get_end_log_ts() > start_log_ts) { start_pos = i; break; } } return ret; } int ObPGMemtableMgr::get_memtables_v2(ObTablesHandle& 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; TCRLockGuard 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; } memtable::ObMemtable* ObPGMemtableMgr::get_first_frozen_memtable_() { int ret = OB_SUCCESS; memtable::ObMemtable* memtable = NULL; for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; i++) { memtable = get_memtable_(i); if (NULL == memtable) { ret = OB_ERR_SYS; STORAGE_LOG(ERROR, "memtable must not null", K(ret)); } else { if (memtable->is_frozen_memtable()) { break; } else { memtable = NULL; } } } return memtable; } } // namespace storage } // namespace oceanbase