上一講《Zookeeper C API 指南五(同步 API 介紹)》講了Zookeeper 同步 API 的分類和相關解釋,相信大家對 Zookeeper 同步 API 也有了一個大致的了解,本文我會給大家介紹 Zookeeper C API 中的異步調用的函數(即以 zoo_a* 開頭的函數),本文大致結構與《Zookeeper C API 指南五(同步 API 介紹)》,先匯總 API,然后再分類,並對每個 API 作出解釋。
在具體講解 Zookeeper 異步 API 之前,首先回顧一下《Zookeeper C API 指南三(回調函數)》,除了監視器回調函數以外,還有其他 7 種回調函數,他們通常在異步 API 調用結束或 Zookeeper 客戶端失去連接時被調用。根據回調函數返回參數(即函數的輸出參數)的類型不同分為以下幾類:返回 void 類型的回調函數,返回 Stat 結構的回調函數,返回字符串的回調函數,返回數據的回調函數,返回字符串列表(a list of string)的回調函數,同時返回字符串列表(a list of string)和 Stat 結構的回調函數,以及返回 ACL 信息的回調函數,7 中回調函數原型聲明如下:
// 返回 void 類型的回調函數 typedef void(* void_completion_t)(int rc, const void *data); // 返回 Stat 結構的回調函數 typedef void(* stat_completion_t)(int rc, const struct Stat *stat, const void *data); // 返回字符串的回調函數 typedef void(* string_completion_t)(int rc, const char *value, const void *data); // 返回數據的回調函數 typedef void(* data_completion_t)(int rc, const char *value, int value_len, const struct Stat *stat, const void *data); // 返回字符串列表(a list of string)的回調函數 typedef void(* strings_completion_t)(int rc, const struct String_vector *strings, const void *data); // 同時返回字符串列表(a list of string)和 Stat 結構的回調函數 typedef void(* strings_stat_completion_t)(int rc, const struct String_vector *strings, const struct Stat *stat, const void *data); // 以及返回 ACL 信息的回調函數 typedef void(* acl_completion_t)(int rc, struct ACL_vector *acl, struct Stat *stat, const void *data);
可能這么說還不是很理解,那么我們以異步創建 znode 節點(zoo_acreate())為例解釋一下:
zoo_acreate函數原型如下:
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path, const char *value, int valuelen, const struct ACL_vector *acl, int flags, string_completion_t completion, const void *data);
其中參數 string_completion_t completion 即返回字符串的回調函數,那么當 zoo_acreate 調用結束時將會觸發 completion 回調函數的調用,同時傳遞給 completion 的 rc 參數為: ZOK 操作完成;ZNONODE 父節點不存在;ZNODEEXISTS 節點已存在;ZNOAUTH 客戶端沒有權限創建節點。ZNOCHILDRENFOREPHEMERALS 臨時節點不能創建子節點。而 string_completion_t completion 中 const char *value 參數即新節點的路徑名(注:如果 zoo_acreate 設置了ZOO_EPHEMERAL,則創建節點成功后,節點名稱並不是 zoo_acreate 中 path 參數所指定的名稱,而是類似與 /xyz0000000001,/xyz0000000002... 的名稱)。另外,string_completion_t completion 中 const void *data 參數即為 zoo_acreate 中的 const void *data。
一般來說,zoo_acreate 函數可以按照以下方式調用:
int ret = zoo_acreate(zkhandle, "/xyz", "hello", 5, &ZOO_OPEN_ACL_UNSAFE, 0 /* ZOO_SEQUENCE */, zktest_string_completion, "acreate"); if (ret) { fprintf(stderr, "Error %d for %s\n", ret, "acreate"); exit(EXIT_FAILURE); }
其中 zktest_string_completion 功能很簡單,就是把創建成功后的節點名稱打印出來,函數定義如下:
void zktest_string_completion(int rc, const char *name, const void *data) { fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc); if (!rc) { fprintf(stderr, "\tname = %s\n", name); } }
好了,有了上面的基礎,我們接下來再來講講 Zookeeper 異步 API 吧 :-)
Zookeeper C API 中與訪問 Zookeeper 服務相關(比如創建、刪除 znode 節點,獲取子節點,設置 znode 數據等)的異步 API 如下:
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path, const char *value, int valuelen, const struct ACL_vector *acl, int flags, string_completion_t completion, const void *data); ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version, void_completion_t completion, const void *data); ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch, stat_completion_t completion, const void *data); ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, stat_completion_t completion, const void *data); ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch, data_completion_t completion, const void *data); ZOOAPI int zoo_awget(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, data_completion_t completion, const void *data); ZOOAPI int zoo_aset(zhandle_t * zh, const char *path, const char *buffer, int buflen, int version, stat_completion_t completion, const void *data); ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path, int watch, strings_completion_t completion, const void *data); ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, strings_completion_t completion, const void *data); ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path, int watch, strings_stat_completion_t completion, const void *data); ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, strings_stat_completion_t completion, const void *data); ZOOAPI int zoo_async(zhandle_t * zh, const char *path, string_completion_t completion, const void *data); ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path, acl_completion_t completion, const void *data); ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version, struct ACL_vector *acl, void_completion_t, const void *data); ZOOAPI int zoo_amulti(zhandle_t * zh, int count, const zoo_op_t * ops, zoo_op_result_t * results, void_completion_t, const void *data);
本文將以上異步 API 細分為以下幾類:(1). 創建、刪除 znode 節點,(2). 可設置 watch 的 API,(3). 訪問、設置節點 ACL 的 API,(4). 異步批處理 API。
- 創建、刪除 znode 節點
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path, const char *value, int valuelen, const struct ACL_vector *acl, int flags, string_completion_t completion, const void *data); ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version, void_completion_t completion, const void *data);
- 創建 znode 節點
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path, const char *value, int valuelen, const struct ACL_vector *acl, int flags, string_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
value | 該節點保存的數據。 |
valuelen | 該節點保存數據的大小。 |
acl | 該節點初始 ACL,ACL 不能為null 或空。 |
flags | 該參數可以設置為 0,或者創建標識符 ZOO_EPHEMERAL, ZOO_SEQUENCE 的組合或(OR)。 |
completion | 當創建節點請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 父節點不存在;ZNODEEXISTS 節點已存在;ZNOAUTH 客戶端沒有權限創建節點。ZNOCHILDRENFOREPHEMERALS 臨時節點不能創建子節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 刪除 znode 節點
ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version, void_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
version | 期望的節點版本號,如果真實的版本號與期望的版本號不同則 zoo_delete() 調用失敗,-1 表示不不檢查版本號。 |
completion | 當刪除節點請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點;ZBADVERSION 版包號不匹配;ZNOTEMPTY 當前節點存在子節點,不能被刪除。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 可設置 watch 的 API(exists(兩個) + get(兩個) + get_children(四個) = 八個)
ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch, stat_completion_t completion, const void *data); ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, stat_completion_t completion, const void *data); ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch, data_completion_t completion, const void *data); ZOOAPI int zoo_awget(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, data_completion_t completion, const void *data); ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path, int watch, strings_completion_t completion, const void *data); ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, strings_completion_t completion, const void *data); ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path, int watch, strings_stat_completion_t completion, const void *data); ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, strings_stat_completion_t completion, const void *data);
- 檢查節點狀態 exists(兩個,分別是 zoo_aexists() 和 zoo_awexists(),區別是后者可以指定單獨的 watcher_fn(監視器回調函數),而前者只能用 zookeeper_init() 設置的全局監視器回調函數,同時 aget 和 aget_children兩族函數也一樣,帶有zoo_w* 的函數可以指定單獨的 watcher_fn)。)
ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch, stat_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watch | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。 |
completion | 當 zoo_aexists 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, stat_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watcher | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。 |
watcherCtx | 用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。 |
completion | 當 zoo_awexists 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 獲取節點數據 aget(兩個)
ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch, data_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watch | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。 |
completion | 當 zoo_aget 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
ZOOAPI int zoo_awget(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, data_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watcher | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。 |
watcherCtx | 用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。 |
completion | 當 zoo_awget 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 獲取子節點列表 aget_children (四個)
ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path, int watch, strings_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watch | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。 |
completion | 當 zoo_aget_children 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, strings_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watcher | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。 |
watcherCtx | 用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。 |
completion | 當zoo_awget_children 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path, int watch, strings_stat_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watch | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。 |
completion | 當 zoo_aget_children2 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx, strings_stat_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
watcher | 如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。 |
watcherCtx | 用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。 |
completion | 當zoo_awget_children2 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 訪問、設置節點 ACL 的 API
ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path, acl_completion_t completion, const void *data); ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version, struct ACL_vector *acl, void_completion_t, const void *data);
- 訪問節點 ACL
ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path, acl_completion_t completion, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
completion | 當 zoo_aget_acl 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 設置節點 ACL
ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version, struct ACL_vector *acl, void_completion_t, const void *data);
zh | zookeeper_init() 返回的 zookeeper 句柄。 |
path | 節點路徑。 |
buffer | 保存需要設置的 ACL。 |
buflen | buffer 的長度。 |
completion | 當 zoo_aset_acl 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的 rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點;ZINVALIDACL 非法 ACL;ZBADVERSION 版本號不匹配。 |
data | completion 函數被調用時,傳遞給 completion 的數據。 |
- 異步批處理 API
ZOOAPI int zoo_amulti(zhandle_t * zh, int count, const zoo_op_t * ops, zoo_op_result_t * results, void_completion_t, const void *data);
異步批處理與同步批處理方式類似見《Zookeeper C API 指南五(同步 API 介紹)》,只是需要額外設置一個 void_completion_t 回調函數,在此不再贅述。
以上內容是 Zookeeper C API 中異步 API 的介紹,如有錯誤請留下您的想法和意見,我會盡快更正;同時,我也將在后面的文章中列舉一些示例來說明上述 API 的用法,如有興趣請繼續關注。