498 lines
25 KiB
C++
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();
|
|
}
|