514 lines
21 KiB
C++
514 lines
21 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 SHARE
|
|
|
|
#include "lib/mysqlclient/ob_mysql_result.h"
|
|
#include "lib/mysqlclient/ob_mysql_transaction.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "observer/ob_sql_client_decorator.h"
|
|
#include "observer/ob_srv_network_frame.h"
|
|
#include "share/ob_autoincrement_service.h"
|
|
#include "share/ob_define.h"
|
|
#include "share/ob_global_autoinc_service.h"
|
|
#include "storage/ls/ob_ls_tx_service.h"
|
|
#include "storage/slog/ob_storage_logger.h"
|
|
#include "storage/slog/ob_storage_log.h"
|
|
#include "storage/slog/ob_storage_log_replayer.h"
|
|
#include "storage/tx_storage/ob_ls_service.h"
|
|
#include "share/schema/ob_schema_struct.h"
|
|
#include "share/schema/ob_schema_getter_guard.h"
|
|
#include "share/schema/ob_multi_version_schema_service.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::share;
|
|
|
|
namespace share
|
|
{
|
|
|
|
int ObAutoIncCacheNode::init(const uint64_t sequence_value,
|
|
const uint64_t last_available_value,
|
|
const uint64_t sync_value,
|
|
const int64_t autoinc_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (sequence_value <= 0 || last_available_value < sequence_value || sync_value > sequence_value || autoinc_version < OB_INVALID_VERSION) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(sequence_value), K(last_available_value), K(sync_value));
|
|
} else {
|
|
sequence_value_ = sequence_value;
|
|
last_available_value_ = last_available_value;
|
|
sync_value_ = sync_value;
|
|
autoinc_version_ = autoinc_version;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObAutoIncCacheNode::need_fetch_next_node(const uint64_t base_value,
|
|
const uint64_t desired_cnt,
|
|
const uint64_t max_value) const
|
|
{
|
|
bool bret = false;
|
|
if (OB_UNLIKELY(last_available_value_ == max_value)) {
|
|
bret = false;
|
|
} else if (OB_LIKELY(last_available_value_ >= desired_cnt)) {
|
|
uint64_t new_base_value = std::max(base_value, sequence_value_);
|
|
bret = new_base_value > last_available_value_ - desired_cnt + 1;
|
|
} else {
|
|
bret = true;
|
|
}
|
|
return bret;
|
|
}
|
|
|
|
int ObAutoIncCacheNode::update_sequence_value(const uint64_t sequence_value)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!is_valid())) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("update invalid cache is not allowed", K(ret));
|
|
} else if (OB_UNLIKELY(sequence_value > last_available_value_ ||
|
|
sequence_value < sequence_value_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(sequence_value),
|
|
K(sequence_value_), K(last_available_value_));
|
|
} else {
|
|
sequence_value_ = sequence_value;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObAutoIncCacheNode::update_available_value(const uint64_t available_value)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!is_valid())) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("update invalid cache is not allowed", K(ret));
|
|
} else if (OB_UNLIKELY(available_value < last_available_value_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(available_value), K(last_available_value_));
|
|
} else {
|
|
last_available_value_ = available_value;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObAutoIncCacheNode::update_sync_value(const uint64_t sync_value)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!is_valid())) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("update invalid cache is not allowed", K(ret));
|
|
} else if (OB_UNLIKELY(sync_value > sequence_value_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(sync_value), K(sequence_value_));
|
|
} else {
|
|
sync_value_ = sync_value;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::init(const ObAddr &addr, ObMySQLProxy *mysql_proxy)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObMemAttr attr(MTL_ID(), ObModIds::OB_AUTOINCREMENT);
|
|
if (OB_ISNULL(mysql_proxy)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), KP(mysql_proxy));
|
|
} else if (OB_FAIL(inner_table_proxy_.init(mysql_proxy))) {
|
|
LOG_WARN("init inner table proxy failed", K(ret));
|
|
} else if (OB_FAIL(autoinc_map_.create(ObGlobalAutoIncService::INIT_HASHMAP_SIZE,
|
|
attr,
|
|
attr))) {
|
|
LOG_WARN("init autoinc_map_ failed", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; i < MUTEX_NUM; ++i) {
|
|
op_mutex_[i].set_latch_id(common::ObLatchIds::AUTO_INCREMENT_GAIS_LOCK);
|
|
}
|
|
self_ = addr;
|
|
is_inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::mtl_init(ObGlobalAutoIncService *&gais)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObMySQLProxy *mysql_proxy = GCTX.sql_proxy_;
|
|
const ObAddr &self = GCTX.self_addr();
|
|
ret = gais->init(self, mysql_proxy);
|
|
return ret;
|
|
}
|
|
|
|
void ObGlobalAutoIncService::destroy()
|
|
{
|
|
autoinc_map_.destroy();
|
|
inner_table_proxy_.reset();
|
|
ObSpinLockGuard lock(cache_ls_lock_);
|
|
cache_ls_ = NULL;
|
|
is_leader_ = false;
|
|
is_inited_ = false;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::clear()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (autoinc_map_.size() > 0) {
|
|
ret = autoinc_map_.clear();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::handle_next_autoinc_request(
|
|
const ObGAISNextAutoIncValReq &request,
|
|
obrpc::ObGAISNextValRpcResult &result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const AutoincKey &key = request.autoinc_key_;
|
|
const uint64_t desired_count = request.desired_cnt_;
|
|
bool is_leader = false;
|
|
lib::ObMutex &mutex = op_mutex_[key.hash() % MUTEX_NUM];
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("gloabl service is not init", K(ret));
|
|
} else if (OB_UNLIKELY(!request.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(request));
|
|
} else if (OB_FAIL(check_leader_(key.tenant_id_, is_leader))) {
|
|
LOG_WARN("check leader failed", K(ret), K(request.sender_), K(self_));
|
|
} else if (OB_UNLIKELY(!is_leader)) {
|
|
ret = OB_NOT_MASTER;
|
|
LOG_WARN("gais service is not leader", K(ret));
|
|
} else if (OB_FAIL(mutex.lock())) {
|
|
LOG_WARN("fail to get lock", K(ret));
|
|
} else {
|
|
ObAutoIncCacheNode cache_node;
|
|
int err = autoinc_map_.get_refactored(key, cache_node);
|
|
const int64_t tenant_id = key.tenant_id_;
|
|
const int64_t request_version = request.autoinc_version_;
|
|
LOG_TRACE("begin handle req autoinc request", K(request), K(cache_node));
|
|
if (OB_UNLIKELY(OB_SUCCESS != err && OB_HASH_NOT_EXIST != err)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to get seq value", K(ret), K(key));
|
|
} else if (OB_UNLIKELY(!cache_node.is_valid()
|
|
|| (request_version == cache_node.autoinc_version_
|
|
&& cache_node.need_fetch_next_node(
|
|
request.base_value_, desired_count, request.max_value_)))) {
|
|
OZ(fetch_next_node_(request, cache_node));
|
|
} else if (OB_UNLIKELY(request_version > cache_node.autoinc_version_)) {
|
|
LOG_INFO("start to reset old global table node", K(tenant_id), K(key.table_id_),
|
|
K(request_version), K(cache_node.autoinc_version_));
|
|
cache_node.reset();
|
|
OZ(fetch_next_node_(request, cache_node));
|
|
} else if (OB_UNLIKELY(request_version < cache_node.autoinc_version_)) {
|
|
ret = OB_AUTOINC_CACHE_NOT_EQUAL;
|
|
LOG_WARN("request autoinc_version is less than autoinc_version_ in table_node, it should retry", KR(ret), K(tenant_id), K(key.table_id_),
|
|
K(request_version), K(cache_node.autoinc_version_));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_UNLIKELY(!cache_node.is_valid())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Unexpected cache node", K(ret), K(cache_node));
|
|
} else {
|
|
const uint64_t start_inclusive = std::max(cache_node.sequence_value_, request.base_value_);
|
|
const uint64_t max_value = request.max_value_;
|
|
uint64_t end_inclusive = 0;
|
|
if (max_value >= request.desired_cnt_ &&
|
|
start_inclusive <= max_value - request.desired_cnt_ + 1) {
|
|
end_inclusive = start_inclusive + request.desired_cnt_ - 1;
|
|
if (OB_UNLIKELY(end_inclusive > cache_node.last_available_value_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected value", K(ret), K(end_inclusive), K(cache_node));
|
|
} else if (OB_UNLIKELY(end_inclusive == cache_node.last_available_value_)) {
|
|
// the cache node is run out
|
|
cache_node.reset();
|
|
} else if (OB_FAIL(cache_node.update_sequence_value(end_inclusive + 1))) {
|
|
LOG_WARN("fail to update sequence value", K(ret), K(cache_node), K(end_inclusive));
|
|
}
|
|
} else if (OB_FAIL(cache_node.update_sequence_value(max_value))) {
|
|
LOG_WARN("fail to update sequence value", K(ret), K(cache_node), K(max_value));
|
|
} else {
|
|
end_inclusive = max_value;
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
uint64_t sync_value = cache_node.sync_value_;
|
|
if (request.base_value_ != 0 && request.base_value_ - 1 > sync_value) {
|
|
sync_value = request.base_value_ - 1;
|
|
}
|
|
if (OB_FAIL(result.init(start_inclusive, end_inclusive, sync_value))) {
|
|
LOG_WARN("init result failed", K(ret), K(cache_node));
|
|
} else if (OB_FAIL(autoinc_map_.set_refactored(key, cache_node, 1))) {
|
|
LOG_WARN("set autoinc_map_ failed", K(ret));
|
|
}
|
|
}
|
|
LOG_TRACE("after handle req autoinc request", K(request), K(cache_node));
|
|
}
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::handle_curr_autoinc_request(const ObGAISAutoIncKeyArg &request,
|
|
obrpc::ObGAISCurrValRpcResult &result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const AutoincKey &key = request.autoinc_key_;
|
|
uint64_t sequence_value = 0;
|
|
uint64_t sync_value = 0;
|
|
bool is_leader = false;
|
|
lib::ObMutex &mutex = op_mutex_[key.hash() % MUTEX_NUM];
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("gloabl service is not init", K(ret));
|
|
} else if (OB_UNLIKELY(!request.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(request));
|
|
} else if (OB_FAIL(check_leader_(key.tenant_id_, is_leader))) {
|
|
LOG_WARN("check leader failed", K(ret), K(request.sender_), K(self_));
|
|
} else if (OB_FAIL(mutex.lock())) {
|
|
LOG_WARN("fail to get lock", K(ret));
|
|
} else {
|
|
ObAutoIncCacheNode cache_node;
|
|
const int64_t tenant_id = key.tenant_id_;
|
|
int err = autoinc_map_.get_refactored(key, cache_node);
|
|
const int64_t request_version = request.autoinc_version_;
|
|
LOG_TRACE("start handle get autoinc request", K(request), K(cache_node));
|
|
if (OB_UNLIKELY(OB_SUCCESS != err && OB_HASH_NOT_EXIST != err)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to get seq value", K(ret), K(key));
|
|
} else if (is_leader
|
|
&& OB_LIKELY(cache_node.is_valid())
|
|
&& request_version == cache_node.autoinc_version_) {
|
|
// get autoinc values from cache
|
|
sequence_value = cache_node.sequence_value_;
|
|
sync_value = cache_node.sync_value_;
|
|
// hash not exist, cache node is non-valid or service is not leader,
|
|
// read value from inner table
|
|
} else if (OB_FAIL(read_value_from_inner_table_(key, request_version, sequence_value, sync_value))) {
|
|
LOG_WARN("fail to read value from inner table", KR(ret), K(tenant_id), K_(key.table_id));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(result.init(sequence_value, sync_value))) {
|
|
LOG_WARN("failed to init result", KR(ret), K(tenant_id), K_(key.table_id), K(request_version), K(cache_node));
|
|
}
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::handle_push_autoinc_request(
|
|
const ObGAISPushAutoIncValReq &request,
|
|
uint64_t &sync_value)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const AutoincKey &key = request.autoinc_key_;
|
|
bool is_leader = false;
|
|
lib::ObMutex &mutex = op_mutex_[key.hash() % MUTEX_NUM];
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("gloabl service is not init", K(ret));
|
|
} else if (OB_UNLIKELY(!request.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(request));
|
|
} else if (OB_FAIL(check_leader_(key.tenant_id_, is_leader))) {
|
|
LOG_WARN("check leader failed", K(ret), K(request.sender_), K(self_));
|
|
} else if (OB_UNLIKELY(!is_leader)) {
|
|
ret = OB_NOT_MASTER;
|
|
LOG_WARN("gais service is not leader", K(ret));
|
|
} else if (OB_FAIL(mutex.lock())) {
|
|
LOG_WARN("fail to get lock", K(ret));
|
|
} else {
|
|
ObAutoIncCacheNode cache_node;
|
|
const int64_t tenant_id = key.tenant_id_;
|
|
int err = autoinc_map_.get_refactored(key, cache_node);
|
|
const int64_t request_version = request.autoinc_version_;
|
|
LOG_TRACE("start handle push global autoinc request", K(request), K(cache_node));
|
|
if (OB_UNLIKELY(OB_SUCCESS != err && OB_HASH_NOT_EXIST != err)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to get seq value", K(ret), K(key));
|
|
} else if (OB_UNLIKELY(OB_HASH_NOT_EXIST == err
|
|
|| (request_version == cache_node.autoinc_version_
|
|
&& cache_node.need_sync(request.base_value_))
|
|
// cache node is expired
|
|
|| (request_version > cache_node.autoinc_version_))) {
|
|
if (request_version > cache_node.autoinc_version_) {
|
|
cache_node.reset();
|
|
}
|
|
if (OB_FAIL(sync_value_to_inner_table_(request, cache_node, sync_value))) {
|
|
LOG_WARN("sync to inner table failed", K(ret));
|
|
} else if (OB_FAIL(autoinc_map_.set_refactored(key, cache_node, 1))) {
|
|
LOG_WARN("set autoinc_map_ failed", K(ret));
|
|
}
|
|
// old request just ignore
|
|
} else if (OB_UNLIKELY(request_version < cache_node.autoinc_version_)) {
|
|
ret = OB_AUTOINC_CACHE_NOT_EQUAL;
|
|
LOG_WARN("request autoinc_version is less than cache_node autoinc_version", KR(ret), K(tenant_id), K_(key.table_id),
|
|
K(request_version), K(cache_node.autoinc_version_));
|
|
} else if (OB_LIKELY(request_version == cache_node.autoinc_version_)) {
|
|
sync_value = cache_node.sync_value_;
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::handle_clear_autoinc_cache_request(const ObGAISAutoIncKeyArg &request)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const AutoincKey &key = request.autoinc_key_;
|
|
bool is_leader = false;
|
|
lib::ObMutex &mutex = op_mutex_[key.hash() % MUTEX_NUM];
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("gloabl service is not init", K(ret));
|
|
} else if (OB_UNLIKELY(!request.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(request));
|
|
} else if (OB_FAIL(check_leader_(key.tenant_id_, is_leader))) {
|
|
LOG_WARN("check leader failed", K(ret), K(request.sender_), K(self_));
|
|
} else if (OB_UNLIKELY(!is_leader)) {
|
|
ret = OB_NOT_MASTER;
|
|
LOG_WARN("gais service is not leader", K(ret));
|
|
} else if (OB_FAIL(mutex.lock())) {
|
|
LOG_WARN("fail to get lock", K(ret));
|
|
} else {
|
|
LOG_TRACE("start clear autoinc cache request", K(request));
|
|
if (OB_FAIL(autoinc_map_.erase_refactored(key))) {
|
|
LOG_WARN("fail to erase autoinc cache map key", K(ret));
|
|
}
|
|
if (ret == OB_HASH_NOT_EXIST) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::check_leader_(const uint64_t tenant_id, bool &is_leader)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_leader = ATOMIC_LOAD(&is_leader_);
|
|
if (OB_LIKELY(is_leader)) {
|
|
} else {
|
|
// try to get role from logstream
|
|
ObRole role = ObRole::INVALID_ROLE;
|
|
int64_t proposal_id = 0;
|
|
ObSpinLockGuard lock(cache_ls_lock_);
|
|
if (OB_ISNULL(cache_ls_)) {
|
|
ret = OB_NOT_MASTER;
|
|
LOG_WARN("cache ls is null", K(ret));
|
|
} else if (OB_FAIL(cache_ls_->get_log_handler()->get_role(role, proposal_id))) {
|
|
int tmp_ret = ret;
|
|
ret = OB_NOT_MASTER;
|
|
LOG_WARN("get ls role fail", K(ret), K(tmp_ret));
|
|
} else if (common::ObRole::LEADER == role) {
|
|
is_leader = true;
|
|
} else {
|
|
is_leader = false;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::fetch_next_node_(const ObGAISNextAutoIncValReq &request,
|
|
ObAutoIncCacheNode &node)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t desired_count = std::max(request.cache_size_, request.desired_cnt_);
|
|
uint64_t start_inclusive = 0;
|
|
uint64_t end_inclusive = 0;
|
|
uint64_t sync_value = 0;
|
|
const int64_t autoinc_version = request.autoinc_version_;
|
|
if (OB_FAIL(inner_table_proxy_.next_autoinc_value(request.autoinc_key_,
|
|
request.offset_,
|
|
request.increment_,
|
|
request.base_value_,
|
|
request.max_value_,
|
|
desired_count,
|
|
autoinc_version,
|
|
start_inclusive,
|
|
end_inclusive,
|
|
sync_value))) {
|
|
LOG_WARN("fail to require autoinc value from inner table", K(ret));
|
|
} else if (OB_LIKELY(node.is_valid() && node.last_available_value_ == start_inclusive - 1)) {
|
|
if (OB_FAIL(node.update_available_value(end_inclusive))) {
|
|
LOG_WARN("fail to update available value", K(ret), K(node), K(end_inclusive));
|
|
} else {
|
|
LOG_TRACE("fetch next node done", K(request), K(node));
|
|
}
|
|
} else if (OB_FAIL(node.init(start_inclusive, end_inclusive, sync_value, autoinc_version))){
|
|
LOG_WARN("fail to init node", K(ret), K(start_inclusive), K(end_inclusive), K(sync_value));
|
|
} else {
|
|
LOG_TRACE("fetch next node done", K(request), K(node));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGlobalAutoIncService::read_value_from_inner_table_(const share::AutoincKey &key,
|
|
const int64_t &autoinc_version,
|
|
uint64_t &sequence_val,
|
|
uint64_t &sync_val)
|
|
{
|
|
return inner_table_proxy_.get_autoinc_value(key, autoinc_version, sequence_val, sync_val);
|
|
}
|
|
|
|
int ObGlobalAutoIncService::sync_value_to_inner_table_(
|
|
const ObGAISPushAutoIncValReq &request,
|
|
ObAutoIncCacheNode &node,
|
|
uint64_t &sync_value)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const uint64_t insert_value = request.base_value_;
|
|
uint64_t seq_value = node.is_valid() ? node.sequence_value_ : 0;
|
|
const int64_t autoinc_version = request.autoinc_version_;
|
|
if (OB_FAIL(inner_table_proxy_.sync_autoinc_value(request.autoinc_key_,
|
|
insert_value,
|
|
request.max_value_,
|
|
autoinc_version,
|
|
seq_value,
|
|
sync_value))) {
|
|
LOG_WARN("fail to sync autoinc value to inner table", K(ret));
|
|
} else if (OB_LIKELY(node.is_valid())) {
|
|
if (seq_value > node.last_available_value_) {
|
|
// the node is expired.
|
|
node.reset();
|
|
node.sync_value_ = sync_value; // update sync value for next sync
|
|
} else if (sync_value == request.max_value_) {
|
|
if (node.last_available_value_ != request.max_value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected error", K(ret), K(node), K(request.max_value_));
|
|
} else if (OB_FAIL(node.init(request.max_value_, request.max_value_, request.max_value_, autoinc_version))) {
|
|
LOG_WARN("fail to init node", K(ret), K(request.max_value_));
|
|
}
|
|
} else if (OB_FAIL(node.update_sequence_value(seq_value))) {
|
|
LOG_WARN("fail to update sequence value", K(ret), K(seq_value));
|
|
} else if (OB_FAIL(node.update_sync_value(sync_value))) {
|
|
LOG_WARN("fail to update sync value", K(ret), K(sync_value));
|
|
}
|
|
} else {
|
|
node.reset();
|
|
node.sync_value_ = sync_value; // update sync value for next sync
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
node.autoinc_version_ = autoinc_version > node.autoinc_version_ ? autoinc_version : node.autoinc_version_;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // share
|
|
} // oceanbase
|