203 lines
5.3 KiB
C++
203 lines
5.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_partition_log_service.h"
|
|
#include "storage/ob_partition_service.h"
|
|
#include "ob_clog_config.h"
|
|
|
|
namespace oceanbase {
|
|
using namespace common;
|
|
namespace clog {
|
|
|
|
int ObClogAggreTask::set_partition_key(const ObPartitionKey& pkey)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!pkey.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else {
|
|
pkey_ = pkey;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObClogAggreTask::set_run_ts(const int64_t run_ts)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (0 >= run_ts) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else {
|
|
run_ts_ = run_ts;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObClogAggreTask::handle()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t cur_ts = ObTimeUtility::current_time();
|
|
const int64_t sleep_ts = run_ts_ - cur_ts;
|
|
if (sleep_ts > 0) {
|
|
usleep(sleep_ts);
|
|
}
|
|
if (NULL != ps_) {
|
|
if (OB_FAIL(ps_->try_freeze_aggre_buffer(pkey_))) {
|
|
CLOG_LOG(WARN, "try freeze aggre buffer failed", K(ret), K_(pkey));
|
|
}
|
|
}
|
|
if (NULL != host_) {
|
|
if (OB_FAIL(host_->push_back(this))) {
|
|
CLOG_LOG(WARN, "push back aggre task failed", K(ret), K_(pkey));
|
|
}
|
|
}
|
|
}
|
|
|
|
ObClogAggreRunnable::ObClogAggreRunnable() : is_inited_(false), available_index_(-1), tg_id_(-1)
|
|
{
|
|
for (int64_t i = 0; i < TOTAL_TASK; i++) {
|
|
task_array_[i] = NULL;
|
|
}
|
|
}
|
|
|
|
ObClogAggreRunnable::~ObClogAggreRunnable()
|
|
{
|
|
destroy();
|
|
}
|
|
|
|
int ObClogAggreRunnable::init(storage::ObPartitionService* partition_service)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_inited_) {
|
|
ret = OB_INIT_TWICE;
|
|
CLOG_LOG(WARN, "ObClogAggreRunnable has already been inited", K(ret));
|
|
} else if (OB_ISNULL(partition_service)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CLOG_LOG(WARN, "invalid argument", K(ret), KP(partition_service));
|
|
} else if (OB_FAIL(TG_CREATE(lib::TGDefIDs::ClogAggre, tg_id_))) {
|
|
TRANS_LOG(WARN, "create tg failed", K(ret));
|
|
} else {
|
|
ObMemAttr memattr(OB_SERVER_TENANT_ID, "ObClogAggreTask");
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < TOTAL_TASK; i++) {
|
|
ObClogAggreTask* ptr = (ObClogAggreTask*)ob_malloc(sizeof(ObClogAggreTask), memattr);
|
|
if (NULL == ptr) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
} else {
|
|
new (ptr) ObClogAggreTask(this, partition_service);
|
|
task_array_[i] = ptr;
|
|
available_index_ = i;
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
is_inited_ = true;
|
|
} else {
|
|
destroy();
|
|
}
|
|
CLOG_LOG(INFO, "ObClogAggreRunnable init finished", K(ret));
|
|
return ret;
|
|
}
|
|
|
|
int ObClogAggreRunnable::start()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(TG_SET_HANDLER_AND_START(tg_id_, *this))) {
|
|
TRANS_LOG(WARN, "thread pool init error", K(ret));
|
|
} else {
|
|
CLOG_LOG(INFO, "clog aggre runnable start success", KP(this));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObClogAggreRunnable::stop()
|
|
{
|
|
TG_STOP(tg_id_);
|
|
CLOG_LOG(INFO, "clog aggre runnable stop success", KP(this));
|
|
}
|
|
|
|
void ObClogAggreRunnable::wait()
|
|
{
|
|
CLOG_LOG(INFO, "clog aggre runnable wait success", KP(this));
|
|
}
|
|
|
|
void ObClogAggreRunnable::destroy()
|
|
{
|
|
if (is_inited_) {
|
|
stop();
|
|
wait();
|
|
while (available_index_ >= 0) {
|
|
task_array_[available_index_]->~ObClogAggreTask();
|
|
ob_free(task_array_[available_index_]);
|
|
task_array_[available_index_] = NULL;
|
|
available_index_--;
|
|
}
|
|
tg_id_ = -1;
|
|
is_inited_ = false;
|
|
CLOG_LOG(INFO, "clog aggre runnable destroy", KP(this));
|
|
}
|
|
}
|
|
|
|
int ObClogAggreRunnable::add_task(const ObPartitionKey& pkey, const int64_t delay_us)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!pkey.is_valid() || 0 >= delay_us) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CLOG_LOG(WARN, "invalid argument", K(ret), K(pkey), K(delay_us));
|
|
} else {
|
|
ObClogAggreTask* task = NULL;
|
|
{
|
|
ObSpinLockGuard guard(lock_);
|
|
if (available_index_ >= 0) {
|
|
task = task_array_[available_index_];
|
|
task_array_[available_index_] = NULL;
|
|
available_index_--;
|
|
} else {
|
|
ret = OB_EAGAIN;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(task->set_partition_key(pkey))) {
|
|
CLOG_LOG(WARN, "set partition key failed", K(ret), K(pkey));
|
|
} else if (OB_FAIL(task->set_run_ts(ObTimeUtility::current_time() + delay_us))) {
|
|
CLOG_LOG(WARN, "set run ts failed", K(delay_us));
|
|
} else if (OB_FAIL(TG_PUSH_TASK(tg_id_, task))) {
|
|
CLOG_LOG(WARN, "schedule timer task failed", K(ret), K(pkey), K(delay_us));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObClogAggreRunnable::handle(void* task)
|
|
{
|
|
if (NULL == task) {
|
|
TRANS_LOG(ERROR, "task is null", KP(task));
|
|
} else {
|
|
ObClogAggreTask* aggre_task = static_cast<ObClogAggreTask*>(task);
|
|
aggre_task->handle();
|
|
}
|
|
}
|
|
|
|
int ObClogAggreRunnable::push_back(ObClogAggreTask* task)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(task)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CLOG_LOG(WARN, "invalid argument", K(ret), KP(task));
|
|
} else {
|
|
ObSpinLockGuard guard(lock_);
|
|
task_array_[++available_index_] = task;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace clog
|
|
} // namespace oceanbase
|