Files
oceanbase/src/rootserver/ob_table_creator.cpp
2023-01-12 19:02:33 +08:00

413 lines
18 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 "rootserver/ob_table_creator.h"
#include "rootserver/ob_root_service.h"
#include "share/tablet/ob_tablet_to_table_history_operator.h" // ObTabletToTableHistoryOperator
#include "share/scn.h"
namespace oceanbase
{
namespace rootserver
{
ObTableCreator::~ObTableCreator()
{
}
int ObTableCreator::init()
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("ObTableCreator init twice", KR(ret));
} else if (OB_FAIL(tablet_creator_.init())) {
LOG_WARN("fail to init tablet creator", KR(ret));
} else {
inited_ = true;
}
return ret;
}
void ObTableCreator::reset()
{
tablet_creator_.reset();
}
int ObTableCreator::execute()
{
int ret = OB_SUCCESS;
if (OB_FAIL(tablet_creator_.execute())) {
LOG_WARN("fail to execute tablet creator", KR(ret));
} else if (tablet_infos_.count() > 0
&& OB_FAIL(share::ObTabletToLSTableOperator::batch_update(trans_, tenant_id_, tablet_infos_))) {
LOG_WARN("fail to batch update tablet info", KR(ret));
}
return ret;
}
int ObTableCreator::add_create_tablets_of_local_aux_tables_arg(
const common::ObIArray<const share::schema::ObTableSchema*> &schemas,
const share::schema::ObTableSchema *data_table_schema,
const common::ObIArray<share::ObLSID> &ls_id_array)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(data_table_schema)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("data_table_schema must be null, when table_schema is not local index", KR(ret));
} else if (!data_table_schema->has_tablet() ||
data_table_schema->is_index_table() ||
data_table_schema->is_aux_lob_table()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("data_table_schema must be data table", KR(ret), KPC(data_table_schema));
}
for (int64_t i = 0; OB_SUCC(ret) && i < schemas.count(); ++i) {
const share::schema::ObTableSchema *aux_schema = schemas.at(i);
if (OB_ISNULL(aux_schema)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("ptr is null", KR(ret), K(schemas));
} else if (!aux_schema->is_index_local_storage() && !aux_schema->is_aux_lob_table()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("aux_schema must be local aux table", KR(ret), K(schemas), KPC(aux_schema));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(add_create_tablets_of_tables_arg_(
schemas, data_table_schema, ls_id_array))) {
LOG_WARN("fail to add_create_tablets_of_tables_arg_", KR(ret), K(schemas));
}
return ret;
}
int ObTableCreator::add_create_bind_tablets_of_hidden_table_arg(
const share::schema::ObTableSchema &orig_table_schema,
const share::schema::ObTableSchema &hidden_table_schema,
const common::ObIArray<share::ObLSID> &ls_id_array)
{
int ret = OB_SUCCESS;
ObSEArray<const ObTableSchema *, 1> schemas;
if (OB_UNLIKELY(!orig_table_schema.has_tablet()
|| orig_table_schema.is_index_table()
|| hidden_table_schema.is_index_table()
|| !hidden_table_schema.is_user_hidden_table())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("both orig and hidden table must be data table", K(ret), K(orig_table_schema), K(hidden_table_schema));
} else if (OB_FAIL(schemas.push_back(&hidden_table_schema))) {
LOG_WARN("failed to push back hidden table schema", K(ret));
} else if (OB_FAIL(add_create_tablets_of_tables_arg_(
schemas, &orig_table_schema, ls_id_array))) {
LOG_WARN("failed to add arg", K(ret), K(schemas));
}
return ret;
}
int ObTableCreator::add_create_tablets_of_table_arg(
const share::schema::ObTableSchema &table_schema,
const common::ObIArray<share::ObLSID> &ls_id_array)
{
int ret = OB_SUCCESS;
ObSEArray<const share::schema::ObTableSchema*, 1> schemas;
if (!table_schema.has_tablet() || table_schema.is_index_local_storage() || table_schema.is_aux_lob_table()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("table_schema must be data table or global indexes", KR(ret), K(table_schema));
} else if (OB_FAIL(schemas.push_back(&table_schema))) {
LOG_WARN("failed to push_back", KR(ret), K(table_schema));
} else if (OB_FAIL(add_create_tablets_of_tables_arg_(
schemas, NULL, ls_id_array))) {
LOG_WARN("failed to add create tablet arg", KR(ret), K(table_schema));
}
return ret;
}
int ObTableCreator::add_create_tablets_of_tables_arg(
const common::ObIArray<const share::schema::ObTableSchema*> &schemas,
const common::ObIArray<share::ObLSID> &ls_id_array)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < schemas.count(); ++i) {
const share::schema::ObTableSchema *table_schema = schemas.at(i);
if (OB_ISNULL(table_schema)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("ptr is null", KR(ret), K(schemas));
} else if (0 == i) {
if (!table_schema->has_tablet() || table_schema->is_index_table() || table_schema->is_aux_lob_table()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("data_table_schema must be data table", KR(ret), KPC(table_schema));
}
} else {
if (!table_schema->is_index_local_storage() && !table_schema->is_aux_lob_table()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("table_schema must be local index", KR(ret), K(schemas), KPC(table_schema));
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(add_create_tablets_of_tables_arg_(
schemas, NULL, ls_id_array))) {
LOG_WARN("fail to add_create_tablets_of_tables_arg_", KR(ret), K(schemas));
}
return ret;
}
// data_table_schema != null means to create local index tablets or hidden tablets
// and bind to corresponding data tablets in the tablet meta.
// data_tablet_schema == null means to create normal tablets without any binding.
int ObTableCreator::add_create_tablets_of_tables_arg_(
const common::ObIArray<const share::schema::ObTableSchema*> &schemas,
const share::schema::ObTableSchema *data_table_schema,
const common::ObIArray<share::ObLSID> &ls_id_array)
{
int ret = OB_SUCCESS;
const int64_t schema_cnt = schemas.count();
if (OB_UNLIKELY(schema_cnt < 1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("schemas count is less 1", KR(ret), K(schema_cnt));
} else if (OB_ISNULL(schemas.at(0))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("NULL ptr", KR(ret), K(schemas));
} else {
const share::schema::ObTableSchema &table_schema = *schemas.at(0);
int64_t all_part_num = table_schema.get_all_part_num();
common::ObArray<share::ObTabletTablePair> pairs;
bool is_oracle_mode = false;
bool is_create_bind_hidden_tablets = false;
if (table_schema.is_index_local_storage() || table_schema.is_aux_lob_table()) {
if (OB_ISNULL(data_table_schema)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("data_table_schema is NULL when create local_index", KR(ret));
}
} else if (table_schema.is_user_hidden_table()) {
if (nullptr == data_table_schema) {
// create as normal hidden table (no bind) if data_table_schema is null
data_table_schema = &table_schema;
} else {
if (OB_UNLIKELY(schemas.count() != 1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("unexpected schemas", K(ret), K(schemas.count()));
} else {
is_create_bind_hidden_tablets = true;
}
}
} else {
if (OB_NOT_NULL(data_table_schema)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("data_table_schema must be null, when table_schema is not local index and not hidden table",
KR(ret), K(data_table_schema), K(table_schema));
} else {
data_table_schema = &table_schema;
}
}
if (FAILEDx(pairs.reserve(all_part_num * schema_cnt))) {
LOG_WARN("fail to reserve array", KR(ret), K(all_part_num), K(schema_cnt));
} else if (OB_FAIL(ls_id_array_.reserve(all_part_num))) {
LOG_WARN("fail to reserve array", KR(ret), K(all_part_num));
} else if (OB_FAIL(ls_id_array_.assign(ls_id_array))) {
LOG_WARN("fail to assign ls id array", KR(ret));
} else if (ls_id_array_.count() != all_part_num) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the ls of tablet is not equal partition num", KR(ret),
K(all_part_num), "ls_id_array_cnt", ls_id_array_.count());
} else {
for (int64_t i = 1; OB_SUCC(ret) && i < schema_cnt; ++i) {
if (OB_ISNULL(schemas.at(i))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("ptr is null", KR(ret), K(schemas), K(table_schema));
} else if (schemas.at(i)->get_part_option().get_part_func_type()
!= table_schema.get_part_option().get_part_func_type()
|| schemas.at(i)->get_sub_part_option().get_sub_part_func_type()
!= table_schema.get_sub_part_option().get_sub_part_func_type()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("part type of local index is equal to its datatable", KR(ret), K(i));
}
}
}
if (FAILEDx(data_table_schema->check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check oracle mode", KR(ret), KPC(data_table_schema));
} else {
int64_t ls_idx = 0;
ObPartitionLevel part_level = table_schema.get_part_level();
lib::Worker::CompatMode compat_mode = is_oracle_mode ?
lib::Worker::CompatMode::ORACLE :
lib::Worker::CompatMode::MYSQL;
if (part_level >= PARTITION_LEVEL_MAX) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("part level is unexpected", K(table_schema), KR(ret));
} else if (PARTITION_LEVEL_ZERO == part_level) {
if (OB_FAIL(generate_create_tablet_arg_(
schemas,
*data_table_schema,
compat_mode,
ls_id_array_.at(ls_idx++),
pairs,
OB_INVALID_INDEX,
OB_INVALID_INDEX,
is_create_bind_hidden_tablets))) {
LOG_WARN("fail to generate_create_tablet_arg",
K(table_schema), K(schemas), KR(ret), K(is_create_bind_hidden_tablets));
}
} else {
ObPartition **part_array = table_schema.get_part_array();
int64_t part_num = table_schema.get_partition_num();
if (OB_ISNULL(part_array)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("part array is null", K(table_schema), KR(ret));
} else {
for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) {
if (OB_ISNULL(part_array[i])) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("NULL ptr", K(i), K(table_schema), KR(ret));
} else if (PARTITION_LEVEL_ONE == part_level) {
if (OB_FAIL(generate_create_tablet_arg_(
schemas,
*data_table_schema,
compat_mode,
ls_id_array_.at(ls_idx++),
pairs,
i,
OB_INVALID_INDEX,
is_create_bind_hidden_tablets))) {
LOG_WARN("fail to generate_create_tablet_arg",
K(table_schema), K(schemas), KR(ret), K(i), K(is_create_bind_hidden_tablets));
}
} else if (PARTITION_LEVEL_TWO == part_level) {
ObSubPartition **subpart_array = part_array[i]->get_subpart_array();
int64_t sub_part_num = part_array[i]->get_subpartition_num();
if (OB_ISNULL(subpart_array)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("part array is null", K(table_schema), KR(ret));
} else {
for (int64_t j = 0; j < sub_part_num && OB_SUCC(ret); j++) {
if (OB_ISNULL(subpart_array[j])) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("NULL ptr", K(i), K(j), K(table_schema), KR(ret));
} else {
if (OB_FAIL(generate_create_tablet_arg_(
schemas,
*data_table_schema,
compat_mode,
ls_id_array_.at(ls_idx++),
pairs,
i,
j,
is_create_bind_hidden_tablets))) {
LOG_WARN("fail to generate_create_tablet_arg",
K(table_schema), K(schemas), KR(ret), K(i), K(j), K(is_create_bind_hidden_tablets));
}
}
}
}
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("4.0 not support part type", K(table_schema), KR(ret));
}
}
}
}
}
if (OB_SUCC(ret)) {
int64_t schema_version = table_schema.get_schema_version();
if (is_sys_table(table_schema.get_table_id())) {
} else if (OB_FAIL(share::ObTabletToTableHistoryOperator::create_tablet_to_table_history(
trans_, tenant_id_, schema_version, pairs))) {
LOG_WARN("fail to create tablet to table history",
KR(ret), K_(tenant_id), K(schema_version));
}
}
}
return ret;
}
int ObTableCreator::generate_create_tablet_arg_(
const common::ObIArray<const share::schema::ObTableSchema*> &schemas,
const ObTableSchema &data_table_schema,
const lib::Worker::CompatMode &mode,
const share::ObLSID &ls_id,
common::ObIArray<share::ObTabletTablePair> &pairs,
const int64_t part_idx,
const int64_t subpart_idx,
const bool is_create_bind_hidden_tablets)
{
int ret = OB_SUCCESS;
ObTabletID data_tablet_id;
ObTabletCreatorArg create_tablet_arg;
common::ObArray<ObTabletID> tablet_id_array;
ObTabletID tablet_id;
ObBasePartition *data_part = NULL;
ObBasePartition *part = NULL;
if (PARTITION_LEVEL_ZERO == data_table_schema.get_part_level()) {
data_tablet_id = data_table_schema.get_tablet_id();
} else if (OB_FAIL(data_table_schema.get_part_by_idx(part_idx, subpart_idx, data_part))) {
LOG_WARN("fail to get data part", KR(ret), K(data_table_schema), K(part_idx), K(subpart_idx));
} else if (OB_ISNULL(data_part)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("NULL ptr", K(data_table_schema), KR(ret), K(part_idx), K(subpart_idx));
} else {
data_tablet_id = data_part->get_tablet_id();
}
for (int r = 0; r < schemas.count() && OB_SUCC(ret); r++) {
const share::schema::ObTableSchema *table_schema_ptr = schemas.at(r);
uint64_t table_id = OB_INVALID_ID;
if (OB_ISNULL(table_schema_ptr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("NULL ptr", K(r), K(schemas), KR(ret));
} else if (FALSE_IT(table_id = table_schema_ptr->get_table_id())) {
} else if (PARTITION_LEVEL_ZERO == table_schema_ptr->get_part_level()) {
tablet_id = table_schema_ptr->get_tablet_id();
} else if (OB_FAIL(table_schema_ptr->get_part_by_idx(part_idx, subpart_idx, part))) {
LOG_WARN("fail to get index part", KR(ret), KPC(table_schema_ptr), K(part_idx), K(subpart_idx));
} else if (OB_ISNULL(data_part) || OB_ISNULL(part)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("NULL ptr", K(data_table_schema), KPC(table_schema_ptr), KR(ret), K(part_idx), K(subpart_idx));
} else if (OB_UNLIKELY(!data_part->same_base_partition(*part))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("parts in table and index table is not equal", KR(ret), KPC(data_part), KPC(part));
} else {
tablet_id = part->get_tablet_id();
}
share::ObTabletTablePair pair;
share::ObTabletToLSInfo tablet_info(tablet_id, ls_id, table_schema_ptr->get_table_id());
if (OB_FAIL(ret)) {
} else if (OB_FAIL(tablet_id_array.push_back(tablet_id))) {
LOG_WARN("failed to assign table schema point", KR(ret));
} else if (is_sys_table(table_schema_ptr->get_table_id())) {
} else if (OB_FAIL(tablet_infos_.push_back(tablet_info))) {
LOG_WARN("fail to push_back", KR(ret), K(tablet_info));
} else if (OB_FAIL(pair.init(tablet_id, table_id))) {
LOG_WARN("fail to init tablet-table pair", KR(ret), K(tablet_id), K(table_id));
} else if (OB_FAIL(pairs.push_back(pair))) {
LOG_WARN("fail to push back tablet-table pair", KR(ret), K(pair));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(create_tablet_arg.init(
tablet_id_array,
ls_id,
data_tablet_id,
schemas,
mode,
is_create_bind_hidden_tablets))) {
LOG_WARN("fail to init create tablet arg", KR(ret), K(schemas), K(is_create_bind_hidden_tablets));
} else if (OB_FAIL(tablet_creator_.add_create_tablet_arg(create_tablet_arg))) {
LOG_WARN("fail to add create tablet arg", KR(ret), K(create_tablet_arg));
}
return ret;
}
} // rootserver
} // oceanbase