Files
oceanbase/src/rootserver/ob_tablet_creator.cpp
xuhuleon 9dae112952 [FEAT MERGE] merge transfer
Co-authored-by: wxhwang <wxhwang@126.com>
Co-authored-by: godyangfight <godyangfight@gmail.com>
Co-authored-by: Tyshawn <tuyunshan@gmail.com>
2023-06-21 11:42:28 +00:00

364 lines
13 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 RS
#include "ob_tablet_creator.h"
//#include "ob_freeze_info_manager.h"
#include "storage/tx/ob_trans_service.h"
#include "ob_root_service.h"
#include "lib/allocator/page_arena.h"
#include "share/ob_share_util.h"
#include "observer/ob_inner_sql_connection.h"
#include "storage/tx/ob_tx_log.h"
namespace oceanbase
{
using namespace share;
namespace rootserver
{
bool ObTabletCreatorArg::is_valid() const
{
bool is_valid = ls_key_.is_valid()
&& table_schemas_.count() > 0
&& table_schemas_.count() == tablet_ids_.count()
&& lib::Worker::CompatMode::INVALID != compat_mode_;
for (int64_t i = 0; i < tablet_ids_.count() && is_valid; i++) {
is_valid = tablet_ids_.at(i).is_valid();
}
return is_valid;
}
void ObTabletCreatorArg::reset()
{
tablet_ids_.reset();
ls_key_.reset();
table_schemas_.reset();
data_tablet_id_.reset();
compat_mode_ = lib::Worker::CompatMode::INVALID;
is_create_bind_hidden_tablets_ = false;
}
int ObTabletCreatorArg::assign(const ObTabletCreatorArg &arg)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("arg is invalid", KR(ret), K(arg));
} else if (OB_FAIL(table_schemas_.assign(arg.table_schemas_))) {
LOG_WARN("failed to assign table schemas", KR(ret), K(arg));
} else if (OB_FAIL(tablet_ids_.assign(arg.tablet_ids_))) {
LOG_WARN("failed to assign table schemas", KR(ret), K(arg));
} else {
data_tablet_id_ = arg.data_tablet_id_;
ls_key_ = arg.ls_key_;
compat_mode_ = arg.compat_mode_;
is_create_bind_hidden_tablets_ = arg.is_create_bind_hidden_tablets_;
}
return ret;
}
int ObTabletCreatorArg::init(
const ObIArray<common::ObTabletID> &tablet_ids,
const share::ObLSID &ls_key,
const ObTabletID data_tablet_id,
const ObIArray<const share::schema::ObTableSchema*> &table_schemas,
const lib::Worker::CompatMode &mode,
const bool is_create_bind_hidden_tablets)
{
int ret = OB_SUCCESS;
bool is_valid = ls_key.is_valid() && table_schemas.count() > 0
&& table_schemas.count() == tablet_ids.count();
for (int64_t i = 0; i < tablet_ids.count() && is_valid; i++) {
is_valid = tablet_ids.at(i).is_valid();
}
if (OB_UNLIKELY(!is_valid)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tablet_ids),
"count", table_schemas.count(), K(tablet_ids), K(ls_key));
} else if (OB_FAIL(tablet_ids_.assign(tablet_ids))) {
LOG_WARN("failed to assign table schemas", KR(ret), K(table_schemas));
} else if (OB_FAIL(table_schemas_.assign(table_schemas))) {
LOG_WARN("failed to assign table schemas", KR(ret), K(table_schemas));
} else {
data_tablet_id_ = data_tablet_id;
ls_key_ = ls_key;
compat_mode_ = mode;
is_create_bind_hidden_tablets_ = is_create_bind_hidden_tablets;
}
return ret;
}
DEF_TO_STRING(ObTabletCreatorArg)
{
int64_t pos = 0;
J_KV(K_(compat_mode), K_(tablet_ids), K_(data_tablet_id), K_(ls_key), K_(table_schemas), K_(is_create_bind_hidden_tablets));
return pos;
}
/////////////////////////////////////////////////////////
int ObBatchCreateTabletHelper::init(
const share::ObLSID &ls_key,
const int64_t tenant_id,
const SCN &major_frozen_scn,
const bool need_check_tablet_cnt)
{
int ret = OB_SUCCESS;
const int64_t bucket_count = hash::cal_next_prime(100);
if (OB_UNLIKELY(!ls_key.is_valid()
|| OB_INVALID_TENANT_ID == tenant_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(ls_key));
} else if (OB_FAIL(arg_.init_create_tablet(ls_key, major_frozen_scn, need_check_tablet_cnt))) {
LOG_WARN("failed to init create tablet", KR(ret), K(tenant_id), K(ls_key), K(major_frozen_scn));
} else if (OB_FAIL(table_schemas_map_.create(bucket_count, "CreateTablet", "CreateTablet"))) {
LOG_WARN("failed to create hashmap", KR(ret));
}
return ret;
}
int ObBatchCreateTabletHelper::add_arg_to_batch_arg(
const ObTabletCreatorArg &tablet_arg)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!tablet_arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("arg is invalid", KR(ret), K(tablet_arg));
} else {
ObArray<int64_t> index_array;
for (int64_t i = 0; OB_SUCC(ret) && i < tablet_arg.table_schemas_.count(); ++i) {
const share::schema::ObTableSchema *table_schema = tablet_arg.table_schemas_.at(i);
int64_t index = OB_INVALID_INDEX;
if (OB_ISNULL(table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table schema is null", KR(ret), K(i), K(tablet_arg));
} else if (OB_FAIL(try_add_table_schema(table_schema, index))) {
LOG_WARN("failed to add table schema to batch", KR(ret), K(table_schema), K(index), K(arg_));
} else if (OB_UNLIKELY(OB_INVALID_INDEX == index)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index can not be invalid", KR(ret), K(index), K(tablet_arg), K(arg_));
} else if (OB_FAIL(index_array.push_back(index))) {
LOG_WARN("failed to push back index", KR(ret), K(index));
}
}
if (OB_SUCC(ret)) {
obrpc::ObCreateTabletInfo info;
if (OB_FAIL(info.init(tablet_arg.tablet_ids_,
tablet_arg.data_tablet_id_,
index_array,
tablet_arg.compat_mode_,
tablet_arg.is_create_bind_hidden_tablets_))) {
LOG_WARN("failed to init create tablet info", KR(ret), K(index_array), K(tablet_arg));
} else if (OB_FAIL(arg_.tablets_.push_back(info))) {
LOG_WARN("failed to push back info", KR(ret), K(info));
}
}
}
return ret;
}
int ObBatchCreateTabletHelper::try_add_table_schema(
const share::schema::ObTableSchema *table_schema, int64_t &index)
{
int ret = OB_SUCCESS;
index = OB_INVALID_INDEX;
if (OB_ISNULL(table_schema)
|| OB_UNLIKELY(!table_schema->is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("table schema is invlaid", KR(ret), KPC(table_schema));
} else if (OB_SUCC(table_schemas_map_.get_refactored(table_schema->get_table_id(), index))) {
//nothing
} else if(OB_HASH_NOT_EXIST == ret) {
ret = OB_SUCCESS;
index = arg_.table_schemas_.count();
if (OB_FAIL(arg_.table_schemas_.push_back(*table_schema))) {
LOG_WARN("failed to push back table schema", KR(ret), KPC(table_schema));
} else if (FALSE_IT(arg_.table_schemas_.at(index).reset_partition_schema())) {
} else if (OB_FAIL(table_schemas_map_.set_refactored(table_schema->get_table_id(), index))) {
LOG_WARN("failed to set table schema map", KR(ret), K(index), KPC(table_schema));
}
} else {
LOG_WARN("failed to find table schema in map", KR(ret), KP(table_schema));
}
return ret;
}
DEF_TO_STRING(ObBatchCreateTabletHelper)
{
int64_t pos = 0;
J_KV(K_(arg), K_(result));
return pos;
}
/////////////////////////////////////////////////////////
ObTabletCreator::~ObTabletCreator()
{
reset();
}
void ObTabletCreator::reset()
{
FOREACH(iter, args_map_) {
ObBatchCreateTabletHelper *batch_arg = iter->second;
while (OB_NOT_NULL(batch_arg)) {
ObBatchCreateTabletHelper *tmp = batch_arg;
batch_arg = batch_arg->next_;
tmp->~ObBatchCreateTabletHelper();
}
}
args_map_.clear();
need_check_tablet_cnt_ = false;
}
int ObTabletCreator::init(const bool need_check_tablet_cnt)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("ObTabletCreator init twice", KR(ret));
} else if (OB_FAIL(args_map_.create(MAP_BUCKET_NUM, "TabletCtr"))) {
LOG_WARN("fail to create args map", KR(ret));
} else {
need_check_tablet_cnt_ = need_check_tablet_cnt;
inited_ = true;
}
return ret;
}
int ObTabletCreator::add_create_tablet_arg(const ObTabletCreatorArg &arg)
{
int ret = OB_SUCCESS;
ObBatchCreateTabletHelper *batch_arg = NULL;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObTabletCreator not init", KR(ret));
} else if (OB_UNLIKELY(!arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("arg is invalid", KR(ret), K(arg));
} else if (OB_SUCC(args_map_.get_refactored(arg.ls_key_, batch_arg))) {
//already exist
} else if (OB_HASH_NOT_EXIST == ret) {
//create new arg
void *arg_buf = allocator_.alloc(sizeof(ObBatchCreateTabletHelper));
if (OB_ISNULL(arg_buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to allocate new arg", KR(ret), KP(batch_arg));
} else if (FALSE_IT(batch_arg = new (arg_buf)ObBatchCreateTabletHelper())) {
} else if (OB_FAIL(batch_arg->init(arg.ls_key_, tenant_id_, major_frozen_scn_, need_check_tablet_cnt_))) {
LOG_WARN("failed to init batch arg helper", KR(ret), K(arg));
} else if (OB_FAIL(args_map_.set_refactored(arg.ls_key_, batch_arg, 0/*not overwrite*/))) {
LOG_WARN("fail to set refactored", KR(ret), K(arg));
} else {
LOG_INFO("new log stream", "ls_key", arg.ls_key_);
}
} else {
LOG_WARN("failed to get batch arg", KR(ret), K(arg));
}
if (OB_FAIL(ret)) {
} else if (batch_arg->arg_.get_serialize_size() > transaction::ObTxMultiDataSourceLog::MAX_MDS_LOG_SIZE) {
void *arg_buf = allocator_.alloc(sizeof(ObBatchCreateTabletHelper));
ObBatchCreateTabletHelper *new_arg = NULL;
if (OB_ISNULL(arg_buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to allocate new arg", KR(ret));
} else if (FALSE_IT(new_arg = new (arg_buf)ObBatchCreateTabletHelper())) {
} else if (OB_FAIL(new_arg->init(arg.ls_key_, tenant_id_, major_frozen_scn_, need_check_tablet_cnt_))) {
LOG_WARN("failed to init batch arg helper", KR(ret), K(arg));
} else if (FALSE_IT(new_arg->next_ = batch_arg)) {
} else if (OB_FAIL(args_map_.set_refactored(arg.ls_key_, new_arg, 1/*not overwrite*/))) {
LOG_WARN("fail to set refactored", KR(ret), K(arg));
} else {
batch_arg = new_arg;
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(batch_arg->add_arg_to_batch_arg(arg))) {
LOG_WARN("failed to add arg to batch", KR(ret), K(arg));
}
return ret;
}
int ObTabletCreator::execute()
{
int ret = OB_SUCCESS;
ObTimeoutCtx ctx;
const int64_t default_timeout_ts = GCONF.rpc_timeout;
const int64_t SLEEP_INTERVAL = 100 * 1000L; // 100ms
observer::ObInnerSQLConnection *conn = NULL;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObTabletCreator not init", KR(ret));
} else if (OB_ISNULL(conn = dynamic_cast<observer::ObInnerSQLConnection *>
(trans_.get_connection()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("conn_ is NULL", KR(ret));
} else if (OB_UNLIKELY(0 >= args_map_.size())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("batch arg count is invalid", KR(ret));
} else {
FOREACH_X(iter, args_map_, OB_SUCC(ret)) {
ObBatchCreateTabletHelper *batch_arg = iter->second;
if (OB_ISNULL(batch_arg)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("batch arg not be null", KR(ret));
} else {
while (OB_SUCC(ret) && OB_NOT_NULL(batch_arg)) {
LOG_INFO("generate create arg", KPC(batch_arg), K(lbt()));
int64_t buf_len = batch_arg->arg_.get_serialize_size();
int64_t pos = 0;
char *buf = (char*)allocator_.alloc(buf_len);
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail alloc memory", KR(ret));
} else if (OB_FAIL(batch_arg->arg_.serialize(buf, buf_len, pos))) {
LOG_WARN("fail to serialize", KR(ret), K(batch_arg->arg_));
} else if (OB_FAIL(share::ObShareUtil::set_default_timeout_ctx(ctx, default_timeout_ts))) {
LOG_WARN("fail to set timeout ctx", KR(ret), K(default_timeout_ts));
} else {
do {
if (ctx.is_timeouted()) {
ret = OB_TIMEOUT;
LOG_WARN("already timeout", KR(ret), K(ctx));
} else if (OB_FAIL(conn->register_multi_data_source(tenant_id_, iter->first,
transaction::ObTxDataSourceType::CREATE_TABLET_NEW_MDS, buf, buf_len))) {
if (need_retry(ret)) {
LOG_INFO("fail to register_tx_data, try again", KR(ret), K_(tenant_id), K(batch_arg->arg_));
ob_usleep(SLEEP_INTERVAL);
} else {
LOG_WARN("fail to register_tx_data", KR(ret), K(batch_arg->arg_), K(buf), K(buf_len));
}
}
} while (need_retry(ret));
}
batch_arg = batch_arg->next_;
} // end while
}
} // end for
}
reset();
return ret;
}
bool ObTabletCreator::need_retry(int ret)
{
return is_location_service_renew_error(ret) || OB_NOT_MASTER == ret;
}
} // rootserver
} // oceanbase