您好,登錄后才能下訂單哦!
簡單記錄以備學習,如果有誤請指出。
Observer_info:觀察者 rpl_handler.h
class Observer_info { //插件觀察者public: void *observer; //這個void指針是具體的觀察者,使用指針函數實現多態 st_plugin_int *plugin_int; plugin_ref plugin Observer_info(void *ob, st_plugin_int *p); };
實際觀察者
及void* 指向的對象,其中全部都是函數指針,這里通過函數指針指向了具體的函數,實現了插件的功能。其中的函數指針指向的實際函數就是需要用戶自己實現的。
Trans_observer 結構體 Server_state_observer 結構體 Binlog_transmit_observer 結構體 Binlog_relay_IO_observer 結構體
實際上看具體實現的時候,搜索這些結構的名字,插件中如果實現會定義實際的函數名。如MGR中如下:
Trans_observer trans_observer = { sizeof(Trans_observer), group_replication_trans_before_dml, group_replication_trans_before_commit, group_replication_trans_before_rollback, group_replication_trans_after_commit, group_replication_trans_after_rollback, };
Delegate:委托者基類
其中包含
Observer_info_list observer_info_list; //觀察者鏈表,也就是Observer_info的一個鏈表 mysql_rwlock_t lock;//讀寫鎖 MEM_ROOT memroot;//內存空間 bool inited;//是否初始化
并且實現了一些通用的函數,比如增加和刪除插件
具體的委托者繼承自Delegate
Trans_delegate :事物相關 typedef Trans_observer Observer; Server_state_delegate :服務器相關 typedef Server_state_observer Observer; Binlog_transmit_delegate :傳輸相關 typedef Binlog_transmit_observer Observer; Binlog_relay_IO_delegate :slave 相關typedef Binlog_relay_IO_observer Observer;
舉例rpl_handler.cc中
int register_trans_observer(Trans_observer *observer, void *p){ return transaction_delegate->add_observer(observer, (st_plugin_int *)p); }
observer已經初始化完成,注冊即可。這里加入到了觀察者隊列。一旦加入這個鏈表則,在實際使用的時候就會遍歷整個鏈表執行相應的函數。
RUN_HOOK 宏
定義如下:
#define RUN_HOOK(group, hook, args) \ (group ##_delegate->is_empty() ? \ 0 : group ##_delegate->hook args)#define NO_HOOK(group) (group ##_delegate->is_empty())
這個宏會在MySQL中代碼的相應合適的位置進行調用,進入插件定義的邏輯。
FOREACH_OBSERVER 宏
定義如下:
#define FOREACH_OBSERVER(r, f, thd, args) \ /* Use a struct to make sure that they are allocated adjacent, check delete_dynamic(). */ \ Prealloced_array<plugin_ref, 8> plugins(PSI_NOT_INSTRUMENTED); \ //定義一個插件數組 read_lock(); \ Observer_info_iterator iter= observer_info_iter(); \ //迭代器 Observer_info *info= iter++; \ // for (; info; info= iter++) \ { \ plugin_ref plugin= \ my_plugin_lock(0, &info->plugin); \ if (!plugin) \ { \ /* plugin is not intialized or deleted, this is not an error */ \ r= 0; \ break; \ } \ plugins.push_back(plugin); \ if (((Observer *)info->observer)->f \ && ((Observer *)info->observer)->f args) \ { \ r= 1; \ sql_print_error("Run function '" #f "' in plugin '%s' failed", \ info->plugin_int->name.str); \ break; \ } \ } \
實際上可以看到是在遍歷相應的實際委托者的鏈表observer_info_list,執行相應的回表函數。
RUN_HOOK(transaction, before_commit, (thd, all, thd_get_cache_mngr(thd)->get_binlog_cache_log(true), thd_get_cache_mngr(thd)->get_binlog_cache_log(false), max<my_off_t>(max_binlog_cache_size, max_binlog_stmt_cache_size))
根據RUN_HOOK定義 group ##_delegate->hook args 轉換為:
transaction_delegate->before_commit(thd, all, thd_get_cache_mngr(thd)->get_binlog_cache_log(true), thd_get_cache_mngr(thd)->get_binlog_cache_log(false), max<my_off_t>(max_binlog_cache_size, max_binlog_stmt_cache_size)
此處的transaction_delegate是一個已經初始化的并且已經有插件注冊的Trans_delegate類的全局對象。因為Trans_delegate繼承來自Delegate,而在Trans_delegate中實現了before_commit的邏輯。其中包含的宏調用
FOREACH_OBSERVER(ret, before_commit, thd, (¶m)); //這里會執行回調函數宏定義:(#define FOREACH_OBSERVER(r, f, thd, args) )
做回調,實際上他會遍歷整個transaction_delegate中的觀察者,這些觀察者就是每一個插件實現的特定的GROUP的功能,所以FOREACH_OBSERVER宏的這一句
((Observer *)info->observer)->f args
就裝換為了(Trans_observer *)info->observer)->before_commit(¶m) 其中info是一個Observer_info對象其中包含了一個VOID指針observer,可以轉換為需要的類型,而Trans_observer是一個結構體其中全部都是函數指針before_commit是一個函數指針指向了group_replication_trans_before_commit,整個回調過程完成。
調用圖如下:
RUN_HOOK.png
作者微信:
微信.jpg
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。