Files
oceanbase/src/storage/ob_pg_log.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

669 lines
20 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_pg_log.h"
#include "ob_storage_log_type.h"
#include "common/ob_partition_key.h"
namespace oceanbase {
using namespace common;
using namespace storage;
using namespace clog;
namespace storage {
OB_SERIALIZE_MEMBER(ObOfflinePartitionLog, log_type_, is_physical_drop_, cluster_id_);
OB_SERIALIZE_MEMBER(ObAddPartitionToPGLog, log_type_, arg_);
OB_SERIALIZE_MEMBER(ObRemovePartitionFromPGLog, log_type_, pg_key_, partition_key_);
OB_SERIALIZE_MEMBER(ObPGSchemaChangeLog, log_type_, pg_key_, pkey_, schema_version_, index_id_);
int ObOfflinePartitionLog::init(const int64_t log_type, const bool is_physical_drop)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
LOG_WARN("ObOfflinePartitionLog init twice", K(log_type), K(is_physical_drop));
} else if (!ObStorageLogTypeChecker::is_offline_partition_log_new(log_type)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(log_type), KR(ret));
} else {
log_type_ = log_type;
is_physical_drop_ = is_physical_drop;
cluster_id_ = obrpc::ObRpcNetHandler::CLUSTER_ID;
is_inited_ = true;
}
return ret;
}
void ObOfflinePartitionLog::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
is_physical_drop_ = false;
cluster_id_ = common::OB_INVALID_CLUSTER_ID;
is_inited_ = false;
}
bool ObOfflinePartitionLog::is_valid() const
{
return ObStorageLogTypeChecker::is_offline_partition_log_new(log_type_);
}
int ObAddPartitionToPGLog::init(const int64_t log_type, const obrpc::ObCreatePartitionArg& arg)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
LOG_WARN("ObAddPartitionToPGLog init twice", K(log_type), K(arg));
} else if (!ObStorageLogTypeChecker::is_add_partition_to_pg_log(log_type) || !arg.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(log_type), K(arg));
} else if (OB_FAIL(arg_.deep_copy(arg))) {
STORAGE_LOG(WARN, " deep copy error", K(ret), K(log_type), K(arg));
} else {
log_type_ = log_type;
is_inited_ = true;
}
return ret;
}
void ObAddPartitionToPGLog::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
arg_.reset();
is_inited_ = false;
}
bool ObAddPartitionToPGLog::is_valid() const
{
return ObStorageLogTypeChecker::is_add_partition_to_pg_log(log_type_) && arg_.is_valid();
}
int ObPGSchemaChangeLog::init(const int64_t log_type, const common::ObPGKey& pg_key, const common::ObPartitionKey& pkey,
const int64_t schema_version, const uint64_t index_id)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
LOG_WARN("ObPGSchemaChangeLog init twice", K(ret), K(log_type), K(pg_key), K(pkey), K(schema_version));
} else if (!ObStorageLogTypeChecker::is_schema_version_change_log(log_type) || !pg_key.is_valid() ||
!pkey.is_valid() || schema_version < 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(log_type), K(pg_key), K(pkey), K(schema_version), K(index_id));
} else {
log_type_ = log_type;
pg_key_ = pg_key;
pkey_ = pkey;
schema_version_ = schema_version;
index_id_ = index_id;
is_inited_ = true;
}
return ret;
}
void ObPGSchemaChangeLog::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
pg_key_.reset();
pkey_.reset();
schema_version_ = -1;
index_id_ = 0;
is_inited_ = false;
}
bool ObPGSchemaChangeLog::is_valid() const
{
return ObStorageLogTypeChecker::is_schema_version_change_log(log_type_) && pg_key_.is_valid() && pkey_.is_valid() &&
schema_version_ >= 0;
}
int ObPGSchemaChangeLog::replace_tenant_id(const uint64_t new_tenant_id)
{
int ret = OB_SUCCESS;
if (!is_valid_tenant_id(new_tenant_id)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(new_tenant_id));
} else if (new_tenant_id == pg_key_.get_tenant_id()) {
// no need replace
} else {
ObPartitionKey new_pg_key;
ObPartitionKey new_pkey;
if (OB_FAIL(ObPartitionKey::replace_pkey_tenant_id(pg_key_, new_tenant_id, new_pg_key))) {
STORAGE_LOG(WARN, "replace_pkey_tenant_id failed", K(ret), K(new_tenant_id));
} else if (OB_FAIL(ObPartitionKey::replace_pkey_tenant_id(pkey_, new_tenant_id, new_pkey))) {
STORAGE_LOG(WARN, "replace_pkey_tenant_id failed", K(ret), K(new_tenant_id));
} else if (0 == index_id_) {
// "0 == index_id" indicates unique index and no need to replace tenant_id when log is replaying
} else {
const uint64_t pure_id = extract_pure_id(index_id_);
index_id_ = combine_id(new_tenant_id, pure_id);
pg_key_ = new_pg_key;
pkey_ = new_pkey;
}
}
return ret;
}
int ObRemovePartitionFromPGLog::init(const int64_t log_type, const ObPGKey& pg_key, const ObPartitionKey& pkey)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObRemovePartitionFromPGLog init twice", K(ret), K(log_type), K(pg_key), K(pkey));
} else if (!ObStorageLogTypeChecker::is_remove_partition_from_pg_log(log_type) || !pg_key.is_valid() ||
!pkey.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(log_type), K(pg_key), K(pkey));
} else {
log_type_ = log_type;
pg_key_ = pg_key;
partition_key_ = pkey;
is_inited_ = true;
}
return ret;
}
void ObRemovePartitionFromPGLog::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
pg_key_.reset();
partition_key_.reset();
is_inited_ = false;
}
bool ObRemovePartitionFromPGLog::is_valid() const
{
return ObStorageLogTypeChecker::is_remove_partition_from_pg_log(log_type_) && pg_key_.is_valid() &&
partition_key_.is_valid();
}
int ObRemovePartitionFromPGLog::replace_tenant_id(const uint64_t new_tenant_id)
{
int ret = OB_SUCCESS;
if (!is_valid_tenant_id(new_tenant_id)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(new_tenant_id));
} else if (new_tenant_id == pg_key_.get_tenant_id()) {
// no need replace
} else {
ObPartitionKey new_pg_key;
ObPartitionKey new_pkey;
if (OB_FAIL(ObPartitionKey::replace_pkey_tenant_id(pg_key_, new_tenant_id, new_pg_key))) {
STORAGE_LOG(WARN, "replace_pkey_tenant_id failed", K(ret), K(new_tenant_id));
} else if (OB_FAIL(ObPartitionKey::replace_pkey_tenant_id(partition_key_, new_tenant_id, new_pkey))) {
STORAGE_LOG(WARN, "replace_pkey_tenant_id failed", K(ret), K(new_tenant_id));
} else {
pg_key_ = new_pg_key;
partition_key_ = new_pkey;
}
}
return ret;
}
int ObAddPartitionToPGLogCb::init(
const int64_t log_type, const common::ObPGKey& pg_key, const common::ObPartitionKey& pkey)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObAddPartitionToPGLog init twice", K(log_type), K(pg_key), K(pkey));
} else if (!ObStorageLogTypeChecker::is_add_partition_to_pg_log(log_type) || !pg_key.is_valid() || !pkey.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(log_type), K(pg_key), K(pkey));
} else if (OB_FAIL(ObPartitionService::get_instance().get_partition(pg_key, guard_))) {
STORAGE_LOG(WARN, "get partition group error", K(ret), K(pg_key), K(pkey));
} else {
log_type_ = log_type;
pg_key_ = pg_key;
partition_key_ = pkey;
is_inited_ = true;
}
return ret;
}
void ObAddPartitionToPGLogCb::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
pg_key_.reset();
partition_key_.reset();
// revert partition group
guard_.reset();
write_clog_state_ = CB_INIT;
is_locking_ = false;
is_inited_ = false;
}
bool ObAddPartitionToPGLogCb::is_valid() const
{
return is_inited_ && ObStorageLogTypeChecker::is_add_partition_to_pg_log(log_type_) && pg_key_.is_valid() &&
partition_key_.is_valid();
}
int ObAddPartitionToPGLogCb::on_success(const common::ObPGKey& pg_key, const clog::ObLogType log_type,
const uint64_t log_id, const int64_t version, const bool batch_committed, const bool batch_last_succeed)
{
UNUSED(pg_key);
UNUSED(log_type);
UNUSED(log_id);
UNUSED(version);
UNUSED(batch_committed);
UNUSED(batch_last_succeed);
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not init", K(pg_key), K(log_id), K(version), K(batch_committed), K(batch_last_succeed));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(pg_key), K(log_id), K(version));
} else {
STORAGE_LOG(INFO, "ObAddPartitionToPGLogCb sync callback success", K(pg_key), K(log_id));
// lock
bool need_release = false;
while (true) {
if (false == ATOMIC_TAS(&is_locking_, true)) {
if (CB_END != write_clog_state_) {
write_clog_state_ = CB_SUCCESS;
} else {
need_release = true;
}
ATOMIC_STORE(&is_locking_, false);
break;
}
}
if (need_release) {
op_free(this);
}
}
return ret;
}
int ObAddPartitionToPGLogCb::on_finished(const common::ObPGKey& pg_key, const uint64_t log_id)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not init", K(pg_key), K(log_id));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(pg_key), K(log_id));
} else {
STORAGE_LOG(INFO, "ObAddPartitionToPGLogCb sync callback finished", K(pg_key), K(log_id));
// lock
bool need_release = false;
while (true) {
if (false == ATOMIC_TAS(&is_locking_, true)) {
if (CB_END != write_clog_state_) {
write_clog_state_ = CB_FAIL;
} else {
need_release = true;
}
ATOMIC_STORE(&is_locking_, false);
break;
}
}
if (need_release) {
op_free(this);
}
}
return ret;
}
int ObAddPartitionToPGLogCb::check_can_release(bool& can_release)
{
int ret = OB_SUCCESS;
// lock
while (true) {
if (false == ATOMIC_TAS(&is_locking_, true)) {
// clog callback not finish
if (CB_FAIL != write_clog_state_ && CB_SUCCESS != write_clog_state_) {
write_clog_state_ = CB_END;
can_release = false;
} else {
can_release = true;
}
ATOMIC_STORE(&is_locking_, false);
break;
}
}
return ret;
}
int ObRemovePartitionFromPGLogCb::init(const int64_t log_type, const common::ObPGKey& pg_key,
const common::ObPartitionKey& pkey, ObCLogCallbackAsyncWorker* cb_async_worker)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObAddPartitionToPGLog init twice", K(log_type), K(pg_key), K(pkey));
} else if (!ObStorageLogTypeChecker::is_remove_partition_from_pg_log(log_type) || !pg_key.is_valid() ||
!pkey.is_valid() || OB_ISNULL(cb_async_worker)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(log_type), K(pg_key), K(pkey), KP(cb_async_worker));
} else if (OB_FAIL(ObPartitionService::get_instance().get_partition(pg_key, guard_))) {
STORAGE_LOG(WARN, "get partition group error", K(ret), K(pg_key), K(pkey));
} else {
log_type_ = log_type;
pg_key_ = pg_key;
partition_key_ = pkey;
cb_async_worker_ = cb_async_worker;
is_inited_ = true;
}
return ret;
}
void ObRemovePartitionFromPGLogCb::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
pg_key_.reset();
partition_key_.reset();
// revert partition group
guard_.reset();
cb_async_worker_ = nullptr;
is_inited_ = false;
}
bool ObRemovePartitionFromPGLogCb::is_valid() const
{
return is_inited_ && ObStorageLogTypeChecker::is_remove_partition_from_pg_log(log_type_) && pg_key_.is_valid() &&
partition_key_.is_valid();
}
int ObRemovePartitionFromPGLogCb::on_success(const common::ObPGKey& pg_key, const clog::ObLogType log_type,
const uint64_t log_id, const int64_t version, const bool batch_committed, const bool batch_last_succeed)
{
UNUSED(log_type);
UNUSED(version);
UNUSED(batch_committed);
UNUSED(batch_last_succeed);
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not init", K(pg_key), K(log_id));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(pg_key), K(log_id));
} else {
ObCLogCallbackAsyncTask task;
task.pg_key_ = pg_key;
task.partition_key_ = partition_key_;
task.log_id_ = log_id;
task.log_type_ = log_type_;
if (OB_FAIL(cb_async_worker_->push_task(task))) {
STORAGE_LOG(WARN, "fail to push task to worker", K(ret), K(task));
} else {
STORAGE_LOG(INFO, "ObRemovePartitionFromPGLogCb sync callback success", K(partition_key_), K(pg_key), K(log_id));
op_free(this);
}
}
return ret;
}
int ObRemovePartitionFromPGLogCb::on_finished(const common::ObPGKey& pg_key, const uint64_t log_id)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not init", K(pg_key), K(log_id));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(pg_key), K(log_id));
} else {
STORAGE_LOG(INFO, "ObRemovePartitionFromPGLogCb sync callback finished", K(pg_key), K(log_id));
op_free(this);
}
return ret;
}
int ObSchemaChangeClogCb::init(
const int64_t log_type, const common::ObPGKey& pg_key, const common::ObPartitionKey& pkey)
{
int ret = OB_SUCCESS;
if (is_inited_) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "ObSchemaChangeClogCb init twice", K(ret), K(log_type), K(pg_key), K(pkey));
} else if (!ObStorageLogTypeChecker::is_schema_version_change_log(log_type) || !pg_key.is_valid() ||
!pkey.is_valid()) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(log_type), K(pg_key), K(pkey));
} else if (OB_FAIL(ObPartitionService::get_instance().get_partition(pg_key, guard_))) {
STORAGE_LOG(WARN, "get partition group error", K(ret), K(pg_key), K(pkey));
} else {
log_type_ = log_type;
pg_key_ = pg_key;
partition_key_ = pkey;
is_inited_ = true;
}
return ret;
}
void ObSchemaChangeClogCb::reset()
{
log_type_ = storage::OB_LOG_UNKNOWN;
pg_key_.reset();
partition_key_.reset();
// revert partition group
guard_.reset();
write_clog_state_ = CB_INIT;
is_locking_ = false;
is_inited_ = false;
}
bool ObSchemaChangeClogCb::is_valid() const
{
return is_inited_ && ObStorageLogTypeChecker::is_schema_version_change_log(log_type_) && pg_key_.is_valid() &&
partition_key_.is_valid();
}
int ObSchemaChangeClogCb::on_success(const common::ObPGKey& pg_key, const clog::ObLogType log_type,
const uint64_t log_id, const int64_t version, const bool batch_committed, const bool batch_last_succeed)
{
UNUSED(log_type);
UNUSED(pg_key);
UNUSED(log_id);
UNUSED(version);
UNUSED(batch_committed);
UNUSED(batch_last_succeed);
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not init", K(ret), K(pg_key), K(log_id), K(version), K(batch_committed), K(batch_last_succeed));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(pg_key), K(log_id), K(version));
} else {
STORAGE_LOG(INFO, "ObSchemaChangeClogCb sync callback success", K(pg_key), K(log_id));
// lock
bool need_release = false;
while (true) {
if (false == ATOMIC_TAS(&is_locking_, true)) {
if (CB_END != write_clog_state_) {
write_clog_state_ = CB_SUCCESS;
} else {
// index_builder thread already exit, so it can release memory
need_release = true;
}
ATOMIC_STORE(&is_locking_, false);
break;
}
}
if (need_release) {
op_free(this);
}
}
return ret;
}
int ObSchemaChangeClogCb::on_finished(const common::ObPGKey& pg_key, const uint64_t log_id)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "not init", K(pg_key), K(log_id));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(pg_key), K(log_id));
} else {
STORAGE_LOG(INFO, "ObSchemaChangeClogCb sync callback finished", K(pg_key), K(log_id));
// lock
bool need_release = false;
while (true) {
if (false == ATOMIC_TAS(&is_locking_, true)) {
if (CB_END != write_clog_state_) {
write_clog_state_ = CB_FAIL;
} else {
// index_builder thread already exit, so it can release memory
need_release = true;
}
ATOMIC_STORE(&is_locking_, false);
break;
}
}
if (need_release) {
op_free(this);
}
}
return ret;
}
int ObSchemaChangeClogCb::check_can_release(bool& can_release)
{
int ret = OB_SUCCESS;
// lock
while (true) {
if (false == ATOMIC_TAS(&is_locking_, true)) {
// clog callback not finish
if (CB_FAIL != write_clog_state_ && CB_SUCCESS != write_clog_state_) {
write_clog_state_ = CB_END;
can_release = false;
} else {
can_release = true;
}
ATOMIC_STORE(&is_locking_, false);
break;
}
}
return ret;
}
int ObOfflinePartitionCb::init(ObCLogCallbackAsyncWorker* cb_async_worker, const bool is_physical_drop)
{
int ret = OB_SUCCESS;
if (IS_INIT) {
ret = OB_INIT_TWICE;
STORAGE_LOG(WARN, "init twice", K(ret));
} else if (OB_ISNULL(cb_async_worker)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), KP(cb_async_worker));
} else {
cb_async_worker_ = cb_async_worker;
is_physical_drop_ = is_physical_drop;
is_inited_ = true;
}
if (IS_NOT_INIT) {
destroy();
}
return ret;
}
void ObOfflinePartitionCb::reset()
{
cb_async_worker_ = nullptr;
is_inited_ = false;
is_physical_drop_ = false;
}
void ObOfflinePartitionCb::destroy()
{
reset();
}
int ObOfflinePartitionCb::on_success(const common::ObPartitionKey& partition_key, const clog::ObLogType log_type,
const uint64_t log_id, const int64_t version, const bool batch_committed, const bool batch_last_succeed)
{
UNUSED(log_type);
UNUSED(version);
UNUSED(batch_committed);
UNUSED(batch_last_succeed);
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(ERROR, "not init", K(partition_key), K(log_id), KR(ret));
} else if (OB_UNLIKELY((!partition_key.is_valid()) || log_id <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(ERROR, "invalid argument", K(ret), K(partition_key), K(log_id));
} else {
ObCLogCallbackAsyncTask task;
task.pg_key_ = partition_key;
task.partition_key_ = partition_key;
task.log_type_ = OB_LOG_OFFLINE_PARTITION_V2;
task.log_id_ = log_id;
task.is_physical_drop_ = is_physical_drop_;
if (OB_FAIL(cb_async_worker_->push_task(task))) {
STORAGE_LOG(WARN, "fail to push task to worker", K(ret), K(task), K(partition_key), K(log_id));
} else {
STORAGE_LOG(
INFO, "ObOfflinePartitionCb sync callback success", K(partition_key), K(log_id), K(is_physical_drop_));
op_free(this);
}
}
return ret;
}
int ObOfflinePartitionCb::on_finished(const common::ObPGKey& pg_key, const uint64_t log_id)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
STORAGE_LOG(ERROR, "not init", K(pg_key), K(log_id));
} else if (!pg_key.is_valid() || log_id <= 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(ERROR, "invalid argument", K(pg_key), K(log_id), KR(ret));
} else {
STORAGE_LOG(INFO, "ObOfflinePartitionCb::sync callback finished", K(pg_key), K(log_id));
op_free(this);
}
return ret;
}
} // namespace storage
} // namespace oceanbase