Files
oceanbase/src/storage/ob_saved_storage_info_v2.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

449 lines
15 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.
*/
#include <algorithm>
#include "storage/ob_saved_storage_info_v2.h"
#include "common/ob_partition_key.h"
#include "share/backup/ob_backup_info_mgr.h"
#include "storage/ob_partition_service.h"
#include "storage/ob_saved_storage_info.h"
namespace oceanbase {
using namespace common;
using namespace share;
namespace storage {
OB_DEF_SERIALIZE(ObSavedStorageInfoV2)
{
int ret = OB_SUCCESS;
LST_DO_CODE(OB_UNIS_ENCODE, STORAGE_INFO_VERSION_V3, clog_info_, data_info_, pg_file_id_);
return ret;
}
OB_DEF_SERIALIZE_SIZE(ObSavedStorageInfoV2)
{
int64_t len = 0;
LST_DO_CODE(OB_UNIS_ADD_LEN, STORAGE_INFO_VERSION_V3, clog_info_, data_info_, pg_file_id_);
return len;
}
OB_DEF_DESERIALIZE(ObSavedStorageInfoV2)
{
int ret = OB_SUCCESS;
int64_t tmp_pos = pos;
int16_t version = 0;
if (OB_ISNULL(buf) || data_len <= 0 || pos < 0 || pos >= data_len) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(buf), K(data_len), K(pos), K(ret));
} else if (OB_FAIL(serialization::decode(buf, data_len, tmp_pos, version))) {
STORAGE_LOG(WARN, "deserialize version failed.", K(ret));
} else if (STORAGE_INFO_VERSION_V1 == version) {
ret = OB_NOT_SUPPORTED;
} else if (STORAGE_INFO_VERSION_V2 == version) {
ObRecoverVec tmp_recover_vec;
bool tmp_from_14x = false;
ObVersion tmp_version(STORAGE_INFO_VERSION_V3, 0);
LST_DO_CODE(
OB_UNIS_DECODE, version_, clog_info_, data_info_, tmp_from_14x, tmp_version, tmp_recover_vec, pg_file_id_);
} else if (STORAGE_INFO_VERSION_V3 == version) {
LST_DO_CODE(OB_UNIS_DECODE, version_, clog_info_, data_info_, pg_file_id_);
} else {
ret = OB_DESERIALIZE_ERROR;
STORAGE_LOG(ERROR, "version not recognized", K(ret), K(version));
}
return ret;
}
int ObSavedStorageInfoV2::deep_copy(const ObSavedStorageInfoV2& save_storage_info)
{
int ret = OB_SUCCESS;
if (!save_storage_info.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(save_storage_info));
} else if (OB_FAIL(set_clog_info(save_storage_info.clog_info_))) {
STORAGE_LOG(WARN, "base storage info copy failed", K(ret));
} else if (OB_FAIL(set_data_info(save_storage_info.data_info_))) {
STORAGE_LOG(WARN, "data storage info copy failed", K(ret));
}
if (OB_INVALID_DATA_FILE_ID == pg_file_id_) {
pg_file_id_ = save_storage_info.pg_file_id_;
}
return ret;
}
int ObSavedStorageInfoV2::convert(const ObSavedStorageInfo& save_storage_info)
{
int ret = OB_SUCCESS;
if (!save_storage_info.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(save_storage_info));
} else if (OB_FAIL(set_clog_info(save_storage_info))) {
STORAGE_LOG(WARN, "base storage info copy failed", K(ret));
} else {
ObDataStorageInfo tmp_info;
tmp_info.set_last_replay_log_id(save_storage_info.get_last_replay_log_id());
tmp_info.set_publish_version(save_storage_info.get_publish_version());
tmp_info.set_schema_version(save_storage_info.get_schema_version());
if (OB_FAIL(set_data_info(tmp_info))) {
STORAGE_LOG(WARN, "data storage info copy failed", K(ret));
}
}
return ret;
}
int ObSavedStorageInfoV2::deep_copy(const ObSavedStorageInfo& save_storage_info)
{
int ret = OB_SUCCESS;
if (OB_FAIL(convert(save_storage_info))) {
STORAGE_LOG(WARN, "fail to convert V1 storage info", K(ret));
}
return ret;
}
void ObSavedStorageInfoV2::reset()
{
version_ = STORAGE_INFO_VERSION_V3;
clog_info_.reset();
data_info_.reset();
pg_file_id_ = OB_INVALID_DATA_FILE_ID;
}
int ObSavedStorageInfoV2::set_data_info(const ObDataStorageInfo& data_storage_info)
{
int ret = OB_SUCCESS;
if (!data_storage_info.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(data_storage_info));
} else {
data_info_ = data_storage_info;
}
return ret;
}
int ObSavedStorageInfoV2::query_log_info_with_log_id(const ObPartitionKey& pkey, const int64_t log_id,
const int64_t timeout, int64_t& accum_checksum, int64_t& submit_timestamp, int64_t& epoch_id)
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
if (OB_FAIL(ObPartitionService::get_instance().query_log_info_with_log_id(
pkey, log_id, timeout, accum_checksum, submit_timestamp, epoch_id))) {
STORAGE_LOG(WARN, "failed to query log info", K(ret), K(pkey), K(log_id));
}
const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
if (cost_ts > 1000 * 1000 /*1s*/) {
STORAGE_LOG(WARN, "query_log_info_with_log_id cost too much time", K(pkey), K(log_id), K(cost_ts));
} else {
STORAGE_LOG(INFO, "query_log_info_with_log_id cost time", K(pkey), K(log_id), K(cost_ts));
}
return ret;
}
int ObSavedStorageInfoV2::get_last_replay_log_info_(
const ObPartitionKey& pkey, const int64_t timeout, ObRecoverPoint& point)
{
int ret = OB_SUCCESS;
int64_t submit_timestamp = 0;
int64_t epoch_id = 0;
int64_t checksum = 0;
if (0 == data_info_.get_last_replay_log_id()) {
checksum = 0;
} else if (data_info_.get_last_replay_log_id() < clog_info_.get_last_replay_log_id()) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(ERROR, "filter log id is smaller than last replay log id", K(*this), K(ret));
} else if (data_info_.get_last_replay_log_id() == clog_info_.get_last_replay_log_id()) {
checksum = clog_info_.get_accumulate_checksum();
} else if (OB_FAIL(query_log_info_with_log_id(
pkey, data_info_.get_last_replay_log_id(), timeout, checksum, submit_timestamp, epoch_id))) {
STORAGE_LOG(WARN, "failed to query accum checksum", K(ret), K(pkey), K(*this));
} else {
point.set(
data_info_.get_publish_version(), data_info_.get_last_replay_log_id(), checksum, epoch_id, submit_timestamp);
}
return ret;
}
int ObSavedStorageInfoV2::update_last_replay_log_info_(const ObPartitionKey& pkey, const bool replica_with_data,
const ObBaseStorageInfo& old_clog_info, const int64_t timeout, const bool log_info_usable)
{
int ret = OB_SUCCESS;
int64_t accum_checksum = 0;
int64_t submit_timestamp = 0;
int64_t epoch_id = 0;
bool can_skip_query = log_info_usable;
if (replica_with_data && data_info_.get_last_replay_log_id() < clog_info_.get_last_replay_log_id()) {
clog_info_.set_last_replay_log_id(data_info_.get_last_replay_log_id());
can_skip_query = false;
}
if (can_skip_query) {
STORAGE_LOG(INFO, "clog info unchanged", K(clog_info_));
} else if (clog_info_.get_last_replay_log_id() <= old_clog_info.get_last_replay_log_id()) {
// For the case that the log id clog info may be recycled, the clog info of memtable dump
// point is used. In addition, it should be guaranteed that the last_replay_log_id of clog info
// is smaller than data info.
if (replica_with_data && data_info_.get_last_replay_log_id() < old_clog_info.get_last_replay_log_id()) {
ret = OB_EAGAIN;
STORAGE_LOG(WARN, "data info too old, try again", K(ret), K(pkey), K(old_clog_info), K(*this));
} else {
STORAGE_LOG(INFO, "use saved clog info", K(clog_info_), K(old_clog_info));
if (OB_FAIL(set_clog_info(old_clog_info))) {
STORAGE_LOG(WARN, "base storage info copy failed", K(ret));
}
}
} else if (OB_FAIL(query_log_info_with_log_id(
pkey, clog_info_.get_last_replay_log_id(), timeout, accum_checksum, submit_timestamp, epoch_id))) {
STORAGE_LOG(WARN, "failed to query accum checksum", K(ret), K(pkey), K(*this));
} else {
clog_info_.set_accumulate_checksum(accum_checksum);
clog_info_.set_submit_timestamp(submit_timestamp);
clog_info_.set_epoch_id(epoch_id);
}
return ret;
}
int ObSavedStorageInfoV2::update_last_replay_log_info(const ObPartitionKey& pkey, const bool replica_with_data,
const ObBaseStorageInfo& old_clog_info, const int64_t timeout, const bool log_info_usable)
{
return update_last_replay_log_info_(pkey, replica_with_data, old_clog_info, timeout, log_info_usable);
}
int ObSavedStorageInfoV2::update_and_fetch_log_info(const ObPartitionKey& pkey, const bool replica_with_data,
const ObBaseStorageInfo& old_clog_info, const int64_t timeout, const bool log_info_usable)
{
int ret = OB_SUCCESS;
if (OB_FAIL(update_last_replay_log_info_(pkey, replica_with_data, old_clog_info, timeout, log_info_usable))) {
STORAGE_LOG(WARN, "failed to update log info", K(ret), K(pkey), K(old_clog_info));
}
return ret;
}
int ObSavedStorageInfoV2::clear_recover_points_for_physical_flashback(const int64_t, const ObRecoverPoint&)
{
return OB_NOT_IMPLEMENT;
}
OB_SERIALIZE_MEMBER(ObRecoverPoint, snapshot_version_, recover_log_id_, checksum_, epoch_id_, submit_timestamp_);
OB_SERIALIZE_MEMBER(ObRecoverVec, recover_vec_);
int ObRecoverVec::add_recover_point_(const ObRecoverPoint& point)
{
int ret = OB_SUCCESS;
if (recover_vec_.count() > 0 && point.snapshot_version_ <= recover_vec_[recover_vec_.count() - 1].snapshot_version_) {
STORAGE_LOG(INFO, "add recover point with lower recover point", K(ret), K(point), K(recover_vec_));
ret = OB_SUCCESS;
} else if (OB_FAIL(recover_vec_.push_back(point))) {
STORAGE_LOG(WARN, "push back to vec failed", K(ret), K(point));
}
return ret;
}
int ObRecoverVec::add_recover_point(const ObRecoverPoint& point)
{
ObLockGuard<ObSpinLock> lock_guard(lock_);
return add_recover_point_(point);
}
int ObRecoverVec::reboot_recover_point(const ObRecoverPoint& point)
{
int ret = OB_SUCCESS;
ObLockGuard<ObSpinLock> lock_guard(lock_);
if (0 == recover_vec_.count() && OB_FAIL(add_recover_point_(point))) {
STORAGE_LOG(WARN, "reboot recover point failed", K(point), K(ret), K(*this));
}
return ret;
}
int ObRecoverVec::gc_recover_points(const int64_t gc_snapshot_version, const int64_t kept_backup_version, bool& changed)
{
int ret = OB_SUCCESS;
changed = false;
ObLockGuard<ObSpinLock> lock_guard(lock_);
while (OB_SUCC(ret) && can_gc_recover_point_(gc_snapshot_version, kept_backup_version)) {
ObRecoverPoint point = recover_vec_[0];
if (OB_FAIL(recover_vec_.remove(0))) {
STORAGE_LOG(WARN,
"gc recover points fail",
K(ret),
K(gc_snapshot_version),
K(recover_vec_),
K(kept_backup_version),
K(point));
} else {
STORAGE_LOG(INFO,
"gc recover points succeed",
K(ret),
K(gc_snapshot_version),
K(recover_vec_),
K(kept_backup_version),
K(point));
changed = true;
}
}
return ret;
}
int ObRecoverVec::clear_recover_points_for_physical_flashback(const int64_t version, const ObRecoverPoint& point)
{
int ret = OB_SUCCESS;
int size = 0;
ObLockGuard<ObSpinLock> lock_guard(lock_);
size = recover_vec_.count();
for (int64_t i = size - 1; i >= 0 && OB_SUCC(ret) && recover_vec_[i].snapshot_version_ > version; i--) {
if (OB_FAIL(recover_vec_.remove(i))) {
STORAGE_LOG(ERROR, "remove recover points failed", K(ret), K(version), K(recover_vec_), K(point));
}
}
if (0 == recover_vec_.count() && OB_FAIL(add_recover_point_(point))) {
STORAGE_LOG(ERROR, "remove recover points failed", K(ret), K(version), K(recover_vec_), K(point));
}
return ret;
}
bool ObRecoverVec::can_gc_recover_point_(const int64_t gc_snapshot_version, const int64_t kept_backup_version)
{
// There must be at least one recovery point in the vector.
return recover_vec_.count() > 1 &&
// If the snapshot_version of recover point is not greater than gc point.
recover_vec_[0].snapshot_version_ <= gc_snapshot_version &&
// There must be at least one recovery point's snapshot_version is not greater than backup.
(kept_backup_version == 0 || recover_vec_[1].snapshot_version_ <= kept_backup_version);
}
int ObRecoverVec::get_lower_bound_point(const int64_t snapshot_version, ObRecoverPoint& point)
{
int ret = OB_SUCCESS;
int64_t id = 0;
ObLockGuard<ObSpinLock> lock_guard(lock_);
if (OB_FAIL(get_lower_bound_point_(snapshot_version, id))) {
if (OB_ENTRY_NOT_EXIST != ret) {
STORAGE_LOG(ERROR, "get lower bound point error", K(snapshot_version));
} else {
STORAGE_LOG(INFO, "get lower bound point not exist", K(snapshot_version));
}
} else {
point = recover_vec_[id];
}
return ret;
}
int ObRecoverVec::get_lower_bound_point_(const int64_t snapshot_version, int64_t& id)
{
int ret = OB_SUCCESS;
ObRecoverPoint tmp_point(snapshot_version, 0, 0, 0, 0);
RecoverIter iter;
if (recover_vec_.count() == 0) {
ret = OB_ENTRY_NOT_EXIST;
} else if (recover_vec_.end() == (iter = std::lower_bound(recover_vec_.begin(), recover_vec_.end(), tmp_point))) {
id = recover_vec_.count() - 1;
} else if (iter->snapshot_version_ == snapshot_version) {
id = iter - recover_vec_.begin();
} else if (recover_vec_.begin() == iter) {
ret = OB_ENTRY_NOT_EXIST;
} else {
id = iter - recover_vec_.begin() - 1;
}
return ret;
}
int ObRecoverVec::record_major_recover_point(const int64_t prev_version, const int64_t version, bool& changed)
{
int ret = OB_SUCCESS;
int64_t id = 0;
changed = false;
ObLockGuard<ObSpinLock> lock_guard(lock_);
if (OB_FAIL(get_lower_bound_point_(version, id))) {
if (OB_ENTRY_NOT_EXIST != ret) {
STORAGE_LOG(ERROR, "get lower bound point error", K(version));
} else {
STORAGE_LOG(INFO, "get lower bound point not exist", K(version));
}
} else {
for (int64_t i = id - 1; i >= 0 && OB_SUCC(ret) && recover_vec_[i].snapshot_version_ > prev_version; i--) {
if (OB_FAIL(recover_vec_.remove(i))) {
STORAGE_LOG(WARN, "gc recover points failed", K(ret), K(prev_version), K(version), K(recover_vec_));
} else {
changed = true;
}
}
if (OB_FAIL(ret)) {
STORAGE_LOG(WARN, "record major recover point failed", K(ret), K(prev_version), K(version), K(recover_vec_));
} else {
if (changed) {
STORAGE_LOG(INFO, "record major recover point success", K(prev_version), K(version), K(recover_vec_));
}
}
}
return ret;
}
int ObRecoverVec::assign_recover_points(const ObRecoverVec& vec)
{
int ret = OB_SUCCESS;
ObLockGuard<ObSpinLock> lock_guard(lock_);
recover_vec_.reset();
if (OB_FAIL(recover_vec_.assign(vec.recover_vec_))) {
STORAGE_LOG(WARN, "assign vec failed", K(recover_vec_), K(vec));
}
return ret;
}
} // namespace storage
} // namespace oceanbase