Co-authored-by: wxhwang <wxhwang@126.com> Co-authored-by: godyangfight <godyangfight@gmail.com> Co-authored-by: Tyshawn <tuyunshan@gmail.com>
364 lines
13 KiB
C++
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
|