patch 4.0

This commit is contained in:
wangzelin.wzl
2022-10-24 10:34:53 +08:00
parent 4ad6e00ec3
commit 93a1074b0c
10533 changed files with 2588271 additions and 2299373 deletions

View File

@ -17,35 +17,37 @@
#include "lib/restore/ob_storage.h"
using namespace oceanbase::common;
class TestObDynamicThreadPool : public ::testing::Test {
class TestObDynamicThreadPool: public ::testing::Test
{
public:
TestObDynamicThreadPool()
{}
virtual ~TestObDynamicThreadPool()
{}
TestObDynamicThreadPool() {}
virtual ~TestObDynamicThreadPool(){}
virtual void SetUp()
{}
{
}
virtual void TearDown()
{}
{
}
static void SetUpTestCase()
{}
{
}
static void TearDownTestCase()
{}
{
}
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(TestObDynamicThreadPool);
protected:
// function members
protected:
};
class SimpleTask : public ObDynamicThreadTask {
class SimpleTask: public ObDynamicThreadTask
{
public:
int process(const bool& is_stop)
int process(const bool &is_stop)
{
UNUSED(is_stop);
ATOMIC_INC(&count_);
@ -56,6 +58,7 @@ public:
int64_t SimpleTask::count_ = 0;
TEST_F(TestObDynamicThreadPool, normal)
{
ObDynamicThreadPool pool;
@ -95,13 +98,15 @@ TEST_F(TestObDynamicThreadPool, test_change_thread_num)
pool.stop();
pool.destroy();
ASSERT_EQ(task_count, SimpleTask::count_);
}
int main(int argc, char** argv)
int main(int argc, char **argv)
{
mallopt(M_ARENA_MAX, 1); // disable malloc multiple arena pool
OB_LOGGER.set_log_level("INFO");
OB_LOGGER.set_file_name("test_dynamic_thread_pool.log", true);
::testing::InitGoogleTest(&argc, argv);
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,270 @@
/**
* 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 <gtest/gtest.h>
#include <iostream>
#include "lib/ob_errno.h"
#include "lib/oblog/ob_log.h"
#include "lib/time/ob_time_utility.h"
#include "lib/resource/ob_resource_mgr.h"
#include "lib/coro/testing.h"
#define private public
#include "lib/thread/protected_stack_allocator.h"
using namespace std;
using namespace oceanbase::lib;
using namespace oceanbase::common;
static constexpr int64_t DEFAULT_STACK_SIZE = (1 << 20) * 2; // 2M
static constexpr int64_t MAX_STACK_SIZE = (1 << 20) * 16; // 16M
using CPSA = ProtectedStackAllocator;
#define PAGE_SIZE CPSA::page_size()
#define ALLOC(size) g_stack_allocer.alloc(1, size)
#define DEALLOC(ptr) g_stack_allocer.dealloc(ptr)
//struct MhuGuard
//{
// MhuGuard(CPSA::IMemHoldUpdater &mhu)
// {
// orig_mhu_ = CPSA::ref_mhu_;
// CPSA::ref_mhu_ = &mhu;
// }
// ~MhuGuard() { CPSA::ref_mhu_ = orig_mhu_; }
// CPSA::IMemHoldUpdater *orig_mhu_;
//};
class DoNothingMhu //: public CPSA::IMemHoldUpdater
{
public:
virtual int update_hold(const uint64_t tenant_id ,const ssize_t size, bool &updated)
{
UNUSED(tenant_id);
UNUSED(size);
updated = true;
return OB_SUCCESS;
}
};
class TestHoldMhu //: public CPSA::IMemHoldUpdater
{
public:
TestHoldMhu()
: hold_(0), limit_(0)
{}
void reset()
{
hold_ = 0;
limit_ = 0;
}
virtual int update_hold(const uint64_t tenant_id, const ssize_t size, bool &updated)
{
UNUSED(tenant_id);
updated = false;
if (hold_ + size <= limit_) {
hold_ += size;
updated = true;
}
return OB_SUCCESS;
}
int64_t hold_;
int64_t limit_;
};
DoNothingMhu my_mhu;
void test_fixed_size(const int64_t size)
{
cout << "size: " << size << endl;
//MhuGuard guard(my_mhu);
void *buf = ALLOC(size);
ASSERT_NE(buf, nullptr);
memset(buf, '1', size);
char *str = new char[size];
memset(str, '1', size);
int cmp = memcmp(buf, str, size);
EXPECT_EQ(cmp, 0);
DEALLOC(buf);
delete []str;
}
TEST(TestCPSA, Main)
{
auto size = DEFAULT_STACK_SIZE;
test_fixed_size(size);
size = DEFAULT_STACK_SIZE - (4 << 10);
test_fixed_size(size);
size = DEFAULT_STACK_SIZE + (4 << 10);
test_fixed_size(size);
size = MAX_STACK_SIZE;
test_fixed_size(size);
size = PAGE_SIZE;
test_fixed_size(size);
}
TEST(TestCPSA, EXCEPTION)
{
//MhuGuard guard(my_mhu);
// not page_size align is allowed
ASSERT_NE(nullptr, ALLOC(DEFAULT_STACK_SIZE - 1));
ASSERT_EQ(nullptr, ALLOC(-1));
ASSERT_EQ(nullptr, ALLOC(0));
ASSERT_EQ(nullptr, ALLOC(INT64_MAX));
void *buf = nullptr;
ASSERT_NE(nullptr, buf = ALLOC(-UINT64_MAX + DEFAULT_STACK_SIZE - 1));
DEALLOC(buf);
// nullptr ptr will be ignored
DEALLOC(nullptr);
}
TEST(TestCPSA, DISABLED_HOLD_MOCK)
{
TestHoldMhu mhu;
//MhuGuard guard(mhu);
mhu.limit_ = 1 << 20;
ASSERT_EQ(nullptr, ALLOC(DEFAULT_STACK_SIZE));
mhu.reset();
mhu.limit_ = 1 << 30;
mhu.hold_ = (1 << 30) - DEFAULT_STACK_SIZE;
ASSERT_EQ(nullptr, ALLOC(DEFAULT_STACK_SIZE));
mhu.reset();
mhu.limit_ = 1 << 30;
mhu.hold_ = (1 << 30) - DEFAULT_STACK_SIZE - PAGE_SIZE;
void *buf = NULL;
ASSERT_NE(nullptr, buf = ALLOC(DEFAULT_STACK_SIZE));
ASSERT_EQ(nullptr, ALLOC(DEFAULT_STACK_SIZE));
DEALLOC(buf);
mhu.reset();
int64_t size = 8 << 20;
int64_t N = 100;
mhu.limit_ = (size + PAGE_SIZE) * 100;
vector<void *> bufs;
for (int64_t i = 0; i < N; ++i) {
void *buf = ALLOC(size);
ASSERT_NE(nullptr, buf);
memset(buf, '1', size);
bufs.push_back(buf);
}
ASSERT_EQ(nullptr, ALLOC(size));
for (int64_t i = 0; i < N; ++i) {
DEALLOC(bufs[i]);
}
for (int64_t i = 0; i < N; ++i) {
void *buf = ALLOC(size);
ASSERT_NE(nullptr, buf);
memset(buf, '1', size);
DEALLOC(buf);
}
}
using LimitFunc = std::function<void(ObTenantResourceMgrHandle &, const uint64_t)>;
void test_hold(LimitFunc func)
{
const uint64_t tenant_id = 100;
int64_t size = 8 << 20;
const uint64_t limit = (size + PAGE_SIZE * 2) * 100;
int ret = OB_SUCCESS;
ObTenantResourceMgrHandle resource_handle;
if (OB_FAIL(ObResourceMgr::get_instance().get_tenant_resource_mgr(
tenant_id, resource_handle))) {
LIB_LOG(ERROR, "get_tenant_resource_mgr failed", K(ret), K(tenant_id));
return;
} else {
func(resource_handle, limit);
}
int64_t N = 100;
vector<void *> bufs;
for (int64_t i = 0; i < N; ++i) {
void *buf = g_stack_allocer.alloc(tenant_id, size);
ASSERT_NE(nullptr, buf);
bufs.push_back(buf);
}
//ASSERT_EQ(nullptr, CPSA::alloc(tenant_id, size));
for (int64_t i = 0; i < N; ++i) {
DEALLOC(bufs[i]);
}
for (int64_t i = 0; i < N; ++i) {
void *buf = g_stack_allocer.alloc(tenant_id, size);
ASSERT_NE(nullptr, buf);
DEALLOC(buf);
}
}
TEST(TestCPSA, HOLD)
{
test_hold(
[](ObTenantResourceMgrHandle &resource_handle, const uint64_t limit)
{
resource_handle.get_memory_mgr()->set_limit(limit);
}
);
test_hold(
[](ObTenantResourceMgrHandle &resource_handle, const uint64_t limit)
{
resource_handle.get_memory_mgr()->set_ctx_limit(ObCtxIds::CO_STACK, limit);
}
);
}
TEST(TestCPSA, bench)
{
auto begin_ts = ObTimeUtility::current_time();
const auto CNT = 1000L * 10 ;
for (auto i = 0; i < CNT; ++i) {
auto buf = ALLOC(DEFAULT_STACK_SIZE);
{
int64_t interval = 512 * (1 << 10);
int64_t access_len = 1 << 10;
for (int64_t j = 0; j < DEFAULT_STACK_SIZE; j+= interval) {
memset((char *)buf + j, 'a', std::min(access_len, DEFAULT_STACK_SIZE - j + 1));
}
}
if (nullptr == buf) {
cout << i << endl;
break;
} else {
DEALLOC(buf);
}
}
auto end_ts = ObTimeUtility::current_time();
cout << "alloc bench: " << CNT * 1000 / (end_ts - begin_ts) << "Kps" << endl;
}
#if 0
TEST(TestCPSA, ACCESS_GUARD)
{
CPSA ca;
void *buf = ca.alloc(DEFAULT_STACK_SIZE);
ASSERT_NE(nullptr, buf);
char *p = (char *) buf;
cout << p[0] << endl;
cout << p[-PAGE_SIZE - 1] << endl;
cout << p[-1] << endl;
}
#endif
int main(int argc, char *argv[])
{
OB_LOGGER.set_log_level(3);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -19,12 +19,10 @@ using namespace oceanbase::common;
TEST(DISABLED_TestSimpleThreadPool, Basic)
{
class : public ObSimpleThreadPool {
void handle(void* task)
{
void handle(void *task) {
UNUSED(task);
ATOMIC_INC(&handle_cnt_);
}
public:
int handle_cnt_ = 0;
} pool;
@ -37,11 +35,11 @@ TEST(DISABLED_TestSimpleThreadPool, Basic)
// When routine without coro push items into this pool, there may be
// at most 100ms(default timeout) before a item to be processing.
//
// Update: co_futex has fixed problem of thread waking up co-routine
// Update: ob_futex has fixed problem of thread waking up co-routine
TIME_LESS(10000, [&pool] {
pool.handle_cnt_ = 0;
ASSERT_EQ(OB_SUCCESS, pool.init(1, 10));
this_routine::usleep(1000); // wait for handler waiting for queue
::usleep(1000); // wait for handler waiting for queue
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
@ -49,7 +47,7 @@ TEST(DISABLED_TestSimpleThreadPool, Basic)
if (pool.handle_cnt_ == 3) {
break;
}
this_routine::usleep(1000);
::usleep(1000);
}
ASSERT_EQ(3, pool.handle_cnt_);
});
@ -58,29 +56,27 @@ TEST(DISABLED_TestSimpleThreadPool, Basic)
// When routine with coro push items into this pool, it would be
// processed ASAP.
TIME_LESS(10000, [&pool] {
cotesting::FlexPool(
[&pool] {
pool.handle_cnt_ = 0;
ASSERT_EQ(OB_SUCCESS, pool.init(1, 10));
this_routine::usleep(1000); // wait for handler waiting for queue
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
for (int i = 0; i < 1000; i++) {
if (pool.handle_cnt_ == 3) {
break;
}
this_routine::usleep(1000);
}
ASSERT_EQ(3, pool.handle_cnt_);
},
1)
.start();
cotesting::FlexPool([&pool] {
pool.handle_cnt_ = 0;
ASSERT_EQ(OB_SUCCESS, pool.init(1, 10));
::usleep(1000); // wait for handler waiting for queue
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
ASSERT_EQ(OB_SUCCESS, pool.push((void*)1));
for (int i = 0; i < 1000; i++) {
if (pool.handle_cnt_ == 3) {
break;
}
::usleep(1000);
}
ASSERT_EQ(3, pool.handle_cnt_);
}, 1).start();
});
pool.destroy();
}
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

View File

@ -17,16 +17,16 @@ using namespace oceanbase;
using namespace oceanbase::common;
using namespace oceanbase::lib;
class TestTimerTask : public ObTimerTask {
class TestTimerTask : public ObTimerTask
{
public:
TestTimerTask() : running_(false), task_run_count_(0)
{}
TestTimerTask() : running_(false), task_run_count_(0) {}
void runTimerTask()
{
running_ = true;
++task_run_count_;
this_routine::usleep(50000);
::usleep(50000);
running_ = false;
}
@ -41,38 +41,39 @@ TEST(TG, timer)
// start
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_SCHEDULE(tg_id, task, 0, true));
this_routine::usleep(40000);
::usleep(40000);
ASSERT_TRUE(task.running_);
this_routine::usleep(60000);
::usleep(60000);
ASSERT_EQ(1, task.task_run_count_);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
// restart
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_SCHEDULE(tg_id, task, 0, true));
this_routine::usleep(40000);
::usleep(40000);
ASSERT_TRUE(task.running_);
this_routine::usleep(60000);
::usleep(60000);
ASSERT_EQ(2, task.task_run_count_);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_TRUE(TG_EXIST(tg_id));
TG_DESTROY(tg_id);
ASSERT_FALSE(TG_EXIST(tg_id));
}
class Handler : public TGTaskHandler {
class Handler : public TGTaskHandler
{
public:
void handle(void* task) override
void handle(void *task) override
{
UNUSED(task);
++handle_count_;
this_routine::usleep(50000);
::usleep(50000);
}
int64_t handle_count_ = 0;
int64_t handle_count_=0;
};
TEST(TG, queue_thread)
@ -83,18 +84,18 @@ TEST(TG, queue_thread)
ASSERT_EQ(OB_SUCCESS, TG_SET_HANDLER(tg_id, handler));
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_PUSH_TASK(tg_id, &tg_id));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(1, handler.handle_count_);
// restart
ASSERT_EQ(OB_SUCCESS, TG_SET_HANDLER(tg_id, handler));
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_PUSH_TASK(tg_id, &tg_id));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(2, handler.handle_count_);
ASSERT_TRUE(TG_EXIST(tg_id));
@ -102,31 +103,22 @@ TEST(TG, queue_thread)
ASSERT_FALSE(TG_EXIST(tg_id));
}
class MyDTask : public common::IObDedupTask {
class MyDTask: public common::IObDedupTask
{
public:
MyDTask() : common::IObDedupTask(common::T_BLOOMFILTER)
{}
virtual int64_t hash() const
{
return reinterpret_cast<int64_t>(this);
}
virtual bool operator==(const IObDedupTask& task) const
{
return this == &task;
}
MyDTask() : common::IObDedupTask(common::T_BLOOMFILTER) {}
virtual int64_t hash() const { return reinterpret_cast<int64_t>(this); }
virtual bool operator ==(const IObDedupTask &task) const { return this == &task; }
virtual int64_t get_deep_copy_size() const
{
return sizeof(*this);
}
virtual IObDedupTask* deep_copy(char* buffer, const int64_t buf_size) const
virtual IObDedupTask *deep_copy(char *buffer, const int64_t buf_size) const
{
UNUSED(buf_size);
return new (buffer) MyDTask;
}
virtual int64_t get_abs_expired_time() const
{
return 0;
}
virtual int64_t get_abs_expired_time() const { return 0; }
virtual int process()
{
handle_count_++;
@ -144,17 +136,17 @@ TEST(TG, dedup_queue)
// start
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_PUSH_TASK(tg_id, task));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(1, task.handle_count_);
// restart
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_PUSH_TASK(tg_id, task));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(2, task.handle_count_);
ASSERT_TRUE(TG_EXIST(tg_id));
@ -162,16 +154,18 @@ TEST(TG, dedup_queue)
ASSERT_FALSE(TG_EXIST(tg_id));
}
class MyRunnable : public TGRunnable {
class MyRunnable : public TGRunnable
{
public:
void run1() override
{
run_count_++;
while (!has_set_stop()) {
this_routine::usleep(50000);
::usleep(50000);
}
}
int64_t run_count_ = 0;
int64_t run_count_=0;
};
TEST(TG, thread_pool)
@ -181,17 +175,17 @@ TEST(TG, thread_pool)
// start
ASSERT_EQ(OB_SUCCESS, TG_SET_RUNNABLE(tg_id, runnable));
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(1, runnable.run_count_);
// restart
ASSERT_EQ(OB_SUCCESS, TG_SET_RUNNABLE(tg_id, runnable));
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(2, runnable.run_count_);
ASSERT_TRUE(TG_EXIST(tg_id));
@ -199,21 +193,51 @@ TEST(TG, thread_pool)
ASSERT_FALSE(TG_EXIST(tg_id));
}
class MyTask : public share::ObAsyncTask {
TEST(TG, reentrant_thread_pool)
{
int tg_id = TGDefIDs::TEST7;
MyRunnable runnable;
// start
ASSERT_EQ(OB_SUCCESS, TG_SET_RUNNABLE(tg_id, runnable));
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_REENTRANT_LOGICAL_START(tg_id));
::usleep(50000);
TG_REENTRANT_LOGICAL_STOP(tg_id);
::usleep(50000);
TG_REENTRANT_LOGICAL_WAIT(tg_id);
ASSERT_EQ(1, runnable.run_count_);
ASSERT_EQ(OB_SUCCESS, TG_REENTRANT_LOGICAL_START(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(2, runnable.run_count_);
// restart
ASSERT_EQ(OB_SUCCESS, TG_SET_RUNNABLE(tg_id, runnable));
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(2, runnable.run_count_);
ASSERT_TRUE(TG_EXIST(tg_id));
TG_DESTROY(tg_id);
ASSERT_FALSE(TG_EXIST(tg_id));
}
class MyTask : public share::ObAsyncTask
{
public:
virtual int process() override
{
handle_count_++;
this_routine::usleep(50000);
::usleep(50000);
return OB_SUCCESS;
}
virtual int64_t get_deep_copy_size() const override
{
return sizeof(*this);
}
{ return sizeof(*this); }
virtual ObAsyncTask* deep_copy(char* buf, const int64_t buf_size) const override
virtual ObAsyncTask *deep_copy(char *buf, const int64_t buf_size) const override
{
UNUSED(buf_size);
return new (buf) MyTask();
@ -229,17 +253,17 @@ TEST(TG, async_task_queue)
// start
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_PUSH_TASK(tg_id, task));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(1, task.handle_count_);
// restart
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_PUSH_TASK(tg_id, task));
this_routine::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
::usleep(50000);
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_EQ(2, task.handle_count_);
ASSERT_TRUE(TG_EXIST(tg_id));
@ -256,39 +280,38 @@ TEST(TG, timer_group)
for (int i = 0; i < ARRAYSIZEOF(tasks); i++) {
ASSERT_EQ(OB_SUCCESS, TG_SCHEDULE(tg_id, i, tasks[i], 0, true));
}
this_routine::usleep(40000);
::usleep(40000);
for (int i = 0; i < ARRAYSIZEOF(tasks); i++) {
ASSERT_TRUE(tasks[i].running_);
}
this_routine::usleep(60000);
::usleep(60000);
for (int i = 0; i < ARRAYSIZEOF(tasks); i++) {
ASSERT_EQ(1, tasks[i].task_run_count_);
}
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
// restart
ASSERT_EQ(OB_SUCCESS, TG_START(tg_id));
for (int i = 0; i < ARRAYSIZEOF(tasks); i++) {
ASSERT_EQ(OB_SUCCESS, TG_SCHEDULE(tg_id, i, tasks[i], 0, true));
}
this_routine::usleep(40000);
::usleep(40000);
for (int i = 0; i < ARRAYSIZEOF(tasks); i++) {
ASSERT_TRUE(tasks[i].running_);
}
this_routine::usleep(60000);
::usleep(60000);
for (int i = 0; i < ARRAYSIZEOF(tasks); i++) {
ASSERT_EQ(2, tasks[i].task_run_count_);
}
ASSERT_EQ(OB_SUCCESS, TG_STOP(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_STOP_R(tg_id));
ASSERT_EQ(OB_SUCCESS, TG_WAIT_R(tg_id));
ASSERT_TRUE(TG_EXIST(tg_id));
TG_DESTROY(tg_id);
ASSERT_FALSE(TG_EXIST(tg_id));
}
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
OB_LOGGER.set_log_level("INFO");

View File

@ -14,27 +14,28 @@
#include <gtest/gtest.h>
using namespace oceanbase::common;
class TestObThreadLease : public ::testing::Test {
class TestObThreadLease: public ::testing::Test
{
public:
TestObThreadLease()
{}
virtual ~TestObThreadLease()
{}
TestObThreadLease() {}
virtual ~TestObThreadLease(){}
virtual void SetUp()
{}
{
}
virtual void TearDown()
{}
{
}
static void SetUpTestCase()
{}
{
}
static void TearDownTestCase()
{}
{
}
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(TestObThreadLease);
protected:
// function members
protected:
@ -50,7 +51,7 @@ TEST_F(TestObThreadLease, smoke_test)
ASSERT_EQ(true, lease.revoke());
ASSERT_EQ(ObThreadLease::IDLE, lease.value());
// Revoke directly, expect to return success
// 直接revoke,期望返回成功
ASSERT_EQ(true, lease.revoke());
ASSERT_EQ(ObThreadLease::IDLE, lease.value());
}
@ -64,42 +65,43 @@ TEST_F(TestObThreadLease, simulate_multi_thread)
ASSERT_EQ(true, lease.acquire());
ASSERT_EQ(ObThreadLease::HANDLING, lease.value());
// Acquire again, expect to return failed, status change to READY
// 再次acquire,期望失败,状态变更为READY
ASSERT_EQ(false, lease.acquire());
ASSERT_EQ(ObThreadLease::READY, lease.value());
// Acquire again, expect to return failed, status change to READY
// 再次acquire,期望失败,状态变更为READY
ASSERT_EQ(false, lease.acquire());
ASSERT_EQ(ObThreadLease::READY, lease.value());
// Acquire again, expect to return failed, status change to READY
// 再次acquire,期望失败,状态变更为READY
ASSERT_EQ(false, lease.acquire());
ASSERT_EQ(ObThreadLease::READY, lease.value());
// Revoke once, expect to return failed, status change to HANDLING
// revoke一次,期望失败,状态变更为HANDLING
ASSERT_EQ(false, lease.revoke());
ASSERT_EQ(ObThreadLease::HANDLING, lease.value());
// Acquire again, expect to return failed, status change to READY
// 再次acquire,期望失败,状态变更为READY
ASSERT_EQ(false, lease.acquire());
ASSERT_EQ(ObThreadLease::READY, lease.value());
// Acquire again, expect to return failed, status change to READY
// 再次acquire,期望失败,状态变更为READY
ASSERT_EQ(false, lease.acquire());
ASSERT_EQ(ObThreadLease::READY, lease.value());
// Revoke once, expect to return failed, status change to HANDLING
// revoke一次,期望失败,状态变更为HANDLING
ASSERT_EQ(false, lease.revoke());
ASSERT_EQ(ObThreadLease::HANDLING, lease.value());
// Revoke again, expect to return success, status change to IDLE
// 再次revoke,期望成功,状态变更为IDLE
ASSERT_EQ(true, lease.revoke());
ASSERT_EQ(ObThreadLease::IDLE, lease.value());
}
}
int main(int argc, char** argv)
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}

View File

@ -13,20 +13,22 @@
#include <gtest/gtest.h>
#include <iostream>
#include "lib/thread/thread_pool.h"
#include "lib/time/ob_time_utility.h"
#include "../coro/testing.h"
using namespace oceanbase::lib;
using namespace oceanbase::common;
using namespace std;
TEST(TestThreadPool, Submit1)
TEST(TestThreadPool, DISABLED_Submit1)
{
// construct thread pool.
class : public ThreadPool {
class : public ThreadPool
{
void run1() override
{
while (!has_set_stop()) {
this_routine::usleep(100L * 1000L);
::usleep(100L * 1000L);
}
}
} tp;
@ -38,7 +40,7 @@ TEST(TestThreadPool, Submit1)
int ret = OB_SUCCESS;
ret = tp.submit([] {
cout << "ok2" << endl;
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
});
EXPECT_EQ(OB_SUCCESS, ret);
@ -49,15 +51,15 @@ TEST(TestThreadPool, Submit1)
// after 2s, previous task would be finished so that new task should
// be accepted.
this_routine::usleep(2 * 1000L * 1000L);
::usleep(2 * 1000L * 1000L);
ret = tp.submit([] { cout << "ok4" << endl; });
EXPECT_EQ(OB_SUCCESS, ret);
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
ret = tp.submit([] { cout << "ok5" << endl; });
EXPECT_EQ(OB_SUCCESS, ret);
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
ret = tp.submit([] { cout << "ok6" << endl; });
EXPECT_EQ(OB_SUCCESS, ret);
@ -69,11 +71,12 @@ TEST(TestThreadPool, Submit1)
TEST(TestThreadPool, DISABLED_SubmitX)
{
// construct thread pool.
class : public ThreadPool {
class : public ThreadPool
{
void run1() override
{
while (!has_set_stop()) {
this_routine::usleep(100L * 1000L);
::usleep(100L * 1000L);
}
}
} tp;
@ -81,24 +84,28 @@ TEST(TestThreadPool, DISABLED_SubmitX)
tp.set_thread_max_tasks(1);
tp.start();
TIME_LESS(100 * 1000L, [&tp] {
this_routine::usleep(10L * 1000L);
cout << co_current_time() << endl;
tp.submit([] { cout << co_current_time() << endl; });
TIME_LESS(100*1000L, [&tp] {
::usleep(10L * 1000L);
cout << ObTimeUtility::current_time() << endl;
tp.submit([] {
cout << ObTimeUtility::current_time() << endl;
});
});
tp.stop();
tp.wait();
tp.destroy();
}
TEST(TestThreadPool, Submit2)
TEST(TestThreadPool, DISABLED_Submit2)
{
// construct thread pool.
class : public ThreadPool {
class : public ThreadPool
{
void run1() override
{
this_routine::usleep(3 * 1000L * 1000L);
::usleep(3 * 1000L * 1000L);
}
} tp;
tp.init();
@ -109,12 +116,12 @@ TEST(TestThreadPool, Submit2)
int ret = OB_SUCCESS;
ret = tp.submit([] {
cout << "ok2" << endl;
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
});
EXPECT_EQ(OB_SUCCESS, ret);
ret = tp.submit([] {
cout << "ok2" << endl;
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
});
EXPECT_EQ(OB_SUCCESS, ret);
@ -125,7 +132,7 @@ TEST(TestThreadPool, Submit2)
// after 2s, previous task would be finished so that new task should
// be accepted.
this_routine::usleep(2 * 1000L * 1000L);
::usleep(2 * 1000L * 1000L);
ret = tp.submit([] { cout << "ok4" << endl; });
EXPECT_EQ(OB_SUCCESS, ret);
@ -134,13 +141,14 @@ TEST(TestThreadPool, Submit2)
tp.destroy();
}
TEST(TestThreadPool, SubmitN)
TEST(TestThreadPool, DISABLED_SubmitN)
{
// construct thread pool.
class : public ThreadPool {
class : public ThreadPool
{
void run1() override
{
this_routine::usleep(3 * 1000L * 1000L);
::usleep(3 * 1000L * 1000L);
}
} tp;
tp.init();
@ -153,40 +161,41 @@ TEST(TestThreadPool, SubmitN)
for (i = 0; i < 100; i++) {
ret = tp.submit([] {
cout << "ok2" << endl;
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
});
if (OB_FAIL(ret)) {
break;
}
}
EXPECT_EQ(8, i); // 2 * 4
EXPECT_EQ(8, i); // 2 * 4
// wait 2s for previous tasks finishing.
this_routine::usleep(2 * 1000L * 1000L);
::usleep(2 * 1000L * 1000L);
tp.set_thread_count(5);
for (i = 0; i < 100; i++) {
ret = tp.submit([] {
cout << "ok2" << endl;
this_routine::usleep(1 * 1000L * 1000L);
::usleep(1 * 1000L * 1000L);
});
if (OB_FAIL(ret)) {
break;
}
}
EXPECT_EQ(10, i); // 2 * 5
EXPECT_EQ(10, i); // 2 * 5
// tp.stop();
tp.wait();
tp.destroy();
}
TEST(TestThreadPool, LoopCheckConcurrency)
TEST(TestThreadPool, DISABLED_LoopCheckConcurrency)
{
class : public ThreadPool {
class : public ThreadPool
{
void run1() override
{
while (!has_set_stop()) {
this_routine::usleep(3 * 1000L * 1000L);
::usleep(3 * 1000L * 1000L);
}
}
} tp;
@ -202,7 +211,7 @@ TEST(TestThreadPool, LoopCheckConcurrency)
ASSERT_EQ(OB_SUCCESS, tp.submit([&n] { ATOMIC_INC(&n); }));
ASSERT_EQ(OB_SUCCESS, tp.submit([&n] { ATOMIC_INC(&n); }));
while (ATOMIC_LOAD(&n) != 3) {
this_routine::usleep(1 * 1000L);
::usleep(1*1000L);
}
cout << "loop: " << i << endl;
}
@ -212,7 +221,7 @@ TEST(TestThreadPool, LoopCheckConcurrency)
tp.destroy();
}
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

View File

@ -19,7 +19,8 @@ using namespace std;
TEST(TestThreadPool, Submit)
{
class : public ThreadPool {
class : public ThreadPool
{
void run1() override()
{
cout << "ok" << endl;
@ -29,7 +30,7 @@ TEST(TestThreadPool, Submit)
tp.start();
}
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

View File

@ -0,0 +1,104 @@
/**
* 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 <gtest/gtest.h>
#include "atomic"
#include "lib/thread/threads.h"
using namespace oceanbase::lib;
TEST(TestThreads, CanRun)
{
int val = 0;
val = 0;
class Thread: public Threads {
public:
Thread(int &val) : val_(val) {}
virtual void run(int64_t idx) override
{
val_++;
}
int &val_;
} th(val);
th.start();
th.wait();
ASSERT_EQ(1, val);
}
TEST(TestThreads, CanRunMulti)
{
static std::atomic<int64_t> val;
class Thread: public Threads
{
public:
Thread(std::atomic<int64_t>&val) : val_(val) {}
void run(int64_t idx) final
{
val += idx;
while (!ATOMIC_LOAD(&has_set_stop()))
;
}
std::atomic<int64_t> &val_;
} th(val);
val = 0;
th.set_thread_count(7);
th.start();
th.stop();
th.wait();
ASSERT_EQ(21, val); // 0+1+2+3+4+5+6
}
TEST(TestThreads, DynamicThread)
{
static std::atomic<int64_t> starts;
static std::atomic<int64_t> exits;
class: public Threads
{
std::atomic<int64_t> n_threads_;
public:
int set_thread_count(int64_t n_threads)
{
n_threads_ = n_threads;
return Threads::set_thread_count(n_threads);
}
void run(int64_t idx) final
{
starts++;
while (idx < n_threads_ && !has_set_stop())
;
exits++;
}
} th;
th.set_thread_count(1);
th.start();
while (starts != 1) { ::usleep(10); }
th.set_thread_count(2);
while (starts != 2) { ::usleep(10); }
th.set_thread_count(4);
while (starts != 4) { ::usleep(10); }
th.set_thread_count(1);
while (exits != 3) { ::usleep(10); }
th.submit([]{});
//ASSERT_EQ(1, th.get_cur_tasks());
th.stop();
th.wait();
ASSERT_EQ(4, starts);
ASSERT_EQ(4, exits);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}