1431 lines
45 KiB
C++
1431 lines
45 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/ob_freeze_info_snapshot_mgr.h"
|
|
|
|
#include "common/storage/ob_freeze_define.h"
|
|
#include "lib/mysqlclient/ob_mysql_proxy.h"
|
|
#include "lib/utility/ob_print_utils.h"
|
|
#include "share/ob_global_stat_proxy.h"
|
|
#include "share/ob_tenant_mgr.h"
|
|
#include "share/ob_thread_mgr.h"
|
|
#include "share/ob_zone_table_operation.h"
|
|
#include "share/schema/ob_multi_version_schema_service.h"
|
|
#include "share/schema/ob_schema_getter_guard.h"
|
|
#include "share/ob_multi_cluster_util.h"
|
|
#include "share/backup/ob_backup_info_mgr.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "observer/ob_service.h"
|
|
#include "storage/ob_partition_service.h"
|
|
|
|
namespace oceanbase {
|
|
|
|
using namespace common;
|
|
using namespace share;
|
|
using namespace share::schema;
|
|
|
|
using common::hash::ObHashSet;
|
|
|
|
namespace storage {
|
|
|
|
ObFreezeInfoSnapshotMgr::ObFreezeInfoSnapshotMgr()
|
|
: inited_(false),
|
|
tg_id_(-1),
|
|
reload_task_(*this, schema_query_set_),
|
|
schema_query_set_(schema_cache_),
|
|
snapshot_gc_ts_(0),
|
|
gc_snapshot_info_(),
|
|
schema_cache_(schema_query_set_),
|
|
info_list_(),
|
|
snapshots_(),
|
|
cur_idx_(0),
|
|
lock_()
|
|
{}
|
|
|
|
ObFreezeInfoSnapshotMgr::~ObFreezeInfoSnapshotMgr()
|
|
{}
|
|
|
|
int ObFreezeInfoSnapshotMgr::init(ObISQLClient &sql_proxy, bool is_remote)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
STORAGE_LOG(WARN, "init twice", K(ret));
|
|
} else if (OB_FAIL(schema_query_set_.init())) {
|
|
STORAGE_LOG(ERROR, "fail to init schema query queue", K(ret));
|
|
} else if (OB_FAIL(reload_task_.init(sql_proxy, is_remote))) {
|
|
STORAGE_LOG(ERROR, "fail to init reload task", K(ret));
|
|
} else if (OB_FAIL(schema_cache_.init(sql_proxy))) {
|
|
STORAGE_LOG(ERROR, "fail to init schema cache", K(ret));
|
|
} else if (OB_FAIL(TG_CREATE(lib::TGDefIDs::FreInfoReload, tg_id_))) {
|
|
STORAGE_LOG(ERROR, "fail to init timer", K(ret));
|
|
} else if (OB_FAIL(TG_START(tg_id_))) {
|
|
STORAGE_LOG(ERROR, "fail to init timer", K(ret));
|
|
} else {
|
|
inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::start()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else if (OB_FAIL(TG_SCHEDULE(tg_id_, reload_task_, RELOAD_INTERVAL, true))) {
|
|
STORAGE_LOG(ERROR, "fail to schedule task", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezeInfoSnapshotMgr::wait()
|
|
{
|
|
TG_WAIT(tg_id_);
|
|
}
|
|
|
|
void ObFreezeInfoSnapshotMgr::stop()
|
|
{
|
|
TG_STOP(tg_id_);
|
|
}
|
|
|
|
static inline uint64_t get_tenant_id(const uint64_t table_id)
|
|
{
|
|
// system table of user tenant needs to use the schema version of system
|
|
// tenant
|
|
uint64_t tenant_id = OB_SYS_TENANT_ID;
|
|
if (!is_inner_table(table_id)) {
|
|
tenant_id = extract_tenant_id(table_id);
|
|
}
|
|
return tenant_id;
|
|
}
|
|
|
|
static inline bool is_schema_cache_related_table(const uint64_t table_id)
|
|
{
|
|
uint64_t pure_id = extract_pure_id(table_id);
|
|
return OB_ALL_CORE_TABLE_TID == pure_id || OB_ALL_FREEZE_SCHEMA_VERSION_TID == pure_id;
|
|
}
|
|
|
|
int64_t ObFreezeInfoSnapshotMgr::get_latest_frozen_timestamp()
|
|
{
|
|
int64_t frozen_timestamp = 0;
|
|
RLockGuard lock_guard(lock_);
|
|
ObIArray<FreezeInfoLite> &info_list = info_list_[cur_idx_];
|
|
|
|
if (0 != info_list.count()) {
|
|
frozen_timestamp = info_list.at(info_list.count() - 1).freeze_ts;
|
|
}
|
|
return frozen_timestamp;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_by_major_version(const int64_t major_version, FreezeInfoLite &freeze_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool unused = false;
|
|
RLockGuard lock_guard(lock_);
|
|
ret = get_freeze_info_by_major_version_(major_version, freeze_info, unused);
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_by_major_version(
|
|
const int64_t major_version, FreezeInfoLite &freeze_info, bool &is_first_major_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_first_major_version = false;
|
|
RLockGuard lock_guard(lock_);
|
|
ret = get_freeze_info_by_major_version_(major_version, freeze_info, is_first_major_version);
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_by_major_version_(
|
|
const int64_t major_version, FreezeInfoLite &freeze_info, bool &is_first_major_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_first_major_version = false;
|
|
|
|
ObIArray<FreezeInfoLite> &info_list = info_list_[cur_idx_];
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else {
|
|
bool found = false;
|
|
int64_t l = 0;
|
|
int64_t r = info_list.count();
|
|
|
|
while (l < r && !found) {
|
|
int64_t mid = (l + r) >> 1;
|
|
FreezeInfoLite &tmp_info = info_list.at(mid);
|
|
if (major_version < tmp_info.freeze_version) {
|
|
r = mid;
|
|
} else if (major_version > tmp_info.freeze_version) {
|
|
l = mid + 1;
|
|
} else {
|
|
found = true;
|
|
freeze_info = tmp_info;
|
|
if (0 == mid) {
|
|
is_first_major_version = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_behind_major_version(
|
|
const int64_t major_version, ObIArray<FreezeInfoLite> &freeze_infos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
RLockGuard lock_guard(lock_);
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else if (OB_UNLIKELY(major_version < 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
STORAGE_LOG(WARN, "Invalid argument to get freeze info", K(ret), K(major_version));
|
|
} else {
|
|
ObIArray<FreezeInfoLite> &info_list = info_list_[cur_idx_];
|
|
bool found = false;
|
|
int64_t mid = 0;
|
|
int64_t l = 0;
|
|
int64_t r = info_list.count();
|
|
|
|
while (l < r && !found) {
|
|
mid = (l + r) >> 1;
|
|
FreezeInfoLite &tmp_info = info_list.at(mid);
|
|
if (major_version < tmp_info.freeze_version) {
|
|
r = mid;
|
|
} else if (major_version > tmp_info.freeze_version) {
|
|
l = mid + 1;
|
|
} else {
|
|
found = true;
|
|
}
|
|
}
|
|
if (found) {
|
|
for (int64_t i = mid; OB_SUCC(ret) && i < info_list.count(); i++) {
|
|
if (OB_FAIL(freeze_infos.push_back(info_list.at(i)))) {
|
|
STORAGE_LOG(WARN, "Failed to push back freeze info", K(ret));
|
|
}
|
|
}
|
|
} else {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
STORAGE_LOG(WARN, "Freeze info of specified major version not found", K(ret), K(major_version));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_by_major_version(
|
|
const uint64_t table_id, const int64_t major_version, FreezeInfo &freeze_info)
|
|
{
|
|
uint64_t tenant_id = get_tenant_id(table_id);
|
|
bool async = is_schema_cache_related_table(table_id);
|
|
return get_tenant_freeze_info_by_major_version_(tenant_id, major_version, async, freeze_info);
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_tenant_freeze_info_by_major_version(
|
|
const uint64_t tenant_id, const int64_t major_version, FreezeInfo &freeze_info)
|
|
{
|
|
return get_tenant_freeze_info_by_major_version_(tenant_id, major_version, true, freeze_info);
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_tenant_freeze_info_by_major_version_(
|
|
const uint64_t tenant_id, const int64_t major_version, const bool async, FreezeInfo &freeze_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
FreezeInfoLite lite;
|
|
if (OB_FAIL(get_freeze_info_by_major_version(major_version, lite))) {
|
|
STORAGE_LOG(WARN, "fail to get lite freeze info", K(ret), K(major_version));
|
|
} else if (OB_FAIL(schema_cache_.get_freeze_schema_version(
|
|
tenant_id, lite.freeze_version, async, freeze_info.schema_version))) {
|
|
if (OB_EAGAIN == ret) {
|
|
STORAGE_LOG(INFO, "schema not ready, try again later", K(ret), K(tenant_id), K(lite));
|
|
} else {
|
|
STORAGE_LOG(WARN, "fail to get freeze schema version", K(ret), K(tenant_id), K(lite.freeze_version));
|
|
}
|
|
} else {
|
|
freeze_info = lite;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_by_snapshot_version(
|
|
const int64_t snapshot_version, FreezeInfoLite &freeze_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
RLockGuard lock_guard(lock_);
|
|
ObIArray<FreezeInfoLite> &info_list = info_list_[cur_idx_];
|
|
|
|
if (snapshot_version <= 0 || INT64_MAX == snapshot_version) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
STORAGE_LOG(WARN, "snapshot version is invalid", K(ret), K(snapshot_version));
|
|
} else if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else if (info_list.empty()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_WARN("not freeze info exists", K(ret));
|
|
} else {
|
|
bool found = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !found && i < info_list.count(); ++i) {
|
|
FreezeInfoLite &tmp_info = info_list.at(i);
|
|
if (snapshot_version == tmp_info.freeze_ts) {
|
|
freeze_info = tmp_info;
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (!found) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
STORAGE_LOG(WARN, "can not find the freeze info", K(ret), K(snapshot_version));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_freeze_info_by_snapshot_version(
|
|
const uint64_t table_id, const int64_t snapshot_version, FreezeInfo &freeze_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
FreezeInfoLite lite;
|
|
if (OB_FAIL(get_freeze_info_by_snapshot_version(snapshot_version, lite))) {
|
|
STORAGE_LOG(WARN, "fail to get lite freeze info", K(ret), K(snapshot_version));
|
|
} else if (OB_FAIL(schema_cache_.get_freeze_schema_version(get_tenant_id(table_id),
|
|
lite.freeze_version,
|
|
is_schema_cache_related_table(table_id),
|
|
freeze_info.schema_version))) {
|
|
if (OB_EAGAIN == ret) {
|
|
STORAGE_LOG(INFO, "schema not ready, try again later", K(ret), K(table_id), K(lite));
|
|
} else {
|
|
STORAGE_LOG(WARN, "fail to get freeze schema version", K(ret), K(table_id), K(lite.freeze_version));
|
|
}
|
|
} else {
|
|
freeze_info = lite;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::inner_get_neighbour_major_freeze(
|
|
const int64_t snapshot_version, NeighbourFreezeInfoLite &info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
info.reset();
|
|
|
|
ObIArray<FreezeInfoLite> &info_list = info_list_[cur_idx_];
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else if (info_list.empty()) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_WARN("not freeze info exists", K(ret));
|
|
} else {
|
|
bool found = false;
|
|
for (int64_t i = 0; i < info_list.count() && OB_SUCC(ret) && !found; ++i) {
|
|
FreezeInfoLite &next_info = info_list.at(i);
|
|
if (snapshot_version < next_info.freeze_ts) {
|
|
found = true;
|
|
if (0 == i) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
STORAGE_LOG(
|
|
WARN, "cannot get neighbour major freeze before bootstrap", K(ret), K(snapshot_version), K(next_info));
|
|
} else {
|
|
info.next = next_info;
|
|
info.prev = info_list.at(i - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && !found) {
|
|
info.next.freeze_version = 0;
|
|
info.next.freeze_ts = snapshot_gc_ts_;
|
|
info.prev = info_list.at(info_list.count() - 1);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_neighbour_major_freeze(const int64_t snapshot_version, NeighbourFreezeInfoLite &info)
|
|
{
|
|
RLockGuard lock_guard(lock_);
|
|
return inner_get_neighbour_major_freeze(snapshot_version, info);
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_neighbour_major_freeze(
|
|
const uint64_t table_id, const int64_t snapshot_version, NeighbourFreezeInfo &info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
NeighbourFreezeInfoLite lite;
|
|
|
|
{
|
|
RLockGuard lock_guard(lock_);
|
|
if (OB_FAIL(inner_get_neighbour_major_freeze(snapshot_version, lite))) {
|
|
STORAGE_LOG(WARN, "fail to get lite neighbour freeze info", K(ret), K(snapshot_version));
|
|
} else if (0 == lite.next.freeze_version) {
|
|
info = lite;
|
|
// obtain the schema_version based on gc_snapshot_ts
|
|
GCSnapshotInfo finfo;
|
|
if (OB_FAIL(gc_snapshot_info_[cur_idx_].get_refactored(get_tenant_id(table_id), finfo))) {
|
|
if (OB_HASH_NOT_EXIST == ret) {
|
|
STORAGE_LOG(WARN, "tenant not exist in gc snapshot hash", K(ret), K(table_id));
|
|
} else {
|
|
STORAGE_LOG(WARN, "fail to get gc_snapshot_info", K(ret));
|
|
}
|
|
} else {
|
|
info.next.freeze_ts = finfo.snapshot_ts;
|
|
info.next.schema_version = finfo.schema_version;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (lite.next.freeze_version > 0) {
|
|
info = lite;
|
|
if (OB_FAIL(schema_cache_.get_freeze_schema_version(get_tenant_id(table_id),
|
|
lite.next.freeze_version,
|
|
is_schema_cache_related_table(table_id),
|
|
info.next.schema_version))) {
|
|
if (OB_EAGAIN == ret) {
|
|
STORAGE_LOG(INFO, "schema not ready, try again later", K(ret), K(table_id), K(lite.next));
|
|
} else {
|
|
STORAGE_LOG(WARN, "fail to get freeze schema version", K(ret), K(table_id), K(lite.next.freeze_version));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline int is_snapshot_related_to_table(
|
|
const ObPartitionKey &pkey, const int64_t create_schema_version, const ObSnapshotInfo &snapshot, bool &related)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
related = false;
|
|
const int64_t table_id = pkey.get_table_id();
|
|
|
|
if (!snapshot.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
STORAGE_LOG(WARN, "invalid argument", K(ret), K(snapshot));
|
|
} else if (snapshot.snapshot_type_ == share::SNAPSHOT_FOR_RESTORE_POINT ||
|
|
snapshot.snapshot_type_ == share::SNAPSHOT_FOR_BACKUP_POINT) {
|
|
if (snapshot.snapshot_type_ == share::SNAPSHOT_FOR_RESTORE_POINT && is_inner_table(table_id)) {
|
|
related = false;
|
|
} else if (extract_tenant_id(table_id) == snapshot.tenant_id_) {
|
|
related = true;
|
|
bool is_complete = false;
|
|
if (create_schema_version > snapshot.schema_version_ && !is_inner_table(table_id)) {
|
|
related = false;
|
|
} else if (OB_FAIL(ObPartitionService::get_instance().check_restore_point_complete(
|
|
pkey, snapshot.snapshot_ts_, is_complete))) {
|
|
STORAGE_LOG(WARN, "failed to check restore point exist", K(ret));
|
|
} else if (is_complete) {
|
|
related = false;
|
|
}
|
|
}
|
|
} else {
|
|
// when tenant_id_ equals to 0, it means need all tenants
|
|
if (0 == snapshot.tenant_id_ || extract_tenant_id(table_id) == snapshot.tenant_id_) {
|
|
// when table_id_ equals to 0, it means need all tables in tenant
|
|
if (0 == snapshot.table_id_ || snapshot.table_id_ == table_id) {
|
|
related = true;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_multi_version_duration(const uint64_t tenant_id, int64_t &duration) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObMultiVersionSchemaService &schema_service = ObMultiVersionSchemaService::get_instance();
|
|
ObSchemaGetterGuard guard;
|
|
ObString var_name(share::OB_SV_UNDO_RETENTION);
|
|
const ObSysVarSchema *var_schema = NULL;
|
|
ObArenaAllocator allocator(ObModIds::OB_PARTITION_SERVICE);
|
|
ObObj value;
|
|
|
|
if (!is_valid_tenant_id(tenant_id)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
STORAGE_LOG(WARN, "invalid argument", K(ret), K(tenant_id));
|
|
} else if (OB_FAIL(schema_service.get_tenant_full_schema_guard(tenant_id, guard))) {
|
|
STORAGE_LOG(WARN, "get schema guard failed", K(ret), K(tenant_id));
|
|
} else if (OB_FAIL(guard.get_tenant_system_variable(tenant_id, var_name, var_schema))) {
|
|
STORAGE_LOG(WARN, "get tenant system variable failed", K(ret));
|
|
} else if (NULL == var_schema) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
STORAGE_LOG(ERROR, "unexpected error, var schema is NULL", K(ret));
|
|
} else if (OB_FAIL(var_schema->get_value(&allocator, NULL, value))) {
|
|
STORAGE_LOG(WARN, "get value failed", K(ret));
|
|
} else if (OB_FAIL(value.get_int(duration))) {
|
|
STORAGE_LOG(WARN, "get duration failed", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_min_reserved_snapshot(const ObPartitionKey &pkey, const int64_t merged_version,
|
|
const int64_t create_schema_version, int64_t &snapshot_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
FreezeInfoLite freeze_info;
|
|
int64_t duration = 0;
|
|
bool unused = false;
|
|
const int64_t table_id = pkey.get_table_id();
|
|
|
|
RLockGuard lock_guard(lock_);
|
|
ObIArray<ObSnapshotInfo> &snapshots = snapshots_[cur_idx_];
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else if (OB_FAIL(get_multi_version_duration(get_tenant_id(table_id), duration))) {
|
|
STORAGE_LOG(WARN, "fail to get multi version duration", K(ret), K(table_id));
|
|
} else {
|
|
if (merged_version < 1) {
|
|
freeze_info.freeze_ts = 0;
|
|
} else if (OB_FAIL(get_freeze_info_by_major_version_(merged_version + 1, freeze_info, unused))) {
|
|
if (OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("failed to get_freeze_info_by_major_version", K(ret), K(merged_version));
|
|
} else {
|
|
freeze_info.freeze_ts = INT64_MAX;
|
|
ret = OB_SUCCESS;
|
|
}
|
|
}
|
|
snapshot_version = std::max(0L, snapshot_gc_ts_ - duration * 1000L * 1000L);
|
|
snapshot_version = std::min(snapshot_version, freeze_info.freeze_ts);
|
|
for (int64_t i = 0; i < snapshots.count() && OB_SUCC(ret); ++i) {
|
|
bool related = false;
|
|
const ObSnapshotInfo &snapshot = snapshots.at(i);
|
|
if (OB_FAIL(is_snapshot_related_to_table(pkey, create_schema_version, snapshot, related))) {
|
|
STORAGE_LOG(WARN, "fail to check snapshot relation", K(ret), K(table_id), K(snapshot));
|
|
} else if (related) {
|
|
snapshot_version = std::min(snapshot_version, snapshot.snapshot_ts_);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_reserve_points(const int64_t tenant_id, const share::ObSnapShotType snapshot_type,
|
|
ObIArray<ObSnapshotInfo> &restore_points, int64_t &snapshot_gc_ts)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
restore_points.reset();
|
|
RLockGuard lock_guard(lock_);
|
|
snapshot_gc_ts = snapshot_gc_ts_;
|
|
ObIArray<ObSnapshotInfo> &snapshots = snapshots_[cur_idx_];
|
|
for (int64_t i = 0; i < snapshots.count() && OB_SUCC(ret); ++i) {
|
|
const ObSnapshotInfo &snapshot = snapshots.at(i);
|
|
if (snapshot.snapshot_type_ == snapshot_type && tenant_id == snapshot.tenant_id_) {
|
|
if (OB_FAIL(restore_points.push_back(snapshot))) {
|
|
STORAGE_LOG(WARN, "fail to push back snapshot", K(ret), K(snapshot));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_restore_point_min_schema_version(const int64_t tenant_id, int64_t &schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
schema_version = INT64_MAX;
|
|
RLockGuard lock_guard(lock_);
|
|
ObIArray<ObSnapshotInfo> &snapshots = snapshots_[cur_idx_];
|
|
for (int64_t i = 0; i < snapshots.count() && OB_SUCC(ret); ++i) {
|
|
const ObSnapshotInfo &snapshot = snapshots.at(i);
|
|
if (snapshot.snapshot_type_ == SNAPSHOT_FOR_RESTORE_POINT && tenant_id == snapshot.tenant_id_) {
|
|
schema_version = std::min(snapshot.schema_version_, schema_version);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::get_latest_freeze_version(int64_t &freeze_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
RLockGuard lock_guard(lock_);
|
|
ObIArray<FreezeInfoLite> &info_list = info_list_[cur_idx_];
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else {
|
|
freeze_version = 0;
|
|
|
|
if (info_list.count() > 0) {
|
|
freeze_version = info_list.at(info_list.count() - 1).freeze_version;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::prepare_new_info_list(const int64_t min_major_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t next_idx = get_next_idx();
|
|
info_list_[next_idx].reset();
|
|
snapshots_[next_idx].reset();
|
|
gc_snapshot_info_[next_idx].reuse();
|
|
|
|
for (int64_t i = 0; i < info_list_[cur_idx_].count() && OB_SUCC(ret); ++i) {
|
|
if (INT64_MAX == min_major_version || // no garbage collection is necessary
|
|
// or version is bigger or equal than the smallest major version currently
|
|
info_list_[cur_idx_].at(i).freeze_version >= min_major_version) {
|
|
if (OB_FAIL(info_list_[next_idx].push_back(info_list_[cur_idx_].at(i)))) {
|
|
STORAGE_LOG(WARN, "fail to push back info", K(ret));
|
|
}
|
|
} else {
|
|
STORAGE_LOG(INFO, "update info, gc info list", K(info_list_[cur_idx_].at(i)));
|
|
}
|
|
}
|
|
|
|
if (gc_snapshot_info_[cur_idx_].created()) {
|
|
if (!gc_snapshot_info_[next_idx].created()) {
|
|
if (OB_FAIL(gc_snapshot_info_[next_idx].create(1024, ObModIds::OB_FREEZE_INFO_CACHE))) {
|
|
STORAGE_LOG(WARN, "fail to create hash bucket", K(ret));
|
|
}
|
|
}
|
|
|
|
for (hash::ObHashMap<uint64_t, GCSnapshotInfo>::iterator it = gc_snapshot_info_[cur_idx_].begin();
|
|
it != gc_snapshot_info_[cur_idx_].end() && OB_SUCC(ret);
|
|
++it) {
|
|
if (OB_FAIL(gc_snapshot_info_[next_idx].set_refactored(it->first, it->second))) {
|
|
STORAGE_LOG(WARN, "fail to push back into gc_snapshot_info", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::update_next_gc_schema_version(
|
|
const ObIArray<SchemaPair> &gc_schema_version, const int64_t gc_snapshot_ts)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t next_idx = get_next_idx();
|
|
hash::ObHashMap<uint64_t, GCSnapshotInfo> &next_gc_snapshot_info = gc_snapshot_info_[next_idx];
|
|
|
|
if (!next_gc_snapshot_info.created()) {
|
|
if (OB_FAIL(next_gc_snapshot_info.create(1024, ObModIds::OB_FREEZE_INFO_CACHE))) {
|
|
STORAGE_LOG(WARN, "fail to create hash bucket", K(ret));
|
|
}
|
|
}
|
|
|
|
for (int64_t i = 0; i < gc_schema_version.count() && OB_SUCC(ret); ++i) {
|
|
const SchemaPair &pair = gc_schema_version.at(i);
|
|
if (OB_INVALID_VERSION != pair.schema_version) {
|
|
if (OB_FAIL(next_gc_snapshot_info.set_refactored(
|
|
pair.tenant_id, GCSnapshotInfo(gc_snapshot_ts, pair.schema_version), 1 /*overwrite*/))) {
|
|
STORAGE_LOG(WARN, "fail to set schema version", K(ret));
|
|
}
|
|
} else {
|
|
STORAGE_LOG(WARN,
|
|
"receive invalid schema version from rs, may be memory explosion",
|
|
K(pair.tenant_id),
|
|
K(gc_snapshot_ts));
|
|
}
|
|
}
|
|
|
|
if (REACH_TIME_INTERVAL(60 * 1000 * 1000)) {
|
|
STORAGE_LOG(INFO, "update info", "gc schema version", gc_schema_version, K(gc_snapshot_ts));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::update_next_info_list(const ObIArray<FreezeInfoLite> &info_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t next_idx = get_next_idx();
|
|
ObIArray<FreezeInfoLite> &next_info_list = info_list_[next_idx];
|
|
|
|
for (int64_t i = 0; i < info_list.count() && OB_SUCC(ret); ++i) {
|
|
const FreezeInfoLite &next = info_list.at(i);
|
|
if (next_info_list.count() > 0) {
|
|
FreezeInfoLite &prev = next_info_list.at(next_info_list.count() - 1);
|
|
if (OB_UNLIKELY(prev.freeze_version > next.freeze_version)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
STORAGE_LOG(ERROR, "freeze verison decrease is not allowed", K(ret), K(prev), K(next));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(next_info_list.push_back(next))) {
|
|
STORAGE_LOG(WARN, "fail to push back freeze info", K(ret));
|
|
} else {
|
|
STORAGE_LOG(INFO, "update info", "freeze info", next);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::update_next_snapshots(const ObIArray<ObSnapshotInfo> &snapshots)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t next_idx = get_next_idx();
|
|
ObIArray<ObSnapshotInfo> &next_snapshots = snapshots_[next_idx];
|
|
|
|
for (int64_t i = 0; i < snapshots.count() && OB_SUCC(ret); ++i) {
|
|
if (OB_FAIL(next_snapshots.push_back(snapshots.at(i)))) {
|
|
STORAGE_LOG(WARN, "fail to push back snapshot", K(ret));
|
|
} else {
|
|
STORAGE_LOG(INFO, "update info", "snapshot", snapshots.at(i));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::update_info(const int64_t snapshot_gc_ts, const ObIArray<SchemaPair> &gc_schema_version,
|
|
const ObIArray<FreezeInfoLite> &info_list, const ObIArray<ObSnapshotInfo> &snapshots,
|
|
const int64_t min_major_version, bool &gc_snapshot_ts_changed)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
WLockGuard lock_guard(lock_);
|
|
|
|
gc_snapshot_ts_changed = snapshot_gc_ts != snapshot_gc_ts_;
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not init", K(ret));
|
|
} else if (OB_UNLIKELY(snapshot_gc_ts < snapshot_gc_ts_)) {
|
|
STORAGE_LOG(
|
|
INFO, "update snapshot gc ts is smaller than snapshot_gc_ts cache!", K(snapshot_gc_ts_), K(snapshot_gc_ts));
|
|
} else if (OB_FAIL(prepare_new_info_list(min_major_version))) {
|
|
STORAGE_LOG(WARN, "fail to prepare new info list", K(ret));
|
|
} else if (OB_FAIL(update_next_gc_schema_version(gc_schema_version, snapshot_gc_ts))) {
|
|
STORAGE_LOG(WARN, "fail to update next gc schema version", K(ret));
|
|
} else if (OB_FAIL(update_next_info_list(info_list))) {
|
|
STORAGE_LOG(WARN, "fail to update next info list", K(ret));
|
|
} else if (OB_FAIL(update_next_snapshots(snapshots))) {
|
|
STORAGE_LOG(WARN, "fail to update next snapshots", K(ret));
|
|
} else {
|
|
STORAGE_LOG(INFO, "update info commit", K(snapshot_gc_ts_), K(snapshot_gc_ts));
|
|
switch_info();
|
|
snapshot_gc_ts_ = snapshot_gc_ts;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int64_t ObFreezeInfoSnapshotMgr::get_snapshot_gc_ts()
|
|
{
|
|
RLockGuard lock_guard(lock_);
|
|
return snapshot_gc_ts_;
|
|
}
|
|
|
|
ObFreezeInfoSnapshotMgr::SchemaQuerySet::SchemaQuerySet(SchemaCache &schema_cache)
|
|
: schema_querys_(), schema_cache_(schema_cache), lock_(), inited_(false)
|
|
{}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaQuerySet::init()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_FAIL(schema_querys_.create(128))) {
|
|
STORAGE_LOG(WARN, "fail to init hash set", K(ret));
|
|
} else {
|
|
inited_ = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaQuerySet::submit_async_schema_query(
|
|
const uint64_t tenant_id, const int64_t freeze_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not inited", K(ret));
|
|
} else {
|
|
WLockGuard guard(lock_);
|
|
|
|
SchemaQuery query(tenant_id, freeze_version);
|
|
if (OB_FAIL(schema_querys_.set_refactored(query, 0))) {
|
|
if (OB_HASH_NOT_EXIST == ret) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
STORAGE_LOG(WARN, "fail to add new schema query");
|
|
} else {
|
|
STORAGE_LOG(INFO, "submit schema query", K(ret), K(tenant_id), K(freeze_version));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaQuerySet::update_schema_cache()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not inited", K(ret));
|
|
} else {
|
|
SchemaQuery query;
|
|
|
|
while (OB_SUCC(pop_schema_query(query))) {
|
|
int tmp_ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(
|
|
OB_SUCCESS != (tmp_ret = schema_cache_.update_schema_version(query.tenant_id_, query.freeze_version_)))) {
|
|
STORAGE_LOG(WARN, "fail to update schema cache", K(tmp_ret));
|
|
}
|
|
|
|
STORAGE_LOG(INFO,
|
|
"update schema cache",
|
|
K(tmp_ret),
|
|
"tenant_id",
|
|
query.tenant_id_,
|
|
"freeze_version",
|
|
query.freeze_version_);
|
|
}
|
|
|
|
if (OB_ITER_END == ret) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaQuerySet::pop_schema_query(SchemaQuery &query)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
WLockGuard guard(lock_);
|
|
|
|
ObHashSet<SchemaQuery>::iterator iter = schema_querys_.begin();
|
|
|
|
if (iter != schema_querys_.end()) {
|
|
query = iter->first;
|
|
schema_querys_.erase_refactored(query);
|
|
} else {
|
|
ret = OB_ITER_END;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
ObFreezeInfoSnapshotMgr::ReloadTask::ReloadTask(ObFreezeInfoSnapshotMgr &mgr, SchemaQuerySet &schema_query_set)
|
|
: inited_(false),
|
|
is_remote_(false),
|
|
mgr_(mgr),
|
|
sql_proxy_(NULL),
|
|
freeze_info_proxy_(),
|
|
snapshot_proxy_(),
|
|
last_change_ts_(0),
|
|
schema_query_set_(schema_query_set)
|
|
{}
|
|
|
|
int ObFreezeInfoSnapshotMgr::ReloadTask::init(ObISQLClient &sql_proxy, bool is_remote)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
STORAGE_LOG(WARN, "init twice", K(ret));
|
|
} else {
|
|
sql_proxy_ = &sql_proxy;
|
|
is_remote_ = is_remote;
|
|
last_change_ts_ = ObTimeUtility::current_time();
|
|
inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::ReloadTask::get_global_info_compat_below_220(
|
|
int64_t &snapshot_gc_ts, ObIArray<SchemaPair> &gc_schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t snapshot_gc_timestamp = 0;
|
|
ObGlobalStatProxy stat_proxy(*sql_proxy_);
|
|
ObSEArray<uint64_t, 64> tenant_ids;
|
|
|
|
if (OB_FAIL(ObTenantManager::get_instance().get_all_tenant_id(tenant_ids))) {
|
|
STORAGE_LOG(WARN, "fail to get all tenant id", K(ret));
|
|
} else if (OB_FAIL(stat_proxy.get_snapshot_info(snapshot_gc_ts, snapshot_gc_timestamp))) {
|
|
STORAGE_LOG(WARN, "fail to get global info", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; i < tenant_ids.count() && OB_SUCC(ret); ++i) {
|
|
uint64_t tenant_id = tenant_ids.at(i);
|
|
if (OB_FAIL(gc_schema_version.push_back(SchemaPair(tenant_id, snapshot_gc_timestamp)))) {
|
|
STORAGE_LOG(WARN, "fail to push back schema pair", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::ReloadTask::get_global_info(
|
|
int64_t &snapshot_gc_ts, ObIArray<SchemaPair> &gc_schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSEArray<TenantIdAndSchemaVersion, 64> tmp;
|
|
ObGlobalStatProxy stat_proxy(*sql_proxy_);
|
|
bool need_gc_schema_version = (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2230);
|
|
if (OB_FAIL(stat_proxy.get_snapshot_info_v2(*sql_proxy_, 0, need_gc_schema_version, snapshot_gc_ts, tmp))) {
|
|
STORAGE_LOG(WARN, "fail to get global info", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; i < tmp.count() && OB_SUCC(ret); ++i) {
|
|
TenantIdAndSchemaVersion &pair = tmp.at(i);
|
|
if (OB_FAIL(gc_schema_version.push_back(SchemaPair(pair.tenant_id_, pair.schema_version_)))) {
|
|
STORAGE_LOG(WARN, "fail to push back schema pair", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::ReloadTask::get_freeze_info(
|
|
int64_t &min_major_version, ObIArray<FreezeInfoLite> &freeze_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t freeze_version = 0;
|
|
min_major_version = INT64_MAX;
|
|
ObSEArray<ObSimpleFrozenStatus, 8> tmp;
|
|
|
|
if (OB_FAIL(mgr_.get_latest_freeze_version(freeze_version))) {
|
|
STORAGE_LOG(WARN, "fail to get major version", K(ret));
|
|
} else if (OB_FAIL(freeze_info_proxy_.get_min_major_available_and_larger_info(
|
|
*sql_proxy_, freeze_version, min_major_version, tmp))) {
|
|
STORAGE_LOG(WARN, "fail to get freeze info", K(ret), K(freeze_version));
|
|
} else {
|
|
for (int64_t i = 0; i < tmp.count() && OB_SUCC(ret); ++i) {
|
|
ObSimpleFrozenStatus &status = tmp.at(i);
|
|
if (OB_FAIL(freeze_info.push_back(
|
|
FreezeInfoLite(status.frozen_version_, status.frozen_timestamp_, status.cluster_version_)))) {
|
|
STORAGE_LOG(WARN, "fail to push back freeze info", K(ret), K(status));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::ReloadTask::try_update_info()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (!is_remote_) {
|
|
DEBUG_SYNC(BEFORE_UPDATE_FREEZE_SNAPSHOT_INFO);
|
|
}
|
|
STORAGE_LOG(INFO, "start reload freeze info and snapshots", K(is_remote_));
|
|
|
|
if (OB_ISNULL(sql_proxy_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(ERROR, "sql_proxy is NULL", K(ret));
|
|
} else if (is_remote_ && !GCTX.is_standby_cluster()) {
|
|
} else {
|
|
int64_t snapshot_gc_ts = 0;
|
|
ObSEArray<SchemaPair, 64> gc_schema_version;
|
|
// snapshot_gc_ts should be obtained before freeze_info and snapshots
|
|
ObSEArray<FreezeInfoLite, 4> freeze_info;
|
|
ObSEArray<ObSnapshotInfo, 4> snapshots;
|
|
bool changed = false;
|
|
observer::ObService *ob_service = GCTX.ob_service_;
|
|
int64_t min_major_version = INT64_MAX;
|
|
|
|
if (OB_FAIL(schema_query_set_.update_schema_cache())) {
|
|
STORAGE_LOG(WARN, "fail to update schema cache", K(ret));
|
|
ret = OB_SUCCESS; // ignore ret
|
|
}
|
|
|
|
if (OB_FAIL(get_global_info(snapshot_gc_ts, gc_schema_version))) {
|
|
STORAGE_LOG(WARN, "failed to get global info", K(ret));
|
|
} else if (OB_FAIL(get_freeze_info(min_major_version, freeze_info))) {
|
|
STORAGE_LOG(WARN, "failed to get freeze info", K(ret));
|
|
} else if (OB_FAIL(snapshot_proxy_.get_all_snapshots(*sql_proxy_, snapshots))) {
|
|
STORAGE_LOG(WARN, "failed to get snapshots", K(ret));
|
|
} else if (OB_FAIL(mgr_.update_info(
|
|
snapshot_gc_ts, gc_schema_version, freeze_info, snapshots, min_major_version, changed))) {
|
|
STORAGE_LOG(WARN, "update info failed", K(ret), K(snapshot_gc_ts), K(freeze_info), K(snapshots));
|
|
} else {
|
|
if (changed || ob_service->is_heartbeat_expired()) {
|
|
last_change_ts_ = ObTimeUtility::current_time();
|
|
} else {
|
|
const int64_t last_not_change_interval_us = ObTimeUtility::current_time() - last_change_ts_;
|
|
if (MAX_GC_SNAPSHOT_TS_REFRESH_TS <= last_not_change_interval_us &&
|
|
(0 != snapshot_gc_ts && 1 != snapshot_gc_ts)) {
|
|
if (REACH_TIME_INTERVAL(60L * 1000L * 1000L)) {
|
|
STORAGE_LOG(ERROR,
|
|
"snapshot_gc_ts not refresh too long",
|
|
K(snapshot_gc_ts),
|
|
K(freeze_info),
|
|
K(snapshots),
|
|
K(last_change_ts_),
|
|
K(last_not_change_interval_us));
|
|
}
|
|
} else if (FLUSH_GC_SNAPSHOT_TS_REFRESH_TS <= last_not_change_interval_us) {
|
|
STORAGE_LOG(WARN,
|
|
"snapshot_gc_ts not refresh too long",
|
|
K(snapshot_gc_ts),
|
|
K(freeze_info),
|
|
K(snapshots),
|
|
K(last_change_ts_),
|
|
K(last_not_change_interval_us));
|
|
}
|
|
}
|
|
|
|
STORAGE_LOG(DEBUG, "reload freeze info and snapshots", K(snapshot_gc_ts), K(freeze_info), K(snapshots));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezeInfoSnapshotMgr::ReloadTask::runTimerTask()
|
|
{
|
|
try_update_info();
|
|
}
|
|
|
|
ObFreezeInfoSnapshotMgr::SchemaCache::SchemaCache(SchemaQuerySet &schema_query_set)
|
|
: lock_(),
|
|
head_(NULL),
|
|
tail_(NULL),
|
|
cnt_(0),
|
|
inited_(false),
|
|
sql_proxy_(NULL),
|
|
freeze_info_proxy_(),
|
|
mem_attr_(OB_SERVER_TENANT_ID, ObModIds::OB_FREEZE_INFO_CACHE),
|
|
allocator_(sizeof(schema_node), mem_attr_),
|
|
schema_query_set_(schema_query_set)
|
|
{}
|
|
|
|
ObFreezeInfoSnapshotMgr::SchemaCache::~SchemaCache()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::init(ObISQLClient &sql_proxy)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
schema_node *p = NULL;
|
|
|
|
if (OB_UNLIKELY(inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
} else if (NULL == (p = (schema_node *)allocator_.alloc())) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
STORAGE_LOG(WARN, "fail to alloc head node", K(ret));
|
|
} else {
|
|
p->reset();
|
|
head_ = tail_ = p;
|
|
sql_proxy_ = &sql_proxy;
|
|
inited_ = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezeInfoSnapshotMgr::SchemaCache::reset()
|
|
{
|
|
if (!inited_) {
|
|
return;
|
|
}
|
|
|
|
SpinLockGuard guard(lock_);
|
|
|
|
schema_node *curr = head_;
|
|
schema_node *t = NULL;
|
|
|
|
while (curr) {
|
|
t = curr;
|
|
curr = curr->next;
|
|
|
|
allocator_.free(t);
|
|
}
|
|
|
|
head_ = tail_ = NULL;
|
|
cnt_ = 0;
|
|
inited_ = false;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::get_freeze_schema_version(
|
|
const uint64_t tenant_id, const int64_t freeze_version, const bool async, int64_t &schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not inited", K(ret));
|
|
} else {
|
|
bool schema_decided = false;
|
|
schema_version = ObFrozenStatus::INVALID_SCHEMA_VERSION;
|
|
if (OB_FAIL(find(tenant_id, freeze_version, schema_version))) {
|
|
STORAGE_LOG(WARN, "fail to find in cache", K(ret), K(tenant_id), K(freeze_version));
|
|
} else if (ObFrozenStatus::INVALID_SCHEMA_VERSION == schema_version || OB_INVALID_VERSION == schema_version) {
|
|
// cache miss
|
|
if (async) {
|
|
ret = OB_EAGAIN;
|
|
STORAGE_LOG(INFO, "async query freeze schema", K(tenant_id), K(freeze_version));
|
|
|
|
int tmp_ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(
|
|
OB_SUCCESS != (tmp_ret = schema_query_set_.submit_async_schema_query(tenant_id, freeze_version)))) {
|
|
STORAGE_LOG(WARN, "fail to submit async query task", K(tmp_ret), K(tenant_id), K(freeze_version));
|
|
}
|
|
} else if (freeze_info_exist(freeze_version)) {
|
|
// only specific tenant
|
|
schema_decided = true;
|
|
if (OB_FAIL(fetch_freeze_schema(tenant_id, freeze_version, schema_version))) {
|
|
STORAGE_LOG(WARN, "fail to fetch freeze schema", K(ret), K(tenant_id), K(freeze_version));
|
|
} else if (ObFrozenStatus::INVALID_SCHEMA_VERSION != schema_version && OB_INVALID_VERSION != schema_version) {
|
|
if (OB_FAIL(update_freeze_schema(tenant_id, freeze_version, schema_version))) {
|
|
STORAGE_LOG(
|
|
WARN, "fail to update freeze schema", K(ret), K(tenant_id), K(freeze_version), K(schema_version));
|
|
}
|
|
}
|
|
} else {
|
|
// all local tenant
|
|
ObSEArray<SchemaPair, 32> freeze_schema;
|
|
if (OB_FAIL(fetch_freeze_schema(tenant_id, freeze_version, schema_version, freeze_schema))) {
|
|
STORAGE_LOG(WARN, "fail to fetch freeze schema", K(ret), K(freeze_version));
|
|
} else if (freeze_schema.count() > 0) {
|
|
schema_decided = true;
|
|
if (OB_FAIL(update_freeze_schema(freeze_version, freeze_schema))) {
|
|
STORAGE_LOG(WARN, "fail to update freeze schema", K(ret), K(freeze_version), K(freeze_schema));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (ObFrozenStatus::INVALID_SCHEMA_VERSION == schema_version) {
|
|
if (schema_decided) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
STORAGE_LOG(INFO, "tenant schema not exist", K(ret), K(tenant_id), K(freeze_version));
|
|
} else {
|
|
ret = OB_EAGAIN;
|
|
}
|
|
} else if (OB_INVALID_VERSION == schema_version) {
|
|
ret = OB_EAGAIN;
|
|
STORAGE_LOG(WARN,
|
|
"get invalid version(-1) for schema version, may be memory explosion for tenant",
|
|
K(ret),
|
|
K(tenant_id),
|
|
K(freeze_version));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::update_schema_version(const uint64_t tenant_id, const int64_t freeze_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
int64_t schema_version = OB_INVALID_VERSION;
|
|
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
STORAGE_LOG(WARN, "not inited", K(ret));
|
|
} else if (schema_exist(tenant_id, freeze_version)) {
|
|
} else if (OB_FAIL(fetch_freeze_schema(tenant_id, freeze_version, schema_version))) {
|
|
STORAGE_LOG(WARN, "fail to fetch freeze schema", K(ret), K(tenant_id), K(freeze_version));
|
|
} else if (ObFrozenStatus::INVALID_SCHEMA_VERSION != schema_version && OB_INVALID_VERSION != schema_version) {
|
|
if (OB_FAIL(update_freeze_schema(tenant_id, freeze_version, schema_version))) {
|
|
STORAGE_LOG(WARN, "fail to update freeze schema", K(ret), K(tenant_id), K(freeze_version), K(schema_version));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezeInfoSnapshotMgr::SchemaCache::insert(schema_node *p)
|
|
{
|
|
p->next = head_->next;
|
|
p->prev = head_;
|
|
|
|
if (head_->next)
|
|
head_->next->prev = p;
|
|
head_->next = p;
|
|
if (!p->next)
|
|
tail_ = p;
|
|
}
|
|
|
|
void ObFreezeInfoSnapshotMgr::SchemaCache::move_forward(schema_node *p)
|
|
{
|
|
if (!p->next) {
|
|
tail_ = p->prev;
|
|
} else {
|
|
p->next->prev = p->prev;
|
|
}
|
|
p->prev->next = p->next;
|
|
|
|
insert(p);
|
|
}
|
|
|
|
ObFreezeInfoSnapshotMgr::SchemaCache::schema_node *ObFreezeInfoSnapshotMgr::SchemaCache::inner_find(
|
|
const uint64_t tenant_id, const int64_t freeze_version)
|
|
{
|
|
schema_node *node = NULL;
|
|
schema_node *prev = head_;
|
|
schema_node *curr = prev->next;
|
|
|
|
while (curr) {
|
|
if (curr->tenant_id == tenant_id && curr->freeze_version == freeze_version) {
|
|
node = curr;
|
|
break;
|
|
}
|
|
|
|
prev = curr;
|
|
curr = prev->next;
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::find(
|
|
const uint64_t tenant_id, const int64_t freeze_version, int64_t &schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
SpinLockGuard guard(lock_);
|
|
|
|
schema_node *node = inner_find(tenant_id, freeze_version);
|
|
if (NULL != node) {
|
|
schema_version = node->schema_version;
|
|
move_forward(node);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool ObFreezeInfoSnapshotMgr::SchemaCache::freeze_info_exist(const int64_t freeze_version)
|
|
{
|
|
bool bool_ret = false;
|
|
|
|
SpinLockGuard guard(lock_);
|
|
|
|
schema_node *curr = head_;
|
|
do {
|
|
curr = curr->next;
|
|
if (curr && curr->freeze_version == freeze_version) {
|
|
bool_ret = true;
|
|
break;
|
|
}
|
|
} while (curr);
|
|
|
|
return bool_ret;
|
|
}
|
|
|
|
bool ObFreezeInfoSnapshotMgr::SchemaCache::schema_exist(const uint64_t tenant_id, const int64_t freeze_version)
|
|
{
|
|
SpinLockGuard guard(lock_);
|
|
return inner_schema_exist(tenant_id, freeze_version);
|
|
}
|
|
|
|
bool ObFreezeInfoSnapshotMgr::SchemaCache::inner_schema_exist(const uint64_t tenant_id, const int64_t freeze_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool bool_ret = false;
|
|
|
|
schema_node *node = inner_find(tenant_id, freeze_version);
|
|
if (NULL != node) {
|
|
bool_ret = true;
|
|
}
|
|
|
|
return bool_ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::update_freeze_schema(
|
|
const uint64_t tenant_id, const int64_t freeze_version, const int64_t schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
SpinLockGuard guard(lock_);
|
|
|
|
if (inner_schema_exist(tenant_id, freeze_version)) {
|
|
// skip
|
|
} else if (cnt_ < MAX_SCHEMA_ENTRY) {
|
|
schema_node *p = NULL;
|
|
if (NULL == (p = (schema_node *)allocator_.alloc())) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
STORAGE_LOG(WARN, "fail to alloc schema node", K(ret));
|
|
} else {
|
|
p->reset();
|
|
p->set(tenant_id, freeze_version, schema_version);
|
|
insert(p);
|
|
cnt_++;
|
|
}
|
|
} else {
|
|
schema_node *p = tail_;
|
|
p->set(tenant_id, freeze_version, schema_version);
|
|
move_forward(p);
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
STORAGE_LOG(INFO, "update freeze schema", K(tenant_id), K(freeze_version), K(schema_version));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::update_freeze_schema(
|
|
const int64_t freeze_version, ObIArray<SchemaPair> &freeze_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
for (int64_t i = 0; i < freeze_schema.count() && OB_SUCC(ret); ++i) {
|
|
SchemaPair &pair = freeze_schema.at(i);
|
|
if (OB_FAIL(update_freeze_schema(pair.tenant_id, freeze_version, pair.schema_version))) {
|
|
STORAGE_LOG(WARN, "fail to update freeze schema", K(ret), K(freeze_version), K(pair));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::fetch_freeze_schema(
|
|
const uint64_t tenant_id, const int64_t freeze_version, int64_t &schema_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObFrozenStatus status;
|
|
if (OB_FAIL(freeze_info_proxy_.get_freeze_info_v2(*sql_proxy_, tenant_id, freeze_version, status))) {
|
|
STORAGE_LOG(WARN, "fail to get freeze info", K(ret), K(tenant_id), K(freeze_version));
|
|
} else if (status.schema_version_ != ObFrozenStatus::INVALID_SCHEMA_VERSION) {
|
|
schema_version = status.schema_version_;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoSnapshotMgr::SchemaCache::fetch_freeze_schema(const uint64_t tenant_id, const int64_t freeze_version,
|
|
int64_t &schema_version, ObIArray<SchemaPair> &freeze_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
ObSEArray<TenantIdAndSchemaVersion, 64> tmp;
|
|
ObFrozenStatus old_status;
|
|
if (OB_FAIL(freeze_info_proxy_.get_freeze_info_v2(*sql_proxy_, freeze_version, old_status, tmp))) {
|
|
STORAGE_LOG(WARN, "fail to get freeze info", K(ret), K(freeze_version));
|
|
} else if (old_status.schema_version_ > 0) {
|
|
// minor freeze before 2.2.x
|
|
schema_version = old_status.schema_version_;
|
|
if (OB_FAIL(freeze_schema.push_back(SchemaPair(tenant_id, schema_version)))) {
|
|
STORAGE_LOG(WARN, "fail to push back schema pair", K(ret));
|
|
}
|
|
} else if (tmp.count() > 0) {
|
|
for (int64_t i = 0; i < tmp.count() && OB_SUCC(ret); ++i) {
|
|
TenantIdAndSchemaVersion &pair = tmp.at(i);
|
|
|
|
if (tenant_id == pair.tenant_id_) {
|
|
schema_version = pair.schema_version_;
|
|
}
|
|
|
|
// ignore schema version that remote doesn't know
|
|
if (OB_INVALID_VERSION != pair.schema_version_) {
|
|
if (tenant_id == pair.tenant_id_ || ObTenantManager::get_instance().has_tenant(pair.tenant_id_)) {
|
|
if (OB_FAIL(freeze_schema.push_back(SchemaPair(pair.tenant_id_, pair.schema_version_)))) {
|
|
STORAGE_LOG(WARN, "fail to push back schema pair", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
ObFreezeInfoSnapshotMgr &ObFreezeInfoMgrWrapper::get_instance(const uint64_t table_id)
|
|
{
|
|
bool remote_table =
|
|
OB_INVALID_ID != table_id && is_sys_table(table_id) && !ObMultiClusterUtil::is_cluster_private_table(table_id);
|
|
bool use_remote = GCTX.is_standby_cluster() && remote_table;
|
|
|
|
if (use_remote) {
|
|
STORAGE_LOG(INFO, "use remote freeze info", K(table_id));
|
|
return remote_mgr_;
|
|
} else {
|
|
return local_mgr_;
|
|
}
|
|
}
|
|
|
|
int ObFreezeInfoMgrWrapper::init(common::ObISQLClient &local_proxy, common::ObISQLClient &remote_proxy)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_FAIL(local_mgr_.init(local_proxy, false))) {
|
|
STORAGE_LOG(ERROR, "fail to init local mgr", K(ret));
|
|
} else if (OB_FAIL(remote_mgr_.init(remote_proxy, true))) {
|
|
STORAGE_LOG(ERROR, "fail to init remote mgr", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObFreezeInfoMgrWrapper::start()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_FAIL(local_mgr_.start())) {
|
|
STORAGE_LOG(ERROR, "fail to start local mgr", K(ret));
|
|
} else if (OB_FAIL(remote_mgr_.start())) {
|
|
STORAGE_LOG(ERROR, "fail to start remote mgr", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObFreezeInfoMgrWrapper::wait()
|
|
{
|
|
local_mgr_.wait();
|
|
remote_mgr_.wait();
|
|
}
|
|
|
|
void ObFreezeInfoMgrWrapper::stop()
|
|
{
|
|
local_mgr_.stop();
|
|
remote_mgr_.stop();
|
|
}
|
|
|
|
ObFreezeInfoSnapshotMgr ObFreezeInfoMgrWrapper::local_mgr_;
|
|
ObFreezeInfoSnapshotMgr ObFreezeInfoMgrWrapper::remote_mgr_;
|
|
|
|
} // namespace storage
|
|
} // namespace oceanbase
|