dup table new gc method

This commit is contained in:
Minionyh
2023-08-17 12:15:37 +00:00
committed by ob-robot
parent cac1b6f7f1
commit cffbba7518
4 changed files with 404 additions and 34 deletions

View File

@ -550,6 +550,7 @@ void ObDupTableLogOperator::reset()
int ObDupTableLogOperator::submit_log_entry() int ObDupTableLogOperator::submit_log_entry()
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
SpinWLockGuard guard(log_lock_); SpinWLockGuard guard(log_lock_);
@ -559,6 +560,9 @@ int ObDupTableLogOperator::submit_log_entry()
bool submit_result = false; bool submit_result = false;
DupLogTypeArray type_array; DupLogTypeArray type_array;
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
if (OB_TMP_FAIL(tablet_mgr_ptr_->scan_readable_set_for_gc())) {
DUP_TABLE_LOG(WARN, "scan readable set failed", K(tmp_ret));
}
if (OB_FAIL(prepare_serialize_log_entry_(max_ser_size, type_array))) { if (OB_FAIL(prepare_serialize_log_entry_(max_ser_size, type_array))) {
DUP_TABLE_LOG(WARN, "prepare serialize log entry failed", K(ret)); DUP_TABLE_LOG(WARN, "prepare serialize log entry failed", K(ret));
} else if (!type_array.empty()) { } else if (!type_array.empty()) {

View File

@ -741,7 +741,7 @@ public:
bool need_block_confirming() const { return DUP_SPECIAL_OP_BLOCK_CONFIRMING == sp_op_type_; } bool need_block_confirming() const { return DUP_SPECIAL_OP_BLOCK_CONFIRMING == sp_op_type_; }
// bool contain_special_op(uint64_t special_op) const { return get_special_op_() == special_op; } // bool contain_special_op(uint64_t special_op) const { return get_special_op_() == special_op; }
bool no_specail_op() const { return INVALID_SPECIAL_OP == sp_op_type_; } bool no_specail_op() const { return INVALID_SPECIAL_OP == sp_op_type_; }
void copy_tablet_set_type(const DupTabletSetCommonHeader &src_common_header) void copy_tablet_set_common_header(const DupTabletSetCommonHeader &src_common_header)
{ {
set_unique_id_(src_common_header.get_unique_id()); set_unique_id_(src_common_header.get_unique_id());
set_special_op_(src_common_header.get_special_op()); set_special_op_(src_common_header.get_special_op());

View File

@ -32,6 +32,7 @@ const int64_t ObLSDupTabletsMgr::GC_TIMEOUT = 1 * 1000 * 1000L; // 1s
const int64_t ObLSDupTabletsMgr::RESERVED_FREE_SET_COUNT = 64; const int64_t ObLSDupTabletsMgr::RESERVED_FREE_SET_COUNT = 64;
const int64_t ObLSDupTabletsMgr::MAX_FREE_SET_COUNT = 1000; const int64_t ObLSDupTabletsMgr::MAX_FREE_SET_COUNT = 1000;
const int64_t ObLSDupTabletsMgr::MAX_GC_TABLET_COUNT = 1000;
const int64_t ObLSDupTabletsMgr::MAX_CONFIRMING_TABLET_COUNT = 20000; const int64_t ObLSDupTabletsMgr::MAX_CONFIRMING_TABLET_COUNT = 20000;
OB_SERIALIZE_MEMBER(DupTabletSetCommonHeader, unique_id_, tablet_set_type_, sp_op_type_); OB_SERIALIZE_MEMBER(DupTabletSetCommonHeader, unique_id_, tablet_set_type_, sp_op_type_);
@ -90,6 +91,37 @@ bool ObLSDupTabletsMgr::GcDiscardedDupTabletHandler::operator()(
return will_remove; return will_remove;
} }
int ObLSDupTabletsMgr::GcOneReadableSetHandler::operator()(
common::hash::HashMapPair<common::ObTabletID, DupTabletInfo> &hash_pair)
{
int ret = OB_SUCCESS;
if (0 > hash_pair.second.update_dup_schema_ts_ || 0 > gc_ts_) {
ret = OB_INVALID_ARGUMENT;
DUP_TABLE_LOG_RET(WARN, ret, "invalid timestamp", K(hash_pair.first),
K(hash_pair.second.update_dup_schema_ts_), K(gc_ts_));
} else {
if ((gc_ts_ - hash_pair.second.update_dup_schema_ts_) >= tablet_gc_window_) {
if (OB_FAIL(old_tablets_.set_refactored(hash_pair.first, hash_pair.second, 1))) {
DUP_TABLE_LOG(WARN, "insert into old_tablets_ failed", K(ret),
K(hash_pair.first), K(hash_pair.second));
} else {
gc_tablet_cnt_++;
if (gc_tablet_cnt_ >= max_gc_tablet_cnt_) {
ret = OB_SIZE_OVERFLOW;
}
}
}
// for debug
DUP_TABLE_LOG(DEBUG, "try copy one tablet from readable set to old", K(ret),
K(old_tablets_), K(gc_ts_), K(hash_pair.second.update_dup_schema_ts_),
K(gc_ts_ - hash_pair.second.update_dup_schema_ts_), K(tablet_gc_window_),
K(gc_tablet_cnt_), K(max_gc_tablet_cnt_));
}
return ret;
}
int ObLSDupTabletsMgr::ConfirmedDupTabletHandler::operator()( int ObLSDupTabletsMgr::ConfirmedDupTabletHandler::operator()(
common::hash::HashMapPair<common::ObTabletID, DupTabletInfo> &hash_pair) common::hash::HashMapPair<common::ObTabletID, DupTabletInfo> &hash_pair)
{ {
@ -370,7 +402,7 @@ int ObLSDupTabletsMgr::init_free_tablet_pool_()
DUP_TABLE_LOG(WARN, "get free tablet set failed", K(ret)); DUP_TABLE_LOG(WARN, "get free tablet set failed", K(ret));
} else { } else {
removing_old_set_->get_common_header().set_old(); removing_old_set_->get_common_header().set_old();
removing_old_set_->set_related_set_type(DupTableRelatedSetType::OLD_GC); removing_old_set_->set_related_set_op_type(DupTableRelatedSetOpType::NEW_GC);
} }
DUP_TABLE_LOG(INFO, "finish init tablet map", K(ret), KPC(removing_old_set_), DUP_TABLE_LOG(INFO, "finish init tablet map", K(ret), KPC(removing_old_set_),
@ -423,6 +455,9 @@ void ObLSDupTabletsMgr::reset()
last_gc_succ_time_ = 0; last_gc_succ_time_ = 0;
last_no_free_set_time_ = 0; last_no_free_set_time_ = 0;
extra_free_set_alloc_count_ = 0; extra_free_set_alloc_count_ = 0;
tablet_gc_window_ = 2 * ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL;
gc_start_time_ = 0;
readable_set_in_gc_ = nullptr;
if (OB_NOT_NULL(tablet_set_diag_info_log_buf_)) { if (OB_NOT_NULL(tablet_set_diag_info_log_buf_)) {
ob_free(tablet_set_diag_info_log_buf_); ob_free(tablet_set_diag_info_log_buf_);
@ -642,7 +677,7 @@ int ObLSDupTabletsMgr::gc_dup_tablets(const int64_t gc_ts, const int64_t max_tas
int64_t gc_timeout = 0; int64_t gc_timeout = 0;
if ((gc_ts - last_gc_succ_time_) > GC_DUP_TABLETS_FAILED_TIMEOUT && last_gc_succ_time_ != 0) { if ((gc_ts - last_gc_succ_time_) > GC_DUP_TABLETS_FAILED_TIMEOUT && last_gc_succ_time_ != 0) {
gc_timeout = INT64_MAX; gc_timeout = INT64_MAX;
DUP_TABLE_LOG(WARN, "gc failed too much times, this time should not break", ); DUP_TABLE_LOG(WARN, "gc failed too much times, this time should not break");
} else { } else {
gc_timeout = GC_TIMEOUT; gc_timeout = GC_TIMEOUT;
} }
@ -666,7 +701,7 @@ int ObLSDupTabletsMgr::gc_dup_tablets(const int64_t gc_ts, const int64_t max_tas
ret = OB_EAGAIN; // should not update gc succ time to increase gc freq ret = OB_EAGAIN; // should not update gc succ time to increase gc freq
DUP_TABLE_LOG(INFO, "old tablet set can not be modified, skip gc readable tablets", K(ret), DUP_TABLE_LOG(INFO, "old tablet set can not be modified, skip gc readable tablets", K(ret),
KPC(old_tablet_set)); KPC(old_tablet_set));
} else if (old_tablet_set->get_related_set_type() == DupTableRelatedSetType::OLD_GC) { } else if (old_tablet_set->get_related_set_op_type() == DupTableRelatedSetOpType::OLD_GC) {
DLIST_FOREACH(readable_tablets_ptr, readable_tablets_list_) DLIST_FOREACH(readable_tablets_ptr, readable_tablets_list_)
{ {
if (readable_tablets_ptr->is_logging()) { if (readable_tablets_ptr->is_logging()) {
@ -737,6 +772,143 @@ int ObLSDupTabletsMgr::gc_dup_tablets(const int64_t gc_ts, const int64_t max_tas
return ret; return ret;
} }
DupTabletChangeMap *ObLSDupTabletsMgr::get_need_gc_set_(bool &new_round)
{
if (OB_NOT_NULL(readable_set_in_gc_)) {
if (!readable_set_in_gc_->get_common_header().is_readable_set()) {
DUP_TABLE_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "this ptr not in readable list",
KPC(removing_old_set_), KPC(readable_set_in_gc_));
readable_set_in_gc_ = nullptr;
} else {
while (OB_NOT_NULL(readable_set_in_gc_)
&& !readable_set_in_gc_->need_gc_scan(gc_start_time_)
&& readable_set_in_gc_->get_related_set_op_type() != DupTableRelatedSetOpType::INVALID // skip operated set
&& readable_set_in_gc_ != readable_tablets_list_.get_header()) {
readable_set_in_gc_ = readable_set_in_gc_->get_next();
}
if (readable_set_in_gc_ == readable_tablets_list_.get_header()) {
readable_set_in_gc_ = nullptr;
}
}
}
if (OB_ISNULL(readable_set_in_gc_)) {
if (!readable_tablets_list_.is_empty()) {
readable_set_in_gc_ = readable_tablets_list_.get_first();
new_round = true;
}
}
return readable_set_in_gc_;
}
int ObLSDupTabletsMgr::scan_readable_set_for_gc()
{
int ret = OB_SUCCESS;
DupTabletChangeMap *tmp_readable_gc_set_ptr = nullptr;
bool new_round = false;
SpinWLockGuard guard(dup_tablets_lock_);
if (OB_ISNULL(removing_old_set_)) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(WARN, "old set is nullptr", K(ret), KPC(removing_old_set_));
} else if (removing_old_set_->get_related_set_op_type() <= DupTableRelatedSetOpType::INVALID) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(WARN, "invalid related set type", K(ret), KPC(removing_old_set_));
} else if (removing_old_set_->get_related_set_op_type() == DupTableRelatedSetOpType::NEW_GC) {
if ((!removing_old_set_->empty()) ||
removing_old_set_->get_related_common_header().is_valid()) {
// old set not confimed and clear, not need scan this time
} else if (OB_ISNULL(tmp_readable_gc_set_ptr = get_need_gc_set_(new_round))) {
// get null set
} else {
int64_t cur_time = ObTimeUtility::fast_current_time();
if (new_round
|| gc_start_time_ <= 0) {
gc_start_time_ = cur_time;
}
GcOneReadableSetHandler gc_handler(cur_time, tablet_gc_window_,
*removing_old_set_, MAX_GC_TABLET_COUNT);
if (OB_FAIL(hash_for_each_update(*tmp_readable_gc_set_ptr, gc_handler))) {
DUP_TABLE_LOG(WARN, "scan readable for gc failed", K(ret), KPC(removing_old_set_),
KPC(tmp_readable_gc_set_ptr), K(cur_time), K(gc_start_time_));
if (OB_SIZE_OVERFLOW == ret) {
ret = OB_SUCCESS;
}
} else if (OB_FALSE_IT(tmp_readable_gc_set_ptr->set_last_gc_scan_ts(gc_start_time_))) {
// mark set finish scan
}
if (OB_SUCC(ret)) {
if (!removing_old_set_->empty()) {
removing_old_set_->set_related_common_header(tmp_readable_gc_set_ptr->get_common_header());
tmp_readable_gc_set_ptr->set_related_set_op_type(DupTableRelatedSetOpType::OPERATED_NEW_GC);
}
} else {
return_tablet_set_(removing_old_set_);
}
DUP_TABLE_LOG(DEBUG, "finish scan readable set", K(ret), K(gc_handler.get_gc_tablet_cnt()),
KPC(removing_old_set_), KPC(tmp_readable_gc_set_ptr), K(new_round), K(gc_start_time_));
}
}
return ret;
}
// leader and follower remove tablet from readable set after first log synced
// lock outside this func
int ObLSDupTabletsMgr::remove_tablet_from_readable_set_()
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
DupTabletChangeMap *related_readable_set = nullptr;
if (OB_ISNULL(removing_old_set_)) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(WARN, "removing_old_set_ is null", K(ret), KPC(removing_old_set_));
} else if (removing_old_set_->get_related_set_op_type() <= DupTableRelatedSetOpType::INVALID) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(WARN, "invalid related set type", K(ret), KPC(removing_old_set_));
} else if (removing_old_set_->get_related_set_op_type() == DupTableRelatedSetOpType::NEW_GC
&& removing_old_set_->get_change_status()->is_change_logging()) {
// only new_gc type need remove
if (removing_old_set_->empty()
|| (!removing_old_set_->get_related_common_header().is_valid())) {
// old set cleared, not need remove tablet
} else if (OB_FAIL(get_target_tablet_set_(removing_old_set_->get_related_common_header(),
related_readable_set))) {
DUP_TABLE_LOG(WARN, "get target readable set failed", K(ret), KPC(related_readable_set),
KPC(removing_old_set_));
if (OB_ENTRY_NOT_EXIST == ret) {
ret = OB_SUCCESS;
}
} else if (OB_NOT_NULL(related_readable_set)) {
DupTabletChangeMap::const_iterator iter = removing_old_set_->begin();
// iterate old_set and erase it form target_readable_set and ignore fail
for (; OB_SUCC(ret) && iter != removing_old_set_->end(); iter++) {
if (OB_TMP_FAIL(related_readable_set->erase_refactored(iter->first))) {
if (tmp_ret != OB_HASH_NOT_EXIST) {
ret = tmp_ret;
DUP_TABLE_LOG(WARN, "remove tablet form reabable set failed", K(ret), KPC(related_readable_set),
KPC(removing_old_set_));
}
}
}
if (OB_SUCC(ret)) {
related_readable_set->set_related_set_op_type(DupTableRelatedSetOpType::INVALID);
DUP_TABLE_LOG(INFO, "finish remove tablet from readable set", K(ret),
KPC(removing_old_set_), KPC(related_readable_set));
}
}
} else {
DUP_TABLE_LOG(WARN, "other related set op type or other status", K(ret), KPC(removing_old_set_));
}
return ret;
}
int ObLSDupTabletsMgr::refresh_dup_tablet(const common::ObTabletID &tablet_id, int ObLSDupTabletsMgr::refresh_dup_tablet(const common::ObTabletID &tablet_id,
bool is_dup_table, bool is_dup_table,
int64_t refresh_time) int64_t refresh_time)
@ -763,7 +935,7 @@ int ObLSDupTabletsMgr::refresh_dup_tablet(const common::ObTabletID &tablet_id,
} else { } else {
if (OB_NOT_NULL(removing_old_set_) if (OB_NOT_NULL(removing_old_set_)
&& removing_old_set_->get_related_set_type() == DupTableRelatedSetType::OLD_GC) { && removing_old_set_->get_related_set_op_type() == DupTableRelatedSetOpType::OLD_GC) {
if (OB_FAIL(lose_dup_tablet_(tablet_id))) { if (OB_FAIL(lose_dup_tablet_(tablet_id))) {
DUP_TABLE_LOG(WARN, "a dup tablet lose dup attr failed", K(tablet_id)); DUP_TABLE_LOG(WARN, "a dup tablet lose dup attr failed", K(tablet_id));
} }
@ -775,6 +947,103 @@ int ObLSDupTabletsMgr::refresh_dup_tablet(const common::ObTabletID &tablet_id,
return ret; return ret;
} }
int ObLSDupTabletsMgr::remove_src_and_related_set_header_from_array_(
DupTabletChangeMap *src_set,
DupTabletChangeMap *related_set,
DupTabletSetIDArray &unique_id_array)
{
int ret = OB_SUCCESS;
int64_t last_idx = unique_id_array.count() - 1;
if (last_idx < 0) {
DUP_TABLE_LOG(INFO, "array is empty, not need pop back", K(last_idx), K(unique_id_array));
} else {
int64_t i = last_idx;
int64_t loop_end_idx = unique_id_array.count() - 2;
for (; OB_SUCC(ret) && i >=0 && i >= loop_end_idx; i--) {
if (OB_NOT_NULL(src_set)
&& unique_id_array.at(i) == src_set->get_common_header()) {
if (OB_FAIL(unique_id_array.remove(i))) {
DUP_TABLE_LOG(INFO, "remove src set header from array failed", K(last_idx), K(i), K(unique_id_array),
KPC(src_set));
} else {
src_set->clean_logging();
}
} else if (OB_NOT_NULL(related_set)
&& unique_id_array.at(i) == related_set->get_common_header()) {
if (OB_FAIL(unique_id_array.remove(i))) {
DUP_TABLE_LOG(INFO, "remove related set header from array failed", K(last_idx), K(i), K(unique_id_array),
KPC(src_set));
} else {
related_set->clean_logging();
}
} else {
DUP_TABLE_LOG(INFO, "ele not match, not need pop back", KPC(src_set), KPC(related_set),
K(unique_id_array.at(i)), K(i), K(last_idx));
}
}
}
return ret;
}
int ObLSDupTabletsMgr::prepare_serialize_src_set_with_related_set_(DupTabletChangeMap *src_set,
int64_t &max_ser_size,
const int64_t max_log_buf_len,
DupTabletSetIDArray &unique_id_array,
DupTabletChangeMap *related_set) // out_param
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
if (OB_NOT_NULL(src_set)) {
if (src_set->get_related_set_op_type() <= DupTableRelatedSetOpType::INVALID) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(WARN, "invalid related set type", K(ret), KPC(src_set));
} else if (src_set->get_related_set_op_type() == DupTableRelatedSetOpType::NEW_GC) {
// prepare serialize related readable set for new gc
if (OB_FAIL(cal_single_set_max_ser_size_(src_set, max_ser_size,
max_log_buf_len, unique_id_array))) {
DUP_TABLE_LOG(WARN, "ser src set failed", K(ret), KPC(src_set), KPC(related_set));
if (OB_SIZE_OVERFLOW == ret) {
ret = OB_LOG_TOO_LARGE;
}
} else if (OB_FALSE_IT(src_set->set_logging())) {
} else if (OB_FAIL(get_target_tablet_set_(src_set->get_related_common_header(), related_set))) {
DUP_TABLE_LOG(WARN, "get related set failed", K(ret), KPC(src_set), KPC(related_set));
if (ret == OB_ENTRY_NOT_EXIST) {
// related set recycled, old set not confirmed, rewrite ret code to log old set to confirm
ret = OB_SUCCESS;
}
} else if (OB_FAIL(cal_single_set_max_ser_size_(related_set, max_ser_size,
max_log_buf_len, unique_id_array))) {
DUP_TABLE_LOG(WARN, "cal related set se size falied", K(ret), K(max_ser_size), KPC(src_set), KPC(related_set));
if (OB_SIZE_OVERFLOW == ret) {
ret = OB_LOG_TOO_LARGE;
}
} else if (OB_FALSE_IT(related_set->set_logging())) {
}
if (OB_FAIL(ret)) {
// if failed, remove ser header from array
if (OB_TMP_FAIL(remove_src_and_related_set_header_from_array_(src_set,
related_set,
unique_id_array))) {
ret = tmp_ret;
DUP_TABLE_LOG(WARN, "remove src and related header failed", K(ret), K(max_ser_size),
KPC(src_set), KPC(related_set));
}
}
}
} else {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(ERROR, "src set is null ptr", K(ret), KPC(src_set));
}
return ret;
}
int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size, int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size,
DupTabletSetIDArray &unique_id_array, DupTabletSetIDArray &unique_id_array,
const int64_t max_log_buf_len) const int64_t max_log_buf_len)
@ -851,28 +1120,25 @@ int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size,
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
DupTabletChangeMap *old_tablet_set = nullptr; DupTabletChangeMap *old_tablet_set = nullptr;
DupTabletChangeMap *related_readable_set = nullptr;
DupTabletSetCommonHeader old_tablets_header; DupTabletSetCommonHeader old_tablets_header;
old_tablets_header.set_old(); old_tablets_header.set_old();
old_tablets_header.set_invalid_unique_id(); old_tablets_header.set_invalid_unique_id();
if (OB_FAIL(get_target_tablet_set_(old_tablets_header, old_tablet_set))) { if (OB_FAIL(get_target_tablet_set_(old_tablets_header, old_tablet_set))) {
DUP_TABLE_LOG(WARN, "get old tablets failed", K(ret)); DUP_TABLE_LOG(WARN, "get old tablets failed", K(ret));
} else if (old_tablet_set->empty()) { } else if (old_tablet_set->empty()) {
// do nothing // do nothing
} else if (!old_tablet_set->get_change_status()->need_log()) { } else if (!old_tablet_set->get_change_status()->need_log()) {
DUP_TABLE_LOG(INFO, "no need serialize old tablets in log", K(ret), KPC(old_tablet_set)); DUP_TABLE_LOG(INFO, "no need serialize old tablets in log", K(ret), KPC(old_tablet_set));
} else if (OB_FAIL(cal_single_set_max_ser_size_(old_tablet_set, max_ser_size, max_log_buf_len, } else if (OB_FAIL(prepare_serialize_src_set_with_related_set_(old_tablet_set, max_ser_size,
unique_id_array))) { max_log_buf_len, unique_id_array,
DUP_TABLE_LOG(WARN, "cal old set max ser_size failed", K(ret)); related_readable_set))) {
if (OB_SIZE_OVERFLOW == ret) { DUP_TABLE_LOG(WARN, "prepare serialize related_readable_set failed", K(ret));
ret = OB_LOG_TOO_LARGE;
}
} else if (OB_FALSE_IT(old_tablet_set->set_logging())) {
// do nothing
} else if (OB_FAIL(old_tablet_set->get_change_status()->prepare_serialize())) { } else if (OB_FAIL(old_tablet_set->get_change_status()->prepare_serialize())) {
DUP_TABLE_LOG(WARN, "old set prepare serialize failed", K(ret)); DUP_TABLE_LOG(WARN, "old set prepare serialize failed", K(ret));
} else { } else {
// try confirm old tablets // try confirm old tablets
int64_t tmp_ret = OB_SUCCESS;
if (OB_TMP_FAIL(old_tablet_set->get_change_status()->try_set_confirmed(true))) { if (OB_TMP_FAIL(old_tablet_set->get_change_status()->try_set_confirmed(true))) {
if (tmp_ret != OB_EAGAIN) { if (tmp_ret != OB_EAGAIN) {
ret = tmp_ret; ret = tmp_ret;
@ -889,8 +1155,12 @@ int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size,
} else { } else {
DLIST_FOREACH(readable_ptr, readable_tablets_list_) DLIST_FOREACH(readable_ptr, readable_tablets_list_)
{ {
if (OB_FAIL(cal_single_set_max_ser_size_(readable_ptr, max_ser_size, max_log_buf_len, if (readable_ptr->is_logging()) {
unique_id_array))) { // set logging by old perpare serialize
DUP_TABLE_LOG(INFO, "this readable set is prepare serialized", K(ret),
K(readable_ptr->get_RO_common_header()));
} else if (OB_FAIL(cal_single_set_max_ser_size_(readable_ptr, max_ser_size, max_log_buf_len,
unique_id_array))) {
DUP_TABLE_LOG(WARN, "cal readable set max ser_size failed", K(ret)); DUP_TABLE_LOG(WARN, "cal readable set max ser_size failed", K(ret));
if (OB_SIZE_OVERFLOW == ret) { if (OB_SIZE_OVERFLOW == ret) {
ret = OB_LOG_TOO_LARGE; ret = OB_LOG_TOO_LARGE;
@ -1182,8 +1452,15 @@ int ObLSDupTabletsMgr::tablet_log_synced(const bool sync_result,
clean_readable = true; clean_readable = true;
} }
if (logging_common_header.is_old_set() && !logging_tablet_set->empty()) { if (OB_SUCC(ret) && logging_common_header.is_old_set() && !logging_tablet_set->empty()) {
modify_readable_set = true; if (logging_tablet_set->get_related_set_op_type() == DupTableRelatedSetOpType::OLD_GC) {
} else if (OB_FAIL(remove_tablet_from_readable_set_())) {
DUP_TABLE_LOG(WARN, "try remove tablet from readable set failed", K(ret),
KPC(removing_old_set_));
}
if (OB_SUCC(ret)) {
modify_readable_set = true;
}
} }
} }
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
@ -1196,6 +1473,8 @@ int ObLSDupTabletsMgr::tablet_log_synced(const bool sync_result,
if (OB_SUCC(ret) && sync_result) { if (OB_SUCC(ret) && sync_result) {
// if old is confirmed, clear it // if old is confirmed, clear it
if (logging_common_header.is_old_set()) { if (logging_common_header.is_old_set()) {
DUP_TABLE_LOG(DEBUG, "clean old set", K(ret),
KPC(logging_tablet_set), K(for_replay));
return_tablet_set_(logging_tablet_set); return_tablet_set_(logging_tablet_set);
// move need_confirm_queue to readable // move need_confirm_queue to readable
} else if (OB_FAIL(merge_into_readable_tablets_(logging_tablet_set, for_replay))) { } else if (OB_FAIL(merge_into_readable_tablets_(logging_tablet_set, for_replay))) {
@ -1895,9 +2174,11 @@ int ObLSDupTabletsMgr::discover_dup_tablet_(const common::ObTabletID &tablet_id,
changing_new_set_header.set_invalid_unique_id(); changing_new_set_header.set_invalid_unique_id();
changing_new_set_header.set_new(); changing_new_set_header.set_new();
DupTabletChangeMap *changing_new_map = nullptr; DupTabletChangeMap *changing_new_map = nullptr;
int64_t rmoving_tablet_cnt = OB_NOT_NULL(old_tablets_ptr)
? old_tablets_ptr->size() : 0;
if (OB_FAIL(get_target_tablet_set_(changing_new_set_header, changing_new_map))) { if (OB_FAIL(get_target_tablet_set_(changing_new_set_header, changing_new_map))) {
DUP_TABLE_LOG(WARN, "get changing new set failed", K(ret), KPC(changing_new_map)); DUP_TABLE_LOG(WARN, "get changing new set failed", K(ret), KPC(changing_new_map));
} else if (confirming_tablet_cnt + changing_new_map->size() > MAX_CONFIRMING_TABLET_COUNT } else if (confirming_tablet_cnt + changing_new_map->size() + rmoving_tablet_cnt > MAX_CONFIRMING_TABLET_COUNT
|| contain_confirming_special_op) { || contain_confirming_special_op) {
DUP_TABLE_LOG( DUP_TABLE_LOG(
INFO, INFO,
@ -2167,7 +2448,7 @@ int ObLSDupTabletsMgr::return_tablet_set_(DupTabletChangeMap *need_free_set)
} else if (need_free_set->get_common_header().is_old_set()) { } else if (need_free_set->get_common_header().is_old_set()) {
need_free_set->reuse(); need_free_set->reuse();
need_free_set->get_common_header().set_old(); need_free_set->get_common_header().set_old();
need_free_set->set_related_set_type(DupTableRelatedSetType::OLD_GC); need_free_set->set_related_set_op_type(DupTableRelatedSetOpType::NEW_GC);
} else { } else {
if (OB_FAIL(ret)) { if (OB_FAIL(ret)) {
} else { } else {
@ -2205,6 +2486,9 @@ int ObLSDupTabletsMgr::check_and_recycle_empty_readable_set_(DupTabletChangeMap
DUP_TABLE_LOG(WARN, "remove empty readable set from list failed", K(ret), KPC(readable_set)); DUP_TABLE_LOG(WARN, "remove empty readable set from list failed", K(ret), KPC(readable_set));
} else if (OB_FAIL(return_tablet_set_(readable_set))) { } else if (OB_FAIL(return_tablet_set_(readable_set))) {
DUP_TABLE_LOG(WARN, "return empty readable set failed", K(ret), KPC(readable_set)); DUP_TABLE_LOG(WARN, "return empty readable set failed", K(ret), KPC(readable_set));
} else if (readable_set == readable_set_in_gc_) {
// readable_set recycled, restart scan readable list
readable_set_in_gc_ = nullptr;
} }
} }
@ -2237,6 +2521,11 @@ int ObLSDupTabletsMgr::clean_readable_tablets_(const share::SCN &min_reserve_tab
} }
} }
} }
// if clean readable set, set null to avoid dangerous operation
if (OB_SUCC(ret) && OB_NOT_NULL(readable_set_in_gc_)) {
DUP_TABLE_LOG(INFO, "set readable_set_in_gc nullptr", K(ret), KPC(readable_set_in_gc_));
readable_set_in_gc_ = nullptr;
}
} }
return ret; return ret;

View File

@ -61,12 +61,13 @@ enum class DupTabletSetChangeFlag
}; };
enum class DupTableRelatedSetType enum class DupTableRelatedSetOpType
{ {
INVALID = 0, INVALID = 0,
OLD_GC, OLD_GC,
NEW_GC, NEW_GC,
MEGRE_READABLE, MEGRE_READABLE,
OPERATED_NEW_GC, // this type means this set in operate
}; };
static const char *get_dup_tablet_flag_str(const DupTabletSetChangeFlag &flag) static const char *get_dup_tablet_flag_str(const DupTabletSetChangeFlag &flag)
@ -129,10 +130,11 @@ public:
DupTabletSetChangeStatus() { reset(); } DupTabletSetChangeStatus() { reset(); }
~DupTabletSetChangeStatus() { reset(); } ~DupTabletSetChangeStatus() { reset(); }
const share::SCN &get_readable_version() { return readable_version_; } const share::SCN &get_readable_version() const { return readable_version_; }
const share::SCN &get_tablet_change_scn() { return tablet_change_scn_; } const share::SCN &get_tablet_change_scn() const { return tablet_change_scn_; }
const share::SCN &get_need_confirm_scn() { return need_confirm_scn_; } const share::SCN &get_need_confirm_scn() const { return need_confirm_scn_; }
const DupTabletSetChangeFlag &get_tablet_set_change_falg() { return flag_; } const DupTabletSetChangeFlag &get_tablet_set_change_flag() const { return flag_; }
int64_t get_trx_ref() const { return trx_ref_; }
bool is_valid() const { return flag_ != DupTabletSetChangeFlag::UNKNOWN; } bool is_valid() const { return flag_ != DupTabletSetChangeFlag::UNKNOWN; }
bool need_log() const bool need_log() const
@ -310,26 +312,31 @@ struct RelatedSetAttribute
{ {
DupTabletSetCommonHeader related_common_header_; DupTabletSetCommonHeader related_common_header_;
DupTabletSetChangeStatus related_change_status_; DupTabletSetChangeStatus related_change_status_;
DupTableRelatedSetType related_set_type_; DupTableRelatedSetOpType related_set_type_;
void reuse() void reuse()
{ {
related_change_status_.init(); related_change_status_.init();
related_change_status_.set_temporary(); related_change_status_.set_temporary();
related_common_header_.reuse(); related_common_header_.reuse();
related_set_type_ = DupTableRelatedSetType::INVALID; related_set_type_ = DupTableRelatedSetOpType::INVALID;
} }
void reset() void reset()
{ {
related_common_header_.reset(); related_common_header_.reset();
related_change_status_.reset(); related_change_status_.reset();
related_set_type_ = DupTableRelatedSetType::INVALID; related_set_type_ = DupTableRelatedSetOpType::INVALID;
} }
RelatedSetAttribute(const uint64_t uid) : related_common_header_(uid), related_change_status_() { reuse(); } RelatedSetAttribute(const uint64_t uid) : related_common_header_(uid), related_change_status_() { reuse(); }
RelatedSetAttribute() { reset(); } RelatedSetAttribute() { reset(); }
DupTableRelatedSetType get_related_set_type() const { return related_set_type_; }
void set_related_set_type(DupTableRelatedSetType related_set_type) { related_set_type_ = related_set_type; } DupTableRelatedSetOpType get_related_set_op_type() const { return related_set_type_; }
void set_related_set_op_type(DupTableRelatedSetOpType related_set_type) { related_set_type_ = related_set_type; }
const DupTabletSetCommonHeader &get_related_common_header() const { return related_common_header_; }
void set_related_common_header(const DupTabletSetCommonHeader &related_common_header) {
related_common_header_.copy_tablet_set_common_header(related_common_header);
}
TO_STRING_KV(K(related_change_status_), K(related_common_header_), K(related_set_type_)); TO_STRING_KV(K(related_change_status_), K(related_common_header_), K(related_set_type_));
@ -350,8 +357,9 @@ public:
void reuse() void reuse()
{ {
dup_set_attr_.reuse(); dup_set_attr_.reuse();
related_set_attr_.reuse(); related_set_attr_.reset();
DupTabletIdMap::clear(); DupTabletIdMap::clear();
last_gc_scan_ts_ = 0;
} }
void destroy() void destroy()
@ -359,6 +367,7 @@ public:
dup_set_attr_.reset(); dup_set_attr_.reset();
common::ObDLinkBase<DupTabletChangeMap>::reset(); common::ObDLinkBase<DupTabletChangeMap>::reset();
DupTabletIdMap::destroy(); DupTabletIdMap::destroy();
last_gc_scan_ts_ = 0;
} }
int create(const uint64_t tenant_id, const int64_t bucket_num); int create(const uint64_t tenant_id, const int64_t bucket_num);
@ -374,8 +383,14 @@ public:
return change_status_ptr; return change_status_ptr;
} }
DupTabletSetCommonHeader &get_common_header() { return dup_set_attr_.common_header_; } DupTabletSetCommonHeader &get_common_header() { return dup_set_attr_.common_header_; }
void set_related_set_type (DupTableRelatedSetType type) { related_set_attr_.set_related_set_type(type); } const DupTabletSetCommonHeader &get_RO_common_header() const { return dup_set_attr_.common_header_; }
DupTableRelatedSetType get_related_set_type() const { return related_set_attr_.get_related_set_type(); } void set_related_set_op_type (DupTableRelatedSetOpType type) { related_set_attr_.set_related_set_op_type(type); }
DupTableRelatedSetOpType get_related_set_op_type() const { return related_set_attr_.get_related_set_op_type(); }
const DupTabletSetCommonHeader &get_related_common_header() const { return related_set_attr_.get_related_common_header(); }
const RelatedSetAttribute &get_related_set_attr() { return related_set_attr_; }
void set_related_common_header(const DupTabletSetCommonHeader &common_header) {
related_set_attr_.set_related_common_header(common_header);
}
bool need_reserve(const share::SCN &scn) const bool need_reserve(const share::SCN &scn) const
{ {
return dup_set_attr_.change_status_.need_reserve(scn); return dup_set_attr_.change_status_.need_reserve(scn);
@ -386,6 +401,26 @@ public:
return dup_set_attr_.change_status_; return dup_set_attr_.change_status_;
} }
bool need_gc_scan(int64_t gc_start_time) {
bool bool_ret = false;
if (last_gc_scan_ts_ <= 0
|| gc_start_time > last_gc_scan_ts_) {
bool_ret = true;
}
return bool_ret;
}
void set_last_gc_scan_ts(const int64_t gc_start_time) {
if (gc_start_time < last_gc_scan_ts_) {
DUP_TABLE_LOG(INFO, "not update last_gc_scan_ts_ with min value",
K(gc_start_time), KPC(this));
} else {
last_gc_scan_ts_ = gc_start_time;
}
}
int64_t get_last_gc_scan_ts() { return last_gc_scan_ts_; }
bool is_logging() const { return dup_set_attr_.change_status_.check_logging(); } bool is_logging() const { return dup_set_attr_.change_status_.check_logging(); }
void set_logging() { dup_set_attr_.change_status_.set_logging(); } void set_logging() { dup_set_attr_.change_status_.set_logging(); }
void clean_logging() { dup_set_attr_.change_status_.clean_logging(); } void clean_logging() { dup_set_attr_.change_status_.clean_logging(); }
@ -396,6 +431,7 @@ public:
private: private:
DupTabletSetAttribute dup_set_attr_; DupTabletSetAttribute dup_set_attr_;
RelatedSetAttribute related_set_attr_; RelatedSetAttribute related_set_attr_;
int64_t last_gc_scan_ts_;
}; };
class TabletsSerCallBack : public IHashSerCallBack class TabletsSerCallBack : public IHashSerCallBack
@ -566,6 +602,9 @@ public:
const share::SCN &from_scn, const share::SCN &from_scn,
const share::SCN &to_scn); const share::SCN &to_scn);
int gc_dup_tablets(const int64_t gc_ts, const int64_t max_task_interval); int gc_dup_tablets(const int64_t gc_ts, const int64_t max_task_interval);
// new gc methods
int scan_readable_set_for_gc();
int refresh_dup_tablet(const common::ObTabletID &tablet_id, int refresh_dup_tablet(const common::ObTabletID &tablet_id,
bool is_dup_table, bool is_dup_table,
int64_t refresh_time); int64_t refresh_time);
@ -639,6 +678,28 @@ private:
DupTabletChangeMap &old_tablets_; DupTabletChangeMap &old_tablets_;
}; };
class GcOneReadableSetHandler
{
public:
GcOneReadableSetHandler(int64_t update_ts,
int64_t tablet_gc_window,
DupTabletChangeMap &old_tablets,
int64_t max_gc_tablet_cnt)
: gc_ts_(update_ts), tablet_gc_window_(tablet_gc_window), gc_tablet_cnt_(0),
max_gc_tablet_cnt_(max_gc_tablet_cnt), old_tablets_(old_tablets)
{}
int operator()(common::hash::HashMapPair<common::ObTabletID, DupTabletInfo> &hash_pair);
int64_t get_gc_tablet_cnt() const { return gc_tablet_cnt_; }
private:
int64_t gc_ts_;
int64_t tablet_gc_window_;
int64_t gc_tablet_cnt_;
int64_t max_gc_tablet_cnt_;
DupTabletChangeMap &old_tablets_;
};
class ConfirmedDupTabletHandler class ConfirmedDupTabletHandler
{ {
/** /**
@ -754,7 +815,17 @@ private:
int validate_replay_dup_tablet_set(const DupTabletSetCommonHeader &target_common_header, int validate_replay_dup_tablet_set(const DupTabletSetCommonHeader &target_common_header,
const DupTabletSetChangeStatus &target_change_status, const DupTabletSetChangeStatus &target_change_status,
DupTabletChangeMap *replay_target_set); DupTabletChangeMap *replay_target_set);
int prepare_serialize_src_set_with_related_set_(DupTabletChangeMap *src_set,
int64_t &max_ser_size,
const int64_t max_log_buf_len,
DupTabletSetIDArray &unique_id_array,
DupTabletChangeMap *related_set);
int remove_src_and_related_set_header_from_array_(DupTabletChangeMap *src_set,
DupTabletChangeMap *related_set,
DupTabletSetIDArray &unique_id_array);
DupTabletChangeMap *get_need_gc_set_(bool &new_round);
int remove_tablet_from_readable_set_();
private: private:
// //
static int64_t GC_DUP_TABLETS_TIME_INTERVAL; // 5 min static int64_t GC_DUP_TABLETS_TIME_INTERVAL; // 5 min
@ -763,6 +834,7 @@ private:
const static int64_t RESERVED_FREE_SET_COUNT; const static int64_t RESERVED_FREE_SET_COUNT;
const static int64_t MAX_FREE_SET_COUNT; const static int64_t MAX_FREE_SET_COUNT;
const static int64_t MAX_GC_TABLET_COUNT;
public: public:
@ -793,7 +865,12 @@ private:
DupTabletChangeMap *removing_old_set_; DupTabletChangeMap *removing_old_set_;
// gc_dup_table // gc_dup_table
int64_t last_gc_succ_time_; int64_t last_gc_succ_time_;
/* 1. gc one round means iter all readable set
* 2. use readable_set_in_gc_ point to readable set not finish gc in one round
* 3. use gc_start_time_ mark gc one round start time one round
*/
DupTabletChangeMap *readable_set_in_gc_;
int64_t gc_start_time_;
int64_t last_no_free_set_time_; int64_t last_no_free_set_time_;
int64_t extra_free_set_alloc_count_; int64_t extra_free_set_alloc_count_;