Files
oceanbase/src/storage/ob_build_index_task.cpp

2194 lines
85 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 STORAGE
#include "ob_build_index_task.h"
#include "lib/utility/ob_tracepoint.h"
#include "share/ob_dml_sql_splicer.h"
#include "share/ob_index_status_table_operator.h"
#include "share/ob_index_checksum.h"
#include "storage/ob_partition_scheduler.h"
#include "storage/ob_partition_merge_task.h"
#include "storage/ob_long_ops_monitor.h"
#include "storage/ob_partition_storage.h"
#include "storage/ob_partition_group.h"
#include "storage/ob_pg_storage.h"
#include "ob_i_table.h"
#include "observer/ob_server_struct.h"
using namespace oceanbase::common;
using namespace oceanbase::storage;
using namespace oceanbase::blocksstable;
using namespace oceanbase::compaction;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
using namespace oceanbase::observer;
using namespace oceanbase::omt;
ObBuildIndexDag::ObBuildIndexDag()
: ObIDag(DAG_TYPE_CREATE_INDEX, DAG_PRIO_CREATE_INDEX),
is_inited_(false),
pkey_(),
param_(),
context_(),
partition_service_(NULL),
guard_(),
partition_storage_(NULL),
compat_mode_(ObWorker::CompatMode::INVALID)
{}
ObBuildIndexDag::~ObBuildIndexDag()
{
clean_up();
}
int ObBuildIndexDag::init(const ObPartitionKey& pkey, ObPartitionService* partition_service)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObBuildIndexDag has already been inited", K(ret));
} else if (!pkey.is_valid() || NULL == partition_service) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(pkey), KP(partition_service));
} else {
pkey_ = pkey;
partition_service_ = partition_service;
is_inited_ = true;
if (OB_FAIL(get_compat_mode_with_table_id(pkey.table_id_, compat_mode_))) {
STORAGE_LOG(WARN, "failed to get compat mode", K(ret), K(pkey));
} else if (OB_FAIL(prepare())) {
STORAGE_LOG(WARN, "fail to prepare building index", K(ret));
}
}
return ret;
}
int64_t ObBuildIndexDag::hash() const
{
int tmp_ret = OB_SUCCESS;
int64_t hash_val = 0;
if (NULL == param_.index_schema_) {
tmp_ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "index schema must not be NULL", K(tmp_ret));
} else {
hash_val = pkey_.hash() + param_.index_schema_->get_table_id();
}
return hash_val;
}
bool ObBuildIndexDag::operator==(const ObIDag& other) const
{
int tmp_ret = OB_SUCCESS;
bool is_equal = false;
if (OB_UNLIKELY(this == &other)) {
is_equal = true;
} else if (get_type() == other.get_type()) {
const ObBuildIndexDag& dag = static_cast<const ObBuildIndexDag&>(other);
if (NULL == param_.index_schema_ || NULL == dag.param_.index_schema_) {
tmp_ret = OB_ERR_SYS;
STORAGE_LOG(
ERROR, "index schema must not be NULL", K(tmp_ret), KP(param_.index_schema_), KP(dag.param_.index_schema_));
} else {
is_equal = pkey_ == dag.pkey_ && param_.index_schema_->get_table_id() == dag.param_.index_schema_->get_table_id();
}
}
return is_equal;
}
int ObBuildIndexDag::get_partition(ObPGPartition*& partition)
{
int ret = OB_SUCCESS;
partition = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag has not been inited", K(ret));
} else if (OB_ISNULL(partition = guard_.get_pg_partition())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, partition must not be NULL", K(ret));
}
return ret;
}
int ObBuildIndexDag::get_partition_group(ObIPartitionGroup*& pg)
{
int ret = OB_SUCCESS;
pg = nullptr;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag has not been inited", K(ret));
} else if (OB_ISNULL(pg = pg_guard_.get_partition_group())) {
ret = OB_ERR_SYS;
STORAGE_LOG(WARN, "error sys, partition must not be null", K(ret));
}
return ret;
}
int ObBuildIndexDag::fill_comment(char* buf, const int64_t buf_len) const
{
int ret = OB_SUCCESS;
int64_t index_id = 0;
if (NULL != param_.index_schema_) {
index_id = param_.index_schema_->get_table_id();
}
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag has not been inited", K(ret));
} else if (OB_FAIL(databuff_printf(buf,
buf_len,
"build index task: pkey=%s index_id=%ld snapshot_version=%ld parallelism=%ld",
to_cstring(pkey_),
index_id,
param_.snapshot_version_,
param_.concurrent_cnt_))) {
STORAGE_LOG(WARN, "failed to fill comment", K(ret), K(pkey_));
}
return ret;
}
int ObBuildIndexDag::get_partition_storage(ObPartitionStorage*& storage)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag has not been inited", K(ret));
} else {
storage = partition_storage_;
}
return ret;
}
int ObBuildIndexDag::check_index_need_build(bool& need_build)
{
int ret = OB_SUCCESS;
need_build = false;
ObPartitionStorage* storage = NULL;
ObSpinLockGuard guard(context_.lock_);
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag is not inited", K(ret));
} else if (!context_.need_build_) {
need_build = false;
} else if (OB_FAIL(get_partition_storage(storage))) {
STORAGE_LOG(WARN, "fail to get partition storage", K(ret));
} else if (OB_ISNULL(storage)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, storage must not be NULL", K(ret));
} else if (OB_FAIL(storage->check_index_need_build(*param_.index_schema_, context_.need_build_))) {
STORAGE_LOG(WARN, "fail to check index need build", K(ret));
} else {
need_build = context_.need_build_;
}
return ret;
}
int ObBuildIndexDag::get_partition_service(ObPartitionService*& part_service)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag has not been inited", K(ret));
} else {
part_service = partition_service_;
}
return ret;
}
int ObBuildIndexDag::get_pg(ObIPartitionGroup*& pg)
{
int ret = OB_SUCCESS;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "build index dag is not inited", K(ret));
} else {
pg = pg_guard_.get_partition_group();
}
return ret;
}
int ObBuildIndexDag::prepare()
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "dag is not init", K(ret));
} else if (OB_ISNULL(partition_service_) || OB_UNLIKELY(!pkey_.is_valid())) {
ret = OB_ERR_SYS;
STORAGE_LOG(WARN, "invalid inner status", K(ret), KP(partition_service_), K(pkey_));
} else if (OB_FAIL(partition_service_->get_partition(pkey_, pg_guard_)) ||
OB_ISNULL(pg_guard_.get_partition_group())) {
STORAGE_LOG(WARN, "fail to get partition", K_(pkey), K(ret));
} else if (OB_FAIL(pg_guard_.get_partition_group()->get_pg_partition(pkey_, guard_)) ||
OB_ISNULL(guard_.get_pg_partition())) {
STORAGE_LOG(WARN, "fail to get pg partition", K_(pkey), K(ret));
} else {
partition_storage_ = static_cast<ObPartitionStorage*>(guard_.get_pg_partition()->get_storage());
}
return ret;
}
int ObBuildIndexDag::clean_up()
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObBuildIndexDag has not been inited", K(ret));
} else {
bool need_retry = true;
if (context_.need_build_ && !context_.is_report_succ_ && OB_FAIL(context_.build_index_ret_)) {
if (OB_FAIL(ObReportIndexStatusTask::report_index_status(pkey_, param_, &context_, need_retry))) {
STORAGE_LOG(ERROR, "fail to report index status", K(ret), K(pkey_), K(param_), K(context_));
}
}
if (NULL != context_.output_sstable_) {
context_.output_sstable_ = NULL;
context_.output_sstable_handle_.reset();
}
}
STORAGE_LOG(INFO, "build index finish", K(context_.build_index_ret_), K(pkey_), K(param_), K(context_));
return ret;
}
ObIndexPrepareTask::ObIndexPrepareTask() : ObITask(TASK_TYPE_INDEX_PERPARE), is_inited_(false), param_(), context_(NULL)
{}
ObIndexPrepareTask::~ObIndexPrepareTask()
{}
int ObIndexPrepareTask::init(ObBuildIndexParam& param, ObBuildIndexContext* context)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObIndexPrepareTask has already been inited", K(ret));
} else if (!param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(param), KP(context));
} else {
param_ = &param;
context_ = context;
is_inited_ = true;
}
return ret;
}
int ObIndexPrepareTask::process()
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
ObIndexLocalSortTask* local_sort_task = NULL;
ObIndexMergeTask* merge_task = NULL;
ObCompactToLatestTask* compact_task = NULL;
ObUniqueCheckingTask* checking_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (NULL == tmp_dag || ObIDag::DAG_TYPE_CREATE_INDEX != tmp_dag->get_type()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "dag is invalid", K(ret), KP(tmp_dag));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(generate_local_sort_tasks(dag, local_sort_task))) {
STORAGE_LOG(WARN, "fail to generate local sort tasks", K(ret));
} else if (OB_FAIL(generate_index_merge_task(dag, local_sort_task, merge_task))) {
STORAGE_LOG(WARN, "fail to generate index merge task", K(ret));
} else if (OB_FAIL(generate_compact_task(dag, merge_task, compact_task))) {
STORAGE_LOG(WARN, "fail to generate compact task", K(ret));
} else if (OB_FAIL(generate_unique_checking_task(dag, compact_task, checking_task))) {
STORAGE_LOG(WARN, "fail to generate unique checking task", K(ret));
} else if (OB_FAIL(generate_report_index_status_task(dag, checking_task))) {
STORAGE_LOG(WARN, "fail to generate report index status task", K(ret));
}
if (OB_SUCC(ret)) {
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = add_monitor_info(dag))) {
STORAGE_LOG(WARN, "fail to add monitor info", K(tmp_ret));
}
}
if (OB_FAIL(ret)) {
context_->build_index_ret_ = ret;
ret = OB_SUCCESS;
}
return ret;
}
int ObIndexPrepareTask::generate_report_index_status_task(ObBuildIndexDag* dag, ObUniqueCheckingTask* checking_task)
{
int ret = OB_SUCCESS;
ObReportIndexStatusTask* report_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), KP(dag));
} else if (OB_FAIL(dag->alloc_task(report_task))) {
STORAGE_LOG(WARN, "fail to alloc report index status task", K(ret));
} else if (OB_FAIL(report_task->init(dag->get_partition_key(), *param_, context_))) {
STORAGE_LOG(WARN, "fail to init report index status task", K(ret));
} else if (OB_FAIL(checking_task->add_child(*report_task))) {
STORAGE_LOG(WARN, "fail to add child for report index status task", K(ret));
} else if (OB_FAIL(dag->add_task(*report_task))) {
STORAGE_LOG(WARN, "fail to add report index status task", K(ret));
}
return ret;
}
int ObIndexPrepareTask::generate_compact_task(
ObBuildIndexDag* dag, ObIndexMergeTask* merge_task, ObCompactToLatestTask*& compact_task)
{
int ret = OB_SUCCESS;
compact_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag) || OB_ISNULL(merge_task)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(dag), KP(merge_task));
} else if (OB_FAIL(dag->alloc_task(compact_task))) {
STORAGE_LOG(WARN, "fail to alloc compact task", K(ret));
} else if (OB_FAIL(compact_task->init(dag->get_partition_key(), *param_, context_))) {
STORAGE_LOG(WARN, "fail to init compact task", K(ret));
} else if (OB_FAIL(merge_task->add_child(*compact_task))) {
STORAGE_LOG(WARN, "fail to add child for index merge task", K(ret));
} else if (OB_FAIL(dag->add_task(*compact_task))) {
STORAGE_LOG(WARN, "fail to add compact task", K(ret));
}
return ret;
}
int ObIndexPrepareTask::generate_unique_checking_task(
ObBuildIndexDag* dag, ObCompactToLatestTask* compact_task, ObUniqueCheckingTask*& checking_task)
{
int ret = OB_SUCCESS;
checking_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag) || OB_ISNULL(compact_task)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(dag), KP(compact_task));
} else if (OB_FAIL(dag->alloc_task(checking_task))) {
STORAGE_LOG(WARN, "fail to alloc checking task", K(ret));
} else if (OB_FAIL(checking_task->init(*param_, context_))) {
STORAGE_LOG(WARN, "fail to init unique checking task", K(ret));
} else if (OB_FAIL(compact_task->add_child(*checking_task))) {
STORAGE_LOG(WARN, "fail to add child for compact task", K(ret));
} else if (OB_FAIL(dag->add_task(*checking_task))) {
STORAGE_LOG(WARN, "fail to add unique checking task", K(ret));
}
return ret;
}
int ObIndexPrepareTask::generate_index_merge_task(
ObBuildIndexDag* dag, ObIndexLocalSortTask* local_sort_task, ObIndexMergeTask*& merge_task)
{
int ret = OB_SUCCESS;
merge_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag) || OB_ISNULL(local_sort_task)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(dag), KP(local_sort_task));
} else if (OB_FAIL(dag->alloc_task(merge_task))) {
STORAGE_LOG(WARN, "fail to alloc index merge task", K(ret));
} else if (OB_FAIL(merge_task->init(*param_, context_))) {
STORAGE_LOG(WARN, "fail to init index merge task", K(ret));
} else if (OB_FAIL(local_sort_task->add_child(*merge_task))) {
STORAGE_LOG(WARN, "fail to add child for index local sort task", K(ret));
} else if (OB_FAIL(dag->add_task(*merge_task))) {
STORAGE_LOG(WARN, "fail to add index merge task", K(ret));
}
return ret;
}
int ObIndexPrepareTask::generate_local_sort_tasks(ObBuildIndexDag* dag, ObIndexLocalSortTask*& local_sort_task)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(dag));
} else {
if (OB_FAIL(dag->alloc_task(local_sort_task))) {
STORAGE_LOG(WARN, "fail to alloc local sort task", K(ret));
} else if (OB_FAIL(local_sort_task->init(0, *param_, context_))) {
STORAGE_LOG(WARN, "fail to init local sort task", K(ret));
} else if (OB_FAIL(add_child(*local_sort_task))) {
STORAGE_LOG(WARN, "fail to add child for index prepare task", K(ret));
} else if (OB_FAIL(dag->add_task(*local_sort_task))) {
STORAGE_LOG(WARN, "fail to add local sort task to dag", K(ret));
}
}
return ret;
}
int ObIndexPrepareTask::add_monitor_info(ObBuildIndexDag* dag)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), KP(dag));
} else {
const int64_t concurrent_cnt = param_->concurrent_cnt_;
const int64_t total_task_cnt =
2 * concurrent_cnt + 1; // scan(concurrent_cnt), local_sort(concurrent_cnt), merge(1)
ObPGPartition* partition = NULL;
if (OB_FAIL(dag->get_partition(partition))) {
STORAGE_LOG(WARN, "fail to get partition", K(ret));
} else {
ObCreateIndexKey key;
ObCreateIndexPartitionStat part_stat;
key.index_table_id_ = param_->index_schema_->get_table_id();
key.tenant_id_ = extract_tenant_id(key.index_table_id_);
key.partition_id_ = dag->get_partition_key().get_partition_id();
if (OB_FAIL(key.to_key_string())) {
STORAGE_LOG(WARN, "fail to key string", K(ret));
} else {
part_stat.key_ = key;
part_stat.common_value_.start_time_ = ObTimeUtility::current_time();
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(LONG_OPS_MONITOR_INSTANCE.add_long_ops_stat(key, part_stat))) {
STORAGE_LOG(WARN, "fail to add partition stat", K(ret));
} else {
// scan task
for (int64_t i = 0; OB_SUCC(ret) && i < concurrent_cnt; ++i) {
ObCreateIndexScanTaskStat task_stat;
task_stat.task_id_ = i;
task_stat.type_ = ObILongOpsTaskStat::TaskType::SCAN;
if (OB_FAIL(LONG_OPS_MONITOR_INSTANCE.update_task_stat(key, task_stat))) {
STORAGE_LOG(WARN, "fail to update task stat", K(ret), K(key));
}
}
// local sort task and merge task
for (int64_t i = concurrent_cnt; OB_SUCC(ret) && i < total_task_cnt; ++i) {
ObCreateIndexSortTaskStat task_stat;
task_stat.task_id_ = i;
task_stat.type_ = ObILongOpsTaskStat::TaskType::SORT;
if (OB_FAIL(LONG_OPS_MONITOR_INSTANCE.update_task_stat(key, task_stat))) {
STORAGE_LOG(WARN, "fail to update task stat", K(ret), K(key));
}
}
}
}
}
return ret;
}
ObIndexLocalSortTask::ObIndexLocalSortTask()
: ObITask(TASK_TYPE_INDEX_LOCAL_SORT),
is_inited_(false),
task_id_(0),
param_(NULL),
context_(NULL),
local_sorter_(NULL)
{}
ObIndexLocalSortTask::~ObIndexLocalSortTask()
{}
int ObIndexLocalSortTask::init(const int64_t task_id, ObBuildIndexParam& param, ObBuildIndexContext* context)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObIndexLocalSortTask has already been inited", K(ret));
} else if (task_id < 0 || !param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(task_id), K(param), KP(context));
} else {
task_id_ = task_id;
param_ = &param;
context_ = context;
is_inited_ = true;
if (task_id_ >= 0 && task_id < context_->sorters_.count()) {
local_sorter_ = context_->sorters_.at(task_id);
}
if (OB_ISNULL(local_sorter_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, local_sort must not be NULL", K(ret));
}
}
return ret;
}
int ObIndexLocalSortTask::process()
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
ObPartitionStorage* storage = NULL;
bool need_build = false;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexLocalSortTask has not been inited", K(ret));
} else if (NULL == tmp_dag || ObIDag::DAG_TYPE_CREATE_INDEX != tmp_dag->get_type()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "dag is invalid", K(ret), KP(tmp_dag));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(dag->get_partition_storage(storage))) {
STORAGE_LOG(WARN, "fail to get partition storage", K(ret));
} else if (OB_ISNULL(storage)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, storage must not be NULL", K(ret));
} else if (OB_SUCCESS != (context_->build_index_ret_)) {
STORAGE_LOG(WARN, "build index has already failed", "ret", context_->build_index_ret_);
} else if (OB_FAIL(dag->check_index_need_build(need_build))) {
STORAGE_LOG(WARN, "fail to check index need build", K(ret), K(*param_));
} else if (!need_build) {
STORAGE_LOG(INFO, "index do not need build", "index_id", param_->index_schema_->get_table_id());
} else if (OB_FAIL(storage->local_sort_index_by_range(task_id_, *param_, *context_))) {
STORAGE_LOG(WARN, "fail to do local sort index by range", K(ret));
} else {
STORAGE_LOG(INFO, "finish local sort", "index_id", param_->index_schema_->get_table_id());
}
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = E(EventTable::EN_INDEX_LOCAL_SORT_TASK) OB_SUCCESS;
}
#endif
if (OB_FAIL(ret) && NULL != context_) {
context_->build_index_ret_ = ret;
ret = OB_SUCCESS;
}
return ret;
}
int ObIndexLocalSortTask::generate_next_task(ObITask*& next_task)
{
int ret = OB_SUCCESS;
ObIDag* dag = get_dag();
ObBuildIndexDag* build_index_dag = NULL;
ObIndexLocalSortTask* index_local_sort_task = NULL;
const int64_t next_task_id = task_id_ + 1;
next_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexLocalSortTask has not been inited", K(ret));
} else if (next_task_id == param_->concurrent_cnt_) {
ret = OB_ITER_END;
} else if (OB_ISNULL(dag)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, dag must not be NULL", K(ret));
} else if (OB_UNLIKELY(ObIDag::DAG_TYPE_CREATE_INDEX != dag->get_type())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, dag type is invalid", K(ret), "dag type", dag->get_type());
} else if (FALSE_IT(build_index_dag = static_cast<ObBuildIndexDag*>(dag))) {
} else if (OB_FAIL(build_index_dag->alloc_task(index_local_sort_task))) {
STORAGE_LOG(WARN, "fail to alloc task", K(ret));
} else if (OB_FAIL(index_local_sort_task->init(next_task_id, *param_, context_))) {
STORAGE_LOG(WARN, "fail to init index local task", K(ret));
} else {
next_task = index_local_sort_task;
STORAGE_LOG(INFO, "generate next local sort task", K(ret), "index_id", param_->index_schema_->get_table_id());
}
if (OB_FAIL(ret) && NULL != context_) {
if (OB_ITER_END != ret) {
context_->build_index_ret_ = ret;
}
}
return ret;
}
ObIndexMergeTask::ObIndexMergeTask()
: ObITask(TASK_TYPE_INDEX_MERGE), is_inited_(false), param_(), context_(NULL), sorters_(NULL)
{}
ObIndexMergeTask::~ObIndexMergeTask()
{}
int ObIndexMergeTask::init(ObBuildIndexParam& param, ObBuildIndexContext* context)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObIndexMergeTask has already been inited", K(ret));
} else if (!param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(param), KP(context));
} else {
param_ = &param;
context_ = context;
sorters_ = &context_->sorters_;
is_inited_ = true;
}
return ret;
}
int ObIndexMergeTask::process()
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
ObPartitionStorage* storage = NULL;
ObIPartitionGroup* pg = nullptr;
bool need_build = false;
ObTableHandle new_sstable;
ObSSTable* sstable = nullptr;
const int64_t max_kept_major_version_number = 1;
const bool in_slog_trans = false;
if (OB_ISNULL(sorters_) || 0 == sorters_->count() || OB_ISNULL(tmp_dag) || OB_ISNULL(context_)) {
ret = OB_ERR_SYS;
STORAGE_LOG(WARN, "invalid inner state", K(ret), KP(sorters_), KP(tmp_dag), KP(context_));
} else if (OB_SUCCESS != (context_->build_index_ret_)) {
STORAGE_LOG(WARN, "Build Index has already failed", "ret", context_->build_index_ret_);
} else if (ObIDag::DAG_TYPE_CREATE_INDEX != tmp_dag->get_type()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "dag is invalid", K(ret), K(tmp_dag->get_type()));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(dag->get_partition_storage(storage))) {
STORAGE_LOG(WARN, "fail to get partition storage", K(ret));
} else if (OB_ISNULL(storage)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, storage must not be NULL", K(ret));
} else if (OB_FAIL(dag->get_pg(pg))) {
STORAGE_LOG(WARN, "failed to get pg", K(ret));
} else if (OB_ISNULL(pg)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "pg is null", K(ret));
} else if (OB_FAIL(dag->check_index_need_build(need_build))) {
STORAGE_LOG(WARN, "fail to check index need build", K(ret), K(*param_));
} else if (!need_build) {
STORAGE_LOG(INFO, "index do not need build", "index_id", param_->index_schema_->get_table_id());
} else if (OB_FAIL(merge_local_sort_index(*param_, *sorters_, merge_sorter_, context_, new_sstable))) {
STORAGE_LOG(WARN, "fail to merge local sort index", K(ret));
} else if (OB_FAIL(new_sstable.get_sstable(sstable))) {
STORAGE_LOG(WARN, "failed to get sstable", K(ret));
} else if (OB_FAIL(pg->get_pg_storage().add_sstable(
dag->get_partition_key(), sstable, max_kept_major_version_number, in_slog_trans))) {
STORAGE_LOG(WARN, "failed to add sstable", K(ret), K(*param_));
} else if (OB_FAIL(param_->report_->submit_checksum_update_task(dag->get_partition_key(),
param_->index_schema_->get_table_id(),
ObITable::MAJOR_SSTABLE,
ObSSTableChecksumUpdateType::UPDATE_ALL,
false /*do not batch report immedidately*/))) {
STORAGE_LOG(WARN, "fail to submit checksum update task", K(ret));
}
STORAGE_LOG(INFO, "do clean up merge sorter");
merge_sorter_.clean_up();
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = E(EventTable::EN_INDEX_MERGE_TASK) OB_SUCCESS;
}
#endif
if (OB_FAIL(ret) && NULL != context_) {
context_->build_index_ret_ = ret;
ret = OB_SUCCESS;
}
return ret;
}
int ObIndexMergeTask::merge_local_sort_index(const ObBuildIndexParam& param,
const ObIArray<ObExternalSort<ObStoreRow, ObStoreRowComparer>*>& local_sorters,
ObExternalSort<ObStoreRow, ObStoreRowComparer>& merge_sorter, ObBuildIndexContext* context,
ObTableHandle& new_sstable)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
int comp_ret = OB_SUCCESS;
ObArray<int64_t> sort_column_indexes;
ObStoreRowComparer comparer(comp_ret, sort_column_indexes);
ObCreateIndexKey key;
ObCreateIndexSortTaskStat sort_task_stat;
const int64_t file_buf_size = ObExternalSortConstant::DEFAULT_FILE_READ_WRITE_BUFFER;
const int64_t expire_timestamp = 0; // no time limited
const int64_t buf_limit = param.DEFAULT_INDEX_SORT_MEMORY_LIMIT;
ObPGPartition* partition = NULL;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = nullptr;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObPartitionStorage has not been inited", K(ret));
} else if (!param.is_valid() || 0 == local_sorters.count() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(param), K(local_sorters.count()), KP(context));
} else if (ObIDag::DAG_TYPE_CREATE_INDEX != tmp_dag->get_type()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "dag is invalid", K(ret), K(tmp_dag->get_type()));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(dag->get_partition(partition))) {
STORAGE_LOG(WARN, "fail to get partition", K(ret));
} else {
key.index_table_id_ = param.index_schema_->get_table_id();
key.tenant_id_ = extract_tenant_id(key.index_table_id_);
key.partition_id_ = partition->get_partition_key().get_partition_id();
sort_task_stat.task_id_ = 2 * param.concurrent_cnt_;
sort_task_stat.type_ = ObILongOpsTaskStat::TaskType::SORT;
sort_task_stat.state_ = ObILongOpsTaskStat::TaskState::RUNNING;
sort_task_stat.macro_count_ = context->index_macro_cnt_;
sort_task_stat.run_count_ = 1;
if (OB_SUCCESS != (tmp_ret = LONG_OPS_MONITOR_INSTANCE.update_task_stat(key, sort_task_stat))) {
STORAGE_LOG(WARN, "fail to update task stat", K(ret), K(sort_task_stat));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < param.index_schema_->get_rowkey_column_num(); ++i) {
if (OB_FAIL(sort_column_indexes.push_back(i))) {
STORAGE_LOG(WARN, "Fail to push sort column indexes, ", K(ret), K(i));
}
}
STORAGE_LOG(INFO, "begin merging index local sort result", K(ret), K(param));
if (OB_SUCC(ret)) {
const uint64_t tenant_id = extract_tenant_id(param.index_schema_->get_table_id());
if (OB_FAIL(merge_sorter.init(buf_limit, file_buf_size, expire_timestamp, tenant_id, &comparer))) {
STORAGE_LOG(WARN, "fail to init merge sorter", K(ret));
} else {
const bool is_final_merge = true;
for (int64_t i = 0; OB_SUCC(ret) && i < local_sorters.count(); ++i) {
ObExternalSort<ObStoreRow, ObStoreRowComparer>* local_sort = local_sorters.at(i);
if (OB_ISNULL(local_sort)) {
ret = OB_ERR_SYS;
STORAGE_LOG(WARN, "local_sort must not be NULL", K(ret));
} else if (OB_FAIL(local_sort->transfer_final_sorted_fragment_iter(merge_sorter))) {
STORAGE_LOG(WARN, "fail to get final sorted fragment iterator", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(merge_sorter.do_sort(is_final_merge))) {
STORAGE_LOG(WARN, "fail to do final merge", K(ret));
} else if (OB_FAIL(add_build_index_sstable(param, merge_sorter, context, new_sstable))) {
STORAGE_LOG(WARN, "fail to add build index sstable", K(ret));
} else {
STORAGE_LOG(INFO, "finish merging index local sort result", K(ret));
}
}
}
}
sort_task_stat.state_ =
(OB_SUCCESS == ret) ? ObILongOpsTaskStat::TaskState::SUCCESS : ObILongOpsTaskStat::TaskState::FAIL;
if (OB_SUCCESS != (tmp_ret = key.to_key_string())) {
STORAGE_LOG(WARN, "fail to key string", K(ret));
} else if (OB_SUCCESS != (tmp_ret = LONG_OPS_MONITOR_INSTANCE.update_task_stat(key, sort_task_stat))) {
STORAGE_LOG(WARN, "fail to update task stat", K(ret));
}
return ret;
}
int ObIndexMergeTask::add_build_index_sstable(const ObBuildIndexParam& param,
ObExternalSort<ObStoreRow, ObStoreRowComparer>& external_sort, ObBuildIndexContext* context,
ObTableHandle& new_sstable)
{
int ret = OB_SUCCESS;
ObColumnChecksumCalculator checksum;
const bool is_major_merge = true;
ObMacroDataSeq macro_start_seq(0);
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = nullptr;
ObPGPartition* partition = nullptr;
ObIPartitionGroup* pg = nullptr;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObPartitionStorage has not been inited", K(ret));
} else if (!param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(param), KP(context));
} else if (ObIDag::DAG_TYPE_CREATE_INDEX != tmp_dag->get_type()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "dag is invalid", K(ret), K(tmp_dag->get_type()));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(dag->get_partition(partition))) {
STORAGE_LOG(WARN, "fail to get partition", K(ret));
} else if (OB_FAIL(checksum.init(param.index_schema_->get_column_count()))) {
STORAGE_LOG(WARN, "fail to init checksum", K(ret));
} else if (OB_FAIL(dag->get_pg(pg))) {
STORAGE_LOG(WARN, "fail to get pg", K(ret));
} else if (OB_FAIL(data_desc_.init(*param.index_schema_,
param.version_,
nullptr,
partition->get_partition_key().get_partition_id(),
MAJOR_MERGE,
blocksstable::CCM_VALUE_ONLY == param.checksum_method_ /*need calc column checksum*/,
true /*store column checksum in micro block*/,
pg->get_partition_key(),
pg->get_storage_file_handle()))) {
STORAGE_LOG(WARN, "Fail to init data store desc, ", K(ret));
} else if (FALSE_IT(data_desc_.is_unique_index_ = param.index_schema_->is_unique_index())) {
} else if (OB_FAIL(writer_.open(data_desc_, macro_start_seq))) {
STORAGE_LOG(WARN, "Fail to open macro block writer, ", K(ret));
} else {
common::ObArenaAllocator allocator(ObModIds::OB_SSTABLE_CREATE_INDEX);
const ObStoreRow* row = NULL;
int64_t row_count = 0;
while (OB_SUCC(ret)) {
if (OB_FAIL(external_sort.get_next_item(row))) {
if (OB_ITER_END != ret) {
STORAGE_LOG(WARN, "Fail to get next row from external sort, ", K(ret));
} else {
ret = OB_SUCCESS;
break;
}
} else if (OB_FAIL(writer_.append_row(*row))) {
if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret && param.index_schema_->is_unique_index()) {
LOG_USER_ERROR(OB_ERR_PRIMARY_KEY_DUPLICATE, "", static_cast<int>(sizeof("UNIQUE IDX") - 1), "UNIQUE IDX");
} else {
STORAGE_LOG(WARN, "Fail to append row to sstable, ", K(ret));
}
} else if (OB_FAIL(checksum.calc_column_checksum(param.checksum_method_, row, NULL, NULL))) {
STORAGE_LOG(WARN, "fail to calc column checksum", K(ret));
} else {
#ifdef ERRSIM
if (OB_SUCC(ret)) {
ret = E(EventTable::EN_INDEX_WRITE_BLOCK) OB_SUCCESS;
}
#endif
++row_count;
}
}
STORAGE_LOG(INFO, "index table row count", K(row_count), "index_id", param.index_schema_->get_table_id());
if (OB_SUCC(ret)) {
if (OB_FAIL(writer_.close())) {
STORAGE_LOG(WARN, "fail to close writer", K(ret));
} else if (!param.index_schema_->is_domain_index() &&
OB_FAIL(
context->check_column_checksum(checksum.get_column_checksum(), row_count, context->column_cnt_))) {
STORAGE_LOG(WARN, "fail to check column checksum", K(ret));
} else if (OB_FAIL(add_new_index_sstable(param, &writer_, checksum.get_column_checksum(), new_sstable))) {
STORAGE_LOG(WARN, "fail to update sstore", K(ret));
}
}
}
if (OB_FAIL(ret)) {
writer_.reset();
}
return ret;
}
int ObIndexMergeTask::add_new_index_sstable(const ObBuildIndexParam& param, ObMacroBlockWriter* writer,
const int64_t* column_checksum, ObTableHandle& new_sstable)
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = nullptr;
ObIPartitionGroup* pg = nullptr;
ObPGPartition* pg_partition = nullptr;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObPartitionStorage has not been inited", K(ret));
} else if (!param.is_valid() || OB_ISNULL(writer) || OB_ISNULL(column_checksum)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(param), KP(writer), KP(column_checksum));
} else if (ObIDag::DAG_TYPE_CREATE_INDEX != tmp_dag->get_type()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "dag is invalid", K(ret), K(tmp_dag->get_type()));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(dag->get_partition_group(pg))) {
STORAGE_LOG(WARN, "fail to get partition group", K(ret));
} else if (OB_ISNULL(pg)) {
ret = OB_ERR_SYS;
STORAGE_LOG(WARN, "error sys, invalid partition group", K(ret));
} else if (OB_FAIL(dag->get_partition(pg_partition))) {
STORAGE_LOG(WARN, "fail to get partition", K(ret));
} else {
const ObTableSchema& index_schema = *param.index_schema_;
ObITable::TableKey table_key;
ObPGCreateSSTableParam pg_create_sstable_param;
ObCreateSSTableParamWithTable sstable_param;
table_key.table_type_ = ObITable::MAJOR_SSTABLE;
table_key.pkey_ = pg_partition->get_partition_key();
table_key.table_id_ = index_schema.get_table_id();
table_key.trans_version_range_.multi_version_start_ = param.snapshot_version_;
table_key.trans_version_range_.base_version_ = ObVersionRange::MIN_VERSION;
table_key.trans_version_range_.snapshot_version_ = param.snapshot_version_;
table_key.version_ = param.version_;
sstable_param.table_key_ = table_key;
sstable_param.schema_ = &index_schema;
sstable_param.schema_version_ = param.schema_version_;
sstable_param.create_snapshot_version_ = param.snapshot_version_;
sstable_param.checksum_method_ = param.checksum_method_;
sstable_param.progressive_merge_round_ = index_schema.get_progressive_merge_round();
sstable_param.progressive_merge_step_ = 0;
sstable_param.logical_data_version_ = table_key.version_;
pg_create_sstable_param.with_table_param_ = &sstable_param;
if (OB_FAIL(pg_create_sstable_param.data_blocks_.push_back(&writer->get_macro_block_write_ctx()))) {
LOG_WARN("fail to push back writer macro block ctx", K(ret));
} else if (OB_FAIL(pg->create_sstable(pg_create_sstable_param, new_sstable))) {
LOG_WARN("fail to create sstable", K(ret));
}
}
return ret;
}
ObCompactToLatestTask::ObCompactToLatestTask()
: ObITask(ObITaskType::TASK_TYPE_COMPACT_TO_LASTEST), is_inited_(false), pkey_(), param_(NULL), context_(NULL)
{}
ObCompactToLatestTask::~ObCompactToLatestTask()
{}
int ObCompactToLatestTask::init(
const ObPartitionKey& pkey, const compaction::ObBuildIndexParam& param, compaction::ObBuildIndexContext* context)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("ObCompactToLatestTask has already been inited", K(ret));
} else if (OB_UNLIKELY(!pkey.is_valid() || !param.is_valid() || OB_ISNULL(context))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(pkey), K(param), KP(context));
} else {
pkey_ = pkey;
param_ = &param;
context_ = context;
is_inited_ = true;
}
return ret;
}
int ObCompactToLatestTask::process()
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
bool need_build = false;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObCompactToLatestTask has not been inited", K(ret));
} else if (!context_->need_build_) {
STORAGE_LOG(INFO, "index does not need build", K(*param_));
} else if (FALSE_IT(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
} else if (OB_FAIL(dag->check_index_need_build(need_build))) {
STORAGE_LOG(WARN, "fail to check index need build", K(ret), K(*param_));
} else if (!need_build) {
STORAGE_LOG(INFO, "index do not need build", "index_id", param_->index_schema_->get_table_id());
} else if (OB_SUCCESS != (context_->build_index_ret_)) {
STORAGE_LOG(WARN, "Build Index has already failed", "ret", context_->build_index_ret_);
} else if (OB_FAIL(wait_compact_to_latest(pkey_, param_->index_schema_->get_table_id()))) {
STORAGE_LOG(WARN, "fail to wait compact to latest", K(ret));
}
if (OB_FAIL(ret) && NULL != context_) {
context_->build_index_ret_ = ret;
ret = OB_SUCCESS;
}
LOG_INFO("compact task ret", "ret", context_->build_index_ret_);
return ret;
}
int ObCompactToLatestTask::wait_compact_to_latest(const ObPartitionKey& pkey, const uint64_t index_id)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!pkey.is_valid() || OB_INVALID_ID == index_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(pkey), K(index_id));
} else {
int tmp_ret = OB_SUCCESS;
bool is_merged = false;
while (OB_SUCC(ret)) {
bool is_finished = false;
if (OB_SUCCESS != (tmp_ret = ObPartitionScheduler::get_instance().schedule_merge(pkey, is_merged))) {
LOG_WARN("fail to schedule merge", K(tmp_ret));
}
if (OB_FAIL(ObPartitionScheduler::get_instance().check_index_compact_to_latest(pkey, index_id, is_finished))) {
LOG_WARN("fail to check index compact to latest", K(ret));
} else if (is_finished) {
break;
}
if (OB_SUCC(ret)) {
usleep(RETRY_INTERVAL);
dag_yield();
}
}
}
LOG_INFO("compact index to latest finish", K(ret), K(index_id));
return ret;
}
ObUniqueIndexChecker::ObUniqueIndexChecker()
: is_inited_(false),
part_service_(NULL),
pkey_(),
index_schema_(NULL),
data_table_schema_(NULL),
execution_id_(0),
snapshot_version_(0),
part_guard_()
{}
int ObUniqueIndexChecker::init(ObPartitionService* part_service, const common::ObPartitionKey& pkey,
const ObTableSchema* data_table_schema, const ObTableSchema* index_schema, const uint64_t execution_id,
const int64_t snapshot_version)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObUniqueIndexChecker has already been inited", K(ret));
} else if (OB_UNLIKELY(
NULL == part_service || !pkey.is_valid() || NULL == data_table_schema || NULL == index_schema)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), KP(part_service), K(pkey), KP(data_table_schema), KP(index_schema));
} else {
is_inited_ = true;
part_service_ = part_service;
pkey_ = pkey;
data_table_schema_ = data_table_schema;
index_schema_ = index_schema;
execution_id_ = execution_id;
snapshot_version_ = snapshot_version;
}
return ret;
}
int ObUniqueIndexChecker::calc_column_checksum(const int64_t column_cnt, ObIStoreRowIterator& iterator,
common::ObIArray<int64_t>& column_checksum, int64_t& row_count)
{
int ret = OB_SUCCESS;
row_count = 0;
column_checksum.reuse();
if (OB_UNLIKELY(column_cnt <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(column_cnt));
} else if (OB_FAIL(column_checksum.reserve(column_cnt))) {
STORAGE_LOG(WARN, "fail to reserve column", K(ret), K(column_cnt));
} else {
const ObStoreRow* row = NULL;
for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt; ++i) {
if (OB_FAIL(column_checksum.push_back(0))) {
STORAGE_LOG(WARN, "fail to push back column checksum", K(ret));
}
}
while (OB_SUCC(ret)) {
if (OB_FAIL(iterator.get_next_row(row))) {
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
break;
} else {
STORAGE_LOG(WARN, "fail to get next row", K(ret));
}
} else if (OB_ISNULL(row)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "store row must not be NULL", K(ret), KP(row));
} else if (column_cnt != row->row_val_.count_) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(
WARN, "column cnt not as expected", K(ret), K(column_cnt), "row_val_column_cnt", row->row_val_.count_);
} else {
++row_count;
for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt; ++i) {
column_checksum.at(i) += row->row_val_.cells_[i].checksum(0);
}
dag_yield();
}
}
}
return ret;
}
int ObUniqueIndexChecker::scan_table_with_column_checksum(
const ObScanTableParam& param, ObIArray<int64_t>& column_checksum, int64_t& row_count)
{
int ret = OB_SUCCESS;
ObPartitionStorage* storage = NULL;
if (OB_UNLIKELY(!param.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(param));
} else if (OB_ISNULL(part_guard_.get_pg_partition())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, partition must not be NULL", K(ret));
} else if (OB_ISNULL(storage = static_cast<ObPartitionStorage*>(part_guard_.get_pg_partition()->get_storage()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, storage must not be NULL", K(ret));
} else {
ObQueryFlag query_flag(ObQueryFlag::Forward,
true, /*is daily merge scan*/
true, /*is read multiple macro block*/
true, /*sys task scan, read one macro block in single io*/
false, /*is full row scan?*/
false,
false);
ObArray<ObColumnParam*> col_params;
ObArray<uint64_t> output_column_ids;
ObTableAccessParam access_param;
ObTableAccessContext access_ctx;
ObBlockCacheWorkingSet block_cache_ws;
ObStoreCtx ctx;
ObArenaAllocator allocator(ObModIds::OB_CS_BUILD_INDEX);
ObMultipleScanMerge* scan_merge = NULL;
for (int64_t i = 0; OB_SUCC(ret) && i < param.col_ids_->count(); i++) {
const ObColumnSchemaV2* col = param.index_schema_->get_column_schema(param.col_ids_->at(i).col_id_);
if (NULL == col) {
// generated column's depend column, get column schema from data table
col = param.data_table_schema_->get_column_schema(param.col_ids_->at(i).col_id_);
}
if (NULL == col) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to get column schema", K(ret));
} else {
void* buf = allocator.alloc(sizeof(ObColumnParam));
if (NULL == buf) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "fail to allocate memory", K(ret));
} else {
ObColumnParam* col_param = new (buf) ObColumnParam(allocator);
if (OB_FAIL(ObTableParam::convert_column_schema_to_param(*col, *col_param))) {
STORAGE_LOG(WARN, "fail to convert schema column to column parameter", K(ret));
} else if (OB_FAIL(col_params.push_back(col_param))) {
STORAGE_LOG(WARN, "fail to push array", K(ret));
} else if (OB_FAIL(output_column_ids.push_back(param.col_ids_->at(i).col_id_))) {
LOG_WARN("push back output column id fail", K(ret), K(param.col_ids_->at(i)));
}
}
}
}
if (OB_SUCC(ret)) {
transaction::ObTransService* txs = ObPartitionService::get_instance().get_trans_service();
const ObTableSchema& query_schema = param.is_scan_index_ ? *param.index_schema_ : *param.data_table_schema_;
if (OB_ISNULL(ctx.mem_ctx_ = txs->get_mem_ctx_factory()->alloc())) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(ERROR, "fail to allocate transaction memory context", K(ret));
} else if (OB_FAIL(ctx.mem_ctx_->trans_begin())) {
STORAGE_LOG(WARN, "fail to begin transaction", K(ret));
} else if (OB_FAIL(ctx.mem_ctx_->sub_trans_begin(param.snapshot_version_, BUILD_INDEX_READ_SNAPSHOT_VERSION))) {
STORAGE_LOG(WARN, "fail to begin sub transaction", K(ret), K(param.snapshot_version_));
} else if (OB_FAIL(block_cache_ws.init(extract_tenant_id(param.index_schema_->get_table_id())))) {
LOG_WARN("fail to init block cache working set", K(ret));
} else if (OB_FAIL(access_param.out_col_desc_param_.init())) {
LOG_WARN("fail to init out cols", K(ret));
} else if (OB_FAIL(access_param.out_col_desc_param_.assign(*param.col_ids_))) {
LOG_WARN("fail to assign out cols", K(ret));
} else {
void* buf = NULL;
ObExtStoreRange range;
ObGetTableParam get_table_param;
range.get_range().set_whole_range();
access_param.iter_param_.table_id_ = query_schema.get_table_id();
access_param.iter_param_.rowkey_cnt_ = query_schema.get_rowkey_column_num();
access_param.iter_param_.schema_version_ = query_schema.get_schema_version();
access_param.iter_param_.out_cols_project_ = param.output_projector_;
access_param.iter_param_.out_cols_ = &access_param.out_col_desc_param_.get_col_descs();
access_param.out_cols_param_ = &col_params;
access_param.reserve_cell_cnt_ = param.output_projector_->count();
common::ObVersionRange trans_version_range;
trans_version_range.snapshot_version_ = param.snapshot_version_;
trans_version_range.multi_version_start_ = param.snapshot_version_;
trans_version_range.base_version_ = 0;
get_table_param.partition_store_ = &storage->get_partition_store();
ObPartitionKey pg_key;
if (OB_FAIL(ObPartitionService::get_instance().get_pg_key(pkey_, pg_key))) {
STORAGE_LOG(WARN, "failed to get_pg_key", K(ret), K_(pkey));
} else if (OB_FAIL(ctx.init_trans_ctx_mgr(pg_key))) {
STORAGE_LOG(WARN, "failed to init_ctx_mgr", K(ret), K(pg_key));
} else if (OB_FAIL(
access_ctx.init(query_flag, ctx, allocator, allocator, block_cache_ws, trans_version_range))) {
LOG_WARN("Failed to init trans_version range", K(ret));
} else if (OB_ISNULL(buf = allocator.alloc(sizeof(ObMultipleScanMerge)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "fail to allocate memory", K(ret));
} else if (OB_ISNULL(scan_merge = new (buf) ObMultipleScanMerge())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, placement new failed", K(ret));
} else if (OB_FAIL(scan_merge->init(access_param, access_ctx, get_table_param))) {
STORAGE_LOG(WARN, "fail to init multiple scan merge", K(ret));
} else if (OB_FAIL(scan_merge->open(range))) {
STORAGE_LOG(WARN, "fail to open scan merge", K(ret));
} else {
const_cast<ObScanTableParam&>(param).tables_handle_->reset();
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(calc_column_checksum(
access_param.iter_param_.out_cols_project_->count(), *scan_merge, column_checksum, row_count))) {
STORAGE_LOG(WARN, "fail to calc column checksum", K(ret));
}
}
if (NULL != scan_merge) {
scan_merge->~ObMultipleScanMerge();
scan_merge = NULL;
}
if (NULL != ctx.mem_ctx_) {
ctx.mem_ctx_->trans_end(true, 0);
ctx.mem_ctx_->trans_clear();
txs->get_mem_ctx_factory()->free(ctx.mem_ctx_);
ctx.mem_ctx_ = NULL;
}
}
}
return ret;
}
int ObUniqueIndexChecker::scan_main_table_with_column_checksum(const ObTableSchema& data_table_schema,
const ObTableSchema& index_schema, const int64_t snapshot_version, ObTablesHandle& tables_handle,
ObIArray<int64_t>& column_checksum, int64_t& row_count)
{
int ret = OB_SUCCESS;
ObArray<share::schema::ObColDesc> col_ids;
ObArray<share::schema::ObColDesc> org_col_ids;
ObArray<int32_t> output_projector;
int64_t unique_key_cnt = 0;
if (OB_UNLIKELY(!data_table_schema.is_valid() || !index_schema.is_valid() || snapshot_version <= 0 ||
0 == tables_handle.get_count())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN,
"invalid arguments",
K(ret),
K(data_table_schema),
K(index_schema),
K(snapshot_version),
K(tables_handle));
} else if (OB_FAIL(ObPartitionStorage::generate_index_output_param(
data_table_schema, index_schema, col_ids, org_col_ids, output_projector, unique_key_cnt))) {
STORAGE_LOG(WARN, "fail to generate index output param", K(ret));
} else {
ObScanTableParam param;
param.data_table_schema_ = &data_table_schema;
param.index_schema_ = &index_schema;
param.snapshot_version_ = snapshot_version;
param.col_ids_ = &col_ids;
param.output_projector_ = &output_projector;
param.is_scan_index_ = false;
param.tables_handle_ = &tables_handle;
if (OB_FAIL(scan_table_with_column_checksum(param, column_checksum, row_count))) {
STORAGE_LOG(WARN, "fail to scan table with column checksum", K(ret));
}
}
return ret;
}
int ObUniqueIndexChecker::scan_index_table_with_column_checksum(const ObTableSchema& data_table_schema,
const ObTableSchema& index_schema, const int64_t snapshot_version, ObTablesHandle& tables_handle,
ObIArray<int64_t>& column_checksum, int64_t& row_count)
{
int ret = OB_SUCCESS;
ObArray<ObColDesc> column_ids;
if (OB_UNLIKELY(!index_schema.is_valid() || snapshot_version <= 0 || 0 == tables_handle.get_count())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(index_schema), K(snapshot_version), K(tables_handle));
} else if (OB_FAIL(index_schema.get_column_ids(column_ids))) {
STORAGE_LOG(WARN, "fail to get column ids", K(ret), "index_id", index_schema.get_table_id());
} else {
ObArray<int32_t> output_projector;
for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) {
if (OB_FAIL(output_projector.push_back(static_cast<int32_t>(i)))) {
STORAGE_LOG(WARN, "fail to push back output projector", K(ret));
}
}
if (OB_SUCC(ret)) {
ObScanTableParam param;
param.data_table_schema_ = &data_table_schema;
param.index_schema_ = &index_schema;
param.snapshot_version_ = snapshot_version;
param.col_ids_ = &column_ids;
param.output_projector_ = &output_projector;
param.is_scan_index_ = true;
param.tables_handle_ = &tables_handle;
if (OB_FAIL(scan_table_with_column_checksum(param, column_checksum, row_count))) {
STORAGE_LOG(WARN, "fail to scan table with column checksum", K(ret));
}
}
}
return ret;
}
int ObUniqueIndexChecker::check_global_index(ObIDag* dag, ObPartitionStorage* storage)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(dag) || OB_ISNULL(storage)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(dag), KP(storage));
} else {
ObTablesHandle tables_handle;
ObArray<int64_t> column_checksum;
int64_t row_count = 0;
if (OB_FAIL(try_get_read_tables(pkey_.get_table_id(), snapshot_version_, dag, tables_handle))) {
LOG_WARN("fail to try get read tables", K(ret));
}
if (OB_SUCC(ret) && !dag->has_set_stop()) {
if (pkey_.get_table_id() == data_table_schema_->get_table_id()) {
if (OB_FAIL(scan_main_table_with_column_checksum(
*data_table_schema_, *index_schema_, snapshot_version_, tables_handle, column_checksum, row_count))) {
STORAGE_LOG(WARN, "fail to scan main table with column checksum", K(ret));
}
} else if (pkey_.get_table_id() == index_schema_->get_table_id()) {
if (OB_FAIL(scan_index_table_with_column_checksum(
*data_table_schema_, *index_schema_, snapshot_version_, tables_handle, column_checksum, row_count))) {
STORAGE_LOG(WARN, "fail to scan index table with column checksum", K(ret));
}
}
}
if (OB_SUCC(ret) && !dag->has_set_stop()) {
ObArray<ObColDesc> column_ids;
if (OB_FAIL(index_schema_->get_column_ids(column_ids))) {
STORAGE_LOG(WARN, "fail to get columns ids", K(ret));
} else if (column_ids.count() != column_checksum.count()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(
WARN, "error unexpected, column count mismatch", K(ret), K(column_ids.count()), K(column_checksum.count()));
} else {
ObArray<ObIndexChecksumItem> checksum_items;
for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) {
// generated column in index schema is not marked as generated, so we should retreive the column schema from
// data table
const ObColumnSchemaV2* column_schema = data_table_schema_->get_column_schema(column_ids.at(i).col_id_);
if (NULL == column_schema) {
column_schema = index_schema_->get_column_schema(column_ids.at(i).col_id_);
}
if (OB_ISNULL(column_schema)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, column schema must not be NULL", K(ret), K(column_ids.at(i).col_id_));
} else if (column_schema->is_shadow_column() || column_schema->is_generated_column() ||
!column_schema->is_column_stored_in_sstable()) {
STORAGE_LOG(INFO, "column do not need to compare checksum", K(column_ids.at(i).col_id_));
} else {
ObIndexChecksumItem item;
item.execution_id_ = execution_id_;
item.tenant_id_ = extract_tenant_id(pkey_.get_table_id());
item.table_id_ = pkey_.get_table_id();
item.partition_id_ = pkey_.get_partition_id();
item.column_id_ = column_ids.at(i).col_id_;
item.task_id_ = -1;
item.checksum_ = column_checksum.at(i);
item.checksum_method_ = blocksstable::CCM_TYPE_AND_VALUE;
if (OB_FAIL(checksum_items.push_back(item))) {
LOG_WARN("fail to push back item", K(ret));
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(ObIndexChecksumOperator::update_checksum(checksum_items, *GCTX.sql_proxy_))) {
LOG_WARN("fail to update checksum", K(ret));
}
}
}
}
}
return ret;
}
int ObUniqueIndexChecker::try_get_read_tables(
const uint64_t table_id, const int64_t snapshot_version, ObIDag* dag, ObTablesHandle& tables_handle)
{
int ret = OB_SUCCESS;
tables_handle.reset();
if (OB_INVALID_ID == table_id || snapshot_version <= 0 || NULL == dag) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(table_id), K(snapshot_version), KP(dag));
} else {
ObIPartitionGroupGuard part_guard;
ObPartitionStorage* storage = NULL;
const bool allow_not_ready = false;
const bool need_safety_check = true;
const bool reset_handle = true;
const bool print_dropped_alert = false;
while (OB_SUCC(ret) && !dag->has_set_stop()) {
if (OB_FAIL(part_service_->get_partition(pkey_, part_guard))) {
if (OB_PARTITION_NOT_EXIST == ret) {
STORAGE_LOG(INFO, "partition not exist, may be deleted", K(pkey_));
ret = OB_SUCCESS;
break;
} else {
STORAGE_LOG(WARN, "fail to get partition", K(ret), K_(pkey));
}
} else if (OB_ISNULL(part_guard_.get_pg_partition())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "The partition is NULL", K(ret), K_(pkey));
} else if (OB_ISNULL(storage = static_cast<ObPartitionStorage*>(part_guard_.get_pg_partition()->get_storage()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, storage must not be NULL", K(ret), K(pkey_));
} else if (OB_FAIL(storage->get_partition_store().get_read_tables(table_id,
snapshot_version,
tables_handle,
allow_not_ready,
need_safety_check,
reset_handle,
print_dropped_alert))) {
if (OB_REPLICA_NOT_READABLE == ret) {
usleep(RETRY_INTERVAL);
dag_yield();
ret = OB_SUCCESS;
} else {
LOG_WARN("fail to get read tables", K(ret));
}
} else {
break;
}
}
}
return ret;
}
int ObUniqueIndexChecker::check_local_index(ObIDag* dag, ObPartitionStorage* storage, const int64_t snapshot_version)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(storage) || snapshot_version <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(storage), K(snapshot_version));
} else {
// scan data table
ObTablesHandle data_table_handle;
ObArray<int64_t> data_table_column_checksum;
ObTablesHandle index_table_handle;
ObArray<int64_t> index_table_column_checksum;
int64_t index_table_row_count = 0;
int64_t main_table_row_count = 0;
if (OB_FAIL(try_get_read_tables(data_table_schema_->get_table_id(), snapshot_version, dag, data_table_handle))) {
LOG_WARN("fail to try get read tables", K(ret));
}
// read data table data and calc column checksum
if (OB_SUCC(ret) && !dag->has_set_stop() && data_table_handle.get_count() > 0) {
if (OB_FAIL(scan_main_table_with_column_checksum(*data_table_schema_,
*index_schema_,
snapshot_version,
data_table_handle,
data_table_column_checksum,
main_table_row_count))) {
STORAGE_LOG(WARN, "fail to scan main table with column checksum", K(ret));
} else {
data_table_handle.reset();
}
}
// scan index table
if (OB_SUCC(ret)) {
if (OB_FAIL(try_get_read_tables(index_schema_->get_table_id(), snapshot_version, dag, index_table_handle))) {
LOG_WARN("fail to try get read tables", K(ret));
}
// read index table data and calc column checksum
if (OB_SUCC(ret) && !dag->has_set_stop() && index_table_handle.get_count() > 0) {
if (OB_FAIL(scan_index_table_with_column_checksum(*data_table_schema_,
*index_schema_,
snapshot_version,
index_table_handle,
index_table_column_checksum,
index_table_row_count))) {
STORAGE_LOG(WARN, "fail to scan index table with column checksum", K(ret));
} else {
index_table_handle.reset();
}
}
}
// validate column checksum
if (OB_SUCC(ret) && !dag->has_set_stop() && data_table_column_checksum.count() > 0 &&
index_table_column_checksum.count() > 0) {
ObArray<ObColDesc> column_ids;
if (OB_FAIL(index_schema_->get_column_ids(column_ids))) {
STORAGE_LOG(WARN, "fail to get columns ids", K(ret));
} else if (main_table_row_count != index_table_row_count) {
ret = OB_ERR_PRIMARY_KEY_DUPLICATE;
STORAGE_LOG(WARN,
"check unique index failed",
K(ret),
K(main_table_row_count),
K(index_table_row_count),
"index_id",
index_schema_->get_table_id());
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) {
// generated column in index schema is not marked as generated, so we should retreive the column schema from
// data table
const ObColumnSchemaV2* column_schema = data_table_schema_->get_column_schema(column_ids.at(i).col_id_);
if (NULL == column_schema) {
column_schema = index_schema_->get_column_schema(column_ids.at(i).col_id_);
}
if (OB_ISNULL(column_schema)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, column schema must not be NULL", K(ret));
} else if (column_schema->is_shadow_column() || column_schema->is_generated_column() ||
!column_schema->is_column_stored_in_sstable()) {
STORAGE_LOG(INFO, "column do not need to compare checksum", K(column_ids.at(i).col_id_));
continue;
} else if (data_table_column_checksum.at(i) != index_table_column_checksum.at(i)) {
ret = OB_ERR_PRIMARY_KEY_DUPLICATE;
STORAGE_LOG(WARN,
"check unique index failed",
K(ret),
K(data_table_column_checksum),
K(index_table_column_checksum),
K(column_ids),
K(i),
"index_id",
index_schema_->get_table_id());
}
}
if (OB_SUCC(ret)) {
STORAGE_LOG(INFO,
"build index checksum",
K(data_table_column_checksum),
K(index_table_column_checksum),
K(column_ids),
"index_id",
index_schema_->get_table_id());
}
}
}
}
return ret;
}
int ObUniqueIndexChecker::check_unique_index(ObIDag* dag)
{
int ret = OB_SUCCESS;
ObPartitionStorage* storage = NULL;
ObTablesHandle table_handle;
ObIPartitionGroupGuard pg_guard;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObUniqueIndexChecker has not been inited", K(ret));
} else if (OB_ISNULL(dag)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), KP(dag));
} else if (OB_FAIL(part_service_->get_partition(pkey_, pg_guard)) || OB_ISNULL(pg_guard.get_partition_group())) {
STORAGE_LOG(WARN, "fail to get partition", K(ret), K_(pkey));
} else if (OB_FAIL(pg_guard.get_partition_group()->get_pg_partition(pkey_, part_guard_)) ||
OB_ISNULL(part_guard_.get_pg_partition())) {
STORAGE_LOG(WARN, "fail to get pg partition", K(ret), K_(pkey));
} else if (OB_ISNULL(storage = static_cast<ObPartitionStorage*>(part_guard_.get_pg_partition()->get_storage()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, partition storage must not be NULL", K(ret));
} else if (index_schema_->is_domain_index()) {
STORAGE_LOG(INFO, "do not need to check unique for domain index", "index_id", index_schema_->get_table_id());
} else {
int64_t check_end_snapshot_version = 0;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(wait_trans_end(dag, check_end_snapshot_version))) {
LOG_WARN("fail to wait trans end", K(ret));
} else {
if (index_schema_->is_global_index_table()) {
if (OB_FAIL(check_global_index(dag, storage))) {
LOG_WARN("fail to check global index", K(ret));
}
} else {
if (OB_FAIL(check_local_index(dag, storage, check_end_snapshot_version))) {
STORAGE_LOG(WARN, "fail to check local index", K(ret), K(check_end_snapshot_version));
}
}
}
}
if (is_inited_) {
int tmp_ret = OB_SUCCESS;
ObIndexStatusTableOperator::ObBuildIndexStatus status;
const ObAddr& self_addr = GCTX.self_addr_;
const uint64_t index_table_id = index_schema_->get_table_id();
status.index_status_ = index_schema_->get_index_status();
status.ret_code_ = ret;
status.role_ = common::FOLLOWER;
STORAGE_LOG(INFO, "begin report build index status", K(index_table_id), K(pkey_), K(status));
while (!dag->has_set_stop()) {
if (OB_SUCCESS != (tmp_ret = ObIndexStatusTableOperator::report_build_index_status(
index_table_id, pkey_.get_partition_id(), self_addr, status, *GCTX.sql_proxy_))) {
STORAGE_LOG(WARN, "fail to report build index status", K(ret), K(pkey_));
usleep(RETRY_INTERVAL);
dag_yield();
} else {
break;
}
}
}
return ret;
}
int ObUniqueIndexChecker::wait_trans_end(ObIDag* dag, int64_t& snapshot_version)
{
int ret = OB_SUCCESS;
snapshot_version = 0;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("ObUniqueIndexChecker has not been inited", K(ret));
} else {
const int64_t now = ObTimeUtility::current_time();
while (OB_SUCC(ret) && !dag->has_set_stop() && 0 == snapshot_version) {
if (OB_FAIL(part_service_->check_ctx_create_timestamp_elapsed(pkey_, now))) {
if (OB_EAGAIN == ret) {
ret = OB_SUCCESS;
usleep(RETRY_INTERVAL);
dag_yield();
} else {
LOG_WARN("fail to check ctx create timestamp elapsed", K(ret));
break;
}
} else if (OB_FAIL(OB_TS_MGR.get_publish_version(pkey_.get_tenant_id(), snapshot_version))) {
LOG_WARN("fail to get publish version", K(ret), K(pkey_));
}
}
}
return ret;
}
ObUniqueCheckingTask::ObUniqueCheckingTask()
: ObITask(TASK_TYPE_UNIQUE_INDEX_CHECKING), is_inited_(false), param_(), context_(NULL)
{}
ObUniqueCheckingTask::~ObUniqueCheckingTask()
{}
int ObUniqueCheckingTask::init(const ObBuildIndexParam& param, ObBuildIndexContext* context)
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
ObPartitionService* part_service = NULL;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObUniqueCheckingTask has already been inited", K(ret));
} else if (!param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(param), KP(context));
} else if (OB_ISNULL(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to cast pointer", K(ret));
} else if (OB_FAIL(dag->get_partition_service(part_service))) {
STORAGE_LOG(WARN, "fail to get partition service", K(ret));
} else {
const ObPartitionKey pkey = dag->get_partition_key();
if (OB_FAIL(unique_checker_.init(part_service, pkey, param.table_schema_, param.index_schema_))) {
STORAGE_LOG(WARN, "fail to init unique index checker", K(ret));
} else {
param_ = &param;
context_ = context;
is_inited_ = true;
}
}
return ret;
}
int ObUniqueCheckingTask::process()
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
bool need_build = false;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObUniqueCheckingTask has not been inited", K(ret));
} else if (!context_->need_build_) {
STORAGE_LOG(INFO, "index does not need build", K(*param_));
} else if (OB_ISNULL(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to cast pointer", K(ret));
} else if (OB_FAIL(dag->check_index_need_build(need_build))) {
STORAGE_LOG(WARN, "fail to check index need build", K(ret), K(*param_));
} else if (!need_build) {
STORAGE_LOG(INFO, "index do not need build", "index_id", param_->index_schema_->get_table_id());
} else if (OB_SUCCESS != (context_->build_index_ret_)) {
STORAGE_LOG(WARN, "Build Index has already failed", "ret", context_->build_index_ret_);
} else if (context_->is_unique_checking_complete_) {
// do nothing
} else if (!param_->index_schema_->is_unique_index()) {
context_->is_unique_checking_complete_ = true;
} else if (OB_FAIL(unique_checker_.check_unique_index(dag))) {
STORAGE_LOG(WARN, "fail to check unique index", K(ret));
}
context_->is_unique_checking_complete_ = true;
if (OB_FAIL(ret) && NULL != context_) {
context_->build_index_ret_ = ret;
ret = OB_SUCCESS;
}
return ret;
}
ObReportIndexStatusTask::ObReportIndexStatusTask()
: ObITask(TASK_TYPE_REPORT_INDEX_STATUS), is_inited_(false), pkey_(), param_(), context_(NULL)
{}
ObReportIndexStatusTask::~ObReportIndexStatusTask()
{}
int ObReportIndexStatusTask::init(
const ObPartitionKey& pkey, const ObBuildIndexParam& param, ObBuildIndexContext* context)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObReportIndexStatusTask has already been inited", K(ret));
} else if (!pkey.is_valid() || !param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(pkey), K(param), KP(context));
} else {
pkey_ = pkey;
param_ = &param;
context_ = context;
is_inited_ = true;
}
return ret;
}
int ObReportIndexStatusTask::process()
{
int ret = OB_SUCCESS;
ObIDag* tmp_dag = get_dag();
ObBuildIndexDag* dag = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObReportIndexStatusTask has not been inited", K(ret));
} else if (OB_ISNULL(dag = static_cast<ObBuildIndexDag*>(tmp_dag))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to cast pointer", K(ret));
} else {
bool need_retry = true;
bool need_build = false;
const int64_t RETRY_INTERVAL = 5000 * 1000; // 5s
while (need_retry) {
if (OB_FAIL(dag->check_index_need_build(need_build))) {
STORAGE_LOG(WARN, "fail to check index need rebuild", K(ret));
} else if (!need_build) {
STORAGE_LOG(INFO, "index does not need build", K(*param_));
need_retry = false;
} else if (OB_FAIL(report_index_status(pkey_, *param_, context_, need_retry))) {
STORAGE_LOG(
WARN, "fail to report index status", K(ret), K(pkey_), "index_id", param_->index_schema_->get_table_id());
}
if (need_retry) {
if (dag_->has_set_stop()) {
STORAGE_LOG(INFO,
"dag is stopped, cannot retry now",
K(ret),
K(pkey_),
"index_id",
param_->index_schema_->get_table_id());
break;
}
usleep(RETRY_INTERVAL);
dag_yield();
}
}
}
if (OB_FAIL(ret) && NULL != context_) {
context_->build_index_ret_ = OB_SUCCESS;
ret = OB_SUCCESS;
}
return ret;
}
int ObReportIndexStatusTask::report_index_status(
const ObPartitionKey& pkey, const ObBuildIndexParam& param, ObBuildIndexContext* context, bool& need_retry)
{
int ret = OB_SUCCESS;
need_retry = true;
if (!pkey.is_valid() || !param.is_valid() || OB_ISNULL(context)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(pkey), K(param), KP(context));
} else if (context->is_report_succ_ || !context->need_build_) {
// do nothing
need_retry = false;
} else {
ObIndexStatusTableOperator::ObBuildIndexStatus status;
const ObAddr& self_addr = GCTX.self_addr_;
const uint64_t index_table_id = param.index_schema_->get_table_id();
status.index_status_ = param.index_schema_->get_index_status();
status.ret_code_ = context->build_index_ret_;
status.role_ = common::FOLLOWER;
if (OB_FAIL(ObIndexStatusTableOperator::report_build_index_status(
index_table_id, pkey.get_partition_id(), self_addr, status, *GCTX.sql_proxy_))) {
STORAGE_LOG(WARN, "fail to report build index status", K(ret), K(pkey));
} else {
context->is_report_succ_ = true;
need_retry = false;
}
STORAGE_LOG(INFO,
"process index status report task",
K(ret),
K(pkey),
"build_index_ret_code",
status.ret_code_,
"index_id",
param.index_schema_->get_table_id());
}
return ret;
}
ObUniqueCheckingDag::ObUniqueCheckingDag()
: ObIDag(ObIDag::DAG_TYPE_UNIQUE_CHECKING, ObIDag::DAG_PRIO_CREATE_INDEX),
is_inited_(false),
part_service_(NULL),
pkey_(),
schema_service_(NULL),
schema_guard_(share::schema::ObSchemaMgrItem::MOD_UNIQ_CHECK),
index_schema_(NULL),
data_table_schema_(NULL),
callback_(NULL),
execution_id_(0),
snapshot_version_(0),
compat_mode_(ObWorker::CompatMode::INVALID)
{}
ObUniqueCheckingDag::~ObUniqueCheckingDag()
{
if (NULL != callback_) {
ob_free(callback_);
callback_ = NULL;
}
}
int ObUniqueCheckingDag::init(const ObPartitionKey& pkey, ObPartitionService* part_service,
ObMultiVersionSchemaService* schema_service, const uint64_t index_id, const int64_t schema_version,
const uint64_t execution_id, const int64_t snapshot_version)
{
int ret = OB_SUCCESS;
ObIPartitionGroupGuard pg_guard;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObUniqueCheckingDag has already been inited", K(ret));
} else if (OB_UNLIKELY(!pkey.is_valid() || NULL == part_service || NULL == schema_service ||
OB_INVALID_ID == index_id || schema_version <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN,
"invalid arguments",
K(ret),
K(pkey),
KP(part_service),
KP(schema_service),
K(index_id),
K(schema_version));
} else if (OB_FAIL(part_service->get_partition(pkey, pg_guard)) || OB_ISNULL(pg_guard.get_partition_group())) {
STORAGE_LOG(WARN, "fail to get partition", K(ret), K(pkey));
} else if (OB_FAIL(pg_guard.get_partition_group()->get_pg_partition(pkey, part_guard_)) ||
OB_ISNULL(part_guard_.get_pg_partition())) {
STORAGE_LOG(WARN, "fail to get pg partition", K(ret), K(pkey));
} else if (OB_FAIL(schema_service->get_tenant_schema_guard(
extract_tenant_id(pkey.get_table_id()), schema_guard_, schema_version))) {
STORAGE_LOG(WARN, "fail to get schema guard", K(ret), K(schema_version));
} else if (OB_FAIL(schema_guard_.check_formal_guard())) {
LOG_WARN("schema_guard is not formal", K(ret), K(pkey));
} else if (OB_FAIL(schema_guard_.get_table_schema(index_id, index_schema_))) {
STORAGE_LOG(WARN, "fail to get table schema", K(ret));
} else if (OB_ISNULL(index_schema_)) {
ret = OB_TABLE_NOT_EXIST;
STORAGE_LOG(WARN, "fail to get table schema", K(ret), K(index_id));
} else if (OB_FAIL(schema_guard_.get_table_schema(index_schema_->get_data_table_id(), data_table_schema_))) {
STORAGE_LOG(WARN, "fail to get table schema", K(ret));
} else if (OB_ISNULL(data_table_schema_)) {
ret = OB_TABLE_NOT_EXIST;
STORAGE_LOG(WARN, "data table not exist", K(ret));
} else if (OB_FAIL(get_compat_mode_with_table_id(pkey.table_id_, compat_mode_))) {
STORAGE_LOG(WARN, "failed to get compat mode", K(ret), K(pkey));
} else {
is_inited_ = true;
pkey_ = pkey;
part_service_ = part_service;
schema_service_ = schema_service;
execution_id_ = execution_id;
snapshot_version_ = snapshot_version;
}
return ret;
}
int ObUniqueCheckingDag::alloc_unique_checking_prepare_task(ObIUniqueCheckingCompleteCallback* callback)
{
int ret = OB_SUCCESS;
ObUniqueCheckingPrepareTask* prepare_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObUniqueCheckingDag has not been inited", K(ret));
} else if (OB_FAIL(alloc_task(prepare_task))) {
STORAGE_LOG(WARN, "fail to alloc task", K(ret));
} else if (OB_FAIL(prepare_task->init(callback))) {
STORAGE_LOG(WARN, "fail to init prepare task", K(ret));
} else if (OB_FAIL(add_task(*prepare_task))) {
STORAGE_LOG(WARN, "fail to add task", K(ret));
}
return ret;
}
int ObUniqueCheckingDag::alloc_local_index_task_callback(ObLocalUniqueIndexCallback*& callback)
{
int ret = OB_SUCCESS;
void* buf = NULL;
callback = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObUniqueCheckingDag has not been inited", K(ret));
} else if (OB_ISNULL(buf = ob_malloc(sizeof(ObLocalUniqueIndexCallback), ObModIds::OB_CS_BUILD_INDEX))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "fail to allocate memory", K(ret));
} else if (OB_ISNULL(callback = new (buf) ObLocalUniqueIndexCallback())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to placement new local index callback", K(ret));
} else {
callback_ = callback;
}
return ret;
}
int ObUniqueCheckingDag::alloc_global_index_task_callback(
const ObPartitionKey& pkey, const uint64_t index_id, ObGlobalUniqueIndexCallback*& callback)
{
int ret = OB_SUCCESS;
void* buf = NULL;
callback = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObUniqueCheckingDag has not been inited", K(ret));
} else if (OB_UNLIKELY(!pkey.is_valid() || OB_INVALID_ID == index_id)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), K(pkey), K(index_id));
} else if (OB_ISNULL(buf = ob_malloc(sizeof(ObGlobalUniqueIndexCallback), ObModIds::OB_CS_BUILD_INDEX))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "fail to allocate memory", K(ret));
} else if (OB_ISNULL(callback = new (buf) ObGlobalUniqueIndexCallback(pkey, index_id))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to placement new local index callback", K(ret));
} else {
callback_ = callback;
}
return ret;
}
int64_t ObUniqueCheckingDag::hash() const
{
int tmp_ret = OB_SUCCESS;
int64_t hash_val = 0;
if (NULL == index_schema_) {
tmp_ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "index schema must not be NULL", K(tmp_ret));
} else {
hash_val = pkey_.hash() + index_schema_->get_table_id();
}
return hash_val;
}
int ObUniqueCheckingDag::fill_comment(char* buf, const int64_t buf_len) const
{
int ret = OB_SUCCESS;
int64_t index_id = 0;
if (NULL != index_schema_) {
index_id = index_schema_->get_table_id();
}
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not inited", K(ret));
} else if (OB_FAIL(databuff_printf(
buf, buf_len, "unique check task: key=%s index_id=%ld", to_cstring(pkey_), index_id))) {
STORAGE_LOG(WARN, "failed to fill comment", K(ret), K(pkey_), K(index_id));
}
return ret;
}
bool ObUniqueCheckingDag::operator==(const ObIDag& other) const
{
int tmp_ret = OB_SUCCESS;
bool is_equal = false;
if (OB_UNLIKELY(this == &other)) {
is_equal = true;
} else if (get_type() == other.get_type()) {
const ObUniqueCheckingDag& dag = static_cast<const ObUniqueCheckingDag&>(other);
if (NULL == index_schema_ || NULL == dag.index_schema_) {
tmp_ret = OB_ERR_SYS;
STORAGE_LOG(ERROR, "index schema must not be NULL", K(tmp_ret), KP(index_schema_), KP(dag.index_schema_));
} else {
is_equal = pkey_ == dag.pkey_ && index_schema_->get_table_id() == dag.index_schema_->get_table_id();
}
}
return is_equal;
}
ObUniqueCheckingPrepareTask::ObUniqueCheckingPrepareTask()
: ObITask(TASK_TYPE_UNIQUE_CHECKING_PREPARE),
is_inited_(false),
index_schema_(NULL),
data_table_schema_(NULL),
callback_(NULL)
{}
int ObUniqueCheckingPrepareTask::init(ObIUniqueCheckingCompleteCallback* callback)
{
int ret = OB_SUCCESS;
ObUniqueCheckingDag* dag = NULL;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObUniqueCheckingPrepareTask has already been inited", K(ret));
} else if (OB_ISNULL(dag = static_cast<ObUniqueCheckingDag*>(get_dag()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, dag must not be NULL", K(ret));
} else if (OB_ISNULL(index_schema_ = dag->get_index_schema())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(index_schema_));
} else if (OB_ISNULL(data_table_schema_ = dag->get_data_table_schema())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid data table schema", K(ret));
} else {
callback_ = callback;
is_inited_ = true;
}
return ret;
}
int ObUniqueCheckingPrepareTask::process()
{
int ret = OB_SUCCESS;
ObUniqueCheckingDag* dag = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObUniqueCheckingPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag = static_cast<ObUniqueCheckingDag*>(get_dag()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, dag must not be NULL", K(ret));
} else if (OB_FAIL(generate_unique_checking_task(dag))) {
STORAGE_LOG(WARN, "fail to generate unique checking task", K(ret));
}
return ret;
}
int ObUniqueCheckingPrepareTask::generate_unique_checking_task(ObUniqueCheckingDag* dag)
{
int ret = OB_SUCCESS;
ObSimpleUniqueCheckingTask* checking_task = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObIndexPrepareTask has not been inited", K(ret));
} else if (OB_ISNULL(dag)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(dag));
} else if (OB_FAIL(dag->alloc_task(checking_task))) {
STORAGE_LOG(WARN, "fail to alloc checking task", K(ret));
} else if (OB_FAIL(checking_task->init(data_table_schema_, index_schema_, callback_))) {
STORAGE_LOG(WARN, "fail to init unique checking task", K(ret));
} else if (OB_FAIL(add_child(*checking_task))) {
STORAGE_LOG(WARN, "fail to add child for prepare task", K(ret));
} else if (OB_FAIL(dag->add_task(*checking_task))) {
STORAGE_LOG(WARN, "fail to add unique checking task", K(ret));
}
return ret;
}
ObSimpleUniqueCheckingTask::ObSimpleUniqueCheckingTask()
: ObITask(TASK_TYPE_SIMPLE_UNIQUE_CHECKING),
is_inited_(false),
unique_checker_(),
index_schema_(NULL),
data_table_schema_(NULL),
pkey_(),
callback_(NULL)
{}
int ObSimpleUniqueCheckingTask::init(const ObTableSchema* data_table_schema, const ObTableSchema* index_schema,
ObIUniqueCheckingCompleteCallback* callback)
{
int ret = OB_SUCCESS;
ObUniqueCheckingDag* dag = NULL;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObSimpleUniqueCheckingTask has already been inited", K(ret));
} else if (OB_ISNULL(data_table_schema) || OB_ISNULL(index_schema) || OB_ISNULL(callback)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(data_table_schema), KP(index_schema), KP(callback));
} else if (OB_ISNULL(dag = static_cast<ObUniqueCheckingDag*>(get_dag()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, dag must not be NULL", K(ret));
} else {
ObPartitionService* part_service = dag->get_partition_service();
pkey_ = dag->get_partition_key();
if (OB_UNLIKELY(NULL == part_service || !pkey_.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(part_service), K(pkey_));
} else if (OB_FAIL(unique_checker_.init(part_service,
pkey_,
data_table_schema,
index_schema,
dag->get_execution_id(),
dag->get_snapshot_version()))) {
STORAGE_LOG(WARN, "fail to init unique index checker", K(ret));
} else {
index_schema_ = index_schema;
data_table_schema_ = data_table_schema;
callback_ = callback;
is_inited_ = true;
}
}
return ret;
}
int ObSimpleUniqueCheckingTask::process()
{
int ret = OB_SUCCESS;
int ret_code = OB_SUCCESS;
ObUniqueCheckingDag* dag = NULL;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObSimpleUniqueCheckingTask has not been inited", K(ret));
} else if (OB_ISNULL(dag = static_cast<ObUniqueCheckingDag*>(get_dag()))) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "error unexpected, dag must not be NULL", K(ret));
} else if (OB_FAIL(unique_checker_.check_unique_index(dag))) {
STORAGE_LOG(WARN, "fail to check unique index", K(ret));
}
ret_code = ret;
// overwrite ret
if (NULL != callback_) {
if (NULL != index_schema_) {
STORAGE_LOG(INFO, "unique checking callback", K(pkey_), "index_id", index_schema_->get_table_id());
}
if (OB_FAIL(callback_->operator()(ret_code))) {
STORAGE_LOG(WARN, "fail to check unique index response", K(ret));
}
}
return ret;
}
ObGlobalUniqueIndexCallback::ObGlobalUniqueIndexCallback(const common::ObPartitionKey& pkey, const uint64_t index_id)
: pkey_(pkey), index_id_(index_id)
{}
int ObGlobalUniqueIndexCallback::operator()(const int ret_code)
{
int ret = OB_SUCCESS;
obrpc::ObCalcColumnChecksumResponseArg arg;
ObAddr rs_addr;
arg.pkey_ = pkey_;
arg.index_id_ = index_id_;
arg.ret_code_ = ret_code;
if (OB_ISNULL(GCTX.rs_rpc_proxy_) || OB_ISNULL(GCTX.rs_mgr_)) {
ret = OB_ERR_SYS;
STORAGE_LOG(WARN, "innner system error, rootserver rpc proxy or rs mgr must not be NULL", K(ret), K(GCTX));
} else if (OB_FAIL(GCTX.rs_mgr_->get_master_root_server(rs_addr))) {
STORAGE_LOG(WARN, "fail to get rootservice address", K(ret));
} else if (OB_FAIL(GCTX.rs_rpc_proxy_->to(rs_addr).calc_column_checksum_response(arg))) {
STORAGE_LOG(WARN, "fail to check unique index response", K(ret), K(arg));
}
return ret;
}
ObLocalUniqueIndexCallback::ObLocalUniqueIndexCallback()
{}
int ObLocalUniqueIndexCallback::operator()(const int ret_code)
{
int ret = OB_SUCCESS;
UNUSED(ret_code);
return ret;
}