442 lines
14 KiB
C++
442 lines
14 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 SHARE
|
|
|
|
#include "share/tablet/ob_tablet_table_iterator.h"
|
|
#include "share/tablet/ob_tablet_info.h"
|
|
#include "share/tablet/ob_tablet_to_ls_operator.h"
|
|
#include "share/schema/ob_part_mgr_util.h"
|
|
#include "share/schema/ob_multi_version_schema_service.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "share/ob_tablet_meta_table_compaction_operator.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace share
|
|
{
|
|
using namespace common;
|
|
using namespace schema;
|
|
|
|
|
|
ObTabletMetaIterator::ObTabletMetaIterator()
|
|
: is_inited_(false),
|
|
prefetch_tablet_idx_(0),
|
|
tenant_id_(OB_INVALID_TENANT_ID)
|
|
{}
|
|
|
|
void ObTabletMetaIterator::reset()
|
|
{
|
|
is_inited_ = false;
|
|
tenant_id_ = OB_INVALID_TENANT_ID;
|
|
prefetch_tablet_idx_ = -1;
|
|
prefetched_tablets_.reset();
|
|
}
|
|
|
|
int ObTabletMetaIterator::inner_init(
|
|
const uint64_t tenant_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_INIT) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_WARN("ObLSTabletMetaIterator init twice", KR(ret));
|
|
} else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("tenant_id invalid", KR(ret), K(tenant_id));
|
|
} else {
|
|
tenant_id_ = tenant_id;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTabletMetaIterator::next(ObTabletInfo &tablet_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not init", KR(ret));
|
|
} else if (prefetch_tablet_idx_ == -1) {
|
|
ret = OB_ITER_END;
|
|
} else {
|
|
bool find = false;
|
|
while (OB_SUCC(ret) && !find) {
|
|
if (prefetch_tablet_idx_ < prefetched_tablets_.count()) {
|
|
// directly get from prefetched tablet_info
|
|
tablet_info.reset();
|
|
if (OB_FAIL(tablet_info.assign(prefetched_tablets_.at(prefetch_tablet_idx_)))) {
|
|
LOG_WARN("fail to assign tablet_info", KR(ret), K_(prefetch_tablet_idx));
|
|
} else if (tablet_info.replica_count() > 0) {
|
|
//
|
|
if (OB_FAIL(tablet_info.filter(filters_))) {
|
|
LOG_WARN("fail to filter tablet_info", KR(ret), K(tablet_info));
|
|
} else {
|
|
find = true;
|
|
}
|
|
}
|
|
++prefetch_tablet_idx_;
|
|
} else if (OB_FAIL(prefetch())) { // need to prefetch a batch of tablet_info
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("fail to prefetch", KR(ret), K_(tenant_id), K_(prefetch_tablet_idx));
|
|
}
|
|
prefetch_tablet_idx_ = -1;
|
|
} else {
|
|
prefetch_tablet_idx_ = 0;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* -------------------------------------------------------------------ObCompactionTabletMetaIterator-------------------------------------------------------------------
|
|
*/
|
|
ObCompactionTabletMetaIterator::ObCompactionTabletMetaIterator(
|
|
const bool first_check, const int64_t compaction_scn)
|
|
: ObTabletMetaIterator(),
|
|
first_check_(first_check),
|
|
compaction_scn_(compaction_scn),
|
|
batch_size_(TABLET_META_TABLE_RANGE_GET_SIZE),
|
|
end_tablet_id_()
|
|
{}
|
|
|
|
void ObCompactionTabletMetaIterator::reset()
|
|
{
|
|
ObTabletMetaIterator::reset();
|
|
first_check_ = false;
|
|
compaction_scn_ = 0;
|
|
end_tablet_id_.reset();
|
|
batch_size_ = 0;
|
|
}
|
|
|
|
int ObCompactionTabletMetaIterator::init(
|
|
const uint64_t tenant_id,
|
|
const int64_t batch_size,
|
|
share::ObIServerTrace &server_trace)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(batch_size <= 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", KR(ret), K(batch_size));
|
|
} else if (OB_FAIL(ObTabletMetaIterator::inner_init(tenant_id))) {
|
|
LOG_WARN("failed to init", KR(ret), K(tenant_id));
|
|
// Keep set_filter_not_exist_server before setting all the other filters,
|
|
// otherwise the other filters may return OB_ENTRY_NOT_EXIST error code.
|
|
} else if (OB_FAIL(filters_.set_filter_not_exist_server(server_trace))) {
|
|
LOG_WARN("fail to set not exist server filter", KR(ret), K(tenant_id));
|
|
} else if (OB_FAIL(filters_.set_filter_permanent_offline(server_trace))) {
|
|
LOG_WARN("fail to set filter", KR(ret), K(tenant_id));
|
|
} else {
|
|
batch_size_ = batch_size;
|
|
is_inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObCompactionTabletMetaIterator::prefetch()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (prefetch_tablet_idx_ >= prefetched_tablets_.count()) {
|
|
ObTabletID tmp_last_tablet_id;
|
|
if (OB_FAIL(ObTabletMetaTableCompactionOperator::range_scan_for_compaction(
|
|
tenant_id_,
|
|
compaction_scn_,
|
|
end_tablet_id_,
|
|
batch_size_,
|
|
!first_check_/*add_report_scn_filter*/,
|
|
tmp_last_tablet_id,
|
|
prefetched_tablets_))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("fail to range get by operator", KR(ret),
|
|
K_(tenant_id), K_(end_tablet_id), K_(batch_size), K_(prefetched_tablets));
|
|
} else {
|
|
prefetch_tablet_idx_ = -1;
|
|
}
|
|
} else if (prefetched_tablets_.count() <= 0) {
|
|
prefetch_tablet_idx_ = -1;
|
|
ret = OB_ITER_END;
|
|
} else {
|
|
end_tablet_id_ = tmp_last_tablet_id;
|
|
prefetch_tablet_idx_ = 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
ObTenantTabletMetaIterator::ObTenantTabletMetaIterator()
|
|
: ObTabletMetaIterator(),
|
|
first_prefetch_(true),
|
|
sql_proxy_(nullptr),
|
|
valid_tablet_ls_pairs_idx_(0)
|
|
{
|
|
}
|
|
|
|
ObTenantTabletMetaIterator::~ObTenantTabletMetaIterator()
|
|
{
|
|
}
|
|
|
|
int ObTenantTabletMetaIterator::init(
|
|
common::ObISQLClient &sql_proxy,
|
|
const uint64_t tenant_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(ObTabletMetaIterator::inner_init(tenant_id))) {
|
|
LOG_WARN("fail to init", KR(ret), K(tenant_id));
|
|
} else if (OB_FAIL(tablet_table_operator_.init(sql_proxy))) {
|
|
LOG_WARN("fail to init tablet table operator", KR(ret), K(tenant_id));
|
|
} else {
|
|
sql_proxy_ = &sql_proxy;
|
|
valid_tablet_ls_pairs_.reuse();
|
|
valid_tablet_ls_pairs_idx_ = 0;
|
|
if (OB_FAIL(prefetch())) { // need to prefetch a batch of tablet_info
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("fail to prefetch", KR(ret), K_(tenant_id), K_(prefetch_tablet_idx));
|
|
}
|
|
} else {
|
|
is_inited_ = true;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObTenantTabletMetaIterator::reset()
|
|
{
|
|
ObTabletMetaIterator::reset();
|
|
first_prefetch_ = true;
|
|
sql_proxy_ = nullptr;
|
|
valid_tablet_ls_pairs_idx_ = -1;
|
|
valid_tablet_ls_pairs_.reset();
|
|
tablet_table_operator_.reset();
|
|
}
|
|
|
|
int ObTenantTabletMetaIterator::prefetch()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(prefetch_valid_tablet_ids())) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("fail to prefetch valid tablet ids", KR(ret), K_(tenant_id),
|
|
K_(valid_tablet_ls_pairs_idx), K_(valid_tablet_ls_pairs));
|
|
}
|
|
} else if (OB_FAIL(prefetch_tablets())) {
|
|
LOG_WARN("fail to prefetch tablets", KR(ret), K_(tenant_id),
|
|
K_(prefetch_tablet_idx), "prefetch count", prefetched_tablets_.count());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTenantTabletMetaIterator::prefetch_valid_tablet_ids()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObTenantTabletMetaIterator is not inited", KR(ret));
|
|
} else if (OB_UNLIKELY(prefetch_tablet_idx_ != prefetched_tablets_.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("prefetched valid tablet ids have not been iterated to end",
|
|
KR(ret), K_(valid_tablet_ls_pairs_idx), "tablet ls pair count",
|
|
valid_tablet_ls_pairs_.count());
|
|
} else {
|
|
// for any tenant, firstly, get its sys tables' tablet_ids, then get user
|
|
// tables' tablet_ids if it has user tables.
|
|
if (first_prefetch_) {
|
|
if (OB_FAIL(prefetch_sys_table_tablet_ids())) {
|
|
LOG_WARN("fail to prefetch sys tables' tablet_id", KR(ret), K_(tenant_id));
|
|
} else {
|
|
first_prefetch_ = false;
|
|
}
|
|
} else if (OB_FAIL(prefetch_user_table_tablet_ids())) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("fail to prefetch user tables' tablet_id", KR(ret), K_(tenant_id));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTenantTabletMetaIterator::prefetch_tablets()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObTenantTabletMetaIterator is not inited", KR(ret));
|
|
} else if (OB_UNLIKELY(prefetch_tablet_idx_ != prefetched_tablets_.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("prefetched tablet infos have not been iterated to end",
|
|
KR(ret), K_(prefetch_tablet_idx),
|
|
"prefetched tablet count", prefetched_tablets_.count());
|
|
} else {
|
|
prefetch_tablet_idx_ = 0;
|
|
prefetched_tablets_.reuse();
|
|
|
|
if (OB_FAIL(tablet_table_operator_.batch_get(tenant_id_,
|
|
valid_tablet_ls_pairs_,
|
|
prefetched_tablets_))) {
|
|
LOG_WARN("fail to do batch_get through tablet_table_operator", KR(ret),
|
|
K_(tenant_id), K_(valid_tablet_ls_pairs), K_(prefetched_tablets));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTenantTabletMetaIterator::prefetch_sys_table_tablet_ids()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSchemaGetterGuard schema_guard;
|
|
ObArray<const ObSimpleTableSchemaV2 *> table_schemas;
|
|
if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_full_schema_guard(tenant_id_, schema_guard))) {
|
|
LOG_WARN("fail to get tenant schema guard", KR(ret), K_(tenant_id));
|
|
} else if (OB_FAIL(schema_guard.get_table_schemas_in_tenant(tenant_id_, table_schemas))) {
|
|
LOG_WARN("fail to get tenant table schemas", KR(ret), K_(tenant_id));
|
|
} else {
|
|
ObTabletLSPair pair;
|
|
for (int64_t i = 0; (i < table_schemas.count()) && OB_SUCC(ret); ++i) {
|
|
const ObSimpleTableSchemaV2 *simple_schema = table_schemas.at(i);
|
|
if (OB_ISNULL(simple_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected err, table schema is null", KR(ret), K_(tenant_id));
|
|
} else {
|
|
const uint64_t tid = simple_schema->get_table_id();
|
|
if (is_sys_table(tid)) {
|
|
// sys-table only has one tablet in 4.0 version
|
|
const ObTabletID &tablet_id = simple_schema->get_tablet_id();
|
|
pair.reset();
|
|
if (OB_FAIL(pair.init(tablet_id, SYS_LS))) {
|
|
LOG_WARN("fail to init tablet_ls_pair", KR(ret), K(tablet_id));
|
|
} else if (OB_FAIL(valid_tablet_ls_pairs_.push_back(pair))) {
|
|
LOG_WARN("fail to push back tablet_ls_pair", KR(ret), K(pair));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTenantTabletMetaIterator::prefetch_user_table_tablet_ids()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObTabletID start_tablet_id;
|
|
if (valid_tablet_ls_pairs_.count() <= 0) {
|
|
// start with default invalid ObTabletLSPair(0,-1) in the first time
|
|
} else {
|
|
const int64_t last_idx = valid_tablet_ls_pairs_.count() - 1;
|
|
start_tablet_id = valid_tablet_ls_pairs_.at(last_idx).get_tablet_id();
|
|
}
|
|
const int64_t range_count = GCONF.tablet_meta_table_scan_batch_count;
|
|
valid_tablet_ls_pairs_.reuse();
|
|
if (OB_FAIL(ObTabletToLSTableOperator::range_get_tablet(
|
|
*sql_proxy_,
|
|
tenant_id_,
|
|
start_tablet_id,
|
|
range_count,
|
|
valid_tablet_ls_pairs_))) {
|
|
LOG_WARN("fail to get a range of tablet through tablet_to_ls_table_operator",
|
|
KR(ret), K_(tenant_id), K(start_tablet_id), K(range_count),
|
|
K_(valid_tablet_ls_pairs));
|
|
} else if (valid_tablet_ls_pairs_.count() <= 0) {
|
|
ret = OB_ITER_END;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
ObTenantTabletTableIterator::ObTenantTabletTableIterator()
|
|
: inited_(false),
|
|
tenant_id_(OB_INVALID_TENANT_ID),
|
|
inner_idx_(0),
|
|
tt_operator_(NULL),
|
|
inner_tablet_infos_(),
|
|
filters_()
|
|
{
|
|
}
|
|
|
|
int ObTenantTabletTableIterator::init(ObTabletTableOperator &tt_operator, const uint64_t tenant_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_WARN("init twice", KR(ret));
|
|
} else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid tenant_id", KR(ret), K(tenant_id));
|
|
} else {
|
|
tt_operator_ = &tt_operator;
|
|
tenant_id_ = tenant_id;
|
|
inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTenantTabletTableIterator::next(ObTabletInfo &tablet_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not init", KR(ret));
|
|
} else if (OB_UNLIKELY(inner_idx_ < 0)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("inner_idx_ can't be smaller than 0", KR(ret), K_(inner_idx));
|
|
} else {
|
|
tablet_info.reset();
|
|
if (inner_idx_ >= inner_tablet_infos_.count()) {
|
|
if (OB_FAIL(prefetch_())) {
|
|
if (OB_UNLIKELY(OB_ITER_END != ret)) {
|
|
LOG_WARN("fail to prfetch", KR(ret));
|
|
}
|
|
} else {
|
|
inner_idx_ = 0;
|
|
}
|
|
}
|
|
if (FAILEDx(tablet_info.assign(inner_tablet_infos_[inner_idx_]))) {
|
|
LOG_WARN("failed to assign tablet_info",
|
|
KR(ret), K_(inner_idx), K_(inner_tablet_infos));
|
|
} else if (OB_FAIL(tablet_info.filter(filters_))) {
|
|
LOG_WARN("fail to filter tablet info", KR(ret), K(tablet_info));
|
|
} else {
|
|
++inner_idx_;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTenantTabletTableIterator::prefetch_()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!inited_) || OB_ISNULL(tt_operator_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not init", KR(ret));
|
|
} else {
|
|
ObTabletID last_tablet_id; // start with INVALID_TABLET_ID = 0
|
|
if (inner_tablet_infos_.count() > 0) {
|
|
const int64_t last_idx = inner_tablet_infos_.count() - 1;
|
|
last_tablet_id = inner_tablet_infos_.at(last_idx).get_tablet_id();
|
|
}
|
|
inner_tablet_infos_.reset();
|
|
const int64_t range_size = GCONF.tablet_meta_table_scan_batch_count;
|
|
if (OB_FAIL(tt_operator_->range_get(
|
|
tenant_id_,
|
|
last_tablet_id,
|
|
range_size,
|
|
inner_tablet_infos_))) {
|
|
LOG_WARN("fail to range get by operator", KR(ret),
|
|
K_(tenant_id), K(last_tablet_id), K(range_size), K_(inner_tablet_infos));
|
|
} else if (inner_tablet_infos_.count() <= 0) {
|
|
ret = OB_ITER_END;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // end namespace share
|
|
} // end namespace oceanbase
|