Files
oceanbase/src/share/deadlock/ob_deadlock_detector_mgr.h

620 lines
24 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.
*/
#ifndef OCEANBASE_SHARE_DEADLOCK_OB_DEADLOCK_DETECTOR_MGR_
#define OCEANBASE_SHARE_DEADLOCK_OB_DEADLOCK_DETECTOR_MGR_
#include "lib/utility/ob_macro_utils.h"
#include "ob_deadlock_detector_common_define.h"
#include "ob_deadlock_parameters.h"
#include "lib/hash/ob_linear_hash_map.h"
#include "lib/hash/ob_link_hashmap.h"
#include "storage/tx/ob_time_wheel.h"
#include "lib/utility/utility.h"
#include "lib/allocator/ob_malloc.h"
#include "ob_deadlock_arg_checker.h"
#include "ob_deadlock_message.h"
#include "lib/function/ob_function.h"
#include "observer/ob_server_struct.h"
#include "share/rc/ob_tenant_base.h"
#include "ob_lcl_scheme/ob_lcl_batch_sender_thread.h"
#include <type_traits>
namespace oceanbase
{
namespace unittest
{
class TestObDeadLockDetector;
}
namespace obrpc
{
class ObDetectorRpcProxy;
class ObDeadLockDetectorRpc;
}// namespace obrpc
namespace rpc
{
namespace frame
{
class ObReqTransport;
}// namespace frame
}// namespace rpc
namespace share
{
namespace detector
{
class ObDeadLockDetectorRpc;
class ObLCLBatchSenderThread;
// ObDeadLockDetectorMgr is the unique global manager(within observer),
// who manages all operations of all detector instances(within observer also)
// Operations including register, unregister, block, and activate,
// specified by variable types of user key, no need of building a user adapter layer
//
// Note:
// Here are all main operation interfaces:
// 1, register resource operation: register_key()
// 2, ungister resource operation: unregister_key()
// 3, build directed dependency relationship between two detector: block()
// 4, remove directed dependency relationship between two detector: activate()
// all interfaces above thread-safe guaranteed
class ObDeadLockDetectorMgr
{
friend class DetectorRefGuard;
friend class ActivateFn;
friend class ObLCLNode;
friend class ObLCLBatchSenderThread;
friend class unittest::TestObDeadLockDetector;
friend class ObLCLBatchSenderThread;
public:
static bool is_deadlock_enabled() { return ObServerConfig::get_instance()._lcl_op_interval != 0; }
public:
ObDeadLockDetectorMgr();
// all inner object centralized initialization interface,
// should be callde from partition_service's init()
int init();
static int mtl_init(ObDeadLockDetectorMgr *&p_deadlock_detector_mgr);
int start();
void stop();
void wait();
// all inner object centralized destruction interface,
// should be called from partition_service's destroy()
void destroy();
// simple summary detector number info, for unittest
int64_t get_detector_create_count() { return ATOMIC_LOAD(&inner_alloc_handle_.inner_factory_.create_count_); }
int64_t get_detector_release_count() { return ATOMIC_LOAD(&inner_alloc_handle_.inner_factory_.release_count_); }
// register resource operation
template<typename KeyType>
int register_key(const KeyType &key,
const DetectCallBack &detect_callback,
const CollectCallBack &on_collect_operation,
const ObDetectorPriority &priority = ObDetectorPriority(0),
const uint64_t start_delay = 0,
const bool auto_activate_when_detected = true);
template<typename KeyType1, typename KeyType2>
int add_parent(const KeyType1 &key, const KeyType2 &parent_key);
template<typename KeyType1, typename KeyType2>
int add_parent(const KeyType1 &key,
const common::ObAddr &dest_addr,
const KeyType2 &parent_key);
template<typename KeyType>
int set_timeout(const KeyType &key, const int64_t timeout);
// ungister resource operation
template<typename KeyType>
int unregister_key(const KeyType &key);
int unregister_key_(const UserBinaryKey &key);
// build directed dependency relationship between two detector
template<typename T1, typename T2, typename std::enable_if<!std::is_base_of<common::ObIArray<ObDependencyResource>, T2>::value, bool>::type = true>
int block(const T1 &src_key, const T2 &dest_key);
template<typename T1>
int block(const T1 &src_key, const common::ObIArray<ObDependencyResource> &new_list);
template<typename T1, typename T2, typename std::enable_if<!std::is_base_of<common::ObIArray<ObDependencyResource>, T2>::value, bool>::type = true>
int block(const T1 &src_key, const common::ObAddr &dest_addr, const T2 &dest_key);
// func is a callback method to get DependencyResource dynamically
// func input args: ObDependencyResource& - the resource will blocked on
// bool& - remove this callback from block list if true, setted false by default
// func return value: int - err code, this callback's result will not used if ret is not SUCCESS
template<typename T>
int block(const T &src_key, const BlockCallBack &func);
// replace block list by new one
template<typename T>
int replace_block_list(const T &src_key,
const common::ObIArray<ObDependencyResource> &new_list);
template<typename T>
int get_block_list(const T &src_key, common::ObIArray<ObDependencyResource> &cur_list);
// remove directed dependency relationship between two detector
template<typename T1, typename T2>
int activate(const T1 &src_key, const T2 &dest_key);
template<typename T1, typename T2>
int activate(const T1 &src_key, const common::ObAddr &dest_addr, const T2 &dest_key);
template<typename T1>
int activate_all(const T1 &src_key);
// exposed to detector RPC, shouldn't called from others
int process_lcl_message(const ObLCLMessage &lcl_msg);
int process_collect_info_message(const ObDeadLockCollectInfoMessage &collect_info_msg);
int process_notify_parent_message(const ObDeadLockNotifyParentMessage &collect_info_msg);
private:
// exposed to deadlock detector, shouldn't called from others
common::ObTimeWheel& get_time_wheel() { return time_wheel_; }
ObDeadLockDetectorRpc& get_rpc() { return (*rpc_); }
int check_and_report_cycle_(const ObDeadLockCollectInfoMessage &collect_info_msg);
uint64_t calculate_cycle_hash_(const ObDeadLockCollectInfoMessage &collect_info_msg);
int check_and_record_cycle_hash_(const uint64_t hash);
// define for ObLinkHashMap
class InnerAllocHandle
{
public:
// factory for creating detecor instance
class InnerFactory
{
public:
InnerFactory() : logic_id_(0) {}
int create(const UserBinaryKey &key,
const DetectCallBack &on_detect_operation,
const CollectCallBack &on_collect_operation,
const ObDetectorPriority &priority,
const uint64_t start_delay,
const bool auto_activate_when_detected,
ObIDeadLockDetector *&p_detector);
void release(ObIDeadLockDetector *p_detector);
static uint64_t create_count_;
static uint64_t release_count_;
private:
uint64_t logic_id_;
} inner_factory_;
ObIDeadLockDetector *alloc_value();
void free_value(ObIDeadLockDetector *p);
common::LinkHashNode<UserBinaryKey> *alloc_node(ObIDeadLockDetector *p);
void free_node(common::LinkHashNode<UserBinaryKey> *node);
} inner_alloc_handle_;
// A simple guard object for protecting reference count of detector instance
// should only used on stack
class DetectorRefGuard
{
public:
DetectorRefGuard() : p_detector_(nullptr) {}
~DetectorRefGuard();
int set_detector(ObIDeadLockDetector* p_detector);
ObIDeadLockDetector* const& get_detector() const { return p_detector_; }
private:
ObIDeadLockDetector* p_detector_;
};
class ActivateFn
{
public:
bool operator()(const UserBinaryKey &key, ObIDeadLockDetector *p_detector);
};
template <typename KeyType>
int try_create_inner_detector_(const KeyType &key);
int get_detector_(const UserBinaryKey &user_key, DetectorRefGuard &detector_guard);
bool is_inited_;// marked ObDeadLockDetectorMgr hash been inited or not
int64_t stop_ts_;// the timestamp of stop() called
// global single instance timer for detector period tansmit operation
common::ObTimeWheel time_wheel_;
obrpc::ObDetectorRpcProxy *proxy_;// used by rpc_
ObDeadLockDetectorRpc *rpc_;// message sender/receiver
ObLCLBatchSenderThread sender_thread_;// inner thread to cache, batch message and send them
common::ObLinkHashMap<UserBinaryKey,
ObIDeadLockDetector,
InnerAllocHandle,
common::RefHandle> detector_map_;//UserBinaryKey to detector instance
};
// register a user specified key
// register action means user specified key is associated with a new created detector instance
//
// all related out-of-function state are from detector_map_/InnerFactory,
// their interfaces provide thread-safe semantics, thus this interface is thread-safe guaranteed
//
// @param [in] key user specified key
// @param [in] on_detect_operation call-back operation clalled while deadlock detected
// @param [in] report_info user input info, for reporting while deadlock detected
// @param [in] priority priority of created detector instance,
// lower priority means higher killed probability.
// @param [in] start_delay the associated detector start work after start_delay(ms) time
// @param [in] auto_activate_when_detected indicate whether auto-remove related dependency
// relationship while deadlock detected or not. setted true by default,
// otherwise on_detect_operation may be called more than one time,
// which usually unexpected
// @return error code
template<typename KeyType>
int ObDeadLockDetectorMgr::register_key(const KeyType &key,
const DetectCallBack &on_detect_operation,
const CollectCallBack &on_collect_operation,
const ObDetectorPriority &priority,
const uint64_t start_delay,
const bool auto_activate_when_detected)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(key, on_detect_operation, on_collect_operation, priority, start_delay);
#define PRINT_WRAPPER KR(ret), K(key), K(on_detect_operation), K(on_collect_operation),\
K(priority), K(start_delay), K(auto_activate_when_detected)
int ret = common::OB_SUCCESS;
ObIDeadLockDetector *p_detector = nullptr;
UserBinaryKey binary_key;
if (OB_FAIL(binary_key.set_user_key(key))) {
DETECT_LOG(WARN, "user key seialized to binary code failed", PRINT_WRAPPER);
} else if (common::OB_SUCCESS == (ret = detector_map_.get(binary_key, p_detector))) {
ret = common::OB_ENTRY_EXIST;
detector_map_.revert(p_detector);
// DETECT_LOG(INFO, "key already exist", PRINT_WRAPPER);
} else if (common::OB_ENTRY_NOT_EXIST == ret) {// create obj and insert to map
if (OB_FAIL(inner_alloc_handle_.inner_factory_.create(binary_key,
on_detect_operation,
on_collect_operation,
priority,
start_delay,
auto_activate_when_detected,
p_detector))) {
DETECT_LOG(WARN, "create new detector instance failed", PRINT_WRAPPER, KP(p_detector));
} else if (OB_FAIL(detector_map_.insert_and_get(binary_key, p_detector))) {
DETECT_LOG(WARN, "detector_map_ insert key and value failed", PRINT_WRAPPER, KP(p_detector));
inner_alloc_handle_.inner_factory_.release(p_detector);
} else if (OB_FAIL(p_detector->register_timer_task())) {
if (common::OB_ENTRY_NOT_EXIST == ret) {
ret = common::OB_EAGAIN;// telling user there is a concurrent problem, need retry
}
DETECT_LOG(WARN, "start timer task failed", PRINT_WRAPPER, KP(p_detector));
(void)detector_map_.del(binary_key);
detector_map_.revert(p_detector);
} else {
detector_map_.revert(p_detector);
DETECT_LOG(INFO, "register key success", PRINT_WRAPPER);
}
} else {
DETECT_LOG(ERROR, "get key error, couldn't handle", PRINT_WRAPPER);
}
return ret;
#undef PRINT_WRAPPER
}
// unregister a user specified key
// unregister action means:
// 1. the detector instance associated with user specified key will be released
// 2. user specified key will not associated with a local unqiue ID anymore
//
// all related out-of-function state are from id_map_/detector_map_/InnerFactory
// their interfaces provide thread-safe semantics, thus this interface is thread-safe guaranteed
//
// @param [in] key user specified key
// @return error code
template<typename KeyType>
int ObDeadLockDetectorMgr::unregister_key(const KeyType &key)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(key);
#define PRINT_WRAPPER KR(ret), K(key)
int ret = common::OB_SUCCESS;
UserBinaryKey user_key;
if (OB_FAIL(user_key.set_user_key(key))) {
DETECT_LOG(WARN, "user key serialization failed", PRINT_WRAPPER);
} else {
ret = unregister_key_(user_key);
}
return ret;
#undef PRINT_WRAPPER
}
// call for building directed dependency relationship between two detector(both in local)
// thread-safe guaranteed
//
// @param [in] src_key the source key resource specified by user
// @param [in] dest_key the destination key resource specified by user
// @return error code
template<typename T1, typename T2, typename std::enable_if<!std::is_base_of<common::ObIArray<ObDependencyResource>, T2>::value, bool>::type>
int ObDeadLockDetectorMgr::block(const T1 &src_key, const T2 &dest_key)
{
return block(src_key, GCTX.self_addr(), dest_key);
}
// call for building directed dependency relationship between two detector(local to remote)
// thread-safe guaranteed
//
// @param [in] src_key the source key resource specified by user
// @param [in] appened_list the destination network address specified by user
// @return error code
template<typename T1>
int ObDeadLockDetectorMgr::block(const T1 &src_key,
const common::ObIArray<ObDependencyResource> &appened_list)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(src_key);
#define PRINT_WRAPPER KR(ret), K(src_key), K(appened_list)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else {
for (int64_t idx = 0; idx < appened_list.count() && OB_SUCC(ret); ++idx) {
if (OB_FAIL(ref_guard.get_detector()->block(appened_list.at(idx)))) {
if (OB_ENTRY_EXIST == ret) {
ret = OB_SUCCESS;
} else {
DETECT_LOG(WARN, "detector block op failed", PRINT_WRAPPER);
}
}
}
}
return ret;
#undef PRINT_WRAPPER
}
// call for building directed dependency relationship between two detector(local to remote)
// thread-safe guaranteed
//
// @param [in] src_key the source key resource specified by user
// @param [in] dest_addr the destination network address specified by user
// @param [in] dest_key the destination key resource specified by user
// @return error code
template<typename T1, typename T2, typename std::enable_if<!std::is_base_of<common::ObIArray<ObDependencyResource>, T2>::value, bool>::type>
int ObDeadLockDetectorMgr::block(const T1 &src_key,
const common::ObAddr &dest_addr,
const T2 &dest_key)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(src_key, dest_addr, dest_key);
#define PRINT_WRAPPER KR(ret), K(src_key), K(dest_addr), K(dest_key)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
UserBinaryKey dest_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(dest_user_key.set_user_key(dest_key))) {
DETECT_LOG(WARN, "dest_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else {
ObDependencyResource resource(dest_addr, dest_user_key);
if (OB_FAIL(ref_guard.get_detector()->block(resource))) {
DETECT_LOG(WARN, "detector block op failed", PRINT_WRAPPER);
} else {
DETECT_LOG(INFO, "detector block op success", PRINT_WRAPPER);
}
}
return ret;
#undef PRINT_WRAPPER
}
template<typename T>
int ObDeadLockDetectorMgr::block(const T &src_key,
const BlockCallBack &func)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(func, src_key);
#define PRINT_WRAPPER KR(ret), K(src_key)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else if (OB_FAIL(ref_guard.get_detector()->block(func))) {
DETECT_LOG(WARN, "block on callback failed", PRINT_WRAPPER);
} else {}
return ret;
#undef PRINT_WRAPPER
}
// replace block list by new one
//
// @param [in] src_key detector key
// @param [in] new_list specified new block list
// @return error code
template<typename T>
int ObDeadLockDetectorMgr::replace_block_list(const T &src_key,
const common::ObIArray<ObDependencyResource>
&new_list)
{
CHECK_INIT();
CHECK_ENABLED();
#define PRINT_WRAPPER KR(ret), K(src_key), K(new_list)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else if (OB_FAIL(ref_guard.get_detector()->replace_block_list(new_list))) {
// DETECT_LOG(WARN, "replace block list failed", PRINT_WRAPPER);
} else {
// DETECT_LOG(INFO, "replace block list success", PRINT_WRAPPER);
}
return ret;
#undef PRINT_WRAPPER
}
template<typename T>
int ObDeadLockDetectorMgr::get_block_list(const T &src_key,
common::ObIArray<ObDependencyResource> &cur_list)
{
CHECK_INIT();
CHECK_ENABLED();
#define PRINT_WRAPPER KR(ret), K(src_key), K(cur_list)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else if (OB_FAIL(ref_guard.get_detector()->get_block_list(cur_list))) {
DETECT_LOG(WARN, "get block list failed", PRINT_WRAPPER);
} else {
// DETECT_LOG(INFO, "replace block list success", PRINT_WRAPPER);
}
return ret;
#undef PRINT_WRAPPER
}
// call for removing directed dependency relationship between two detector(both in local)
// thread-safe guaranteed
//
// @param [in] src_key the source resource key specified by user
// @param [in] dest_key the destination resource key specified by user
// @return error code
template<typename T1, typename T2>
int ObDeadLockDetectorMgr::activate(const T1 &src_key, const T2 &dest_key)
{
return activate(src_key, GCTX.self_addr(), dest_key);
}
// call for removing directed dependency relationship between two detector(local to remote)
// thread-safe guaranteed
//
// @param [in] src_key the source resource key specified by user
// @param [in] dest_addr the destination network address specified by user
// @param [in] dest_key the destination resource key specified by user
// @return error code
template<typename T1, typename T2>
int ObDeadLockDetectorMgr::activate(const T1 &src_key,
const common::ObAddr &dest_addr,
const T2 &dest_key)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(src_key, dest_addr, dest_key);
#define PRINT_WRAPPER KR(ret), K(src_key), K(dest_addr), K(dest_key)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
UserBinaryKey dest_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(dest_user_key.set_user_key(dest_key))) {
DETECT_LOG(WARN, "dest_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else {
ObDependencyResource resource(dest_addr, dest_user_key);
if (OB_FAIL(ref_guard.get_detector()->activate(resource))) {
DETECT_LOG(WARN, "detector activate op failed", PRINT_WRAPPER, K(resource));
} else {
DETECT_LOG(INFO, "detector activate op success", PRINT_WRAPPER, K(resource));
}
}
return ret;
#undef PRINT_WRAPPER
}
template<typename T1>
int ObDeadLockDetectorMgr::activate_all(const T1 &src_key)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(src_key);
#define PRINT_WRAPPER KR(ret), K(src_key)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
UserBinaryKey dest_user_key;
if (OB_FAIL(src_user_key.set_user_key(src_key))) {
DETECT_LOG(WARN, "src_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(src_user_key, ref_guard))) {
DETECT_LOG(WARN, "get_detector failed", PRINT_WRAPPER);
} else if (OB_FAIL(ref_guard.get_detector()->activate_all())) {
DETECT_LOG(WARN, "activate all failed", PRINT_WRAPPER);
}
return ret;
#undef PRINT_WRAPPER
}
template<typename KeyType1, typename KeyType2>
int ObDeadLockDetectorMgr::add_parent(const KeyType1 &key,
const KeyType2 &parent_key)
{
return add_parent(key, GCTX.self_addr(), parent_key);
}
template<typename KeyType1, typename KeyType2>
int ObDeadLockDetectorMgr::add_parent(const KeyType1 &key,
const common::ObAddr &dest_addr,
const KeyType2 &parent_key)
{
CHECK_INIT();
CHECK_ENABLED();
CHECK_ARGS(key, dest_addr, parent_key);
#define PRINT_WRAPPER KR(ret), K(src_user_key), K(dest_addr), K(dest_user_key)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey src_user_key;
UserBinaryKey dest_user_key;
if (OB_FAIL(src_user_key.set_user_key(key))) {
DETECT_LOG(WARN, "src_user_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(dest_user_key.set_user_key(parent_key))) {
DETECT_LOG(WARN, "dest_user_key serialzation failed", PRINT_WRAPPER);
} else if (OB_SUCC(get_detector_(src_user_key, ref_guard))) {
ObDependencyResource resource(dest_addr, dest_user_key);
if (OB_FAIL(ref_guard.get_detector()->add_parent(resource))) {
DETECT_LOG(WARN, "detector add parent failed", PRINT_WRAPPER, K(resource));
} else {
DETECT_LOG(INFO, "detector add parent success", PRINT_WRAPPER, K(resource));
}
}
return ret;
#undef PRINT_WRAPPER
}
template<typename KeyType>
int ObDeadLockDetectorMgr::set_timeout(const KeyType &key, const int64_t timeout)
{
CHECK_INIT();
CHECK_ARGS(key, timeout);
#define PRINT_WRAPPER KR(ret), K(user_key), K(timeout)
int ret = common::OB_SUCCESS;
DetectorRefGuard ref_guard;
UserBinaryKey user_key;
if (OB_FAIL(user_key.set_user_key(key))) {
DETECT_LOG(WARN, "dest_user_key serialzation failed", PRINT_WRAPPER);
} else if (OB_FAIL(get_detector_(user_key, ref_guard))) {
DETECT_LOG(WARN, "con not get obj", PRINT_WRAPPER);
} else {
if (timeout > 1_hour && REACH_TIME_INTERVAL(1_s)) {
DETECT_LOG(INFO, "timeout value more than 1 hour", PRINT_WRAPPER);
}
ref_guard.get_detector()->set_timeout(timeout);
}
return ret;
#undef PRINT_WRAPPER
}
}// namespace detector
}// namespace share
}// namespace oceanbase
#endif