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

311 lines
7.3 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.
*/
#include "ob_archive_task_queue.h"
#include "ob_archive_thread_pool.h" // ObArchiveThreadPool
#include "ob_log_archive_define.h" // ARCHIVE_IO_MAX_RETRY_TIME
using namespace oceanbase::common;
namespace oceanbase {
namespace archive {
ObArchiveTaskStatus::ObArchiveTaskStatus() : issue_(false), ref_(0), num_(0), pg_key_(), queue_(), rwlock_()
{}
ObArchiveTaskStatus::~ObArchiveTaskStatus()
{
issue_ = false;
ref_ = 0;
num_ = 0;
pg_key_.reset();
}
void ObArchiveTaskStatus::inc_ref()
{
WLockGuard guard(rwlock_);
ref_ += 1;
}
int64_t ObArchiveTaskStatus::count()
{
return ATOMIC_LOAD(&num_);
}
int ObArchiveTaskStatus::push_unlock(ObLink* link)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(link)) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "task is NULL", KR(ret), K(link));
} else if (OB_FAIL(queue_.push(link))) {
ARCHIVE_LOG(WARN, "push task fail", KR(ret), K(link));
} else {
num_++;
}
return ret;
}
int ObArchiveTaskStatus::pop(ObLink*& link, bool& task_exist)
{
int ret = OB_SUCCESS;
task_exist = false;
RLockGuard guard(rwlock_);
if (OB_UNLIKELY(0 >= ref_)) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "task status ref_ already not bigger than zero", KR(ret), K(ref_), K(pg_key_));
} else if (queue_.is_empty()) {
// skip it
} else if OB_FAIL (queue_.pop(link)) {
ARCHIVE_LOG(WARN, "pop task fail", KR(ret));
} else {
task_exist = true;
num_--;
}
return ret;
}
int ObArchiveTaskStatus::retire(bool& is_empty, bool& is_discarded)
{
WLockGuard guard(rwlock_);
int ret = OB_SUCCESS;
is_empty = true;
is_discarded = false;
if (OB_UNLIKELY(0 >= ref_)) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "task status ref_ already not bigger than zero", KR(ret), K(ref_), K(pg_key_));
} else if (queue_.is_empty()) {
if (OB_FAIL(retire_unlock(is_discarded))) {
ARCHIVE_LOG(WARN, "ObArchiveTaskStatus retire fail", KR(ret));
}
} else {
is_empty = false;
}
return ret;
}
int ObArchiveTaskStatus::retire_unlock(bool& is_discarded)
{
int ret = OB_SUCCESS;
is_discarded = false;
if (OB_UNLIKELY(!issue_)) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "task not issue when retire", KR(ret), K(issue_), K(ref_));
} else {
issue_ = false;
ref_--;
is_discarded = 0 == ref_;
}
return ret;
}
void ObArchiveTaskStatus::free(bool& is_discarded)
{
WLockGuard guard(rwlock_);
int ret = OB_SUCCESS;
is_discarded = false;
if (ref_ < 1) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "ObArchiveTaskStatus free too many", KR(ret), K(ref_));
} else {
ref_--;
is_discarded = 0 == ref_;
}
}
int ObArchiveSendTaskStatus::push(ObArchiveSendTask& task, ObArchiveThreadPool& worker)
{
WLockGuard guard(rwlock_);
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!task.is_valid())) {
ret = OB_INVALID_ARGUMENT;
ARCHIVE_LOG(WARN, "invalid send task", KR(ret), K(task));
} else if (0 >= ref_) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "ref_ already reach not bigger than zero, skip it", KR(ret), K(ref_));
} else if (OB_FAIL(ObArchiveTaskStatus::push_unlock(&task))) {
ARCHIVE_LOG(WARN, "push fail", KR(ret), K(task));
} else if (issue_) {
// skip
} else if (OB_FAIL(worker.push_task_status(this))) {
ARCHIVE_LOG(WARN, "push send_task fail", KR(ret));
} else {
issue_ = true;
ref_++;
}
return ret;
}
int ObArchiveSendTaskStatus::mock_push(ObArchiveSendTask& task, common::ObSpLinkQueue& queue)
{
WLockGuard guard(rwlock_);
int ret = OB_SUCCESS;
if (0 >= ref_) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "ref_ already reach not bigger than zero, skip it", KR(ret), K(ref_));
} else if (OB_FAIL(ObArchiveTaskStatus::push_unlock(&task))) {
ARCHIVE_LOG(WARN, "push fail", KR(ret), K(task));
} else if (issue_) {
// skip
} else if (OB_FAIL(queue.push(this))) {
ARCHIVE_LOG(WARN, "push send_task fail", KR(ret));
} else {
issue_ = true;
ref_++;
}
return ret;
}
int ObArchiveSendTaskStatus::top(ObLink*& link, bool& task_exist)
{
int ret = OB_SUCCESS;
task_exist = false;
RLockGuard guard(rwlock_);
if (queue_.is_empty()) {
// skip it
} else if (OB_FAIL(queue_.top(link))) {
ARCHIVE_LOG(WARN, "top task fail", KR(ret));
} else {
task_exist = true;
}
return ret;
}
ObLink* ObArchiveSendTaskStatus::next(ObLink& pre)
{
ObLink* link = NULL;
RLockGuard guard(rwlock_);
if (queue_.is_empty()) {
// skip it
} else {
link = pre.next_;
}
return link;
}
int ObArchiveSendTaskStatus::pop_front(const int64_t num)
{
int ret = OB_SUCCESS;
RLockGuard guard(rwlock_);
for (int64_t i = 0; OB_SUCC(ret) && i < num; i++) {
ObLink* link = NULL;
if (queue_.is_empty()) {
ret = OB_ERR_UNEXPECTED;
ARCHIVE_LOG(ERROR, "queue_ is empty", KR(ret));
} else if (OB_FAIL(queue_.pop(link))) {
ARCHIVE_LOG(WARN, "pop task fail", KR(ret));
} else {
num_--;
}
}
return ret;
}
bool ObArchiveSendTaskStatus::mark_io_error()
{
bool bret = false;
const int64_t now = ObTimeUtility::fast_current_time();
// two adjoint IO error interval may bigger than ARCHIVE_IO_MAX_RETRY_TIME
// so error count alse needed
const int64_t DEFAULT_ERROR_TOLERATE = 2;
error_occur_count_++;
if (OB_INVALID_TIMESTAMP == error_occur_timestamp_) {
error_occur_timestamp_ = now;
} else {
bret = now - error_occur_timestamp_ > ARCHIVE_IO_MAX_RETRY_TIME && error_occur_count_ > DEFAULT_ERROR_TOLERATE;
}
return bret;
}
void ObArchiveSendTaskStatus::clear_error_info()
{
error_occur_count_ = 0;
error_occur_timestamp_ = OB_INVALID_TIMESTAMP;
}
ObArchiveSendTaskStatus::ObArchiveSendTaskStatus(const ObPGKey& pg_key)
{
error_occur_timestamp_ = OB_INVALID_TIMESTAMP;
error_occur_count_ = 0;
pg_key_ = pg_key;
}
ObArchiveSendTaskStatus::~ObArchiveSendTaskStatus()
{
error_occur_timestamp_ = OB_INVALID_TIMESTAMP;
error_occur_count_ = 0;
}
ObArchiveCLogTaskStatus::ObArchiveCLogTaskStatus(const ObPGKey& pg_key)
{
pg_key_ = pg_key;
}
ObArchiveCLogTaskStatus::~ObArchiveCLogTaskStatus()
{}
int ObArchiveCLogTaskStatus::push(ObPGArchiveCLogTask& task, ObArchiveThreadPool& worker)
{
WLockGuard guard(rwlock_);
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!task.is_valid())) {
ret = OB_INVALID_ARGUMENT;
ARCHIVE_LOG(WARN, "invalid send task", KR(ret), K(task));
} else if (OB_FAIL(ObArchiveTaskStatus::push_unlock(&task))) {
ARCHIVE_LOG(WARN, "push fail", KR(ret), K(task));
} else if (0 >= ref_) {
ret = OB_LOG_ARCHIVE_LEADER_CHANGED;
ARCHIVE_LOG(WARN, "ref_ already reach not bigger than zero, skip it", KR(ret), K(ref_));
} else if (issue_) {
// skip
} else if (OB_FAIL(worker.push_task_status(this))) {
ARCHIVE_LOG(WARN, "push clog_task fail", KR(ret));
} else {
issue_ = true;
ref_++;
}
return ret;
}
} // namespace archive
} // namespace oceanbase