967 lines
32 KiB
C++
967 lines
32 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 "storage/tx/ob_time_wheel.h"
|
|
#include <gtest/gtest.h>
|
|
#include "common/ob_clock_generator.h"
|
|
#include "share/ob_errno.h"
|
|
#include "lib/oblog/ob_log.h"
|
|
#include "lib/random/ob_random.h"
|
|
|
|
#define BASE_TEST
|
|
#define CURRENTCY_TEST
|
|
#define EDGE_TEST
|
|
|
|
#define TEST_TW_CREATE_INIT_DES
|
|
#define TEST_TASK_CREATE_INIT_DES
|
|
#define TEST_TW_SCHEDULE_RUN
|
|
#define TEST_TW_SCHEDULE_RUN_CANCEL
|
|
#define TEST_TW_TASK_RUN_PRECISION
|
|
|
|
#define TEST_TW_HIGHCURRENCY_SCHEDULE
|
|
#define TEST_TW_HIGHCURRENCY_SCHEDULE_RUN
|
|
#define TEST_TW_HIGHCURRENCY_SCHEDULE_CANCEL
|
|
//#define TEST_TW_HIGHCURRENCY_SCHEDULE_CANCEL_RANDOM
|
|
#define TEST_TW_LOCK_AVAILABLITY
|
|
|
|
#define TEST_TIMEWHEELBASE_NO_INIT
|
|
#define TEST_TIMEWHEEL_NO_INIT
|
|
#define TEST_TIMEWHEEL_RUNNING
|
|
#define TEST_TIMEWHEEL_INVALID_INIT
|
|
#define TEST_TIMEWHEEL_REPEAT_INIT
|
|
#define TEST_TIMEWHEEL_REPEAT_DES
|
|
#define TEST_TIMEWHEEL_SCHEDULE_AFTER_DES
|
|
#define TEST_TIMEWHEEL_INVALID_TASK_SCHEDULE
|
|
#define TEST_TIMEWHEEL_REPEAT_SCHEDULE
|
|
#define TEST_TIMEWHEEL_REPEAT_CANCEL
|
|
#define TEST_TIMEWHEEL_REPEAT_SCHEDULE_CANCEL
|
|
#define TEST_TIMEWHEEL_SCHEDULE_SELF
|
|
#define TEST_TIMEWHEEL_CANCEL_RUNOVER_TASK
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
|
|
namespace unittest
|
|
{
|
|
|
|
struct NumTask{
|
|
// thread count
|
|
static const int64_t THREAD_NUM = 15;
|
|
|
|
// high concurrency test task count
|
|
static const int64_t MAX_NUM_TASK = 1000000;
|
|
// static const int64_t HIGH_CURRENCY_NUM_TASK = 100000;
|
|
static const int64_t HIGH_CURRENCY_NUM_TASK = 100000;
|
|
|
|
// lock availablity test paras
|
|
static const int64_t HIGH_CURRENCY_LOCK_NUM_TASK = 1000;
|
|
static const int64_t HIGH_CURRENCY_LOCK_TEST_COUNT = 10;
|
|
|
|
// inc_num for task hash value
|
|
static int64_t inc_num_;
|
|
|
|
// time wheel thread num
|
|
static const int64_t TW_THREAD_NUM = 6;
|
|
};
|
|
int64_t NumTask::inc_num_ = 0;
|
|
|
|
class TestObTimeWheel : public ::testing::Test
|
|
{
|
|
public :
|
|
virtual void SetUP(){}
|
|
virtual void TearDown(){}
|
|
};
|
|
|
|
class ObSampleTimer : public ObTimeWheel{};
|
|
|
|
class ObSampleTask : public ObTimeWheelTask
|
|
{
|
|
public :
|
|
ObSampleTask() : run_over_(false), inc_num_(++NumTask::inc_num_) {}
|
|
~ObSampleTask(){}
|
|
void runTimerTask();
|
|
bool is_run_over() const;
|
|
void reset();
|
|
static int64_t get_total_run_count();
|
|
static void clear_total_run_count();
|
|
uint64_t hash() const { return inc_num_; }
|
|
public :
|
|
static int64_t task_run_count_num_;
|
|
private :
|
|
bool run_over_;
|
|
int64_t inc_num_;
|
|
};
|
|
|
|
int64_t ObSampleTask::task_run_count_num_ = 0;
|
|
|
|
void ObSampleTask::runTimerTask()
|
|
{
|
|
ATOMIC_FAA(&task_run_count_num_, 1);
|
|
run_over_ = true;
|
|
}
|
|
|
|
bool ObSampleTask::is_run_over() const
|
|
{
|
|
return run_over_;
|
|
}
|
|
|
|
void ObSampleTask::reset()
|
|
{
|
|
run_over_ = false;
|
|
}
|
|
|
|
void ObSampleTask::clear_total_run_count()
|
|
{
|
|
task_run_count_num_ = 0;
|
|
}
|
|
|
|
int64_t ObSampleTask::get_total_run_count()
|
|
{
|
|
return task_run_count_num_;
|
|
}
|
|
|
|
class ObSampleTask2 : public ObTimeWheelTask
|
|
{
|
|
public :
|
|
ObSampleTask2() : time_wheel_(NULL), retry_time_(0), inc_num_(++NumTask::inc_num_) { }
|
|
~ObSampleTask2(){};
|
|
void set_time_wheel(ObTimeWheel *time_wheel);
|
|
void runTimerTask();
|
|
int64_t get_retry_time() const;
|
|
uint64_t hash() const { return inc_num_; }
|
|
private :
|
|
ObTimeWheel *time_wheel_;
|
|
int64_t retry_time_;
|
|
int64_t inc_num_;
|
|
};
|
|
|
|
void ObSampleTask2::set_time_wheel(ObTimeWheel *time_wheel)
|
|
{
|
|
if (NULL != time_wheel) {
|
|
time_wheel_ = time_wheel;
|
|
} else {
|
|
TRANS_LOG(INFO, "", "input paras time_wheel = NULL", time_wheel);
|
|
}
|
|
}
|
|
|
|
void ObSampleTask2::runTimerTask()
|
|
{
|
|
if (retry_time_ < 100) {
|
|
retry_time_++;
|
|
EXPECT_EQ(OB_SUCCESS, time_wheel_->schedule(this, 100000));
|
|
}
|
|
}
|
|
|
|
int64_t ObSampleTask2::get_retry_time() const
|
|
{
|
|
return retry_time_;
|
|
}
|
|
|
|
class ObSampleTask3 : public ObTimeWheelTask
|
|
{
|
|
public :
|
|
ObSampleTask3() : tw_precision_(0), run_time_(0), inc_num_(++NumTask::inc_num_) { }
|
|
~ObSampleTask3() {};
|
|
void set_run_time(const int64_t run_time) { run_time_ = run_time; }
|
|
int64_t get_run_time() const { return run_time_; }
|
|
void runTimerTask();
|
|
void set_precision(const int64_t precision) { tw_precision_ = precision; }
|
|
int64_t get_precision() const { return tw_precision_;}
|
|
uint64_t hash() const { return inc_num_; }
|
|
private :
|
|
int64_t tw_precision_;
|
|
int64_t run_time_;
|
|
int64_t inc_num_;
|
|
};
|
|
|
|
void ObSampleTask3::runTimerTask()
|
|
{
|
|
int64_t max = ((get_run_time() + get_precision() - 1) / get_precision() ) * get_precision() + 5000;
|
|
int64_t min = (get_run_time() / get_precision()) * get_precision();
|
|
int64_t current = ObClockGenerator::getClock();
|
|
|
|
if (current < min || current > max) {
|
|
TRANS_LOG(INFO, "run task", K(min), K(max), K(current), "run_time", get_run_time());
|
|
}
|
|
EXPECT_TRUE(current >= min && current <= max);
|
|
}
|
|
|
|
struct InputParas{
|
|
InputParas() : tw_(NULL), task_(NULL), task_num_(0), task_delay_(0) {}
|
|
~InputParas() {}
|
|
ObSampleTimer *tw_;
|
|
ObSampleTask *task_;
|
|
int64_t task_num_;
|
|
int64_t task_delay_;
|
|
};
|
|
|
|
struct OutputParas
|
|
{
|
|
explicit OutputParas(const int64_t count);
|
|
~OutputParas();
|
|
ObSampleTask *task_arr_[NumTask::MAX_NUM_TASK];
|
|
int64_t valid_task_count_;
|
|
};
|
|
|
|
OutputParas::OutputParas(const int64_t count) : valid_task_count_(0)
|
|
{
|
|
for (int64_t i = 0; i < NumTask::MAX_NUM_TASK; i++) {
|
|
task_arr_[i] = NULL;
|
|
}
|
|
valid_task_count_ = count;
|
|
}
|
|
|
|
OutputParas::~OutputParas()
|
|
{
|
|
for (int64_t i = 0; i < valid_task_count_; ++i) {
|
|
task_arr_[i] = NULL;
|
|
}
|
|
}
|
|
|
|
class MyThread
|
|
{
|
|
public :
|
|
static void *create_task(void *args);
|
|
static void *schedule_task(void *args);
|
|
static void *cancel_task(void *args);
|
|
static void schedule_run(const int64_t thread_num, const int64_t task_num, const int64_t sleep_time);
|
|
};
|
|
|
|
// according to the schedule's task, cancel the task randomly
|
|
void MyThread::schedule_run(const int64_t thread_num, const int64_t task_num, const int64_t sleep_time)
|
|
{
|
|
ObSampleTimer *ob_sample_timer = new ObSampleTimer();
|
|
ASSERT_TRUE(NULL != ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->start());
|
|
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
|
|
// create and init the paras
|
|
const int64_t NUM = thread_num;
|
|
const int64_t TASK_NUM_FOR_THREAD = task_num;
|
|
const int64_t SLEEP_TIME = sleep_time;
|
|
InputParas *params = new InputParas[NUM];
|
|
EXPECT_TRUE(NULL != params);
|
|
|
|
for (int64_t i = 0; i < NUM; ++i) {
|
|
params[i].tw_ = ob_sample_timer;
|
|
params[i].task_ = new ObSampleTask[TASK_NUM_FOR_THREAD];
|
|
EXPECT_TRUE(NULL != params[i].task_);
|
|
params[i].task_num_ = NumTask::HIGH_CURRENCY_LOCK_NUM_TASK;
|
|
params[i].task_delay_ = SLEEP_TIME * 1000 + ObRandom::rand(0, 200) % (int64_t) ((i +1) * 1000); // delay = 5s + rand()
|
|
}
|
|
// create five schedule threads, and schedule above tasks respectively
|
|
pthread_t tids[NUM * 2];
|
|
for (int64_t i = 0; i < NUM; ++i) {
|
|
tids[i] = i;
|
|
EXPECT_TRUE(0 == pthread_create(&tids[i], &attr, MyThread::schedule_task, static_cast<void *>(&(params[i]))));
|
|
}
|
|
// sleep 5s
|
|
ObClockGenerator::msleep(SLEEP_TIME);
|
|
// create five cancel threads, and cancel above taask accordingly
|
|
for (int64_t i = 0; i < NUM; ++i) {
|
|
tids[NUM + i] = i;
|
|
EXPECT_TRUE(0 == pthread_create(&tids[NUM + i], &attr, MyThread::cancel_task, static_cast<void *>(&(params[i]))));
|
|
}
|
|
// collect resources of threads
|
|
for (int64_t i = 0; i < NUM * 2; ++i) {
|
|
pthread_join(tids[i], NULL);
|
|
}
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->wait());
|
|
|
|
delete ob_sample_timer;
|
|
ob_sample_timer = NULL;
|
|
|
|
if (NULL != params) {
|
|
for (int64_t i = 0; i < NUM; ++i) {
|
|
if (NULL != params[i].task_) {
|
|
delete [] params[i].task_;
|
|
params[i].task_ = NULL;
|
|
}
|
|
}
|
|
delete [] params;
|
|
params = NULL;
|
|
}
|
|
}
|
|
// schedule tasks in thread functions
|
|
void *MyThread::schedule_task(void *args)
|
|
{
|
|
InputParas *in_paras = static_cast<InputParas *>(args);
|
|
EXPECT_TRUE(NULL != in_paras);
|
|
for (int64_t i = 0; i < in_paras->task_num_; ++i) {
|
|
EXPECT_TRUE(OB_SUCCESS == in_paras->tw_->schedule(&(in_paras->task_[i]), in_paras->task_delay_));
|
|
TRANS_LOG(INFO, "schedule task", "task", &(in_paras->task_[i]), "delay", in_paras->task_delay_);
|
|
}
|
|
pthread_exit(NULL);
|
|
}
|
|
// cancel tasks in thread functions
|
|
void *MyThread::cancel_task(void *args)
|
|
{
|
|
InputParas *in_paras = static_cast<InputParas *>(args);
|
|
EXPECT_TRUE(NULL != in_paras);
|
|
for (int64_t i = 0; i < in_paras->task_num_; ++i) {
|
|
EXPECT_EQ(OB_SUCCESS, in_paras->tw_->cancel(&(in_paras->task_[i])));
|
|
TRANS_LOG(INFO, "cancel task", "task", &(in_paras->task_[i]), "delay", in_paras->task_delay_);
|
|
}
|
|
pthread_exit(NULL);
|
|
}
|
|
// register tasks in thread functions
|
|
void *MyThread::create_task(void *args)
|
|
{
|
|
int64_t start = 0;
|
|
int64_t end = 0;
|
|
InputParas *in_para = static_cast<InputParas *>(args);
|
|
EXPECT_TRUE(in_para != NULL);
|
|
OutputParas *out_para = new OutputParas(in_para->task_num_);
|
|
EXPECT_TRUE(NULL != out_para);
|
|
|
|
start = ObClockGenerator::getClock();
|
|
for (int64_t i = 0; i < in_para->task_num_; i++) {
|
|
out_para->task_arr_[i] = new ObSampleTask();
|
|
EXPECT_TRUE(NULL != out_para->task_arr_[i]);
|
|
}
|
|
end = ObClockGenerator::getClock();
|
|
TRANS_LOG(INFO, "", "alloc used", end - start);
|
|
|
|
start = ObClockGenerator::getClock();
|
|
for (int64_t i = 0; i < in_para->task_num_; i++) {
|
|
EXPECT_TRUE(OB_SUCCESS == in_para->tw_->schedule(out_para->task_arr_[i], in_para->task_delay_));
|
|
}
|
|
end = ObClockGenerator::getClock();
|
|
TRANS_LOG(INFO, "", "schedule used", end - start);
|
|
|
|
pthread_exit(static_cast<void *>(out_para));
|
|
}
|
|
|
|
//------------------------------basic funtions test--------------------------
|
|
// basic functions test are as follows
|
|
// test the time wheel work flows which contain create,init and destroy operations
|
|
|
|
#ifdef BASE_TEST
|
|
#ifdef TEST_TW_CREATE_INIT_DES
|
|
TEST_F(TestObTimeWheel, test_tw_create_init_des)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
int64_t precision = 1;
|
|
for (int64_t i = 0; i < 4; i++) {
|
|
if( i!= 0) {
|
|
precision *= 10;
|
|
}
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(precision, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
ob_sample_timer.destroy();
|
|
}
|
|
}
|
|
#endif
|
|
// test the task token work flows which contain create,init and destroy operations
|
|
#ifdef TEST_TASK_CREATE_INIT_DES
|
|
TEST_F(TestObTimeWheel, test_task_create_init_des)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTask *ob_sample_task = new ObSampleTask();
|
|
ASSERT_TRUE(NULL != ob_sample_task);
|
|
EXPECT_TRUE(!ob_sample_task->is_run_over());
|
|
|
|
delete ob_sample_task;
|
|
ob_sample_task = NULL;
|
|
}
|
|
#endif
|
|
// test the task which delay time is too long.
|
|
#ifdef TEST_TW_SCHEDULE_RUN
|
|
TEST_F(TestObTimeWheel, test_tw_schedule_run)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask ob_sample_task1;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task1, 100000));
|
|
|
|
ObSampleTask ob_sample_task2;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task2, 15000000));
|
|
|
|
ObClockGenerator::msleep(110);
|
|
EXPECT_TRUE(ob_sample_task1.is_run_over());
|
|
ObClockGenerator::msleep(15010);
|
|
EXPECT_TRUE(ob_sample_task2.is_run_over());
|
|
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
}
|
|
#endif
|
|
// test the run process of task
|
|
#ifdef TEST_TW_SCHEDULE_RUN_CANCEL
|
|
TEST_F(TestObTimeWheel, test_tw_schedule_run_cancel)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask ob_sample_task;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task, 1000000));
|
|
ObClockGenerator::msleep(1010);
|
|
EXPECT_TRUE(ob_sample_task.is_run_over());
|
|
|
|
ob_sample_task.reset();
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task, 1000000));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.cancel(&ob_sample_task));
|
|
ObClockGenerator::msleep(1010);
|
|
EXPECT_TRUE(!ob_sample_task.is_run_over());
|
|
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
}
|
|
#endif
|
|
|
|
// test the precision of task
|
|
#ifdef TEST_TW_TASK_RUN_PRECISION
|
|
TEST_F(TestObTimeWheel, test_tw_task_run_precision)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
const int64_t count = 100;
|
|
const int64_t delay = 1000000;
|
|
|
|
ObSampleTask3 *tmp[count];
|
|
for (int64_t i = 0; i < count; i++) {
|
|
tmp[i] = new ObSampleTask3();
|
|
ASSERT_TRUE(NULL != tmp[i]);
|
|
tmp[i]->set_precision(1000);
|
|
tmp[i]->set_run_time(ObClockGenerator::getClock() + delay);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(tmp[i], delay));
|
|
}
|
|
|
|
ObClockGenerator::msleep(1000);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
|
|
for (int64_t i = 0; i < count; i++) {
|
|
EXPECT_TRUE(NULL != tmp[i]);
|
|
delete tmp[i];
|
|
tmp[i] = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
//--------------------- high concurrency schedule and run ------------------
|
|
// high concurrency test are as follows
|
|
// schedule the task in high concurrency way.
|
|
//
|
|
|
|
#ifdef CURRENTCY_TEST
|
|
|
|
#ifdef TEST_TW_HIGHCURRENCY_SCHEDULE
|
|
TEST_F(TestObTimeWheel, test_tw_highcurrency_schedule)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer *ob_sample_timer = new ObSampleTimer();
|
|
ASSERT_TRUE(NULL != ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->start());
|
|
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
pthread_t tids[NumTask::THREAD_NUM];
|
|
|
|
//create para and init
|
|
InputParas *in_para = new InputParas();
|
|
in_para->tw_ = ob_sample_timer;
|
|
in_para->task_num_ = NumTask::HIGH_CURRENCY_NUM_TASK;
|
|
in_para->task_delay_ = 1000000;
|
|
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
EXPECT_TRUE(pthread_create(&tids[i], &attr, MyThread::create_task, static_cast<void *>(in_para)) == 0);
|
|
}
|
|
|
|
void *tmp[NumTask::THREAD_NUM];
|
|
pthread_attr_destroy(&attr);
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
EXPECT_EQ(0, pthread_join(tids[i], &tmp[i]));
|
|
}
|
|
|
|
delete in_para;
|
|
in_para = NULL;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->wait());
|
|
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
OutputParas *out_pars = static_cast<OutputParas *>(tmp[i]);
|
|
EXPECT_TRUE(NULL != out_pars);
|
|
delete out_pars;
|
|
out_pars = NULL;
|
|
}
|
|
delete ob_sample_timer;
|
|
ob_sample_timer = NULL;
|
|
}
|
|
#endif
|
|
|
|
// run the task in high concurrency way.
|
|
#ifdef TEST_TW_HIGHCURRENCY_SCHEDULE_RUN
|
|
TEST_F(TestObTimeWheel, test_tw_highcurrency_schedule_run)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTask::clear_total_run_count();
|
|
ObSampleTimer *ob_sample_timer = new ObSampleTimer();
|
|
ASSERT_TRUE(NULL != ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->start());
|
|
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
pthread_t tids[NumTask::THREAD_NUM];
|
|
|
|
// create para and init
|
|
InputParas *in_para = new InputParas();
|
|
in_para->tw_ = ob_sample_timer;
|
|
in_para->task_num_ = NumTask::HIGH_CURRENCY_NUM_TASK;
|
|
in_para->task_delay_ = 100000;
|
|
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++){
|
|
EXPECT_TRUE(pthread_create(&tids[i], &attr, MyThread::create_task, static_cast<void *>(in_para)) == 0);
|
|
}
|
|
|
|
void *tmp[NumTask::THREAD_NUM];
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
EXPECT_EQ(0, pthread_join(tids[i], &tmp[i]));
|
|
}
|
|
// Error:there are several tasks which have not been executed.
|
|
// success: all tasks have been executed.
|
|
ObClockGenerator::msleep(10000);
|
|
EXPECT_EQ(NumTask::THREAD_NUM * NumTask::HIGH_CURRENCY_NUM_TASK, ObSampleTask::get_total_run_count());
|
|
|
|
delete in_para;
|
|
in_para = NULL;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->wait());
|
|
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
OutputParas *out_pars = static_cast<OutputParas *>(tmp[i]);
|
|
EXPECT_TRUE(NULL != out_pars);
|
|
delete out_pars;
|
|
out_pars = NULL;
|
|
}
|
|
delete ob_sample_timer;
|
|
ob_sample_timer = NULL;
|
|
ObSampleTask::clear_total_run_count();
|
|
}
|
|
#endif
|
|
|
|
// run the task and cancel in high concurrency way.
|
|
#ifdef TEST_TW_HIGHCURRENCY_SCHEDULE_CANCEL
|
|
TEST_F(TestObTimeWheel, test_tw_highcurrency_schedule_cancel)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTask::clear_total_run_count();
|
|
ObSampleTimer *ob_sample_timer = new ObSampleTimer();
|
|
ASSERT_TRUE(NULL != ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->start());
|
|
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
pthread_t tids[NumTask::THREAD_NUM];
|
|
|
|
// create para and init
|
|
InputParas *in_para = new InputParas();
|
|
in_para->tw_ = ob_sample_timer;
|
|
in_para->task_num_ = NumTask::HIGH_CURRENCY_NUM_TASK;
|
|
in_para->task_delay_ = 12000000;
|
|
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
EXPECT_TRUE(pthread_create(&tids[i], &attr, MyThread::create_task, static_cast<void *>(in_para)) == 0);
|
|
}
|
|
void *tmp[NumTask::THREAD_NUM];
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
EXPECT_EQ(0, pthread_join(tids[i], &tmp[i]));
|
|
}
|
|
int64_t start = 0;
|
|
int64_t end = 0;
|
|
start = ObClockGenerator::getClock();
|
|
for (int64_t i = 0; i < NumTask::THREAD_NUM; i++) {
|
|
OutputParas *out_para = static_cast<OutputParas *>(tmp[i]);
|
|
ASSERT_TRUE(NULL != out_para);
|
|
for (int64_t j = 0; j < in_para->task_num_; j++) {
|
|
ASSERT_TRUE(NULL != out_para->task_arr_[j]);
|
|
ob_sample_timer->cancel(out_para->task_arr_[j]);
|
|
}
|
|
delete out_para;
|
|
out_para = NULL;
|
|
}
|
|
end = ObClockGenerator::getClock();
|
|
TRANS_LOG(WARN, "", "used", end - start);
|
|
EXPECT_EQ(0, ObSampleTask::get_total_run_count());
|
|
|
|
delete in_para;
|
|
in_para = NULL;
|
|
ObSampleTask::clear_total_run_count();
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->wait());
|
|
delete ob_sample_timer;
|
|
ob_sample_timer = NULL;
|
|
}
|
|
#endif
|
|
|
|
// purpose: test whether there are bugs after/before executing tasks
|
|
// steps: (a special case is as follows)
|
|
// (1) Create 100,000 tasks in main thread, and use the same timer to schedule these tasks in threads A, B, C, D and E,
|
|
// where A is responsible for the first 20,000 tasks, B the next 20,000 tasks, ....
|
|
// All tasks' delay is set to [5s, 6s]
|
|
// (2) Threads F, G, H, I and J start to cancel the corresponding tasks after main thread sleeps 5s
|
|
#ifdef TEST_TW_HIGHCURRENCY_SCHEDULE_CANCEL_RANDOM
|
|
TEST_F(TestObTimeWheel, test_tw_high_concurrency_run_cancel)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
// 1 schedule thread and 1 cancel thread, each thread schedules 1,000 tasks
|
|
// sleep time is set to 1s
|
|
MyThread::schedule_run(1, 1000, 1000);
|
|
// 2 schedule thread and 2 cancel thread, each thread schedules 10,000 tasks
|
|
// sleep time is set to 2s
|
|
MyThread::schedule_run(2, 10000, 2000);
|
|
// 4 schedule thread and 4 cancel thread, each thread schedules 100,000 tasks
|
|
// sleep time is set to 3s
|
|
MyThread::schedule_run(4, 100 * 1000, 3000);
|
|
// 6 schedule thread and 6 cancel thread, each thread schedules 1,000,000 tasks
|
|
// sleep time is set to 4s
|
|
MyThread::schedule_run(6, 1000 * 1000, 4000 );
|
|
// 8 schedule thread and 8 cancel thread, each thread schedules 10,000,000 tasks
|
|
// sleep time is set to 4s
|
|
MyThread::schedule_run(8, 10 * 1000 * 1000, 4000);
|
|
}
|
|
#endif
|
|
|
|
// when the task will run, cancel it.
|
|
// this case is to test the availablity of lock between run and cancel thread.
|
|
#ifdef TEST_TW_LOCK_AVAILABLITY
|
|
TEST_F(TestObTimeWheel, test_tw_lock_availablity)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer *ob_sample_timer = new ObSampleTimer();
|
|
ASSERT_TRUE(NULL != ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->start());
|
|
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
|
|
// create and init the paras
|
|
InputParas *in_para = new InputParas();
|
|
in_para->tw_ = ob_sample_timer;
|
|
in_para->task_num_ = NumTask::HIGH_CURRENCY_LOCK_NUM_TASK;
|
|
in_para->task_delay_ = 1500000;
|
|
|
|
for (int64_t i = 0; i < NumTask::HIGH_CURRENCY_LOCK_TEST_COUNT; i++) {
|
|
// create a pthread
|
|
pthread_t tid = 0;
|
|
EXPECT_TRUE(pthread_create(&tid, &attr, MyThread::create_task, static_cast<void *>(in_para)) == 0);
|
|
|
|
ObClockGenerator::msleep(1450);
|
|
void *tmp = NULL;
|
|
EXPECT_EQ(0, pthread_join(tid, &tmp));
|
|
OutputParas *out_para = static_cast<OutputParas *>(tmp);
|
|
ASSERT_TRUE(NULL != out_para);
|
|
|
|
for (int i = 0; i < out_para->valid_task_count_; i++) {
|
|
ASSERT_TRUE(NULL != out_para->task_arr_[i]);
|
|
ob_sample_timer->cancel(out_para->task_arr_[i]);
|
|
EXPECT_TRUE(false == (out_para->task_arr_[i])->is_run_over());
|
|
}
|
|
}
|
|
|
|
delete in_para;
|
|
in_para = NULL;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->wait());
|
|
delete ob_sample_timer;
|
|
ob_sample_timer = NULL;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
//-------------------------------boundary test-----------------------------------------
|
|
// boundary test are as follows
|
|
// test the time wheel which wasn't inited before used.
|
|
|
|
#ifdef EDGE_TEST
|
|
|
|
#ifdef TEST_TIMEWHEELBASE_NO_INIT
|
|
TEST_F(TestObTimeWheel, test_timewheel_base_init)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
TimeWheelBase tw_base;
|
|
// not init tw_base
|
|
EXPECT_EQ(OB_NOT_INIT, tw_base.start());
|
|
EXPECT_EQ(OB_NOT_INIT, tw_base.stop());
|
|
EXPECT_EQ(OB_NOT_INIT, tw_base.wait());
|
|
EXPECT_EQ(OB_NOT_INIT, tw_base.schedule(NULL, 1000));
|
|
EXPECT_EQ(OB_NOT_INIT, tw_base.cancel(NULL));
|
|
// after init, no start
|
|
EXPECT_EQ(OB_SUCCESS, tw_base.init(1000));
|
|
EXPECT_EQ(OB_ERR_UNEXPECTED, tw_base.stop());
|
|
EXPECT_EQ(OB_SUCCESS, tw_base.wait());
|
|
EXPECT_EQ(OB_ERR_UNEXPECTED, tw_base.schedule(NULL, 1000));
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, tw_base.cancel(NULL));
|
|
|
|
EXPECT_EQ(OB_SUCCESS, tw_base.start());
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, tw_base.schedule(NULL, 1000));
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, tw_base.cancel(NULL));
|
|
|
|
tw_base.destroy();
|
|
}
|
|
#endif
|
|
// test the fucntions of time wheel
|
|
#ifdef TEST_TIMEWHEEL_NO_INIT
|
|
TEST_F(TestObTimeWheel, test_timewheel_no_init)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
ObSampleTask ob_sample_task;
|
|
const static int64_t precision= 1000;
|
|
const static int64_t delay = 100000;
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.schedule(&ob_sample_task, precision));
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.start());
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.wait());
|
|
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.schedule(&ob_sample_task, delay));
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.cancel(&ob_sample_task));
|
|
}
|
|
#endif
|
|
// test the order of calling start, stop and wait
|
|
#ifdef TEST_TIMEWHEEL_RUNNING
|
|
TEST_F(TestObTimeWheel, test_timewheel_start_stop_wait)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
ObSampleTask ob_sample_task;
|
|
const static int64_t precision= 1000;
|
|
const static int64_t delay = 100000;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(precision, NumTask::TW_THREAD_NUM, "test"));
|
|
// call the functions schedule and cancle without calling start
|
|
EXPECT_EQ(OB_ERR_UNEXPECTED, ob_sample_timer.schedule(&ob_sample_task, delay));
|
|
EXPECT_EQ(OB_TIMER_TASK_HAS_NOT_SCHEDULED, ob_sample_timer.cancel(&ob_sample_task));
|
|
// call the functions stop/wait directly without calling start
|
|
EXPECT_EQ(OB_ERR_UNEXPECTED, ob_sample_timer.stop());
|
|
// call the function start repeatedly
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
EXPECT_EQ(OB_ERR_UNEXPECTED, ob_sample_timer.start());
|
|
// call the fucntion wait without calling stop
|
|
EXPECT_EQ(OB_ERR_UNEXPECTED, ob_sample_timer.wait());
|
|
ob_sample_timer.destroy();
|
|
}
|
|
#endif
|
|
// init the timewheel with invalid argument
|
|
#ifdef TEST_TIMEWHEEL_INVALID_INIT
|
|
TEST_F(TestObTimeWheel, test_timewheel_invalid_init)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, ob_sample_timer.init(-1, NumTask::TW_THREAD_NUM, "test"));
|
|
}
|
|
#endif
|
|
// test the time wheel which was inited twice.
|
|
#ifdef TEST_TIMEWHEEL_REPEAT_INIT
|
|
TEST_F(TestObTimeWheel, test_timewheel_repeat_init)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_INIT_TWICE, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
}
|
|
#endif
|
|
// destroy the time wheel twice
|
|
#ifdef TEST_TIMEWHEEL_REPEAT_DES
|
|
TEST_F(TestObTimeWheel, test_timewheel_repeat_des)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
ob_sample_timer.destroy();
|
|
ob_sample_timer.destroy();
|
|
}
|
|
#endif
|
|
// schedule the task after having destroy time wheel
|
|
#ifdef TEST_TIMEWHEEL_SCHEDULE_AFTER_DES
|
|
TEST_F(TestObTimeWheel, test_timewheel_schedule_after_des)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
ob_sample_timer.destroy();
|
|
|
|
ObSampleTask ob_sample_task;
|
|
EXPECT_EQ(OB_NOT_INIT, ob_sample_timer.schedule(&ob_sample_task, 1000));
|
|
}
|
|
#endif
|
|
// schedule the task which has invalid argument
|
|
#ifdef TEST_TIMEWHEEL_INVALID_TASK_SCHEDULE
|
|
TEST_F(TestObTimeWheel, test_timewheel_invalid_task_schedule)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask *ob_sample_task = NULL;
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, ob_sample_timer.schedule(ob_sample_task, 1000));
|
|
ob_sample_task = new ObSampleTask();
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, ob_sample_timer.schedule(ob_sample_task, -1));
|
|
|
|
delete ob_sample_task;
|
|
ob_sample_task = NULL;
|
|
}
|
|
#endif
|
|
// schedule the task twice
|
|
#ifdef TEST_TIMEWHEEL_REPEAT_SCHEDULE
|
|
TEST_F(TestObTimeWheel, test_timewheel_repeat_schedule)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask ob_sample_task;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task, 100000));
|
|
EXPECT_EQ(OB_TIMER_TASK_HAS_SCHEDULED, ob_sample_timer.schedule(&ob_sample_task, 1000));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
}
|
|
#endif
|
|
|
|
// cancel the same task for several times
|
|
#ifdef TEST_TIMEWHEEL_REPEAT_CANCEL
|
|
TEST_F(TestObTimeWheel, test_timewheel_repeat_cancel)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask ob_sample_task;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task, 1000));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.cancel(&ob_sample_task));
|
|
EXPECT_EQ(OB_TIMER_TASK_HAS_NOT_SCHEDULED, ob_sample_timer.cancel(&ob_sample_task));
|
|
ObSampleTask *task = NULL;
|
|
EXPECT_EQ(OB_INVALID_ARGUMENT, ob_sample_timer.cancel(task));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
}
|
|
#endif
|
|
|
|
// repeat the process "schedule->cancel" for several times
|
|
#ifdef TEST_TIMEWHEEL_REPEAT_SCHEDULE_CANCEL
|
|
TEST_F(TestObTimeWheel, test_timewheel_repeat_schedule_cancel)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer *ob_sample_timer = new ObSampleTimer();
|
|
ASSERT_TRUE(NULL != ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->start());
|
|
ObSampleTask ob_sample_task;
|
|
for (int64_t i = 0; i < 1000000; i++) {
|
|
// the delay time should great and equal to 1000us.
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->schedule(&ob_sample_task, 100000));
|
|
EXPECT_TRUE(!ob_sample_task.is_run_over());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->cancel(&ob_sample_task));
|
|
}
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer->wait());
|
|
delete ob_sample_timer;
|
|
ob_sample_timer = NULL;
|
|
}
|
|
#endif
|
|
|
|
// schedule self for 100 times
|
|
#ifdef TEST_TIMEWHEEL_SCHEDULE_SELF
|
|
TEST_F(TestObTimeWheel, test_timewheel_schedule_self)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask2 ob_sample_task;
|
|
ob_sample_task.set_time_wheel(&ob_sample_timer);
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task, 100000));
|
|
|
|
ObClockGenerator::msleep(15000);
|
|
EXPECT_EQ(100, ob_sample_task.get_retry_time());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
}
|
|
#endif
|
|
|
|
// cancel the task which has been executed.
|
|
#ifdef TEST_TIMEWHEEL_CANCEL_RUNOVER_TASK
|
|
TEST_F(TestObTimeWheel, test_timewheel_cancel_runover_task)
|
|
{
|
|
TRANS_LOG(INFO, "called", "func", test_info_->name());
|
|
ObSampleTimer ob_sample_timer;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.init(1000, NumTask::TW_THREAD_NUM, "test"));
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.start());
|
|
|
|
ObSampleTask ob_sample_task;
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.schedule(&ob_sample_task, 100000));
|
|
|
|
ObClockGenerator::msleep(1000);
|
|
EXPECT_TRUE(true == ob_sample_task.is_run_over());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.stop());
|
|
EXPECT_EQ(OB_SUCCESS, ob_sample_timer.wait());
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
}//end of unittest
|
|
}//end of oceanbase
|
|
|
|
using namespace oceanbase;
|
|
using namespace oceanbase::common;
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int ret = 1;
|
|
ObLogger &logger = ObLogger::get_logger();
|
|
logger.set_file_name("test_ob_time_wheel.log", true);
|
|
logger.set_log_level(OB_LOG_LEVEL_INFO);
|
|
TRANS_LOG(WARN, "init memory pool error!");
|
|
} else if (OB_SUCCESS != (ret = ObClockGenerator::init())) {
|
|
TRANS_LOG(WARN, "init ObClockGenerator error!");
|
|
} else {
|
|
testing::InitGoogleTest(&argc, argv);
|
|
ret = RUN_ALL_TESTS();
|
|
}
|
|
return ret;
|
|
}
|