oceanbase/unittest/share/deadlock/test_deadlock.cpp

498 lines
25 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 UNITTEST_DEBUG
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#define private public
#define protected public
#include "observer/ob_srv_network_frame.h"
#include "lib/net/ob_addr.h"
#include "share/deadlock/ob_deadlock_detector_mgr.h"
#include "share/deadlock/ob_lcl_scheme/ob_lcl_parameters.h"
#include "share/deadlock/ob_lcl_scheme/ob_lcl_node.h"
#include "share/deadlock/ob_lcl_scheme/ob_lcl_message.h"
#include "lib/function/ob_function.h"
#include "common/ob_clock_generator.h"
#include "share/deadlock/test/test_key.h"
#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#include <algorithm>
#include <cstdlib>
#include <numeric>
#include "storage/tx/ob_trans_define.h"
#include "share/deadlock/ob_deadlock_detector_rpc.h"
#include "share/deadlock/mock_deadlock_rpc.h"
#include "storage/memtable/ob_memtable_context.h"
using namespace oceanbase::obrpc;
using namespace std;
namespace oceanbase {
namespace unittest {
using namespace common;
using namespace share::detector;
using namespace share;
using namespace std;
static ObDetectorUserReportInfo user_report_info;
// 用户自定义的operation操作
class TestOperation {
public:
TestOperation(uint64_t hash) : hash_(hash) {
ATOMIC_AAF(&alive_count, 1);
ObSharedGuard<char> ptr;
ptr.assign((char*)"test", [](char*){});
user_report_info.set_module_name(ptr);
ptr.assign((char*)"a", [](char*){});
user_report_info.set_visitor(ptr);
ptr.assign((char*)"b", [](char*){});
user_report_info.set_resource(ptr);
}
TestOperation(const TestOperation &rhs) : hash_(rhs.hash_), key_(rhs.key_) {
ATOMIC_AAF(&alive_count, 1);
ObSharedGuard<char> ptr;
ptr.assign((char*)"test", [](char*){});
user_report_info.set_module_name(ptr);
ptr.assign((char*)"a", [](char*){});
user_report_info.set_visitor(ptr);
ptr.assign((char*)"b", [](char*){});
user_report_info.set_resource(ptr);
}
TestOperation(const ObDeadLockTestIntKey &key) :
key_(key.get_value()) {
ATOMIC_AAF(&alive_count, 1);
ObSharedGuard<char> ptr;
ptr.assign((char*)"test", [](char*){});
user_report_info.set_module_name(ptr);
ptr.assign((char*)"a", [](char*){});
user_report_info.set_visitor(ptr);
ptr.assign((char*)"a", [](char*){});
user_report_info.set_resource(ptr);
}
~TestOperation() { ATOMIC_AAF(&alive_count, -1); }
TO_STRING_KV(K(key_));
uint64_t hash_;
public:
int operator()(const common::ObIArray<ObDetectorInnerReportInfo> &collected_info, const int64_t self_index) {
UNUSED(collected_info);
int64_t interval = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - loop_occurd_time).count();
DETECT_LOG(INFO, "detect delay time", K(interval));
v_record.push_back(interval);
ObDetectorPriority lowest_priority(PRIORITY_RANGE::EXTREMELY_HIGH, UINT64_MAX);
int64_t lowest_priority_idx = -1;
for (int64_t i = 0; i < collected_info.count(); ++i) {
if (collected_info.at(i).get_priority() < lowest_priority) {
lowest_priority_idx = i;
lowest_priority = collected_info.at(i).get_priority();
}
}
v_record_is_lowest_priority.push_back(self_index == lowest_priority_idx);
v_killed_node.push_back(key_.get_value());
if (key_.get_value() != -1) {
MTL(ObDeadLockDetectorMgr*)->unregister_key(key_);
}
std::cout << "my hash is:" << hash_ << std::endl;
return OB_SUCCESS;
}
ObDeadLockTestIntKey key_;
static vector<int64_t> v_record;
static vector<bool> v_record_is_lowest_priority;
static int64_t alive_count;
static vector<int> v_killed_node;
static decltype(chrono::high_resolution_clock::now()) loop_occurd_time;
};
// 真实使用过程中注册和搭建依赖关系的时间点是随机的,通过随机休眠模拟使用场景
auto collect_callback = [](ObDetectorUserReportInfo& arg){ return arg.assign(user_report_info); };
#define JUDGE_RECORDER(v1,v2,v3,v4,v5,v6,v7,v8)\
ASSERT_EQ(recorder.function_default_construct_time, v1);\
ASSERT_EQ(recorder.function_copy_construct_time, v2);\
ASSERT_EQ(recorder.function_move_construct_time, v3);\
ASSERT_EQ(recorder.function_general_construct_time, v4);\
ASSERT_EQ(recorder.function_copy_assign_time, v5);\
ASSERT_EQ(recorder.function_move_assign_time, v6);\
ASSERT_EQ(recorder.function_general_assign_time, v7);\
ASSERT_EQ(recorder.derived_construct_time, v8);\
recorder.reset();
function::DebugRecorder &recorder = function::DebugRecorder::get_instance();
ObDeadLockDetectorMgr *mgr;
class TestObDeadLockDetector : public ::testing::Test {
public:
TestObDeadLockDetector() :
case_num_(0), ctx(1) {}
~TestObDeadLockDetector() {}
virtual void SetUp() {
share::ObTenantEnv::get_tenant_local()->id_ = 1;
auto &gctx = GCTX;
gctx.net_frame_ = new observer::ObSrvNetworkFrame(gctx);
gctx.net_frame_->rpc_transport_ = reinterpret_cast<rpc::frame::ObReqTransport*>(0x123456);
gctx.self_addr_seq_.server_addr_ = ObAddr(ObAddr::VER::IPV4, "127.0.0.1", 1234);
mgr = new ObDeadLockDetectorMgr();
DETECT_LOG(INFO, "print mgr", KP(mgr), KP(&mgr->inner_alloc_handle_.inner_factory_.release_count_));
ctx.set(mgr);
ObTenantEnv::set_tenant(&ctx);
mgr->init();
static int case_num = 0;
++case_num;
cout << "\n<<<<<<<<<<<<<<<<<<<<" << "start case" << case_num << ">>>>>>>>>>>>>>>>>>>>" << endl;
// do not use rpc, will core dump
// ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->init());
oceancase::unittest::MockDeadLockRpc *rpc = (oceancase::unittest::MockDeadLockRpc *)ob_malloc(sizeof(oceancase::unittest::MockDeadLockRpc),
ObNewModIds::TEST);
rpc = new (rpc) oceancase::unittest::MockDeadLockRpc();
MTL(ObDeadLockDetectorMgr*)->rpc_ = rpc;
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->start());
ObServerConfig::get_instance()._lcl_op_interval = 10000;
std::this_thread::sleep_for(chrono::seconds(3));
TestOperation::v_killed_node.clear();
}
virtual void TearDown() {
MTL(ObDeadLockDetectorMgr*)->stop();
MTL(ObDeadLockDetectorMgr*)->wait();
MTL(ObDeadLockDetectorMgr*)->proxy_ = nullptr;
MTL(ObDeadLockDetectorMgr*)->rpc_ = nullptr;
MTL(ObDeadLockDetectorMgr*)->destroy();
DETECT_LOG(INFO, "print mgr", KP(mgr), KP(&mgr->inner_alloc_handle_.inner_factory_.release_count_));
int64_t release_count_from_mtl = MTL(ObDeadLockDetectorMgr*)->get_detector_release_count();
int64_t release_count_from_obj = mgr->get_detector_release_count();
DETECT_LOG(INFO, "print count", K(release_count_from_mtl), K(release_count_from_obj));
ASSERT_EQ(MTL(ObDeadLockDetectorMgr*)->get_detector_create_count(), MTL(ObDeadLockDetectorMgr*)->get_detector_release_count());
ASSERT_EQ(0, TestOperation::alive_count);// 预期用户创建的operation对象销毁
delete MTL(ObDeadLockDetectorMgr*);
}
template <typename T>
ObIDeadLockDetector *get_detector_ptr(const T &key) {
ObDeadLockDetectorMgr::DetectorRefGuard guard;
UserBinaryKey binary_key;
binary_key.set_user_key(key);
MTL(ObDeadLockDetectorMgr*)->get_detector_(binary_key, guard);
return guard.get_detector();
}
private:
int case_num_ = 0;
share::ObTenantBase ctx;
};
vector<int64_t> TestOperation::v_record;
vector<bool> TestOperation::v_record_is_lowest_priority;
int64_t TestOperation::alive_count = 0;
vector<int> TestOperation::v_killed_node;
decltype(chrono::high_resolution_clock::now()) TestOperation::loop_occurd_time = chrono::high_resolution_clock::now();
TEST_F(TestObDeadLockDetector, test_ObDetectorUserReportInfo) {
char a[5] = {'1', '2', '3', '4', '\0'};
{
ObDetectorUserReportInfo info;
int ret = OB_SUCCESS;
char *buffer = nullptr;
if (OB_UNLIKELY(nullptr == (buffer = (char*)ob_malloc(128, "deadlockCB")))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
} else {
transaction::ObTransID self_trans_id;
ObSharedGuard<char> temp_uniqe_guard;
int step = 0;
(void) self_trans_id.to_string(buffer, 128);
char *node_key_buffer = a;
if (++step && OB_FAIL(temp_uniqe_guard.assign((char*)"transaction", [](char*){}))) {
} else if (++step && OB_FAIL(info.set_module_name(temp_uniqe_guard))) {
} else if (++step && OB_FAIL(temp_uniqe_guard.assign(buffer, [](char* buffer){ ob_free(buffer); DETECT_LOG(INFO, "visitor str destory", K(lbt()));}))) {
} else if (++step && OB_FAIL(info.set_visitor(temp_uniqe_guard))) {
} else if (++step && OB_FAIL(temp_uniqe_guard.assign(node_key_buffer, [](char*ptr){ ptr[0] = '2'; DETECT_LOG(INFO, "resource str destory", K(lbt())); }))) {
} else if (++step && OB_FAIL(info.set_resource(temp_uniqe_guard))) {
} else if (++step && OB_FAIL(info.set_extra_info("current sql", "1"))) {
} else {}
if (OB_FAIL(ret)) {
DETECT_LOG(WARN, "get string failed in deadlock", KR(ret), K(step));
}
}
ASSERT_EQ(info.get_extra_columns_names().size(), 1);
ASSERT_EQ(info.get_extra_columns_values().size(), 1);
DETECT_LOG(INFO, "print info", K(info));
}
ASSERT_EQ(a[0], '2');
}
// 正常的注册key和注销key的流程
// 测试重点:
// 1,用户registrer_key后,对应的detector节点会创建,可以拿到对应的resource_id。
// 2,用户ungister_key之后,对应的detector节点预期会被销毁。
// 3,detector节点销毁之后,预期用户创建的operation对象也会被销毁。
TEST_F(TestObDeadLockDetector, register_ungister_key) {
// 由外层来构造自己的operation对象
TestOperation* op = new TestOperation(7710038271457258879UL);
ASSERT_EQ(1, TestOperation::alive_count);// 用户创建了一个operation对象
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(1), *op, collect_callback, 1));// 注册key
//JUDGE_RECORDER()
auto call_back = get_detector_ptr(ObDeadLockTestIntKey(1));
ASSERT_EQ(1, MTL(ObDeadLockDetectorMgr*)->get_detector_create_count());// 预期同步创建出了一个detector对象
ObIDeadLockDetector *ptr = get_detector_ptr(ObDeadLockTestIntKey(1));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->unregister_key(ObDeadLockTestIntKey(1)));// 注销key
delete op;
}
// 异常注册和注销key时的处理
// 测试重点:
// 1,
// 2,同一类型的重复的key的注册应当失败。
// 3,一个key在注册并且注销后,应当可以重新注册
// 4,一个key在未注册的情况下,注销操作应当失败
// 5,一个已经注册的key在已经注销的情况下,二次注销应当失败
// 6, 在ObDeadLockDetectorMgr销毁的时候,还存在detector没有销毁,预期Mgr销毁后,所有创建的detector都销毁
TEST_F(TestObDeadLockDetector, register_ungister_in_wrong_way) {
// do not use rpc, will core dump
TestOperation *op = new TestOperation(7710038271457258879UL);
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(12), *op, collect_callback, 1));
//auto &call_back = ((ObLCLNode*)(get_detector_ptr(ObDeadLockTestIntKey(12))))->get_detect_callback_();
//TestOperation &op_cp = static_cast<ObFunction<int(const common::ObIArray<ObDetectorInnerReportInfo> &, const int64_t)>::Derived<TestOperation>*>(call_back.get_func_ptr())->func_;
DETECT_LOG(INFO, "1");
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(12), *op, collect_callback, 1));// 2,同一类型的重复的key的注册应当失败
DETECT_LOG(INFO, "2");
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->unregister_key(ObDeadLockTestIntKey(12)));
DETECT_LOG(INFO, "3");
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(12), *op, collect_callback, 1));// 3,一个key在注册并且注销后,应当可以重新注册
DETECT_LOG(INFO, "4");
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->unregister_key(ObDeadLockTestIntKey(13)));// 4,一个key在未注册的情况下,注销操作应当失败
DETECT_LOG(INFO, "5");
cout << MTL(ObDeadLockDetectorMgr*)->get_detector_create_count() << " " << MTL(ObDeadLockDetectorMgr*)->get_detector_release_count();
std::this_thread::sleep_for(chrono::milliseconds(100));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->unregister_key(ObDeadLockTestIntKey(12)));
DETECT_LOG(INFO, "6");
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->unregister_key(ObDeadLockTestIntKey(12)));// 5,一个已经注册的key在已经注销的情况下,二次注销应当失败
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(12), *op, collect_callback, 1));// 6, 在ObDeadLockDetectorMgr销毁的时候,还存在detector没有销毁,预期Mgr销毁后,所有创建的detector都销毁
std::this_thread::sleep_for(chrono::microseconds(PERIOD * 2));
delete op;
}
// block和activate的流程
// 测试重点:
// 1,block某个已经存在的key可以成功
// 2,block一个已经block过的key返回失败
// 3,可以block多个不同的已经存在的key
// 4,block某个不存在的key返回失败
// 5,activate某个block过的key可以成功
// 6,重复activate一个key返回失败
// 7,activate一个从未注册过的key返回失败
// 8,activate一个不在block列表里但是已经注册过的key返回失败
TEST_F(TestObDeadLockDetector, block_and_activate) {
TestOperation *op = new TestOperation(7710038271457258879UL);
// 注册第一个key
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(1), *op, collect_callback, 1));
// 注册第二个key
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(2), *op, collect_callback, 1));
// 注册第三个key
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestDoubleKey(3.0), *op, collect_callback, 1));
// 注册第四个key
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestDoubleKey(4.0), *op, collect_callback, 1));
// 为两个key搭建依赖关系
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(1), ObDeadLockTestIntKey(2)));// 1,block某个已经存在的key可以成功
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(1), ObDeadLockTestIntKey(2)));// 2,block一个已经block过的key返回失败
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(1), ObDeadLockTestDoubleKey(3.0)));// 3,可以block多个不同的已经存在的key
// ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(1), ObDeadLockTestDoubleKey(5.0)));// 4,block某个不存在的key返回失败
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->activate(ObDeadLockTestIntKey(1), ObDeadLockTestIntKey(2)));// 5,activate某个block过的key可以成功
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->activate(ObDeadLockTestIntKey(1), ObDeadLockTestIntKey(2)));// 6,重复activate一个key返回失败
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->activate(ObDeadLockTestIntKey(1), ObDeadLockTestDoubleKey(5.0)));// 7,activate一个从未注册过的key返回失败
ASSERT_NE(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->activate(ObDeadLockTestIntKey(1), ObDeadLockTestDoubleKey(4.0)));// 8,activate一个不在block列表里但是已经注册过的key返回失败
delete op;
}
// 测试死锁的探测功能
// 测试重点:
// 1,未形成死锁时不会探测到死锁
// 2,形成死锁后在一定时间内可以探测到死锁,探测时间不超过(节点数+1)*Transmit间隔
TEST_F(TestObDeadLockDetector, dead_lock) {
int loop_times = 5;
std::srand(std::time(nullptr));
for (int i = 0; i < loop_times; ++i) {// 进行多次测试,看探测时延的最大、最小、平均值
int index = i * 5;
std::this_thread::sleep_for(chrono::milliseconds(std::rand() % 300));
// 注册第一个key
// TestOperation *op1 = new TestOperation(ObDeadLockTestIntKey(index + 1));
// ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(index + 1), *op1, collect_callback, 1, std::rand() % 100));
// 注册第二个key
TestOperation *op2 = new TestOperation(ObDeadLockTestIntKey(index + 2));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(index + 2), *op2, collect_callback, 1, std::rand() % 100));
// 注册第三个key
TestOperation *op3 = new TestOperation(ObDeadLockTestIntKey(index + 3));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(index + 3), *op3, collect_callback, 1, std::rand() % 100));
// 注册第四个key
TestOperation *op4 = new TestOperation(ObDeadLockTestIntKey(index + 4));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(index + 4), *op4, collect_callback, 1, std::rand() % 100));
// 注册第五个key
TestOperation *op5 = new TestOperation(ObDeadLockTestIntKey(index + 5));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(index + 5), *op5, collect_callback, 1, std::rand() % 100));
// 为两个key搭建依赖关系
// ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(index + 1), ObDeadLockTestIntKey(index + 2)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->add_parent(ObDeadLockTestIntKey(index + 2), GCTX.self_addr(), ObDeadLockTestIntKey(index + 1)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(index + 2), ObDeadLockTestIntKey(index + 3)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(index + 3), ObDeadLockTestIntKey(index + 4)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(index + 4), ObDeadLockTestIntKey(index + 5)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(index + 5), ObDeadLockTestIntKey(index + 1)));
TestOperation::loop_occurd_time = chrono::high_resolution_clock::now();
std::this_thread::sleep_for(chrono::microseconds(PERIOD * 2));
//delete op1;
delete op2;
delete op3;
delete op4;
delete op5;
ASSERT_EQ(i + 1, TestOperation::v_killed_node.size());// 一个环中只能有一个节点探测到死锁
}
ASSERT_EQ(loop_times, TestOperation::v_killed_node.size());// 一个环中只能有一个节点探测到死锁
ASSERT_EQ(loop_times, TestOperation::v_record_is_lowest_priority.size());
for (int i = 0; i < TestOperation::v_record_is_lowest_priority.size(); ++i)
ASSERT_EQ(true, TestOperation::v_record_is_lowest_priority[i]);
cout << "max delay:" << *max_element(TestOperation::v_record.begin(), TestOperation::v_record.end()) << "ms" << endl;
cout << "min delay:" << *min_element(TestOperation::v_record.begin(), TestOperation::v_record.end()) << "ms" << endl;
cout << "average delay:" << accumulate(TestOperation::v_record.begin(), TestOperation::v_record.end(), 0) / TestOperation::v_record.size() << "ms" << endl;
}
class DeadLockBlockCallBack {
public:
DeadLockBlockCallBack(uint64_t hash) : hash_(hash) {
TRANS_LOG(INFO, "hash value when created", K(hash), K(hash_));
}
int operator()(ObDependencyResource &resource, bool &need_remove) {
UNUSED(resource);
UNUSED(need_remove);
std::cout<<"hash_:"<<hash_<<std::endl;
int ret = OB_SUCCESS;
return ret;
}
private:
uint64_t hash_;
};
TEST_F(TestObDeadLockDetector, block_call_back) {
DeadLockBlockCallBack deadlock_block_call_back(7710038271457258879UL);
ObFunction<int(ObDependencyResource &,bool &)> func = deadlock_block_call_back;
ObDependencyResource re;
bool n;
func(re, n);
}
TEST_F(TestObDeadLockDetector, test_timeout) {
TestOperation *op2 = new TestOperation(ObDeadLockTestIntKey(1));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(1), *op2, collect_callback, 1, std::rand() % 100));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(2), *op2, collect_callback, 1, std::rand() % 100));
MTL(ObDeadLockDetectorMgr*)->set_timeout(ObDeadLockTestIntKey(1), 1000);
std::this_thread::sleep_for(chrono::seconds(1));
delete op2;
ASSERT_EQ(MTL(ObDeadLockDetectorMgr*)->get_detector_create_count(), MTL(ObDeadLockDetectorMgr*)->get_detector_release_count() + 1);
}
// 1 -> 5 -> 3 -> 4 -> 1
// 1 -> 2 - > 3 -> 4 -> 1
// 2 有全局最小优先级
TEST_F(TestObDeadLockDetector, small_cycle_in_big_cycle_bad_case) {
int loop_times = 5;
// 注册第一个key
TestOperation *op1 = new TestOperation(ObDeadLockTestIntKey(1));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(1), *op1, collect_callback, 9));
// 注册第二个key
TestOperation *op2 = new TestOperation(ObDeadLockTestIntKey(2));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(2), *op2, collect_callback, 0));// should kill this node
// 注册第三个key
TestOperation *op3 = new TestOperation(ObDeadLockTestIntKey(3));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(3), *op3, collect_callback, 9));
// 注册第四个key
TestOperation *op4 = new TestOperation(ObDeadLockTestIntKey(4));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(4), *op4, collect_callback, 9));
// 注册第五个key
TestOperation *op5 = new TestOperation(ObDeadLockTestIntKey(5));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->register_key(ObDeadLockTestIntKey(5), *op5, collect_callback, 1));
// 为两个key搭建依赖关系
// ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(index + 1), ObDeadLockTestIntKey(index + 2)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(1), ObDeadLockTestIntKey(5)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(5), ObDeadLockTestIntKey(3)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(3), ObDeadLockTestIntKey(4)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(4), ObDeadLockTestIntKey(1)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(1), ObDeadLockTestIntKey(2)));
ASSERT_EQ(OB_SUCCESS, MTL(ObDeadLockDetectorMgr*)->block(ObDeadLockTestIntKey(2), ObDeadLockTestIntKey(3)));
TestOperation::loop_occurd_time = chrono::high_resolution_clock::now();
std::this_thread::sleep_for(chrono::microseconds(PERIOD * 4));
delete op1;
delete op2;
delete op3;
delete op4;
delete op5;
for (auto v : TestOperation::v_killed_node) {
DETECT_LOG(INFO, "kill node", K(v));
}
ASSERT_EQ(2, TestOperation::v_killed_node.size());
ASSERT_EQ(true, TestOperation::v_killed_node[0] == 2 || TestOperation::v_killed_node[0] == 5);
ASSERT_EQ(true, TestOperation::v_killed_node[1] == 2 || TestOperation::v_killed_node[1] == 5);
}
// TEST_F(TestObDeadLockDetector, test_lock_conflict_print) {
// memtable::RetryInfo retry_info;
// while ((ObClockGenerator::getClock() % 1000000) < 100_ms);
// DETECT_LOG(INFO, "DEBUG1", K(ObClockGenerator::getClock()));
// ASSERT_EQ(retry_info.need_print(), true);
// retry_info.on_conflict();
// ASSERT_EQ(retry_info.need_print(), false);
// this_thread::sleep_for(std::chrono::milliseconds(100));
// DETECT_LOG(INFO, "DEBUG2", K(ObClockGenerator::getClock()));
// ASSERT_EQ(retry_info.need_print(), false);
// this_thread::sleep_for(std::chrono::milliseconds(1000));
// DETECT_LOG(INFO, "DEBUG", K(retry_info));
// ASSERT_EQ(retry_info.need_print(), true);
// for (int i = 0; i < 9; ++i) {
// retry_info.on_conflict();
// }
// ASSERT_EQ(retry_info.need_print(), true);
// }
// TEST_F(TestObDeadLockDetector, print_timestamp) {
// int64_t ts_ = 1623827288705600;
// DETECT_LOG(INFO, "test ts", KTIME(ts_));
// DETECT_LOG(INFO, "test ts", KTIME_(ts));
// DETECT_LOG(INFO, "test ts", KTIMERANGE(ts_, DAY, MSECOND));
// DETECT_LOG(INFO, "test ts", KTIMERANGE_(ts, DAY, MSECOND));
// ObLCLMessage msg;
// UserBinaryKey key;
// key.set_user_key(ObDeadLockTestIntKey(1));
// msg.set_args(GCTX.self_addr(),
// key,
// GCTX.self_addr(),
// key,
// 2,
// ObLCLLabel(1, ObDetectorPriority(1)),
// ObClockGenerator::getRealClock());
// char buffer[4000];
// msg.to_string(buffer, 4000);
// std::cout << "test ts" << buffer << std::endl;
// DETECT_LOG(INFO, "test ts", K(msg));
// }
}// namespace unittest
}// namespace oceanbase
int main(int argc, char **argv)
{
system("rm -rf test_deadlock.log");
oceanbase::common::ObClockGenerator::init();
oceanbase::common::ObLogger &logger = oceanbase::common::ObLogger::get_logger();
logger.set_file_name("test_deadlock.log", false);
logger.set_log_level(OB_LOG_LEVEL_INFO);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}