1782 lines
60 KiB
C++
1782 lines
60 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/ls/ob_freezer.h"
|
|
#include "share/ob_force_print_log.h"
|
|
#include "storage/ls/ob_ls_tx_service.h"
|
|
#include "storage/checkpoint/ob_data_checkpoint.h"
|
|
#include "storage/memtable/ob_memtable.h"
|
|
#include "storage/ls/ob_ls_tablet_service.h"
|
|
#include "storage/tablet/ob_tablet.h"
|
|
#include "storage/tablet/ob_tablet_iterator.h"
|
|
#include "storage/tx/ob_trans_service.h"
|
|
#include "storage/compaction/ob_compaction_diagnose.h"
|
|
#include "logservice/ob_log_service.h"
|
|
#include "storage/ls/ob_ls.h"
|
|
#include "storage/tx_storage/ob_tenant_freezer.h"
|
|
#include "common/ob_tablet_id.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace logservice;
|
|
using namespace share;
|
|
using namespace compaction;
|
|
namespace storage
|
|
{
|
|
ObFrozenMemtableInfo::ObFrozenMemtableInfo()
|
|
: tablet_id_(),
|
|
start_scn_(share::ObScnRange::MIN_SCN),
|
|
end_scn_(share::ObScnRange::MIN_SCN),
|
|
write_ref_cnt_(0),
|
|
unsubmitted_cnt_(0),
|
|
unsynced_cnt_(0),
|
|
current_right_boundary_(0)
|
|
{}
|
|
|
|
ObFrozenMemtableInfo::ObFrozenMemtableInfo(const ObTabletID &tablet_id,
|
|
const SCN &start_scn,
|
|
const SCN &end_scn,
|
|
const int64_t write_ref_cnt,
|
|
const int64_t unsubmitted_cnt,
|
|
const int64_t unsynced_cnt,
|
|
const int64_t current_right_boundary)
|
|
: tablet_id_(tablet_id),
|
|
start_scn_(start_scn),
|
|
end_scn_(end_scn),
|
|
write_ref_cnt_(write_ref_cnt),
|
|
unsubmitted_cnt_(unsubmitted_cnt),
|
|
unsynced_cnt_(unsynced_cnt),
|
|
current_right_boundary_(current_right_boundary)
|
|
{}
|
|
|
|
ObFrozenMemtableInfo::~ObFrozenMemtableInfo()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void ObFrozenMemtableInfo::reset()
|
|
{
|
|
tablet_id_.reset();
|
|
start_scn_ = share::ObScnRange::MIN_SCN;
|
|
end_scn_ = share::ObScnRange::MIN_SCN;
|
|
write_ref_cnt_ = 0;
|
|
unsubmitted_cnt_ = 0;
|
|
unsynced_cnt_ = 0;
|
|
current_right_boundary_ = 0;
|
|
}
|
|
|
|
void ObFrozenMemtableInfo::set(const ObTabletID &tablet_id,
|
|
const SCN &start_scn,
|
|
const SCN &end_scn,
|
|
const int64_t write_ref_cnt,
|
|
const int64_t unsubmitted_cnt,
|
|
const int64_t unsynced_cnt,
|
|
const int64_t current_right_boundary)
|
|
{
|
|
tablet_id_ = tablet_id;
|
|
start_scn_ = start_scn;
|
|
end_scn_ = end_scn;
|
|
write_ref_cnt_ = write_ref_cnt;
|
|
unsubmitted_cnt_ = unsubmitted_cnt;
|
|
unsynced_cnt_ = unsynced_cnt;
|
|
current_right_boundary_ = current_right_boundary;
|
|
}
|
|
|
|
bool ObFrozenMemtableInfo::is_valid()
|
|
{
|
|
return tablet_id_.is_valid() && start_scn_ > share::ObScnRange::MIN_SCN && end_scn_ > share::ObScnRange::MIN_SCN;
|
|
}
|
|
|
|
ObFreezerStat::ObFreezerStat()
|
|
: tablet_id_(),
|
|
is_force_(false),
|
|
state_(ObFreezeState::INVALID),
|
|
freeze_clock_(0),
|
|
start_time_(0),
|
|
end_time_(INT64_MAX),
|
|
ret_code_(-1),
|
|
freeze_snapshot_version_(),
|
|
diagnose_info_(),
|
|
memtables_info_(),
|
|
lock_()
|
|
{}
|
|
|
|
ObFreezerStat::~ObFreezerStat()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void ObFreezerStat::reset()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
tablet_id_.reset();
|
|
is_force_ = false;
|
|
state_ = ObFreezeState::INVALID;
|
|
freeze_clock_ = 0;
|
|
start_time_ = 0;
|
|
end_time_ = INT64_MAX;
|
|
ret_code_ = -1;
|
|
freeze_snapshot_version_.reset();
|
|
diagnose_info_.reset();
|
|
memtables_info_.reset();
|
|
}
|
|
|
|
bool ObFreezerStat::is_valid()
|
|
{
|
|
return get_start_time() > 0 && get_state() > ObFreezeState::INVALID;
|
|
}
|
|
|
|
int ObFreezerStat::add_memtable_info(const ObTabletID &tablet_id,
|
|
const SCN &start_scn,
|
|
const SCN &end_scn,
|
|
const int64_t write_ref_cnt,
|
|
const int64_t unsubmitted_cnt,
|
|
const int64_t unsynced_cnt,
|
|
const int64_t current_right_boundary)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSpinLockGuard guard(lock_);
|
|
if (memtables_info_.count() < FROZEN_MEMTABLE_INFO_CNT) {
|
|
ObFrozenMemtableInfo memtable_info(tablet_id,
|
|
start_scn,
|
|
end_scn,
|
|
write_ref_cnt,
|
|
unsubmitted_cnt,
|
|
unsynced_cnt,
|
|
current_right_boundary);
|
|
if (OB_FAIL(memtables_info_.push_back(memtable_info))) {
|
|
TRANS_LOG(WARN, "fail to push_back memtable_info", K(ret), K(tablet_id));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::remove_memtable_info(const ObTabletID &tablet_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSpinLockGuard guard(lock_);
|
|
for (int i = 0; i < memtables_info_.count(); ++i) {
|
|
if (tablet_id == memtables_info_[i].tablet_id_ && OB_FAIL(memtables_info_.remove(i))) {
|
|
TRANS_LOG(WARN, "fail to remove from memtable_info", K(ret), K(tablet_id));
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::get_memtables_info(common::ObSArray<ObFrozenMemtableInfo> &memtables_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSpinLockGuard guard(lock_);
|
|
if (OB_FAIL(memtables_info.assign(memtables_info_))) {
|
|
TRANS_LOG(WARN, "fail to assign", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::set_memtables_info(const common::ObSArray<ObFrozenMemtableInfo> &memtables_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSpinLockGuard guard(lock_);
|
|
if (OB_FAIL(memtables_info_.assign(memtables_info))) {
|
|
TRANS_LOG(WARN, "fail to assign", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::add_diagnose_info(const ObString &str)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSpinLockGuard guard(lock_);
|
|
if (OB_FAIL(diagnose_info_.assign(str))) {
|
|
TRANS_LOG(WARN, "fail to add diagnose_info");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::get_diagnose_info(ObStringHolder &diagnose_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSpinLockGuard guard(lock_);
|
|
if (OB_FAIL(diagnose_info.assign(diagnose_info_))) {
|
|
TRANS_LOG(WARN, "fail to assign diagnose_info", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezerStat::set_freeze_clock(const int64_t freeze_clock)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
freeze_clock_ = freeze_clock;
|
|
}
|
|
|
|
int64_t ObFreezerStat::get_freeze_clock()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return freeze_clock_;
|
|
}
|
|
|
|
void ObFreezerStat::set_tablet_id(const ObTabletID &tablet_id)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
tablet_id_ = tablet_id;
|
|
}
|
|
|
|
ObTabletID ObFreezerStat::get_tablet_id()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return tablet_id_;
|
|
}
|
|
|
|
void ObFreezerStat::set_is_force(bool is_force)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
is_force_ = is_force;
|
|
}
|
|
|
|
bool ObFreezerStat::get_is_force()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return is_force_;
|
|
}
|
|
|
|
void ObFreezerStat::set_state(int state)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
state_ = state;
|
|
}
|
|
|
|
int ObFreezerStat::get_state()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return state_;
|
|
}
|
|
|
|
void ObFreezerStat::set_start_time(int64_t start_time)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
start_time_ = start_time;
|
|
}
|
|
|
|
int64_t ObFreezerStat::get_start_time()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return start_time_;
|
|
}
|
|
|
|
void ObFreezerStat::set_end_time(int64_t end_time)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
end_time_ = end_time;
|
|
}
|
|
|
|
int64_t ObFreezerStat::get_end_time()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return end_time_;
|
|
}
|
|
|
|
void ObFreezerStat::set_ret_code(int ret_code)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
ret_code_ = ret_code;
|
|
}
|
|
|
|
int ObFreezerStat::get_ret_code()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return ret_code_;
|
|
}
|
|
|
|
void ObFreezerStat::set_freeze_snapshot_version(const share::SCN &freeze_snapshot_version)
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
freeze_snapshot_version_ = freeze_snapshot_version;
|
|
}
|
|
|
|
share::SCN ObFreezerStat::get_freeze_snapshot_version()
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
return freeze_snapshot_version_;
|
|
}
|
|
|
|
int ObFreezerStat::deep_copy_to(ObFreezerStat &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
other.reset();
|
|
ObSpinLockGuard guard(lock_);
|
|
other.set_tablet_id(tablet_id_);
|
|
other.set_is_force(is_force_);
|
|
other.set_state(state_);
|
|
other.set_freeze_clock(freeze_clock_);
|
|
other.set_start_time(start_time_);
|
|
other.set_end_time(end_time_);
|
|
other.set_ret_code(ret_code_);
|
|
other.set_freeze_snapshot_version(freeze_snapshot_version_);
|
|
if (OB_FAIL(other.add_diagnose_info(diagnose_info_.get_ob_string()))) {
|
|
TRANS_LOG(WARN, "fail to add diagnose_info", K(ret));
|
|
} else if (OB_FAIL(other.set_memtables_info(memtables_info_))) {
|
|
TRANS_LOG(WARN, "fail to set memtables_info", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::begin_set_freeze_stat(const int64_t freeze_clock,
|
|
const int64_t start_time,
|
|
const int state,
|
|
const share::SCN &freeze_snapshot_version,
|
|
const ObTabletID &tablet_id,
|
|
const bool is_force)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(lock_);
|
|
|
|
freeze_clock_ = freeze_clock;
|
|
start_time_ = start_time;
|
|
state_ = state;
|
|
freeze_snapshot_version_ = freeze_snapshot_version;
|
|
tablet_id_ = tablet_id;
|
|
is_force_ = is_force;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezerStat::end_set_freeze_stat(const int state,
|
|
const int64_t end_time,
|
|
const int ret_code)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSpinLockGuard guard(lock_);
|
|
|
|
state_ = state;
|
|
end_time_ = end_time;
|
|
ret_code_ = ret_code;
|
|
|
|
return ret;
|
|
}
|
|
|
|
ObFreezer::ObFreezer()
|
|
: freeze_flag_(0),
|
|
freeze_snapshot_version_(),
|
|
max_decided_scn_(),
|
|
ls_(nullptr),
|
|
stat_(),
|
|
empty_memtable_cnt_(0),
|
|
high_priority_freeze_cnt_(0),
|
|
low_priority_freeze_cnt_(0),
|
|
need_resubmit_log_(false),
|
|
enable_(true),
|
|
is_inited_(false)
|
|
{}
|
|
|
|
ObFreezer::ObFreezer(ObLS *ls)
|
|
: freeze_flag_(0),
|
|
freeze_snapshot_version_(),
|
|
max_decided_scn_(),
|
|
ls_(ls),
|
|
stat_(),
|
|
empty_memtable_cnt_(0),
|
|
high_priority_freeze_cnt_(0),
|
|
low_priority_freeze_cnt_(0),
|
|
need_resubmit_log_(false),
|
|
enable_(true),
|
|
is_inited_(false)
|
|
{}
|
|
|
|
ObFreezer::~ObFreezer()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void ObFreezer::reset()
|
|
{
|
|
freeze_flag_ = 0;
|
|
freeze_snapshot_version_.reset();
|
|
max_decided_scn_.reset();
|
|
ls_ = nullptr;
|
|
stat_.reset();
|
|
empty_memtable_cnt_ = 0;
|
|
high_priority_freeze_cnt_ = 0;
|
|
low_priority_freeze_cnt_ = 0;
|
|
need_resubmit_log_ = false;
|
|
enable_ = true;
|
|
is_inited_ = false;
|
|
}
|
|
|
|
int ObFreezer::init(ObLS *ls)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_ISNULL(ls)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
TRANS_LOG(WARN, "[Freezer] invalid argument", K(ret));
|
|
} else {
|
|
freeze_flag_ = 0;
|
|
freeze_snapshot_version_.reset();
|
|
max_decided_scn_.reset();
|
|
ls_ = ls;
|
|
stat_.reset();
|
|
empty_memtable_cnt_ = 0;
|
|
high_priority_freeze_cnt_ = 0;
|
|
low_priority_freeze_cnt_ = 0;
|
|
need_resubmit_log_ = false;
|
|
enable_ = true;
|
|
|
|
is_inited_ = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* ls info */
|
|
share::ObLSID ObFreezer::get_ls_id()
|
|
{
|
|
return OB_ISNULL(ls_) ? INVALID_LS : ls_->get_ls_id();
|
|
}
|
|
|
|
checkpoint::ObDataCheckpoint* ObFreezer::get_ls_data_checkpoint()
|
|
{
|
|
return OB_ISNULL(ls_) ? nullptr : ls_->get_data_checkpoint();
|
|
}
|
|
|
|
ObLSTxService* ObFreezer::get_ls_tx_svr()
|
|
{
|
|
return OB_ISNULL(ls_) ? nullptr : ls_->get_tx_svr();
|
|
}
|
|
|
|
ObLSTabletService* ObFreezer::get_ls_tablet_svr()
|
|
{
|
|
return OB_ISNULL(ls_) ? nullptr : ls_->get_tablet_svr();
|
|
}
|
|
|
|
logservice::ObILogHandler* ObFreezer::get_ls_log_handler()
|
|
{
|
|
return OB_ISNULL(ls_) ? nullptr : ls_->get_log_handler();
|
|
}
|
|
|
|
ObLSWRSHandler* ObFreezer::get_ls_wrs_handler()
|
|
{
|
|
return OB_ISNULL(ls_) ? nullptr : ls_->get_ls_wrs_handler();
|
|
}
|
|
|
|
/* logstream freeze */
|
|
int ObFreezer::logstream_freeze(ObFuture<int> *result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
SCN freeze_snapshot_version;
|
|
SCN max_decided_scn;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
FLOG_INFO("[Freezer] logstream_freeze start", K(ret), K(ls_id));
|
|
int64_t start_time = ObTimeUtility::current_time();
|
|
|
|
ObLSFreezeGuard guard(*this);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] not inited", K(ret), K(ls_id));
|
|
} else if (OB_UNLIKELY(!enable_)) {
|
|
ret = OB_NOT_RUNNING;
|
|
LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(decide_max_decided_scn(max_decided_scn))) {
|
|
TRANS_LOG(WARN, "[Freezer] decide max decided log ts failure", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) {
|
|
TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id));
|
|
} else if (ObScnRange::MAX_SCN == freeze_snapshot_version
|
|
|| ObScnRange::MIN_SCN >= freeze_snapshot_version) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id), K(freeze_snapshot_version));
|
|
} else if (OB_FAIL(set_freeze_flag())) {
|
|
FLOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id));
|
|
} else if (FALSE_IT(max_decided_scn_ = max_decided_scn)) {
|
|
} else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) {
|
|
} else if (FALSE_IT(set_need_resubmit_log(false))) {
|
|
} else if (FALSE_IT(stat_.reset())) {
|
|
} else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(),
|
|
start_time,
|
|
ObFreezeState::NOT_SUBMIT_LOG,
|
|
freeze_snapshot_version,
|
|
ObTabletID(ObTabletID::INVALID_TABLET_ID),
|
|
false/*is_force*/))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(inner_logstream_freeze(result))) {
|
|
TRANS_LOG(WARN, "[Freezer] logstream_freeze failure", K(ret), K(ls_id));
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
undo_freeze_();
|
|
}
|
|
|
|
print_freezer_statistics();
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::inner_logstream_freeze(ObFuture<int> *result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTableHandleV2 handle;
|
|
|
|
if (FALSE_IT(submit_checkpoint_task())) {
|
|
} else if (FALSE_IT(submit_log_for_freeze())) {
|
|
} else if (OB_FAIL(submit_freeze_task(true/*is_ls_freeze*/, result, handle))) {
|
|
TRANS_LOG(ERROR, "failed to submit ls_freeze task", K(ret), K(ls_id));
|
|
stat_.add_diagnose_info("fail to submit ls_freeze_task");
|
|
ob_abort();
|
|
} else {
|
|
TRANS_LOG(INFO, "[Freezer] succeed to start ls_freeze_task", K(ret), K(ls_id));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezer::submit_checkpoint_task()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
do {
|
|
if (OB_FAIL(get_ls_data_checkpoint()->ls_freeze(SCN::max_scn()))) {
|
|
TRANS_LOG(WARN, "[Freezer] data_checkpoint freeze failed", K(ret));
|
|
stat_.add_diagnose_info("data_checkpoint freeze failed");
|
|
ob_usleep(100);
|
|
}
|
|
} while (OB_FAIL(ret));
|
|
}
|
|
|
|
int ObFreezer::ls_freeze_task()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
uint32_t freeze_clock = get_freeze_clock();
|
|
TRANS_LOG(INFO, "[Freezer] freeze_clock", K(ls_id), K(freeze_clock));
|
|
|
|
// wait till all memtables are moved from frozen_list to prepare_list
|
|
// this means that all memtables can be dumped
|
|
while (!get_ls_data_checkpoint()->ls_freeze_finished()) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 5 * 1000 * 1000) {
|
|
if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) {
|
|
if (need_resubmit_log()) {
|
|
int64_t read_lock = LSLOCKALL - LSLOCKLOGMETA;
|
|
int64_t write_lock = 0;
|
|
ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock);
|
|
if (OB_FAIL(check_ls_state())) {
|
|
} else {
|
|
submit_log_for_freeze();
|
|
TRANS_LOG(INFO, "[Freezer] resubmit log for ls_freeze", K(ls_id), K(cost_time));
|
|
}
|
|
}
|
|
TRANS_LOG_RET(WARN, OB_ERR_TOO_MUCH_TIME, "[Freezer] finish ls_freeze costs too much time",
|
|
K(ls_id), K(cost_time));
|
|
stat_.add_diagnose_info("finish ls_freeze costs too much time");
|
|
}
|
|
}
|
|
ob_usleep(100);
|
|
}
|
|
stat_.add_diagnose_info("logstream_freeze success");
|
|
FLOG_INFO("[Freezer] logstream_freeze success", K(ls_id), K(freeze_clock));
|
|
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
|
|
unset_freeze_();
|
|
|
|
return ret;
|
|
}
|
|
|
|
// must be used under the protection of ls_lock
|
|
int ObFreezer::check_ls_state()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(ls_->is_stopped_)) {
|
|
ret = OB_NOT_RUNNING;
|
|
STORAGE_LOG(WARN, "ls stopped", K(ret), K_(ls_->ls_meta));
|
|
} else if (OB_UNLIKELY(!(ls_->get_log_handler()->is_replay_enabled()))) {
|
|
ret = OB_NOT_RUNNING;
|
|
STORAGE_LOG(WARN, "log handler not enable replay, should not freeze", K(ret), K_(ls_->ls_meta));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* tablet freeze */
|
|
int ObFreezer::tablet_freeze(const ObTabletID &tablet_id, ObFuture<int> *result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
|
|
if (tablet_id.is_ls_inner_tablet()) {
|
|
if (OB_FAIL(freeze_ls_inner_tablet_(tablet_id))) {
|
|
TRANS_LOG(WARN, "freeze ls inner tablet failed", KR(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
} else if (OB_FAIL(freeze_normal_tablet_(tablet_id, result))) {
|
|
TRANS_LOG(WARN, "freeze normal tablet failed", KR(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::freeze_normal_tablet_(const ObTabletID &tablet_id, ObFuture<int> *result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTabletHandle handle;
|
|
ObTablet *tablet = nullptr;
|
|
ObTabletMemtableMgr *memtable_mgr = nullptr;
|
|
ObTableHandleV2 frozen_memtable_handle;
|
|
SCN freeze_snapshot_version;
|
|
FLOG_INFO("[Freezer] tablet_freeze start", K(ret), K(ls_id), K(tablet_id));
|
|
int64_t start_time = ObTimeUtility::current_time();
|
|
|
|
ObTabletFreezeGuard guard(*this, true /* try guard */);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_UNLIKELY(!enable_)) {
|
|
ret = OB_NOT_RUNNING;
|
|
LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) {
|
|
// no need freeze now, a ls freeze is running or will be running
|
|
ret = OB_SUCCESS;
|
|
LOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(set_freeze_flag_without_inc_freeze_clock())) {
|
|
LOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
// succeed to set freeze flag
|
|
if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) {
|
|
TRANS_LOG(WARN, "[Freezer] get ls weak read scn failure", K(ret), K(ls_id));
|
|
} else if (ObScnRange::MAX_SCN == freeze_snapshot_version
|
|
|| ObScnRange::MIN_SCN >= freeze_snapshot_version) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id));
|
|
} else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) {
|
|
} else if (FALSE_IT(set_need_resubmit_log(false))) {
|
|
} else if (FALSE_IT(stat_.reset())) {
|
|
} else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(),
|
|
start_time,
|
|
ObFreezeState::NOT_SUBMIT_LOG,
|
|
freeze_snapshot_version,
|
|
tablet_id,
|
|
false/*is_force*/))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id,
|
|
handle, 0,
|
|
ObMDSGetTabletMode::READ_WITHOUT_CHECK))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to get tablet");
|
|
} else if (FALSE_IT(tablet = handle.get_obj())) {
|
|
} else if (OB_ISNULL(memtable_mgr = static_cast<ObTabletMemtableMgr*>(tablet->get_memtable_mgr()))) {
|
|
TRANS_LOG(WARN, "[Freezer] tablet_memtable_mgr is null", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(memtable_mgr->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) {
|
|
if (ret == OB_ENTRY_NOT_EXIST) {
|
|
ret = OB_SUCCESS;
|
|
TRANS_LOG(INFO, "[Freezer] no need to freeze", K(ret),
|
|
K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("no need to freeze");
|
|
} else {
|
|
TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to set is_tablet_freeze");
|
|
}
|
|
} else if (FALSE_IT(submit_log_for_freeze())) {
|
|
} else if (OB_FAIL(submit_freeze_task(false/*is_ls_freeze*/, result, frozen_memtable_handle))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to submit tablet_freeze_task", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to submit tablet_freeze_task");
|
|
} else {
|
|
TRANS_LOG(INFO, "[Freezer] succeed to start tablet_freeze_task", K(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) {
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::freeze_ls_inner_tablet_(const ObTabletID &tablet_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(get_ls_tx_svr())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "[Freezer] ls_tx_svr is unexpected nullptr", KR(ret), K(get_ls_id()), K(tablet_id));
|
|
} else if (OB_FAIL(get_ls_tx_svr()->flush_ls_inner_tablet(tablet_id))) {
|
|
TRANS_LOG(WARN, "[Freezer] freeze ls inner tablet failed", KR(ret), K(get_ls_id()), K(tablet_id));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::force_tablet_freeze(const ObTabletID &tablet_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTabletHandle handle;
|
|
ObTablet *tablet = nullptr;
|
|
ObTabletMemtableMgr *memtable_mgr = nullptr;
|
|
ObTableHandleV2 frozen_memtable_handle;
|
|
SCN freeze_snapshot_version;
|
|
FLOG_INFO("[Freezer] force_tablet_freeze start", K(ret), K(ls_id), K(tablet_id));
|
|
int64_t start_time = ObTimeUtility::current_time();
|
|
|
|
ObTabletFreezeGuard guard(*this);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_UNLIKELY(!enable_)) {
|
|
ret = OB_NOT_RUNNING;
|
|
LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(loop_set_freeze_flag())) {
|
|
TRANS_LOG(WARN, "[Freezer] failed to set freeze_flag", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
// succeed to set freeze flag
|
|
if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) {
|
|
TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id));
|
|
} else if (ObScnRange::MAX_SCN == freeze_snapshot_version
|
|
|| ObScnRange::MIN_SCN >= freeze_snapshot_version) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id));
|
|
} else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) {
|
|
} else if (FALSE_IT(set_need_resubmit_log(false))) {
|
|
} else if (FALSE_IT(stat_.reset())) {
|
|
} else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(),
|
|
start_time,
|
|
ObFreezeState::NOT_SUBMIT_LOG,
|
|
freeze_snapshot_version,
|
|
tablet_id,
|
|
true/*is_force*/))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id,
|
|
handle, 0,
|
|
ObMDSGetTabletMode::READ_WITHOUT_CHECK))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get tablet for freeze", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to get tablet");
|
|
} else if (FALSE_IT(tablet = handle.get_obj())) {
|
|
} else if (OB_FAIL(create_memtable_if_no_active_memtable(tablet))) {
|
|
if (OB_NO_NEED_UPDATE == ret) {
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
LOG_WARN("[Freezer] fail to create an active memtable for force_tablet_freeze", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to create an active memtable for force_tablet_freeze");
|
|
}
|
|
} else if (OB_ISNULL(memtable_mgr = static_cast<ObTabletMemtableMgr*>(tablet->get_memtable_mgr()))) {
|
|
TRANS_LOG(WARN, "[Freezer] tablet_memtable_mgr is null", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(memtable_mgr->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle, true))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to set is_tablet_freeze");
|
|
} else if (FALSE_IT(submit_log_for_freeze())) {
|
|
} else if (OB_FAIL(submit_freeze_task(false/*is_ls_freeze*/, nullptr, frozen_memtable_handle))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to submit freeze_task", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to submit freeze_task");
|
|
} else {
|
|
TRANS_LOG(INFO, "[Freezer] succeed to start force_tablet_freeze_task", K(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) {
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::tablet_freeze_task(ObTableHandleV2 handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
memtable::ObIMemtable *imemtable = nullptr;
|
|
memtable::ObMemtable *memtable = nullptr;
|
|
|
|
if (!handle.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "memtable cannot be null", K(ret), K(ls_id));
|
|
} else {
|
|
// succeed to set freeze_flag
|
|
if (OB_FAIL(handle.get_memtable(imemtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret));
|
|
} else if (FALSE_IT(memtable = static_cast<memtable::ObMemtable*>(imemtable))) {
|
|
} else if (OB_FAIL(wait_memtable_ready_for_flush_with_ls_lock(memtable))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to wait memtable ready_for_flush", K(ret), K(ls_id));
|
|
} else {
|
|
int64_t read_lock = LSLOCKALL - LSLOCKLOGMETA;
|
|
int64_t write_lock = 0;
|
|
ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock);
|
|
if (OB_FAIL(check_ls_state())) {
|
|
} else if (OB_FAIL(memtable->finish_freeze())) {
|
|
TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed",
|
|
K(ret), K(ls_id), KPC(memtable));
|
|
stat_.add_diagnose_info("memtable cannot be flushed");
|
|
} else {
|
|
stat_.add_diagnose_info("tablet_freeze success");
|
|
FLOG_INFO("[Freezer] tablet_freeze_task success", K(ret), K(ls_id), KPC(memtable));
|
|
}
|
|
}
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable *memtable)
|
|
{
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
int ret = OB_SUCCESS;
|
|
bool ready_for_flush = false;
|
|
|
|
do {
|
|
if (OB_FAIL(try_wait_memtable_ready_for_flush_with_ls_lock(memtable, ready_for_flush, start))) {
|
|
TRANS_LOG(WARN, "[Freezer] memtable is not ready_for_flush", K(ret));
|
|
}
|
|
} while (OB_SUCC(ret) && !ready_for_flush);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::try_wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable *memtable, bool &ready_for_flush, const int64_t start)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t read_lock = LSLOCKALL - LSLOCKLOGMETA;
|
|
int64_t write_lock = 0;
|
|
ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock);
|
|
|
|
if (OB_FAIL(check_ls_state())) {
|
|
} else if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "[Freezer] memtable cannot be null", K(ret));
|
|
} else if (FALSE_IT(ready_for_flush = memtable->ready_for_flush())) {
|
|
} else if (!ready_for_flush) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 5 * 1000 * 1000) {
|
|
if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) {
|
|
if (need_resubmit_log()) {
|
|
submit_log_for_freeze();
|
|
TRANS_LOG(INFO, "[Freezer] resubmit log", K(cost_time));
|
|
}
|
|
TRANS_LOG(WARN, "[Freezer] ready_for_flush costs too much time",
|
|
K(cost_time), KPC(memtable));
|
|
stat_.add_diagnose_info("ready_for_flush costs too much time");
|
|
}
|
|
}
|
|
ob_usleep(100);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::tablet_freeze_for_replace_tablet_meta(const ObTabletID &tablet_id, ObTableHandleV2 &frozen_memtable_handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTabletHandle handle;
|
|
ObTablet *tablet = nullptr;
|
|
ObTabletMemtableMgr *memtable_mgr = nullptr;
|
|
SCN freeze_snapshot_version;
|
|
FLOG_INFO("[Freezer] tablet_freeze_for_replace_tablet_meta start", K(ret), K(ls_id), K(tablet_id));
|
|
int64_t start_time = ObTimeUtility::current_time();
|
|
|
|
ObTabletFreezeGuard guard(*this, true /* try guard */);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_UNLIKELY(!enable_)) {
|
|
ret = OB_NOT_RUNNING;
|
|
LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) {
|
|
// no need freeze now, a ls freeze is running or will be running
|
|
FLOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(loop_set_freeze_flag())) {
|
|
FLOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
// succeed to set freeze flag
|
|
if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) {
|
|
TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id));
|
|
} else if (freeze_snapshot_version.is_max()
|
|
|| !freeze_snapshot_version.is_valid_and_not_min()) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id));
|
|
} else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) {
|
|
} else if (FALSE_IT(set_need_resubmit_log(false))) {
|
|
} else if (FALSE_IT(stat_.reset())) {
|
|
} else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(),
|
|
start_time,
|
|
ObFreezeState::NOT_SUBMIT_LOG,
|
|
freeze_snapshot_version,
|
|
tablet_id,
|
|
false/*is_force*/))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id,
|
|
handle, 0,
|
|
ObMDSGetTabletMode::READ_WITHOUT_CHECK))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to get tablet");
|
|
} else if (FALSE_IT(tablet = handle.get_obj())) {
|
|
} else if (OB_ISNULL(memtable_mgr = static_cast<ObTabletMemtableMgr*>(tablet->get_memtable_mgr()))) {
|
|
TRANS_LOG(WARN, "[Freezer] tablet_memtable_mgr is null", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(memtable_mgr->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) {
|
|
if (ret == OB_ENTRY_NOT_EXIST) {
|
|
ret = OB_SUCCESS;
|
|
TRANS_LOG(INFO, "[Freezer] no need to freeze", K(ret),
|
|
K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("no need to freeze");
|
|
} else {
|
|
TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to set is_tablet_freeze");
|
|
}
|
|
}
|
|
if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) {
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// must ensure that call tablet_freeze_for_replace_tablet_meta() successfully before calling the func
|
|
int ObFreezer::handle_frozen_memtable_for_replace_tablet_meta(const ObTabletID &tablet_id, ObTableHandleV2 &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
memtable::ObIMemtable *imemtable = nullptr;
|
|
|
|
if (!handle.is_valid()) {
|
|
ret = OB_SUCCESS;
|
|
FLOG_INFO("[Freezer] no need to tablet_freeze_for_replace_tablet_meta", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
// succeed to set freeze flag
|
|
if (OB_FAIL(handle.get_memtable(imemtable))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get memtable", K(ret));
|
|
} else if (OB_FAIL(handle_memtable_for_tablet_freeze(imemtable))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to handle memtable", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
stat_.add_diagnose_info("tablet_freeze_for_replace_tablet_meta success");
|
|
FLOG_INFO("[Freezer] tablet_freeze_for_replace_tablet_meta success", K(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::batch_tablet_freeze(const ObIArray<ObTabletID> &tablet_ids, ObFuture<int> *result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
SCN freeze_snapshot_version;
|
|
FLOG_INFO("[Freezer] batch_tablet_freeze start", K(ret), K(ls_id), K(tablet_ids));
|
|
int64_t start_time = ObTimeUtility::current_time();
|
|
bool need_freeze = true;
|
|
|
|
ObTabletFreezeGuard guard(*this, true /* try guard */);
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_ids));
|
|
} else if (OB_UNLIKELY(!enable_)) {
|
|
LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) {
|
|
// no need freeze now, a ls freeze is running or will be running
|
|
ret = OB_SUCCESS;
|
|
FLOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K(ls_id), K(tablet_ids));
|
|
} else if (OB_FAIL(loop_set_freeze_flag())) {
|
|
ret = OB_SUCCESS;
|
|
FLOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id), K(tablet_ids));
|
|
} else {
|
|
// succeed to set freeze flag
|
|
if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) {
|
|
TRANS_LOG(WARN, "[Freezer] get ls weak read scn failure", K(ret), K(ls_id));
|
|
} else if (ObScnRange::MAX_SCN == freeze_snapshot_version
|
|
|| ObScnRange::MIN_SCN >= freeze_snapshot_version) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id));
|
|
} else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) {
|
|
} else if (FALSE_IT(set_need_resubmit_log(false))) {
|
|
} else if (FALSE_IT(stat_.reset())) {
|
|
} else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(),
|
|
start_time,
|
|
ObFreezeState::NOT_SUBMIT_LOG,
|
|
freeze_snapshot_version,
|
|
ObTabletID(ObTabletID::INVALID_TABLET_ID),
|
|
false/*is_force*/))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(batch_tablet_freeze_(tablet_ids, result, need_freeze))) {
|
|
TRANS_LOG(WARN, "[Freezer] batch_tablet_freeze failed", K(ret), K(ls_id), K(tablet_ids));
|
|
}
|
|
if (OB_FAIL(ret) || !need_freeze) {
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::batch_tablet_freeze_(const ObIArray<ObTabletID> &tablet_ids, ObFuture<int> *result, bool &need_freeze)
|
|
{
|
|
// succeed to set freeze flag
|
|
int ret = OB_SUCCESS;
|
|
ObTableHandleArray memtable_handles;
|
|
need_freeze= true;
|
|
|
|
for (int i = 0; i < tablet_ids.count() && OB_SUCC(ret); ++i) {
|
|
const ObTabletID &tablet_id = tablet_ids.at(i);
|
|
ObTabletHandle handle;
|
|
ObTablet *tablet = nullptr;
|
|
ObTableHandleV2 frozen_memtable_handle;
|
|
ObTabletMemtableMgr *memtable_mgr = nullptr;
|
|
if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id,
|
|
handle,
|
|
ObTabletCommon::DEFAULT_GET_TABLET_NO_WAIT,
|
|
ObMDSGetTabletMode::READ_WITHOUT_CHECK))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to get tablet");
|
|
} else if (FALSE_IT(tablet = handle.get_obj())) {
|
|
} else if (OB_ISNULL(memtable_mgr = static_cast<ObTabletMemtableMgr*>(tablet->get_memtable_mgr()))) {
|
|
TRANS_LOG(WARN, "[Freezer] tablet_memtable_mgr is null", K(ret), K(tablet_id));
|
|
} else if (OB_FAIL(memtable_mgr->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) {
|
|
if (ret == OB_ENTRY_NOT_EXIST) {
|
|
ret = OB_SUCCESS;
|
|
TRANS_LOG(INFO, "[Freezer] no need to freeze since there is no active memtable", K(ret),
|
|
K(tablet_id));
|
|
stat_.add_diagnose_info("no need to freeze since there is no active memtable");
|
|
} else {
|
|
TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to set is_tablet_freeze");
|
|
}
|
|
} else if (!frozen_memtable_handle.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "[Freezer] frozen_memtable_handle is invalid", K(ret), K(tablet_id));
|
|
stat_.add_diagnose_info("frozen_memtable_handle is invalid");
|
|
} else if (OB_FAIL(memtable_handles.push_back(frozen_memtable_handle))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to push_back", K(ret), K(tablet_id));
|
|
stat_.add_diagnose_info("fail to push_back");
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (0 == memtable_handles.count()) {
|
|
need_freeze = false;
|
|
TRANS_LOG(INFO, "[Freezer] no need to freeze batch tablets", K(ret), K(tablet_ids));
|
|
stat_.add_diagnose_info("no need to freeze batch tablets");
|
|
} else if (FALSE_IT(submit_log_for_freeze())) {
|
|
} else if (OB_FAIL(submit_batch_tablet_freeze_task(memtable_handles, result))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to submit batch_tablet_freeze task", K(ret));
|
|
} else {
|
|
TRANS_LOG(INFO, "[Freezer] succeed to start batch_tablet_freeze task", K(ret), K(tablet_ids));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::submit_batch_tablet_freeze_task(const ObTableHandleArray &tables_array, ObFuture<int> *result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObTenantFreezer *tenant_freezer = nullptr;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
|
|
if (OB_ISNULL(tenant_freezer = MTL(storage::ObTenantFreezer*))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "ObTenantFreezer is null", K(ret), K(ls_id));
|
|
} else {
|
|
ObSpinLockGuard freeze_thread_pool(tenant_freezer->freeze_thread_pool_lock_);
|
|
do {
|
|
if (OB_ISNULL(result)) {
|
|
ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret([this, tables_array]() {
|
|
return batch_tablet_freeze_task(tables_array); });
|
|
} else {
|
|
ret = tenant_freezer->freeze_thread_pool_.commit_task(*result,
|
|
[this, tables_array]() { return batch_tablet_freeze_task(tables_array); });
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 100 * 1000) {
|
|
if (TC_REACH_TIME_INTERVAL(100 * 1000)) {
|
|
TRANS_LOG(WARN, "[Freezer] failed to start freeze_task", K(ret), K(ls_id));
|
|
}
|
|
}
|
|
}
|
|
} while (OB_FAIL(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::batch_tablet_freeze_task(ObTableHandleArray tables_array)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
|
|
while (OB_SUCC(ret) && tables_array.count() > 0) {
|
|
for (int i = 0; OB_SUCC(ret) && i < tables_array.count(); ++i) {
|
|
ObTableHandleV2 &handle = tables_array.at(i);
|
|
memtable::ObIMemtable *imemtable = nullptr;
|
|
memtable::ObMemtable *memtable = nullptr;
|
|
bool ready_for_flush = false;
|
|
if (!handle.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "memtable cannot be null", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(handle.get_memtable(imemtable))) {
|
|
LOG_WARN("fail to get memtable", K(ret));
|
|
} else if (FALSE_IT(memtable = static_cast<memtable::ObMemtable*>(imemtable))) {
|
|
} else if (OB_FAIL(try_wait_memtable_ready_for_flush_with_ls_lock(memtable, ready_for_flush, start))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to wait memtable ready_for_flush", K(ret), K(ls_id));
|
|
} else if (!ready_for_flush) {
|
|
} else if (OB_FAIL(finish_freeze_with_ls_lock(memtable))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to finish_freeze", K(ret), K(ls_id), KPC(memtable));
|
|
} else if (OB_FAIL(tables_array.pop_back(handle))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to pop_back", K(ret), K(ls_id), K(handle), KPC(memtable));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
TRANS_LOG(INFO, "[Freezer] batch_tablet_freeze success", K(ret), K(ls_id));
|
|
}
|
|
|
|
stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret);
|
|
print_freezer_statistics();
|
|
unset_freeze_();
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::finish_freeze_with_ls_lock(memtable::ObMemtable *memtable)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
int64_t read_lock = LSLOCKALL - LSLOCKLOGMETA;
|
|
int64_t write_lock = 0;
|
|
ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock);
|
|
|
|
if (OB_FAIL(check_ls_state())) {
|
|
} else if (OB_ISNULL(memtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "[Freezer] memtable cannot be null", K(ret));
|
|
} else if (OB_FAIL(memtable->finish_freeze())) {
|
|
TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed",
|
|
K(ret), K(ls_id), KPC(memtable));
|
|
stat_.add_diagnose_info("memtable cannot be flushed");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
/* private subfunctions for freeze process */
|
|
int ObFreezer::handle_memtable_for_tablet_freeze(memtable::ObIMemtable *imemtable)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
|
|
if (OB_ISNULL(imemtable)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
} else {
|
|
memtable::ObMemtable *memtable = static_cast<memtable::ObMemtable*>(imemtable);
|
|
submit_log_for_freeze();
|
|
wait_memtable_ready_for_flush(memtable);
|
|
if (OB_FAIL(memtable->finish_freeze())) {
|
|
TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed",
|
|
K(ret), K(ls_id), K(*memtable));
|
|
stat_.add_diagnose_info("memtable cannot be flushed");
|
|
} else {
|
|
TRANS_LOG(INFO, "[Freezer] memtable is ready to be flushed",
|
|
K(ret), K(ls_id), K(*memtable));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::submit_log_for_freeze()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
ObTabletID tablet_id(INT64_MAX); // used for diagnose
|
|
|
|
do {
|
|
ret = OB_SUCCESS;
|
|
transaction::ObTransID fail_tx_id;
|
|
|
|
if (OB_FAIL(get_ls_tx_svr()->traverse_trans_to_submit_redo_log(fail_tx_id))) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 1000 * 1000) {
|
|
if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) {
|
|
TRANS_LOG(WARN, "[Freezer] failed to traverse trans ctx to submit redo log", K(ret),
|
|
K(ls_id), K(cost_time), K(fail_tx_id));
|
|
stat_.add_diagnose_info("traverse_trans_to_submit_redo_log failed");
|
|
int tmp_ret = OB_SUCCESS;
|
|
if (OB_TMP_FAIL(ADD_SUSPECT_INFO(MINI_MERGE,
|
|
ls_id, tablet_id, ObSuspectInfoType::SUSPECT_SUBMIT_LOG_FOR_FREEZE,
|
|
static_cast<int64_t>(ret), fail_tx_id.get_id()))) {
|
|
TRANS_LOG(WARN, "failed to add suspect info", K(tmp_ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_LOG_OUTOF_DISK_SPACE == ret) {
|
|
ob_usleep(100 * 1000);
|
|
}
|
|
} while (OB_FAIL(ret));
|
|
DEL_SUSPECT_INFO(MINI_MERGE, ls_id, tablet_id);
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(get_ls_tx_svr()->traverse_trans_to_submit_next_log())) {
|
|
TRANS_LOG(WARN, "traverse trans ctx to submit next log failed", K(ret));
|
|
}
|
|
}
|
|
|
|
stat_.set_state(ObFreezeState::WAIT_READY_FOR_FLUSH);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::submit_freeze_task(const bool is_ls_freeze, ObFuture<int> *result, ObTableHandleV2 &handle)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObTenantFreezer *tenant_freezer = nullptr;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
|
|
if (OB_ISNULL(tenant_freezer = MTL(storage::ObTenantFreezer*))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "ObTenantFreezer is null", K(ret), K(ls_id));
|
|
} else {
|
|
ObSpinLockGuard freeze_thread_pool(tenant_freezer->freeze_thread_pool_lock_);
|
|
do {
|
|
if (OB_ISNULL(result)) {
|
|
if (is_ls_freeze) {
|
|
ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret([this]() {
|
|
return ls_freeze_task(); });
|
|
} else {
|
|
ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret([this, handle]() {
|
|
return tablet_freeze_task(handle); });
|
|
}
|
|
} else {
|
|
if (is_ls_freeze) {
|
|
ret = tenant_freezer->freeze_thread_pool_.commit_task(*result,
|
|
[this]() { return ls_freeze_task(); });
|
|
} else {
|
|
ret = tenant_freezer->freeze_thread_pool_.commit_task(*result,
|
|
[this, handle]() { return tablet_freeze_task(handle); });
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 100 * 1000) {
|
|
if (TC_REACH_TIME_INTERVAL(100 * 1000)) {
|
|
TRANS_LOG(WARN, "[Freezer] failed to start freeze_task", K(ret), K(ls_id), K(is_ls_freeze));
|
|
}
|
|
}
|
|
}
|
|
} while (OB_FAIL(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::wait_freeze_finished(ObFuture<int> &result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (result.is_valid()) {
|
|
share::ObLSID ls_id = get_ls_id();
|
|
int *ret_code = nullptr;
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
result.get(ret_code);
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
ret = OB_ISNULL(ret_code) ? OB_ERR_UNEXPECTED : *ret_code;
|
|
|
|
if (OB_FAIL(ret)) {
|
|
TRANS_LOG(WARN, "failed to freeze", K(ret), K(cost_time), K(ls_id));
|
|
} else if (cost_time > 3 * 1000 * 1000) {
|
|
TRANS_LOG(WARN, "waiting ready_for_flush costs too much time", K(ret), K(cost_time), K(ls_id));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezer::wait_memtable_ready_for_flush(memtable::ObMemtable *memtable)
|
|
{
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
int ret = OB_SUCCESS;
|
|
|
|
while (!memtable->ready_for_flush()) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 5 * 1000 * 1000) {
|
|
if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) {
|
|
if (need_resubmit_log()) {
|
|
submit_log_for_freeze();
|
|
TRANS_LOG(INFO, "[Freezer] resubmit log for tablet_freeze", K(ls_id), K(cost_time));
|
|
}
|
|
TRANS_LOG_RET(WARN, OB_ERR_TOO_MUCH_TIME, "[Freezer] ready_for_flush costs too much time",
|
|
K(ls_id), K(cost_time), KPC(memtable));
|
|
stat_.add_diagnose_info("ready_for_flush costs too much time");
|
|
memtable->print_ready_for_flush();
|
|
}
|
|
}
|
|
ob_usleep(100);
|
|
}
|
|
}
|
|
|
|
int ObFreezer::create_memtable_if_no_active_memtable(ObTablet *tablet)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTabletMemtableMgr *memtable_mgr = nullptr;
|
|
ObTableHandleV2 last_frozen_memtable_handle;
|
|
memtable::ObMemtable *last_frozen_memtable = nullptr;
|
|
const common::ObTabletID &tablet_id = tablet->get_tablet_meta().tablet_id_;
|
|
SCN clog_checkpoint_scn = tablet->get_tablet_meta().clog_checkpoint_scn_;
|
|
int64_t schema_version = 0;
|
|
SCN max_callbacked_scn = SCN::min_scn();
|
|
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] not inited", K(ret), K_(is_inited), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(get_max_consequent_callbacked_scn(max_callbacked_scn))) {
|
|
LOG_WARN("[Freezer] fail to get max_consequent_callbacked_scn", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (max_callbacked_scn < clog_checkpoint_scn) {
|
|
ret = OB_NO_NEED_UPDATE;
|
|
LOG_WARN("[Freezer] cannot create memtable because max_callbacked_scn < clog_checkpoint_scn", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_ISNULL(memtable_mgr = static_cast<ObTabletMemtableMgr *>(tablet->get_memtable_mgr()))) {
|
|
LOG_WARN("[Freezer] memtable mgr should not be null", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (memtable_mgr->has_active_memtable()) {
|
|
LOG_INFO("[Freezer] no need to create an active memtable", K(ret), K(ls_id), K(tablet_id));
|
|
} else { // create a new memtable since there is no active memtable
|
|
// get schema_version
|
|
if (OB_FAIL(memtable_mgr->get_last_frozen_memtable(last_frozen_memtable_handle))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("[Freezer] fail to get last frozen memtable", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
} else if (last_frozen_memtable_handle.get_data_memtable(last_frozen_memtable)) {
|
|
LOG_WARN("[Freezer] fail to get memtable", K(ret), K(ls_id), K(tablet_id));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_NOT_NULL(last_frozen_memtable)) {
|
|
schema_version = last_frozen_memtable->get_max_schema_version();
|
|
} else {
|
|
schema_version = tablet->get_tablet_meta().max_sync_storage_schema_version_;
|
|
//do nothing
|
|
}
|
|
// create new memtable
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(get_ls_tablet_svr()->create_memtable(tablet_id, schema_version))) {
|
|
if (OB_MINOR_FREEZE_NOT_ALLOW != ret) {
|
|
LOG_WARN("[Freezer] failed to create memtable", K(ret), K(ls_id), K(tablet_id),
|
|
K(schema_version));
|
|
}
|
|
} else {
|
|
LOG_INFO("[Freezer] succeed to create new active memtable", K(ret), K(ls_id),
|
|
K(tablet_id), K(schema_version));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* private subfunctions about freeze flag*/
|
|
int ObFreezer::loop_set_freeze_flag()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
const int64_t start = ObTimeUtility::current_time();
|
|
|
|
do {
|
|
ret = OB_SUCCESS;
|
|
if (OB_FAIL(set_freeze_flag_without_inc_freeze_clock())) {
|
|
const int64_t cost_time = ObTimeUtility::current_time() - start;
|
|
if (cost_time > 10 * 1000 * 1000) {
|
|
TRANS_LOG(WARN, "[Freezer] wait the running freeze too long time", K(ls_id),
|
|
K(cost_time));
|
|
break;
|
|
}
|
|
ob_usleep(100);
|
|
}
|
|
} while (OB_FAIL(ret));
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::set_freeze_flag_without_inc_freeze_clock()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
uint32_t old_v = 0;
|
|
uint32_t new_v = 0;
|
|
|
|
do {
|
|
old_v = ATOMIC_LOAD(&freeze_flag_);
|
|
if (is_freeze(old_v)) {
|
|
ret = OB_EAGAIN;
|
|
break;
|
|
}
|
|
new_v = old_v | (1 << 31);
|
|
} while (ATOMIC_CAS(&freeze_flag_, old_v, new_v) != old_v);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::set_freeze_flag()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
uint32_t old_v = 0;
|
|
uint32_t new_v = 0;
|
|
|
|
// set freeze_flag to flag the start of freeze
|
|
// set the first bit 1
|
|
// inc the freeze clock
|
|
do {
|
|
old_v = ATOMIC_LOAD(&freeze_flag_);
|
|
if (is_freeze(old_v)) {
|
|
ret = OB_EAGAIN;
|
|
TRANS_LOG(WARN, "[Freezer] freeze is running!", K(ret), K(ls_id));
|
|
break;
|
|
}
|
|
new_v = (old_v + 1) | (1 << 31);
|
|
} while (ATOMIC_CAS(&freeze_flag_, old_v, new_v) != old_v);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::inc_freeze_clock()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
uint32_t old_v = 0;
|
|
uint32_t new_v = 0;
|
|
|
|
// inc freeze_clock when freeze_flag has been set
|
|
// before used by force_freeze to resolve concurrency problems
|
|
do {
|
|
old_v = ATOMIC_LOAD(&freeze_flag_);
|
|
if (!is_freeze(old_v)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
TRANS_LOG(WARN, "[Freezer] cannot inc freeze clock without setting freeze flag!",
|
|
K(ret), K(ls_id));
|
|
break;
|
|
}
|
|
new_v = old_v + 1;
|
|
} while (ATOMIC_CAS(&freeze_flag_, old_v, new_v) != old_v);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezer::unset_freeze_()
|
|
{
|
|
uint32_t old_v;
|
|
uint32_t new_v;
|
|
|
|
// Step1: unset freeze_snapshot_version to invalid value
|
|
freeze_snapshot_version_.reset();
|
|
|
|
// Step2: unset max_decided_scn to invalid value
|
|
max_decided_scn_.reset();
|
|
|
|
// Step3: unset need_resubmit_log_
|
|
set_need_resubmit_log(false);
|
|
|
|
// Step4: unset freeze_flag to flag the end of freeze
|
|
// set the first bit 0
|
|
do {
|
|
old_v = ATOMIC_LOAD(&freeze_flag_);
|
|
new_v = old_v & (~(1 << 31));
|
|
} while (ATOMIC_CAS(&freeze_flag_, old_v, new_v) != old_v);
|
|
}
|
|
|
|
void ObFreezer::undo_freeze_()
|
|
{
|
|
uint32_t old_v;
|
|
uint32_t new_v;
|
|
|
|
// Step1: unset freeze_snapshot_version to invalid value
|
|
freeze_snapshot_version_.reset();
|
|
|
|
// Step2: unset max_decided_scn to invalid value
|
|
max_decided_scn_.reset();
|
|
|
|
// Step3: unset need_resubmit_log_
|
|
set_need_resubmit_log(false);
|
|
|
|
// Step4: unset freeze_flag and dec freeze_clock
|
|
// used when freeze fails
|
|
do {
|
|
old_v = ATOMIC_LOAD(&freeze_flag_);
|
|
new_v = (old_v - 1) & (~(1 << 31));
|
|
} while (ATOMIC_CAS(&freeze_flag_, old_v, new_v) != old_v);
|
|
}
|
|
|
|
/* public function about freeze_flag */
|
|
bool ObFreezer::is_freeze(uint32_t freeze_flag) const
|
|
{
|
|
if (freeze_flag == UINT32_MAX) {
|
|
freeze_flag = (ATOMIC_LOAD(&freeze_flag_));
|
|
}
|
|
return 1 == (freeze_flag >> 31);
|
|
}
|
|
|
|
/* other public functions */
|
|
int ObFreezer::decide_max_decided_scn(SCN &max_decided_scn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] not inited", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(get_ls_log_handler()->get_max_decided_scn(max_decided_scn))) {
|
|
if (OB_STATE_NOT_MATCH == ret) {
|
|
max_decided_scn.reset();
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get max_decided_scn", K(ret), K(ls_id),
|
|
K(max_decided_scn));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
TRANS_LOG(TRACE, "[Freezer] decide max decided log ts", K(ret), K(ls_id), K(max_decided_scn));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::get_max_consequent_callbacked_scn(SCN &max_consequent_callbacked_scn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("[Freezer] not inited", K(ret), K(ls_id));
|
|
} else if (OB_FAIL(get_ls_log_handler()->get_max_decided_scn(max_consequent_callbacked_scn))) {
|
|
if (OB_STATE_NOT_MATCH == ret) {
|
|
max_consequent_callbacked_scn.set_min();
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get min_unreplay_scn", K(ret), K(ls_id), K(max_consequent_callbacked_scn));
|
|
}
|
|
} else {
|
|
TRANS_LOG(TRACE, "[Freezer] get_max_decided_scn", K(ret), K(ls_id), K(max_consequent_callbacked_scn));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::get_ls_weak_read_scn(SCN &weak_read_scn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
weak_read_scn.reset();
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret));
|
|
} else {
|
|
weak_read_scn = get_ls_wrs_handler()->get_ls_weak_read_ts();
|
|
TRANS_LOG(TRACE, "[Freezer] get_ls_weak_read_scn", K(ret), K(ls_id), K(weak_read_scn));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::get_newest_clog_checkpoint_scn(const ObTabletID &tablet_id,
|
|
SCN &clog_checkpoint_scn)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTabletHandle handle;
|
|
clog_checkpoint_scn.reset();
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret));
|
|
} else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id,
|
|
handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
clog_checkpoint_scn = handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_;
|
|
TRANS_LOG(TRACE, "[Freezer] get_newest_clog_checkpoint_scn", K(ret), K(ls_id), K(tablet_id),
|
|
K(clog_checkpoint_scn));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezer::get_newest_snapshot_version(const ObTabletID &tablet_id,
|
|
SCN &snapshot_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::ObLSID ls_id = get_ls_id();
|
|
ObTabletHandle handle;
|
|
snapshot_version.reset();
|
|
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
TRANS_LOG(WARN, "[Freezer] not inited", K(ret));
|
|
} else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id,
|
|
handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(ls_id), K(tablet_id));
|
|
} else if (OB_FAIL(snapshot_version.convert_for_tx(handle.get_obj()->get_snapshot_version()))) {
|
|
TRANS_LOG(WARN, "[Freezer] fail to convert from ts", K(ret), K(ls_id), K(tablet_id));
|
|
} else {
|
|
TRANS_LOG(TRACE, "[Freezer] get_snapshot_version", K(ret), K(ls_id), K(tablet_id), K(snapshot_version));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezer::inc_empty_memtable_cnt()
|
|
{
|
|
ATOMIC_INC(&empty_memtable_cnt_);
|
|
}
|
|
|
|
void ObFreezer::clear_empty_memtable_cnt()
|
|
{
|
|
ATOMIC_STORE(&empty_memtable_cnt_, 0);
|
|
}
|
|
|
|
int64_t ObFreezer::get_empty_memtable_cnt()
|
|
{
|
|
return empty_memtable_cnt_;
|
|
}
|
|
|
|
void ObFreezer::print_freezer_statistics()
|
|
{
|
|
// print every 10s
|
|
if (REACH_TIME_INTERVAL(10 * 1000 * 1000)) {
|
|
TRANS_LOG(INFO, "[Freezer] empty table statistics: ", K(get_ls_id()), K(get_empty_memtable_cnt()));
|
|
clear_empty_memtable_cnt();
|
|
}
|
|
}
|
|
|
|
int ObFreezer::try_set_tablet_freeze_begin_()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (ATOMIC_LOAD(&high_priority_freeze_cnt_) != 0) {
|
|
// high priority freeze waiting now, can not do tablet freeze now.
|
|
ret = OB_EAGAIN;
|
|
} else {
|
|
ATOMIC_INC(&low_priority_freeze_cnt_);
|
|
// double check
|
|
if (ATOMIC_LOAD(&high_priority_freeze_cnt_) != 0) {
|
|
ret = OB_EAGAIN;
|
|
ATOMIC_DEC(&low_priority_freeze_cnt_);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezer::set_tablet_freeze_begin_()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t SLEEP_INTERVAL = 100 * 1000; // 100 ms
|
|
int64_t retry_times = 0;
|
|
while (OB_FAIL(try_set_tablet_freeze_begin_())) {
|
|
retry_times++;
|
|
ob_usleep(SLEEP_INTERVAL);
|
|
if (retry_times % 100 == 0) { // 10 s
|
|
LOG_WARN_RET(OB_ERR_TOO_MUCH_TIME, "wait high priority freeze finish cost too much time",
|
|
K(ret), K(high_priority_freeze_cnt_), K(retry_times));
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObFreezer::set_tablet_freeze_end_()
|
|
{
|
|
ATOMIC_DEC(&low_priority_freeze_cnt_);
|
|
}
|
|
|
|
void ObFreezer::set_ls_freeze_begin_()
|
|
{
|
|
const int64_t SLEEP_INTERVAL = 100 * 1000; // 100 ms
|
|
int64_t retry_times = 0;
|
|
ATOMIC_INC(&high_priority_freeze_cnt_);
|
|
while (ATOMIC_LOAD(&low_priority_freeze_cnt_) != 0) {
|
|
retry_times++;
|
|
ob_usleep(SLEEP_INTERVAL);
|
|
if (retry_times % 100 == 0) { // 10 s
|
|
LOG_WARN_RET(OB_ERR_UNEXPECTED, "wait low priority freeze finish cost too much time",
|
|
K(low_priority_freeze_cnt_), K(retry_times));
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObFreezer::set_ls_freeze_end_()
|
|
{
|
|
ATOMIC_DEC(&high_priority_freeze_cnt_);
|
|
}
|
|
|
|
ObFreezer::ObLSFreezeGuard::ObLSFreezeGuard(ObFreezer &parent)
|
|
: parent_(parent)
|
|
{
|
|
parent_.set_ls_freeze_begin_();
|
|
}
|
|
|
|
ObFreezer::ObLSFreezeGuard::~ObLSFreezeGuard()
|
|
{
|
|
parent_.set_ls_freeze_end_();
|
|
}
|
|
|
|
ObFreezer::ObTabletFreezeGuard::ObTabletFreezeGuard(ObFreezer &parent, const bool try_guard)
|
|
: need_release_(!try_guard),
|
|
parent_(parent)
|
|
{
|
|
if (!try_guard) {
|
|
parent_.set_tablet_freeze_begin_();
|
|
}
|
|
}
|
|
|
|
ObFreezer::ObTabletFreezeGuard::~ObTabletFreezeGuard()
|
|
{
|
|
if (need_release_) {
|
|
parent_.set_tablet_freeze_end_();
|
|
}
|
|
}
|
|
|
|
int ObFreezer::ObTabletFreezeGuard::try_set_tablet_freeze_begin()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (need_release_) {
|
|
// this is not a try guard or has try succeed, just return success.
|
|
} else if (OB_FAIL(parent_.try_set_tablet_freeze_begin_())) {
|
|
LOG_WARN("try set tablet freeze failed", K(ret));
|
|
} else {
|
|
need_release_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace storage
|
|
} // namespace oceanbase
|