Files
oceanbase/src/rootserver/ddl_task/ob_modify_autoinc_task.cpp

712 lines
29 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_modify_autoinc_task.h"
#include "rootserver/ob_root_service.h"
#include "share/ob_autoincrement_service.h"
#include "share/ob_ddl_error_message_table_operator.h"
#include "share/ob_ddl_sim_point.h"
#include "storage/tablelock/ob_table_lock_service.h"
#include "storage/tablelock/ob_table_lock_rpc_client.h"
#include "storage/ddl/ob_ddl_lock.h"
#include "share/ob_rpc_struct.h"
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::rootserver;
using namespace oceanbase::transaction::tablelock;
ObUpdateAutoincSequenceTask::ObUpdateAutoincSequenceTask(
const uint64_t tenant_id,
const int64_t data_table_id,
const int64_t dest_table_id,
const int64_t schema_version,
const uint64_t column_id,
const ObObjType &orig_column_type,
const ObSQLMode &sql_mode,
const common::ObCurTraceId::TraceId &trace_id,
const int64_t task_id)
: tenant_id_(tenant_id), data_table_id_(data_table_id), dest_table_id_(dest_table_id),
schema_version_(schema_version), column_id_(column_id), orig_column_type_(orig_column_type),
sql_mode_(sql_mode), trace_id_(trace_id), task_id_(task_id)
{
set_retry_times(0);
}
int ObUpdateAutoincSequenceTask::process()
{
int ret = OB_SUCCESS;
ObTraceIdGuard trace_id_guard(trace_id_);
ObRootService *root_service = GCTX.root_service_;
int64_t max_value = 0;
int tmp_ret = OB_SUCCESS;
if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, root service must not be nullptr", K(ret));
} else if (OB_UNLIKELY(tenant_id_ == OB_INVALID_ID || column_id_ == OB_INVALID_ID || data_table_id_ == OB_INVALID_ID
|| orig_column_type_ >= ObMaxType || dest_table_id_ == OB_INVALID_ID)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(tenant_id_), K(data_table_id_), K(column_id_),
K(orig_column_type_), K(dest_table_id_));
} else if (OB_FAIL(DDL_SIM(tenant_id_, task_id_, UPDATE_AUTOINC_SEQUENCE_FAILED))) {
LOG_WARN("ddl sim failure", K(ret), K(tenant_id_), K(task_id_));
} else {
ObDDLService &ddl_service = root_service->get_ddl_service();
ObMultiVersionSchemaService &schema_service = ddl_service.get_schema_service();
ObMySQLProxy &sql_proxy = ddl_service.get_sql_proxy();
const ObTableSchema *table_schema = nullptr;
const ObDatabaseSchema *db_schema = nullptr;
const ObColumnSchemaV2 *column_schema = nullptr;
ObSchemaGetterGuard schema_guard;
ObDDLTaskKey task_key(tenant_id_, dest_table_id_, schema_version_);
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("get schema guard failed", K(ret), K(tenant_id_));
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, dest_table_id_, table_schema))) {
LOG_WARN("get data table schema failed", K(ret), K(tenant_id_), K(dest_table_id_));
} else if (OB_ISNULL(table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("table schemas should not be null", K(ret), K(table_schema));
} else if (OB_FAIL(schema_guard.get_database_schema(tenant_id_, table_schema->get_database_id(), db_schema))) {
LOG_WARN("failed to get database schema", K(ret), K(table_schema->get_data_table_id()), K(dest_table_id_));
} else if (OB_ISNULL(db_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, database schema must not be nullptr", K(ret));
} else if (OB_ISNULL(column_schema = table_schema->get_column_schema(column_id_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get alter column schema", K(ret), K(column_id_), KPC(table_schema));
} else {
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
ObTimeoutCtx timeout_ctx;
ObSqlString sql;
sqlclient::ObMySQLResult *result = NULL;
common::ObCommonSqlProxy *user_sql_proxy = GCTX.ddl_sql_proxy_;
ObSessionParam session_param;
session_param.sql_mode_ = reinterpret_cast<int64_t *>(&sql_mode_);
session_param.ddl_info_.set_is_ddl(true);
// if data_table_id != dest_table_id, meaning this is happening in ddl double write
session_param.ddl_info_.set_source_table_hidden(data_table_id_ != dest_table_id_);
ObObj obj;
const int64_t DDL_INNER_SQL_EXECUTE_TIMEOUT = ObDDLUtil::calc_inner_sql_execute_timeout();
if (OB_FAIL(timeout_ctx.set_trx_timeout_us(DDL_INNER_SQL_EXECUTE_TIMEOUT))) {
LOG_WARN("set trx timeout failed", K(ret));
} else if (OB_FAIL(timeout_ctx.set_timeout(DDL_INNER_SQL_EXECUTE_TIMEOUT))) {
LOG_WARN("set timeout failed", K(ret));
} else if (OB_FAIL(sql.assign_fmt("SELECT /*+no_rewrite*/ CAST(MAX(`%s`) AS SIGNED) AS MAX_VALUE FROM `%s`.`%s`",
column_schema->get_column_name(),
db_schema->get_database_name(),
table_schema->get_table_name()))) {
LOG_WARN("failed to assign fmt", K(ret), K(column_schema->get_column_name_str()), K(db_schema->get_database_name_str()), K(table_schema->get_table_name_str()));
} else if (OB_FAIL(user_sql_proxy->read(res, tenant_id_, sql.ptr(), &session_param))) {
LOG_WARN("fail to read", KR(ret), K(sql));
} else if (OB_ISNULL(result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get result failed", K(ret));
} else if (OB_FAIL(result->next())) {
LOG_WARN("fail to get next", KR(ret));
} else if (OB_FAIL(result->get_obj("MAX_VALUE", obj))) {
LOG_WARN("fail to get result obj", K(ret));
} else {
max_value = MAX(0, obj.get_int());
}
}
}
if (OB_SUCCESS != (tmp_ret = root_service->get_ddl_scheduler().notify_update_autoinc_end(task_key, max_value + 1, ret))) {
LOG_WARN("fail to finish update autoinc task", K(ret), K(max_value));
}
LOG_INFO("execute finish update autoinc task finish", K(ret), "ddl_event_info", ObDDLEventInfo(), K(task_key), K(data_table_id_), K(column_id_), K(max_value));
}
char table_id_buffer[256];
snprintf(table_id_buffer, sizeof(table_id_buffer), "data_table_id:%ld, dest_table_id:%ld",
data_table_id_, dest_table_id_);
ROOTSERVICE_EVENT_ADD("ddl scheduler", "update autoinc sequence task process",
"tenant_id", tenant_id_,
"ret", ret,
K_(trace_id),
K_(task_id),
"table_id", table_id_buffer,
K_(schema_version),
column_id_);
return ret;
}
ObAsyncTask *ObUpdateAutoincSequenceTask::deep_copy(char *buf, const int64_t buf_size) const
{
int ret = OB_SUCCESS;
ObUpdateAutoincSequenceTask *new_task = nullptr;
if (OB_ISNULL(buf) || buf_size < get_deep_copy_size()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), KP(buf), "deep_copy_size", get_deep_copy_size(), K(buf_size));
} else {
new_task = new (buf) ObUpdateAutoincSequenceTask(tenant_id_,
data_table_id_,
dest_table_id_,
schema_version_,
column_id_,
orig_column_type_,
sql_mode_,
trace_id_,
task_id_);
}
return new_task;
}
ObModifyAutoincTask::ObModifyAutoincTask()
: ObDDLTask(ObDDLType::DDL_INVALID), lock_(), alter_table_arg_(),
update_autoinc_job_ret_code_(INT64_MAX), update_autoinc_job_time_(0)
{
}
int ObModifyAutoincTask::init(const uint64_t tenant_id,
const int64_t task_id,
const int64_t table_id,
const int64_t schema_version,
const int64_t consumer_group_id,
const int32_t sub_task_trace_id,
const obrpc::ObAlterTableArg &alter_table_arg,
const int64_t task_status,
const int64_t snapshot_version)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("ObModifyAutoincTask has already been inited", K(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == table_id || !alter_table_arg.is_valid())
|| task_status < ObDDLTaskStatus::PREPARE || task_status > ObDDLTaskStatus::SUCCESS) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(task_id), K(table_id), K(alter_table_arg), K(task_status));
} else if (OB_FAIL(deep_copy_table_arg(allocator_, alter_table_arg, alter_table_arg_))) {
LOG_WARN("deep copy alter table arg failed", K(ret));
} else if (OB_FAIL(set_ddl_stmt_str(alter_table_arg_.ddl_stmt_str_))) {
LOG_WARN("set ddl stmt str failed", K(ret));
} else {
set_gmt_create(ObTimeUtility::current_time());
task_type_ = ObDDLType::DDL_MODIFY_AUTO_INCREMENT;
object_id_ = table_id;
target_object_id_ = table_id;
schema_version_ = schema_version;
consumer_group_id_ = consumer_group_id;
sub_task_trace_id_ = sub_task_trace_id;
task_status_ = static_cast<ObDDLTaskStatus>(task_status);
snapshot_version_ = snapshot_version;
tenant_id_ = tenant_id;
task_version_ = OB_MODIFY_AUTOINC_TASK_VERSION;
task_id_ = task_id;
dst_tenant_id_ = tenant_id;
dst_schema_version_ = schema_version;
is_inited_ = true;
ddl_tracing_.open();
}
return ret;
}
int ObModifyAutoincTask::init(const ObDDLTaskRecord &task_record)
{
int ret = OB_SUCCESS;
const uint64_t data_table_id = task_record.object_id_;
const uint64_t target_schema_id = task_record.target_object_id_;
const int64_t schema_version = task_record.schema_version_;
task_type_ = ObDDLType::DDL_MODIFY_AUTO_INCREMENT;
int64_t pos = 0;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("ObModifyAutoincTask has already been inited", K(ret));
} else if (OB_UNLIKELY(!task_record.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(task_record));
} else if (OB_FAIL(deserialize_params_from_message(task_record.tenant_id_, task_record.message_.ptr(), task_record.message_.length(), pos))) {
LOG_WARN("deserialize params from message failed", K(ret));
} else if (OB_FAIL(set_ddl_stmt_str(task_record.ddl_stmt_str_))) {
LOG_WARN("set ddl stmt str failed", K(ret));
} else {
object_id_ = data_table_id;
target_object_id_ = target_schema_id;
schema_version_ = schema_version;
task_status_ = static_cast<ObDDLTaskStatus>(task_record.task_status_);
snapshot_version_ = task_record.snapshot_version_;
tenant_id_ = task_record.tenant_id_;
task_id_ = task_record.task_id_;
ret_code_ = task_record.ret_code_;
dst_tenant_id_ = tenant_id_;
dst_schema_version_ = schema_version_;
is_inited_ = true;
// set up span during recover task
ddl_tracing_.open_for_recovery();
}
return ret;
}
int ObModifyAutoincTask::process()
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_FAIL(check_health())) {
LOG_WARN("check health failed", K(ret));
} else {
ddl_tracing_.restore_span_hierarchy();
switch(task_status_) {
case ObDDLTaskStatus::WAIT_TRANS_END: {
if (OB_FAIL(wait_trans_end())) {
LOG_WARN("wait trans end failed", K(ret), K(*this));
}
break;
}
case ObDDLTaskStatus::MODIFY_AUTOINC: {
if (OB_FAIL(modify_autoinc())) {
LOG_WARN("update schema failed", K(ret), K(*this));
}
break;
}
case ObDDLTaskStatus::FAIL: {
if (OB_FAIL(fail())) {
LOG_WARN("process fail failed", K(ret), K(*this));
}
break;
}
case ObDDLTaskStatus::SUCCESS: {
if (OB_FAIL(success())) {
LOG_WARN("process success failed", K(ret), K(*this));
}
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected ObModifyAutoincTask status", K(ret), K(task_status_), K(*this));
break;
}
}
ddl_tracing_.release_span_hierarchy();
if (OB_FAIL(ret)) {
add_event_info("modify autoinc task process fail");
LOG_INFO("modify autoinc task process fail", "ddl_event_info", ObDDLEventInfo());
}
}
return ret;
}
int ObModifyAutoincTask::unlock_table()
{
int ret = OB_SUCCESS;
ObRootService *root_service = GCTX.root_service_;
ObMySQLTransaction trans;
ObTableLockOwnerID owner_id;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, root service must not be nullptr", K(ret));
} else if (OB_FAIL(trans.start(&root_service->get_sql_proxy(), tenant_id_))) {
LOG_WARN("start transaction failed", K(ret));
} else if (OB_FAIL(owner_id.convert_from_value(ObLockOwnerType::DEFAULT_OWNER_TYPE,
task_id_))) {
LOG_WARN("convert owner id failed", K(ret), K(task_id_));
} else if (OB_FAIL(ObDDLLock::unlock_for_offline_ddl(tenant_id_, object_id_, owner_id, trans))) {
LOG_WARN("failed to unlock table", K(ret));
}
bool commit = (OB_SUCCESS == ret);
int tmp_ret = trans.end(commit);
if (OB_SUCCESS != tmp_ret) {
ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
}
return ret;
}
int ObModifyAutoincTask::modify_autoinc()
{
int ret = OB_SUCCESS;
bool is_update_autoinc_end = false;
ObRootService *root_service = GCTX.root_service_;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, root service must not be nullptr", K(ret));
} else if (OB_FAIL(DDL_SIM(tenant_id_, task_id_, MODIFY_AUTOINC_FAILED))) {
LOG_WARN("ddl sim failure", K(ret), K(tenant_id_), K(task_id_));
} else if (OB_FAIL(check_update_autoinc_end(is_update_autoinc_end))) {
LOG_WARN("fail to check update autoinc end", K(ret));
} else if (!is_update_autoinc_end && update_autoinc_job_time_ == 0) {
int64_t refreshed_schema_version = 0;
const ObTableSchema *orig_table_schema = nullptr;
ObTableSchema new_table_schema;
ObSchemaGetterGuard schema_guard;
ObDDLService &ddl_service = root_service->get_ddl_service();
ObMultiVersionSchemaService &schema_service = ddl_service.get_schema_service();
const AlterTableSchema &alter_table_schema = alter_table_arg_.alter_table_schema_;
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("get schema guard failed", K(ret), K(tenant_id_));
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, object_id_, orig_table_schema))) {
LOG_WARN("get data table schema failed", K(ret), K(tenant_id_), K(object_id_));
} else if (OB_ISNULL(orig_table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("cannot find orig table", K(ret), K(alter_table_arg_));
} else {
int64_t alter_column_id = 0;
ObTableSchema::const_column_iterator iter = alter_table_schema.column_begin();
ObTableSchema::const_column_iterator iter_end = alter_table_schema.column_end();
AlterColumnSchema *alter_column_schema = nullptr;
for(; OB_SUCC(ret) && iter != iter_end; iter++) {
if (OB_ISNULL(alter_column_schema = static_cast<AlterColumnSchema *>(*iter))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("iter is NULL", K(ret));
} else {
const ObString &orig_column_name = alter_column_schema->get_origin_column_name();
const ObColumnSchemaV2 *orig_column_schema = orig_table_schema->get_column_schema(orig_column_name);
if (alter_column_schema->is_autoincrement() && !orig_column_schema->is_autoincrement()) {
alter_column_id = orig_column_schema->get_column_id();
break; // there can only be one autoinc column
}
}
}
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(alter_column_id == OB_INVALID_ID)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid alter column info", K(alter_column_id));
} else {
const AlterTableSchema &alter_table_schema = alter_table_arg_.alter_table_schema_;
ObObjType column_type = orig_table_schema->get_column_schema(alter_column_id)->get_data_type();
ObUpdateAutoincSequenceTask task(tenant_id_, object_id_, target_object_id_, schema_version_,
alter_column_id, column_type, alter_table_arg_.sql_mode_,
trace_id_, task_id_);
if (OB_FAIL(root_service->submit_ddl_single_replica_build_task(task))) {
LOG_WARN("fail to submit ObUpdateAutoincSequenceTask", K(ret));
} else {
update_autoinc_job_time_ = ObTimeUtility::current_time();
LOG_INFO("submit ObUpdateAutoincSequenceTask success", K(object_id_), K(alter_column_id));
}
}
}
}
}
if (OB_FAIL(ret) || is_update_autoinc_end) {
if (OB_FAIL(switch_status(ObDDLTaskStatus::WAIT_TRANS_END, true, ret))) {
LOG_WARN("fail to switch status", K(ret));
}
}
return ret;
}
// TODO(shuangcan): abstract this function
int ObModifyAutoincTask::wait_trans_end()
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObDDLTaskStatus new_status = WAIT_TRANS_END;
const ObDDLTaskStatus next_task_status = SUCCESS;
ObRootService *root_service = GCTX.root_service_;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, root service must not be nullptr", K(ret));
} else if (snapshot_version_ > 0) {
new_status = next_task_status;
}
if (OB_SUCC(ret) && new_status != next_task_status && !wait_trans_ctx_.is_inited()) {
const ObTableSchema *updated_table_schema = nullptr;
ObSchemaGetterGuard schema_guard;
ObDDLService &ddl_service = root_service->get_ddl_service();
ObMultiVersionSchemaService &schema_service = ddl_service.get_schema_service();
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("get schema guard failed", K(ret), K(tenant_id_));
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, object_id_, updated_table_schema))) {
LOG_WARN("get data table schema failed", K(ret), K(tenant_id_), K(object_id_));
} else if (OB_ISNULL(updated_table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("cannot find orig table", K(ret), K(alter_table_arg_));
} else if (OB_FAIL(wait_trans_ctx_.init(tenant_id_,
task_id_,
object_id_,
ObDDLWaitTransEndCtx::WAIT_SCHEMA_TRANS,
updated_table_schema->get_schema_version()))) {
LOG_WARN("fail to init wait trans ctx", K(ret));
}
}
// try wait transaction end
if (OB_SUCC(ret) && new_status != next_task_status && snapshot_version_ <= 0) {
bool is_trans_end = false;
if (OB_FAIL(wait_trans_ctx_.try_wait(is_trans_end, snapshot_version_))) {
if (OB_EAGAIN != ret) {
LOG_WARN("fail to try wait transaction", K(ret));
} else {
ret = OB_SUCCESS;
}
} else {
new_status = next_task_status;
}
}
if (new_status != ObDDLTaskStatus::WAIT_TRANS_END || OB_FAIL(ret)) {
if (OB_FAIL(switch_status(new_status, true, ret))) {
LOG_WARN("fail to switch task status", K(ret));
}
}
return ret;
}
int ObModifyAutoincTask::set_schema_available()
{
int ret = OB_SUCCESS;
int64_t tablet_count = 0;
int64_t rpc_timeout = 0;
ObRootService *root_service = GCTX.root_service_;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, root service must not be nullptr", K(ret));
} else if (OB_FAIL(DDL_SIM(tenant_id_, task_id_, DDL_TASK_TAKE_EFFECT_FAILED))) {
LOG_WARN("ddl sim failure", K(ret), K(tenant_id_), K(task_id_));
} else {
ObSArray<uint64_t> unused_ids;
alter_table_arg_.ddl_task_type_ = share::UPDATE_AUTOINC_SCHEMA;
alter_table_arg_.alter_table_schema_.set_tenant_id(tenant_id_);
if (OB_FAIL(ObDDLUtil::get_ddl_rpc_timeout(tenant_id_, object_id_, rpc_timeout))) {
LOG_WARN("get rpc timeout failed", K(ret));
} else if (OB_FAIL(root_service->get_ddl_service().get_common_rpc()->to(obrpc::ObRpcProxy::myaddr_).timeout(rpc_timeout).
execute_ddl_task(alter_table_arg_, unused_ids))) {
LOG_WARN("alter table failed", K(ret));
}
}
return ret;
}
int ObModifyAutoincTask::rollback_schema()
{
int ret = OB_SUCCESS;
int64_t tablet_count = 0;
int64_t rpc_timeout = 0;
ObRootService *root_service = GCTX.root_service_;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys, root service must not be nullptr", K(ret));
} else {
ObArenaAllocator allocator;
SMART_VAR(obrpc::ObAlterTableArg, alter_table_arg) {
if (OB_FAIL(deep_copy_table_arg(allocator, alter_table_arg_, alter_table_arg))) {
LOG_WARN("deep copy table arg failed", K(ret));
} else {
ObSArray<uint64_t> unused_ids;
alter_table_arg.ddl_task_type_ = share::UPDATE_AUTOINC_SCHEMA;
alter_table_arg.alter_table_schema_.set_tenant_id(tenant_id_);
alter_table_arg.alter_table_schema_.reset_column_info();
if (OB_FAIL(ObDDLUtil::get_ddl_rpc_timeout(tenant_id_, object_id_, rpc_timeout))) {
LOG_WARN("get rpc timeout failed", K(ret));
} else if (OB_FAIL(root_service->get_ddl_service().get_common_rpc()->to(obrpc::ObRpcProxy::myaddr_).timeout(rpc_timeout).
execute_ddl_task(alter_table_arg, unused_ids))) {
LOG_WARN("alter table failed", K(ret));
}
}
}
}
return ret;
}
int ObModifyAutoincTask::fail()
{
int ret = OB_SUCCESS;
if (OB_FAIL(rollback_schema())) {
LOG_WARN("fail to set schema available", K(ret));
} else if (OB_FAIL(unlock_table())) {
LOG_WARN("fail to unlock table", K(ret));
} else if (OB_FAIL(cleanup())) {
LOG_WARN("clean up failed", K(ret));
} else {
need_retry_ = false;
}
return ret;
}
int ObModifyAutoincTask::success()
{
int ret = OB_SUCCESS;
if (OB_FAIL(set_schema_available())) {
LOG_WARN("fail to set schema available", K(ret));
} else if (OB_FAIL(unlock_table())) {
LOG_WARN("fail to unlock table", K(ret));
} else if (OB_FAIL(cleanup())) {
LOG_WARN("clean up failed", K(ret));
} else {
need_retry_ = false;
}
return ret;
}
int ObModifyAutoincTask::cleanup_impl()
{
int ret = OB_SUCCESS;
ObString unused_str;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObModifyAutoincTask has not been inited", K(ret));
} else if (OB_FAIL(report_error_code(unused_str))) {
LOG_WARN("report error code failed", K(ret));
} else if (OB_FAIL(remove_task_record())) {
LOG_WARN("remove task record failed", K(ret));
}
return ret;
}
int ObModifyAutoincTask::check_update_autoinc_end(bool &is_end)
{
int ret = OB_SUCCESS;
if (INT64_MAX == update_autoinc_job_ret_code_) {
// not finish
} else {
is_end = true;
ret_code_ = update_autoinc_job_ret_code_;
ret = ret_code_;
}
return ret;
}
int ObModifyAutoincTask::notify_update_autoinc_finish(const uint64_t autoinc_val, const int ret_code)
{
int ret = OB_SUCCESS;
update_autoinc_job_ret_code_ = ret_code;
alter_table_arg_.alter_table_schema_.set_auto_increment(autoinc_val);
return ret;
}
int ObModifyAutoincTask::check_health()
{
int ret = OB_SUCCESS;
ObRootService *root_service = GCTX.root_service_;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not inited", K(ret));
} else if (OB_ISNULL(root_service)) {
ret = OB_ERR_SYS;
LOG_WARN("error sys", K(ret));
} else if (!root_service->in_service()) {
ret = OB_STATE_NOT_MATCH;
LOG_WARN("root service not in service, do not need retry", K(ret), K(object_id_), K(target_object_id_));
need_retry_ = false;
} else if (OB_FAIL(refresh_status())) { // refresh task status
LOG_WARN("refresh status failed", K(ret));
} else if (OB_FAIL(refresh_schema_version())) {
LOG_WARN("refresh schema version failed", K(ret));
} else {
ObMultiVersionSchemaService &schema_service = root_service->get_schema_service();
ObSchemaGetterGuard schema_guard;
const ObTableSchema *index_schema = nullptr;
bool is_source_table_exist = false;
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("get tanant schema guard failed", K(ret), K(tenant_id_));
} else if (OB_FAIL(schema_guard.check_table_exist(tenant_id_, object_id_, is_source_table_exist))) {
LOG_WARN("check data table exist failed", K(ret), K_(tenant_id), K(object_id_));
} else if (!is_source_table_exist) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("data table not exist", K(ret), K(is_source_table_exist));
}
if (OB_FAIL(ret) && !ObIDDLTask::in_ddl_retry_white_list(ret)) {
const ObDDLTaskStatus old_status = static_cast<ObDDLTaskStatus>(task_status_);
const ObDDLTaskStatus new_status = ObDDLTaskStatus::FAIL;
switch_status(new_status, false, ret);
LOG_WARN("switch status to build_failed", K(ret), K(old_status), K(new_status));
}
if (ObDDLTaskStatus::FAIL == static_cast<ObDDLTaskStatus>(task_status_)
|| ObDDLTaskStatus::SUCCESS == static_cast<ObDDLTaskStatus>(task_status_)) {
ret = OB_SUCCESS; // allow clean up
}
}
return ret;
}
int ObModifyAutoincTask::serialize_params_to_message(char *buf, const int64_t buf_len, int64_t &pos) const
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(nullptr == buf || buf_len <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), KP(buf), K(buf_len));
} else if (OB_FAIL(ObDDLTask::serialize_params_to_message(buf, buf_len, pos))) {
LOG_WARN("fail to serialize ObDDLTask", K(ret));
} else if (OB_FAIL(alter_table_arg_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize table arg failed", K(ret));
}
return ret;
}
int ObModifyAutoincTask::deserialize_params_from_message(const uint64_t tenant_id, const char *buf, const int64_t data_len, int64_t &pos)
{
int ret = OB_SUCCESS;
obrpc::ObAlterTableArg tmp_arg;
if (OB_UNLIKELY(!is_valid_tenant_id(tenant_id) || nullptr == buf || data_len <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(tenant_id), KP(buf), K(data_len));
} else if (OB_FAIL(ObDDLTask::deserialize_params_from_message(tenant_id, buf, data_len, pos))) {
LOG_WARN("ObDDLTask deserlize failed", K(ret));
} else if (OB_FAIL(tmp_arg.deserialize(buf, data_len, pos))) {
LOG_WARN("serialize table failed", K(ret));
} else if (OB_FAIL(ObDDLUtil::replace_user_tenant_id(task_type_, tenant_id, tmp_arg))) {
LOG_WARN("replace user tenant id failed", K(ret), K(tenant_id), K(tmp_arg));
} else if (OB_FAIL(deep_copy_table_arg(allocator_, tmp_arg, alter_table_arg_))) {
LOG_WARN("deep copy table arg failed", K(ret));
}
return ret;
}
int64_t ObModifyAutoincTask::get_serialize_param_size() const
{
return alter_table_arg_.get_serialize_size() + ObDDLTask::get_serialize_param_size();
}
void ObModifyAutoincTask::flt_set_task_span_tag() const
{
FLT_SET_TAG(ddl_task_id, task_id_, ddl_parent_task_id, parent_task_id_,
ddl_data_table_id, object_id_, ddl_schema_version, schema_version_,
ddl_snapshot_version, snapshot_version_, ddl_ret_code, ret_code_);
}
void ObModifyAutoincTask::flt_set_status_span_tag() const
{
switch (task_status_) {
case ObDDLTaskStatus::WAIT_TRANS_END: {
FLT_SET_TAG(ddl_data_table_id, object_id_, ddl_ret_code, ret_code_);
break;
}
case ObDDLTaskStatus::OBTAIN_SNAPSHOT: {
FLT_SET_TAG(ddl_data_table_id, object_id_, ddl_ret_code, ret_code_);
break;
}
case ObDDLTaskStatus::MODIFY_AUTOINC: {
FLT_SET_TAG(ddl_ret_code, ret_code_);
break;
}
case ObDDLTaskStatus::FAIL: {
FLT_SET_TAG(ddl_ret_code, ret_code_);
break;
}
case ObDDLTaskStatus::SUCCESS: {
FLT_SET_TAG(ddl_ret_code, ret_code_);
break;
}
default: {
break;
}
}
}