patch 4.0
This commit is contained in:
@ -16,125 +16,107 @@
|
||||
#include "share/ob_define.h"
|
||||
#include "lib/atomic/ob_atomic.h"
|
||||
#include "lib/utility/utility.h"
|
||||
#include "storage/tx/ob_trans_end_trans_callback.h"
|
||||
#include "storage/tx/ob_trans_define.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace oceanbase
|
||||
{
|
||||
|
||||
namespace transaction {
|
||||
class ObTransID;
|
||||
class ObTransID;
|
||||
class ObITxCallback;
|
||||
}
|
||||
|
||||
namespace sql {
|
||||
namespace sql
|
||||
{
|
||||
|
||||
enum ObEndTransCallbackType {
|
||||
SYNC_CALLBACK_TYPE = 0, /* Synchronous waiting, such as DDL statement */
|
||||
/* *
|
||||
* Asynchronously execute operations after transaction submission,
|
||||
* such as DML statements, COMMINT/ROLLBACK statements to send execution results to the client
|
||||
* */
|
||||
ASYNC_CALLBACK_TYPE,
|
||||
enum ObEndTransCallbackType
|
||||
{
|
||||
SYNC_CALLBACK_TYPE = 0, /* 同步等待,如DDL语句 */
|
||||
ASYNC_CALLBACK_TYPE, /* 异步执行事务提交后的操作,如DML语句,COMMINT/ROLLBACK语句对客户端发送执行结果 */
|
||||
// NO_CALLBACK_TYPE, /* 用户中途主动断开链接时会rollback事务, 这种情况也采取SYNC模式较为方便 */
|
||||
NULL_CALLBACK_TYPE,
|
||||
//SQL_CALLBACK_TYPE,
|
||||
WRITE_FROZEN_STAT_CALLBACK_TYPE,
|
||||
MOCK_CALLBACK_TYPE,
|
||||
MAX_CALLBACK_TYPE
|
||||
};
|
||||
|
||||
/* The life cycle of ObIEndTransCallback:
|
||||
* Idea 1. Create at StartTrans and terminate after EndTrans call ends
|
||||
* In disconnect mode, synchronous waiting is adopted.
|
||||
* This action is unpredictable during StartTrans
|
||||
* Idea 2. Create before calling EndTrans and terminate after calling EndTrans
|
||||
* Need to know the current operation type (ac=0/1, commit/rollback, dml, disconnect)
|
||||
|
||||
/* ObIEndTransCallback的生命周期:
|
||||
* 思路1. 在StartTrans的时候创建,在EndTrans调用结束后终止
|
||||
* - disconnect模式下,采取同步等待。这个动作在StartTrans的时候无法预知
|
||||
* 思路2. 在调用EndTrans之前创建,在调用EndTrans之后终止
|
||||
* - 需要知道当前操作类型(ac=0/1, commit/rollback, dml, disconnect)
|
||||
*
|
||||
* Explicit_end_trans (commit/rollback),
|
||||
* on_plan_end (ac=1 dml) two cases need to pass in ObIEndTransCallback from outside,
|
||||
* In other cases, sync mode is used,
|
||||
* and ObIEndTransCallback is internally constructed and released
|
||||
* explicit_end_trans (commit/rollback), on_plan_end (ac=1 dml)两种情况需要从外部传入ObIEndTransCallback,
|
||||
* 其余情况都使用sync模式,内部构造和释放ObIEndTransCallback
|
||||
*
|
||||
* After calling end_trans and before the callback occurs,
|
||||
* is it possible to do the operation [may cause an error]?
|
||||
* The so-called [errors may occur] operation refers to calling a function and obtaining an error code,
|
||||
* which affects the SQL error output.
|
||||
* Assuming that an error code is generated by doing such an operation,
|
||||
* then the error code must be saved, otherwise it will be swallowed.
|
||||
* Can only be saved in Callback.
|
||||
* But there is a multithreading problem:
|
||||
* What should I do if Callback is already called when the error code is saved?
|
||||
* A simpler way: do nothing after end_trans,
|
||||
* and all other operations will be executed in the callback.
|
||||
* 调用end_trans后,回调发生前,是否还可以做【可能会产生错误】的操作?
|
||||
* - 所谓【可能会产生错误】的操作,是指调用了函数,并获得一个错误码,影响SQL错误输出。
|
||||
* - 假设做了这样的操作,产生了错误码,那么这个错误码必须被保存,否则就被吞掉了。
|
||||
* 只能保存到Callback中。但这存在多线程问题:保存错误码的时候Callback已经调用了怎么办?
|
||||
* - 比较简单的方式:end_trans后什么都不做,其余操作全部都放到回调中执行。
|
||||
*
|
||||
*/
|
||||
class ObIEndTransCallback {
|
||||
class ObIEndTransCallback : public transaction::ObITxCallback
|
||||
{
|
||||
public:
|
||||
ObIEndTransCallback()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
virtual ~ObIEndTransCallback(){};
|
||||
ObIEndTransCallback() { reset(); }
|
||||
virtual ~ObIEndTransCallback() {};
|
||||
/*
|
||||
* In some scenarios (such as cmd triggering implicit submission),
|
||||
* you need to wait for the callback to be successfully called synchronously
|
||||
* In order to continue the subsequent operation, so the wait () operation is introduced
|
||||
* 部分场景下(如cmd触发隐式提交)需要同步等待callback调用成功后
|
||||
* 才能继续后面的操作,所以引入wait()操作
|
||||
*/
|
||||
virtual int wait()
|
||||
{
|
||||
return common::OB_NOT_IMPLEMENT;
|
||||
}
|
||||
virtual int wait() { return common::OB_NOT_IMPLEMENT; }
|
||||
/*
|
||||
* Called after the transaction is completed, the specific action is defined by the object itself
|
||||
* Such as: wake up wait(); return a packet to the client; return a packet to the RPC caller, etc.
|
||||
* 由事务完成后调用,具体动作由对象本身定义
|
||||
* 如:唤醒wait(); 向客户端回包; 向RPC调用者回包等
|
||||
*/
|
||||
virtual void callback(int cb_param) = 0;
|
||||
virtual void callback(int cb_param, const transaction::ObTransID& trans_id) = 0;
|
||||
virtual const char* get_type() const = 0;
|
||||
virtual void callback(int cb_param, const transaction::ObTransID &trans_id) = 0;
|
||||
virtual const char *get_type() const = 0;
|
||||
virtual ObEndTransCallbackType get_callback_type() const = 0;
|
||||
// Indicates whether it is possible for the same callback object to be shared
|
||||
// by multiple end trans functions at the same time,
|
||||
// and it is possible to call the callback function of the same callback object concurrently
|
||||
// 表示是否可能同一时间同一个callback对象被多个end trans函数共享,可能并发地调用同一callback对象的callback函数
|
||||
virtual bool is_shared() const = 0;
|
||||
|
||||
void set_last_error(int last_err)
|
||||
{
|
||||
last_err_ = last_err;
|
||||
}
|
||||
/*
|
||||
* 设置外部错误码,事务完成后回调时参考callback(cb_param)中cb_param
|
||||
* 指定的错误码,以及本外部错误码,返回首现错误码
|
||||
*/
|
||||
void set_last_error(int last_err) { last_err_ = last_err; }
|
||||
|
||||
inline void handout()
|
||||
{
|
||||
ATOMIC_INC(&call_counter_);
|
||||
}
|
||||
|
||||
inline void handin()
|
||||
{
|
||||
ATOMIC_INC(&callback_counter_);
|
||||
}
|
||||
/*
|
||||
* 调用ps->end_trans成功后调用
|
||||
*/
|
||||
inline void handout() { ATOMIC_INC(&call_counter_); }
|
||||
/*
|
||||
* 事务层触发cb.callback()后立即在callback中调用
|
||||
*/
|
||||
inline void handin() { ATOMIC_INC(&callback_counter_);}
|
||||
inline void reset()
|
||||
{
|
||||
last_err_ = common::OB_SUCCESS;
|
||||
call_counter_ = 0;
|
||||
callback_counter_ = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void CHECK_BALANCE(const char* type) const
|
||||
// 为了检查是否存在重复调用callback,或漏调callback的问题
|
||||
inline void CHECK_BALANCE(const char *type) const
|
||||
{
|
||||
if (OB_UNLIKELY(callback_counter_ != call_counter_)) {
|
||||
SQL_LOG(ERROR,
|
||||
"Callback times mismatch. bug!!!",
|
||||
K(type),
|
||||
K(this),
|
||||
K(common::lbt()),
|
||||
K_(callback_counter),
|
||||
K_(call_counter));
|
||||
SQL_LOG(ERROR, "Callback times mismatch. bug!!!",
|
||||
K(type), K(this), K(common::lbt()), K_(callback_counter), K_(call_counter));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int last_err_;
|
||||
volatile uint64_t call_counter_;
|
||||
volatile uint64_t callback_counter_;
|
||||
volatile uint64_t call_counter_; // 调用ps->end_trans成功的次数
|
||||
volatile uint64_t callback_counter_; // 调用callback的次数
|
||||
};
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
} /*ns*/
|
||||
}/*ns */
|
||||
|
||||
#endif /* __OB_SQL_I_END_TRANS_CALLBACK_H__ */
|
||||
//// end of header file
|
||||
|
||||
Reference in New Issue
Block a user