久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Zookeeper C API 指南

發布時間:2025/3/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Zookeeper C API 指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以前自己的博客中轉載、翻譯或寫過(不過自己才疏學淺,寫的不好)一些 Zookeeper 方面的文章,但是都沒有涉及到 Zookeeper C API 的內容,今天的這篇博客是我農歷新年的第一篇技術博客,我想詳細講講 Zookeeper C API 的使用規則和示例,算是把以前的舊帳還上吧 :-)

Zookeeper 官方頁面上提供了一些編程指南和 API 文檔,不過大部分都是 Java 示例,涉及 C API 的部分很少,只有在 ZooKeeper Programmer's Guide 中 ACL Permissions 一節講了 Zookeeper C API 中設置 ACL 應該注意的事項,正是由于缺少Zookeeper C API 相關的資料,大部分 Zookeeper C/C++ 開發者只能通過閱讀 Zookeeper C API 的源碼來了解 C API 的使用方法,本文希望在此方面給大家提供一些便利,減少 Zookeeper 新手使用 C API 的困難和恐懼,當然我自己也是一枚新手啦 :-)。

廢話不多說了,先從最基本的開始吧!

Zookeeper 偽分布式安裝

首先是 Zookeeper 的安裝,如果你沒有足夠的機器,建議在單機上通過偽分布式安裝方法來模擬 Zookeeper 集群,我在這里提供給大家一個簡單的安裝包來降低偽分布式 Zookeeper 的安裝難度,該安裝包可以模擬一個 5 Zookeeper 實例的集群。下載zookeeper-3.4.0-pseudoclusters.tar.bz2,解壓至 /tmp/ 目錄(注意,安裝包里面 dataDir 和 dataLogDir 配置已經預設為 /tmp/ 目錄,如果你只是自己在 Zookeeper 上做一些小實驗,建議不要更改該配置,這樣在你做完了實驗以后刪除 /tmp/zookeeper/ 目錄即可),操作方法如下:

forhappy@haiping-ict:/tmp$ pwd /tmp forhappy@haiping-ict:/tmp$ tar xvf zookeeper-3.4.0-pseudoclusters.tar.bz2 forhappy@haiping-ict:/tmp$ cd zookeeper/ forhappy@haiping-ict:/tmp/zookeeper$ ls server001 server003 server005 stopZKCluster.sh server002 server004 startZKCluster.sh

然后在 /tmp/zookeeper 目錄下執行 startZKCluster.sh 啟動 Zookeeper 服務,或者執行 stopZKCluster.sh 停掉 Zookeeper 服務。

啟動 Zookeeper 服務:

forhappy@haiping-ict:/tmp/zookeeper$ ./startZKCluster.sh . starting zookeeper instance server001... JMX enabled by default Using config: /tmp/zookeeper/server001/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server002... JMX enabled by default Using config: /tmp/zookeeper/server002/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server003... JMX enabled by default Using config: /tmp/zookeeper/server003/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server004... JMX enabled by default Using config: /tmp/zookeeper/server004/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server005... JMX enabled by default Using config: /tmp/zookeeper/server005/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED

停掉 Zookeeper 服務:

forhappy@haiping-ict:/tmp/zookeeper$ ./stopZKCluster.sh . stopping zookeeper instance server001... JMX enabled by default Using config: /tmp/zookeeper/server001/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server002... JMX enabled by default Using config: /tmp/zookeeper/server002/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server003... JMX enabled by default Using config: /tmp/zookeeper/server003/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server004... JMX enabled by default Using config: /tmp/zookeeper/server004/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server005... JMX enabled by default Using config: /tmp/zookeeper/server005/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED

Zookeeper C API 安裝

Zookeeper C client 的實現在 src/c 目錄下,進入到該目錄安裝 Zookeeper C client,步驟如下:

$ ./configure $ make $ sudo make install

至此,基本的準備工作已經完成,你可以通過 Zookeeper 本身提供的 Shell 來操作 Zookeeper,操作方法如下,進入 /tmp/zookeeper/server001/zookeeper-3.4.0 目錄,執行bin/zkCli.sh -server 127.0.0.1:2181 進入 Zookeeper shell:

forhappy@haiping-ict:/tmp/zookeeper/server001/zookeeper-3.4.0$ bin/zkCli.sh -server 127.0.0.1:2181 [zk: 127.0.0.1:2181(CONNECTED) 2] help ZooKeeper -server host:port cmd argsconnect host:portget path [watch]ls path [watch]set path data [version]rmr pathdelquota [-n|-b] pathquit printwatches on|offcreate [-s] [-e] path data aclstat path [watch]close ls2 path [watch]history listquota pathsetAcl path aclgetAcl pathsync pathredo cmdnoaddauth scheme authdelete path [version]setquota -n|-b val path

在 shell 中你可以完成基本的操作,如創建、獲取、刪除、設置某一節點,設置節點 ACL等,可以 zookeeper shell 中通過 help 獲取相關命令的用法。

如果你按照上面的步驟完成了 Zookeeper 偽分布式的安裝,并且想繼續了解 Zookeeper C API 的使用方法,請繼續閱讀《Zookeeper C API 指南二(監視(Wathes), 基本常量和結構體介紹)》


接上一篇《Zookeeper C API 指南一(準備工作)》,本問將重點介紹 Zookeeper 監視(Watches),以及 Zookeeper C API 中基本的常量與結構體。

Zookeeper 監視(Watches) 簡介

Zookeeper C API 的聲明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量、結構體聲明也在 zookeeper.h 中,如果如果你在使用 C API 是遇到不明白的地方,最好看看 zookeeper.h,或者自己使用 doxygen 生成 Zookeeper C API 的幫助文檔。

Zookeeper 中最有特色且最不容易理解的是監視(Watches)。Zookeeper 所有的讀操作——getData(),getChildren(), 和 exists() 都 可以設置監視(watch),監視事件可以理解為一次性的觸發器, 官方定義如下: a watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes。對此需要作出如下理解:

  • (一次性觸發)One-time trigger

    當設置監視的數據發生改變時,該監視事件會被發送到客戶端,例如,如果客戶端調用了 getData("/znode1", true) 并且稍后 /znode1 節點上的數據發生了改變或者被刪除了,客戶端將會獲取到 /znode1 發生變化的監視事件,而如果 /znode1 再一次發生了變化,除非客戶端再次對 /znode1 設置監視,否則客戶端不會收到事件通知。

  • (發送至客戶端)Sent to the client

    Zookeeper 客戶端和服務端是通過 socket 進行通信的,由于網絡存在故障,所以監視事件很有可能不會成功地到達客戶端,監視事件是異步發送至監視者的,Zookeeper 本身提供了保序性(ordering guarantee):即客戶端只有首先看到了監視事件后,才會感知到它所設置監視的 znode 發生了變化(a client will never see a change for which it has set a watch until it first sees the watch event). 網絡延遲或者其他因素可能導致不同的客戶端在不同的時刻感知某一監視事件,但是不同的客戶端所看到的一切具有一致的順序。

  • (被設置 watch 的數據)The data for which the watch was set

    這意味著 znode 節點本身具有不同的改變方式。你也可以想象 Zookeeper 維護了兩條監視鏈表:數據監視和子節點監視(data watches and child watches) getData() and exists() 設置數據監視,getChildren() 設置子節點監視。 或者,你也可以想象 Zookeeper 設置的不同監視返回不同的數據,getData() 和 exists() 返回 znode 節點的相關信息,而 getChildren() 返回子節點列表。因此, setData() 會觸發設置在某一節點上所設置的數據監視(假定數據設置成功),而一次成功的 create() 操作則會出發當前節點上所設置的數據監視以及父節點的子節點監視。一次成功的 delete() 操作將會觸發當前節點的數據監視和子節點監視事件,同時也會觸發該節點父節點的child watch。

Zookeeper 中的監視是輕量級的,因此容易設置、維護和分發。當客戶端與 Zookeeper 服務器端失去聯系時,客戶端并不會收到監視事件的通知,只有當客戶端重新連接后,若在必要的情況下,以前注冊的監視會重新被注冊并觸發,對于開發人員來說 這通常是透明的。只有一種情況會導致監視事件的丟失,即:通過 exists() 設置了某個 znode 節點的監視,但是如果某個客戶端在此 znode 節點被創建和刪除的時間間隔內與 zookeeper 服務器失去了聯系,該客戶端即使稍后重新連接 zookeeper服務器后也得不到事件通知。

Zookeeper C API 常量與部分結構(struct)介紹

與 ACL 相關的結構與常量:

struct Id 結構為:

struct Id {char * scheme;char * id; };

struct ACL 結構為:

struct ACL {int32_t perms;struct Id id; };

struct ACL_vector 結構為:

struct ACL_vector {int32_t count;struct ACL *data;};

與 znode 訪問權限有關的常量

  • const int ZOO_PERM_READ; //允許客戶端讀取 znode 節點的值以及子節點列表。

  • const int ZOO_PERM_WRITE;// 允許客戶端設置 znode 節點的值。

  • const int ZOO_PERM_CREATE; //允許客戶端在該 znode 節點下創建子節點。

  • const int ZOO_PERM_DELETE;//允許客戶端刪除子節點。

  • const int ZOO_PERM_ADMIN; //允許客戶端執行 set_acl()。

  • const int ZOO_PERM_ALL;//允許客戶端執行所有操作,等價與上述所有標志的或(OR) 。

與 ACL IDs 相關的常量

  • struct Id ZOO_ANYONE_ID_UNSAFE; //(‘world’,’anyone’)

  • struct Id ZOO_AUTH_IDS;// (‘auth’,’’)

三種標準的 ACL

  • struct ACL_vector ZOO_OPEN_ACL_UNSAFE; //(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)

  • struct ACL_vector ZOO_READ_ACL_UNSAFE;// (ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)

  • struct ACL_vector ZOO_CREATOR_ALL_ACL; //(ZOO_PERM_ALL,ZOO_AUTH_IDS)

與 Interest 相關的常量:ZOOKEEPER_WRITE, ZOOKEEPER_READ

這 兩個常量用于標識感興趣的事件并通知 zookeeper 發生了哪些事件。Interest 常量可以進行組合或(OR)來標識多種興趣(multiple interests: write, read),這兩個常量一般用于 zookeeper_interest() 和 zookeeper_process()兩個函數中。

與節點創建相關的常量:ZOO_EPHEMERAL,?ZOO_SEQUENCE

zoo_create 函數標志,ZOO_EPHEMERAL 用來標識創建臨時節點,ZOO_SEQUENCE 用來標識節點命名具有遞增的后綴序號(一般是節點名稱后填充 10 位字符的序號,如 /xyz0000000000, /xyz0000000001, /xyz0000000002, ...),同樣地,ZOO_EPHEMERAL,?ZOO_SEQUENCE可以組合。

與連接狀態 Stat 相關的常量

以下常量均與 Zookeeper 連接狀態有關,他們通常用作監視器回調函數的參數。

ZOOAPI const int?ZOO_EXPIRED_SESSION_STATE
ZOOAPI const int?ZOO_AUTH_FAILED_STATE
ZOOAPI const int?ZOO_CONNECTING_STATE
ZOOAPI const int?ZOO_ASSOCIATING_STATE
ZOOAPI const int?ZOO_CONNECTED_STATE

與監視類型(Watch Types)相關的常量

以下常量標識監視事件的類型,他們通常用作監視器回調函數的第一個參數。

  • ZOO_CREATED_EVENT; // 節點被創建(此前該節點不存在),通過 zoo_exists() 設置監視。
  • ZOO_DELETED_EVENT; // 節點被刪除,通過 zoo_exists() 和 zoo_get() 設置監視。
  • ZOO_CHANGED_EVENT; // 節點發生變化,通過 zoo_exists() 和 zoo_get() 設置監視。
  • ZOO_CHILD_EVENT; // 子節點事件,通過zoo_get_children() 和 zoo_get_children2()設置監視。
  • ZOO_SESSION_EVENT; // 會話丟失
  • ZOO_NOTWATCHING_EVENT; // 監視被移除。

Zookeeper C API 錯誤碼介紹 ZOO_ERRORS

ZOK?

正常返回

ZSYSTEMERROR?

系統或服務器端錯誤(System and server-side errors),服務器不會拋出該錯誤,該錯誤也只是用來標識錯誤范圍的,即大于該錯誤值,且小于 ZAPIERROR 都是系統錯誤。

ZRUNTIMEINCONSISTENCY?

運行時非一致性錯誤。

ZDATAINCONSISTENCY?

數據非一致性錯誤。

ZCONNECTIONLOSS?

Zookeeper 客戶端與服務器端失去連接

ZMARSHALLINGERROR?

marshallingunmarshalling 數據時出現錯誤(Error while marshalling or unmarshalling data)

ZUNIMPLEMENTED?

該操作未實現(Operation is unimplemented)

ZOPERATIONTIMEOUT?

該操作超時(Operation timeout)

ZBADARGUMENTS?

非法參數錯誤(Invalid arguments)

ZINVALIDSTATE?

非法句柄狀態(Invliad zhandle state)

ZAPIERROR?

API 錯誤(API errors),服務器不會拋出該錯誤,該錯誤也只是用來標識錯誤范圍的,錯誤值大于該值的標識 API 錯誤,而小于該值的標識 ZSYSTEMERROR。

ZNONODE?

節點不存在(Node does not exist)

ZNOAUTH?

沒有經過授權(Not authenticated)

ZBADVERSION?

版本沖突(Version conflict)

ZNOCHILDRENFOREPHEMERALS?

臨時節點不能擁有子節點(Ephemeral nodes may not have children)

ZNODEEXISTS?

節點已經存在(The node already exists)

ZNOTEMPTY?

該節點具有自身的子節點(The node has children)

ZSESSIONEXPIRED?

會話過期(The session has been expired by the server)

ZINVALIDCALLBACK?

非法的回調函數(Invalid callback specified)

ZINVALIDACL?

非法的ACL(Invalid ACL specified)

ZAUTHFAILED?

客戶端授權失敗(Client authentication failed)

ZCLOSING?

Zookeeper 連接關閉(ZooKeeper is closing)

ZNOTHING?

并非錯誤,客戶端不需要處理服務器的響應(not error, no server responses to process)

ZSESSIONMOVED?

會話轉移至其他服務器,所以操作被忽略(session moved to another server, so operation is ignored)

?

至此,Zookeeper C API 中的大部分的常量和結構體均已介紹完畢,下一節《Zookeeper C API 指南三(回調函數)》將介紹 Zookeeper C API 中的回調函數。

接上一篇《Zookeeper C API 指南二(監視(Wathes), 基本常量和結構體介紹)》,本文重點介紹 Zookeeper C API 中的各種回調函數。

Zookeeper C API 中各種回調函數簡介

在具體介紹 Zookeeper C API 之前,首先介紹一下 Zookeeper C API 中的各種回調函數的原型:

監視函數(watch function)原型

typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path,void *watcherCtx);

?監視函數原型的各個參數解釋如下:

zhzookeeper 句柄(handle)
type事件類型(event type). *_EVENT 常量之一.
state連接狀態(connection state). 狀態值為 *_STATE 常量之一.
path觸發監視事件的 znode 節點的路徑,若為 NULL,則事件類型為 ZOO_SESSION_EVENT
watcherCtx監視器上下文(watcher context).

其他回調函數的原型

Zookeeper 中還有幾種在異步 API(一般以 zoo_a*開頭的函數) 中使用的回調函數,根據回調函數處理異步函數返回值類型的不同分為以下幾類:處理返回 void 類型的回調函數,處理返回 Stat 結構的回調函數,處理返回字符串的回調函數,處理返回數據的回調函數,處理返回字符串列表(a list of string)的回調函數,同時處理返回字符串列表(a list of string)和 Stat 結構的回調函數,以及處理返回 ACL 信息的回調函數,它們分別如下:

// 處理返回 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);

?下面一一介紹上述幾種回調函數的用法:

  • 處理返回 void 類型的回調函數
typedef void(* void_completion_t)(int rc, const void *data)

該回調函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
data由調用者傳入指針,調用者可以通過該指針向回調函數傳入自定義的參數,開發人員應負責此指針所指向內存的釋放。

?

  • 處理返回 Stat 結構的回調函數
typedef void(* stat_completion_t)(int rc, const struct Stat *stat, const void *data)

該函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
stat指向與該 znode 節點相關的 Stat 信息,如果返回非 0 值(即異步調用函數出錯),stat 所指向的區域是未定義的,開發者不負責釋放 stat 所指向的內存空間。
data由調用者傳入指針,調用者可以通過該指針向回調函數傳入自定義的參數,開發人員應負責此指針所指向內存的釋放。

?

  • 處理返回字符串的回調函數
typedef void(* string_completion_t)(int rc, const char *value, const void *data)

該函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
value返回的字符串
data由調用者傳入指針,調用者可以通過該指針向回調函數傳入自定義的參數,開發人員應負責此指針所指向內存的釋放。

?

  • 處理返回數據的回調函數
typedef void(* data_completion_t)(int rc, const char *value, int value_len, const struct Stat *stat, const void *data)

該函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
value異步調用的返回值,如果返回非 0 值(即異步調用函數出錯),value 所指向的區域是未定義的,開發者不負責釋放?value 所指向的內存空間。
value_len返回 value 數據字節數(bytes)
stat指向與該 znode 節點相關的 Stat 信息,如果返回非 0 值(即異步調用函數出錯),stat 所指向的區域是未定義的,開發者不負責釋放 stat 所指向的內存空間。
data由調用者傳入指針,調用者可以通過該指針向回調函數傳入自定義的參數,開發人員應負責此指針所指向內存的釋放。

?

  • 處理返回字符串列表(a list of string)的回調函數
typedef void(* strings_completion_t)(int rc, const struct String_vector *strings, const void *data)

該函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
strings指向包含了某 znode 節點的所有子節點名稱列表的結構,如果返回非 0 值(即異步調用函數出錯),strings 所指向的區域是未定義的,開發者不負責釋放strings 所指向的內存空間。
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)

該函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
strings指向包含了某 znode 節點的所有子節點名稱列表的結構,如果返回非 0 值(即異步調用函數出錯),strings 所指向的區域是未定義的,開發者不負責釋放strings 所指向的內存空間。
stat指向與該 znode 節點相關的 Stat 信息,如果返回非 0 值(即異步調用函數出錯),stat 所指向的區域是未定義的,開發者不負責釋放 stat 所指向的內存空間。
data由調用者傳入的指針,調用者可以通過該指針向回調函數傳入自定義的參數,開發人員應負責此指針所指向內存的釋放。

?

  • 處理返回 ACL 信息的回調函數
typedef void(* acl_completion_t)(int rc, struct ACL_vector *acl, struct Stat *stat, const void *data)

該函數一般在異步 API 調用結束或 Zookeeper? 客戶端失去連接時被調用。

rc異步函數調用返回的錯誤碼,連接丟失/超時將觸發該原型函數(此處指具有該函數原型的回調函數,下同)的調用,并且錯誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時;而與數據相關的事件也會觸發該原型函數的調用,同時置相應的錯誤碼,具體見后文(0 代異步函數調用成功)
acl指向包含某 znode 節點 ACL 信息的指針,如果返回非 0 值(即異步調用函數出錯),acl 所指向的區域是未定義的,開發者不負責釋放 acl 所指向的內存空間。
stat指向與該 znode 節點相關的 Stat 信息,如果返回非 0 值(即異步調用函數出錯),stat 所指向的區域是未定義的,開發者不負責釋放 stat 所指向的內存空間。
data由調用者傳入的指針,調用者可以通過該指針向回調函數傳入自定義的參數,開發人員應負責此指針所指向內存的釋放。

?

至此,所有的回調函數均已介紹完畢,下一節將介紹 Zookeeper C API 分類和基本 API 的使用,見第四講《Zookeeper C API 指南四(C API 概覽)》

上一節《Zookeeper C API 指南三(回調函數)》重點講了 Zookeeper C API 中各種回調函數的原型,本節將切入正題,正式講解 Zookeeper C API。相信大家讀完本文后應該對 Zookeeper C API 的使用有一個比較清晰的認識。

Zookeeper C API 概覽

Zookeeper C API 很規范,接口很容易記憶,大部分接口均以 zoo_ 開頭,只有少量接口以 zookeeper_ 開頭,所有的 API 匯總如下:

void zoo_create_op_init(zoo_op_t * op, const char *path, const char *value,int valuelen, const struct ACL_vector *acl,int flags, char *path_buffer, int path_buffer_len);void zoo_delete_op_init(zoo_op_t * op, const char *path, int version);void zoo_set_op_init(zoo_op_t * op, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);void zoo_check_op_init(zoo_op_t * op, const char *path, int version);ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,int recv_timeout,const clientid_t * clientid,void *context, int flags);ZOOAPI int zookeeper_close(zhandle_t * zh);ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);ZOOAPI int zoo_recv_timeout(zhandle_t * zh);ZOOAPI const void *zoo_get_context(zhandle_t * zh);ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);ZOOAPI int zookeeper_interest(zhandle_t * zh, int *fd, int *interest,struct timeval *tv);ZOOAPI int zookeeper_process(zhandle_t * zh, int events);ZOOAPI int zoo_state(zhandle_t * zh);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);ZOOAPI const char *zerror(int c);ZOOAPI int zoo_add_auth(zhandle_t * zh, const char *scheme,const char *cert, int certLen,void_completion_t completion, const void *data);ZOOAPI int is_unrecoverable(zhandle_t * zh);ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);ZOOAPI void zoo_set_log_stream(FILE * logStream);ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_set(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version);ZOOAPI int zoo_set2(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path,struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version,const struct ACL_vector *acl);ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results);

除了基本的初始化、銷毀 Zookeeper 句柄(zhandle),設置日志等級、日志流以及一些具有輔助功能 API(zerror(), zoo_state()等) 外,Zookeeper C API 大部分接口可以根據同步和異步特性分為兩類,同步接口以 zoo_* 開頭,異步接口以則以 zoo_a* 開頭。并且除了 zookeeper_init() 以及與 zoo_multi() 或 zoo_amulti() 批量操作相關的 zoo_op_t 初始化外,其他的 API 的第一個參數均為 zhandle_t * zh, 即 Zookeeper 句柄的指針。

Zookeeper C API 分類

  • 初始化、銷毀 Zookeeper 句柄
ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,int recv_timeout,const clientid_t * clientid,void *context, int flags);ZOOAPI int zookeeper_close(zhandle_t * zh);
  • 輔助函數
// 設置日志等級、日志流 ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel); ZOOAPI void zoo_set_log_stream(FILE * logStream);ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);ZOOAPI int zoo_recv_timeout(zhandle_t * zh);ZOOAPI const void *zoo_get_context(zhandle_t * zh);ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);ZOOAPI int zookeeper_interest(zhandle_t * zh, int *fd, int *interest,struct timeval *tv);ZOOAPI int zookeeper_process(zhandle_t * zh, int events);ZOOAPI int zoo_state(zhandle_t * zh);ZOOAPI const char *zerror(int c);ZOOAPI int is_unrecoverable(zhandle_t * zh);ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);
  • 與 zoo_multi() 和 zoo_amulti() 批量操作相關的 zoo_op_t 初始化
void zoo_create_op_init(zoo_op_t * op, const char *path, const char *value,int valuelen, const struct ACL_vector *acl,int flags, char *path_buffer, int path_buffer_len);void zoo_delete_op_init(zoo_op_t * op, const char *path, int version);void zoo_set_op_init(zoo_op_t * op, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);void zoo_check_op_init(zoo_op_t * op, const char *path, int version);
  • Zookeeper C API 同步接口
ZOOAPI int zoo_add_auth(zhandle_t * zh, const char *scheme,const char *cert, int certLen,void_completion_t completion, const void *data);ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_set(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version);ZOOAPI int zoo_set2(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path,struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version,const struct ACL_vector *acl);ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results);
  • Zookeeper C 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);

?Zookeeper C API 初體驗

有了上面的介紹,下面我們來看一看如何使簡單地使用 Zookeeper C API 吧。

在使用 Zookeeper C API 時應注意:

  • 頭文件包含 #include <zookeeper/zookeeper.h>
  • 如果你需要編譯多線程版本客戶端程序,請添加編譯選項 -DTHREADED,同時鏈接時應鏈接?zookeeper_mt 庫;如果你需要編譯單線程客戶端程序,請不要添加編譯選項 -DTHREADED,同時鏈接時應鏈接?zookeeper_st 庫。

一個基本的程序如下(更詳細的例子可以參看 src/c/src/cli.c):

/** =============================================================================** Filename: zktest.c** Description: zookeeper api testcase.** Created: 02/15/2013 08:48:49 PM** Author: Fu Haiping (forhappy), haipingf@gmail.com* Company: ICT ( Institute Of Computing Technology, CAS )** =============================================================================*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <zookeeper/zookeeper.h> #include <zookeeper/zookeeper_log.h>void zktest_watcher_g(zhandle_t* zh, int type, int state,const char* path, void* watcherCtx) {printf("Something happened.\n");printf("type: %d\n", type);printf("state: %d\n", state);printf("path: %s\n", path);printf("watcherCtx: %s\n", (char *)watcherCtx); }void zktest_dump_stat(const struct Stat *stat) {char tctimes[40];char tmtimes[40];time_t tctime;time_t tmtime;if (!stat) {fprintf(stderr,"null\n");return;}tctime = stat->ctime/1000;tmtime = stat->mtime/1000;ctime_r(&tmtime, tmtimes);ctime_r(&tctime, tctimes);fprintf(stderr, "\tctime = %s\tczxid=%llx\n""\tmtime=%s\tmzxid=%llx\n""\tversion=%x\taversion=%x\n""\tephemeralOwner = %llx\n",tctimes, stat->czxid,tmtimes, stat->mzxid,(unsigned int)stat->version, (unsigned int)stat->aversion,stat->ephemeralOwner); }void zktest_stat_completion(int rc, const struct Stat *stat, const void *data) {fprintf(stderr, "%s: rc = %d Stat:\n", (char*)data, rc);zktest_dump_stat(stat); }void zktest_void_completion(int rc, const void *data) {fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc); }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);} }int main(int argc, const char *argv[]) {const char* host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185";int timeout = 30000;zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);zhandle_t* zkhandle = zookeeper_init(host,zktest_watcher_g, timeout, 0, "hello zookeeper.", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}// struct ACL ALL_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};// struct ACL_vector ALL_PERMS = {1, ALL_ACL};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);}ret = 0;ret = zoo_aexists(zkhandle, "/xyz", 1, zktest_stat_completion, "aexists");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "aexists");exit(EXIT_FAILURE);}ret = 0;// Wait for asynchronous zookeeper call done. getchar();ret = zoo_adelete(zkhandle, "/xyz", -1, zktest_void_completion, "adelete");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "adelete");exit(EXIT_FAILURE);}// Wait for asynchronous zookeeper call done. getchar();zookeeper_close(zkhandle); }

下面簡單講講這個程序的結構:

  • 首先聲明 host, timeout 變量。
const char* host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185"; int timeout = 30000;

其中 host 字符串格式為逗號隔開的 IP:PORT對,可以是 Zookeeper 集群中的全部或部分 Zookeeper 實例的 IP:PORT對,我們在第一講《準備工作》中介紹了如何部署一個偽分布式的集群,上述的 host 就是這些 zookeeper 實例的IP:PORT對。

另外 timeout 是 Zookeeper 客戶端連接服務器的超時時間,單位為毫秒,timeout = 30000 說明如果 30 秒內客戶端沒有連接上 Zookeeper 服務則表示連接超時。

  • 設置日志等級。
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
  • 初始化 Zookeeper 句柄(zhandle_t)。
zhandle_t* zkhandle = zookeeper_init(host,zktest_watcher_g, timeout, 0, "hello zookeeper.", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}

初始化 Zookeeper 句柄 zookeeper_init() 函數原型如下:

ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,int recv_timeout,const clientid_t * clientid,void *context, int flags);

各個參數解釋如下:

host逗號隔開的 host:port 對, 每個代表一個 zk server, 例如: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002"
fn全局的監視器回調函數,當發生事件通知時,該函數會被調用。
clientid客戶端嘗試重連的先前會話的ID,如果不需要重連先前的會話,則設置為 0??蛻舳丝梢酝ㄟ^調用 zoo_client_id來訪問一個已經連接上的并且有效的會話ID,如果clientid對應的會話超時,或者由于某種原因 clientid變為無效了,那么zookeeper_init 將返回一個非法的zhandle_t, 通過 zhandle_t 的狀態可以獲知zookeeper_init 調用失敗的原因。 (通常為 ZOO_EXPIRED_SESSION_STATE).
context與 zhandle_t 實例相關聯的“上下文對象”(可以通過該參數為 zhandle_t 傳入自定義類型的數據),應用程序可以通過 zoo_get_context訪問它(例如在監視器回調函數中),當然 zookeeper 內部沒有用到該參數,所以 context 可以設置為 NULL。
flags目前為保留參數,設置為 0。
  • 創建一個 znode 節點。
// struct ACL ALL_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};// struct ACL_vector ALL_PERMS = {1, ALL_ACL};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);}

這里采用異步方式創建 znode 節點,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);

各個參數解釋如下:

zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
value該節點保存的數據。
valuelen該節點保存數據的大小。
acl該節點初始 ACL,ACL 不能為null 或空。
flags該參數可以設置為 0,或者創建標識符 ZOO_EPHEMERAL,?ZOO_SEQUENCE 的組合或(OR)。
completion當創建節點請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 父節點不存在;ZNODEEXISTS 節點已存在;ZNOAUTH 客戶端沒有權限創建節點。ZNOCHILDRENFOREPHEMERALS 臨時節點不能創建子節點。
datacompletino函數被調用時,傳遞給 completion 的數據。
  • 調用 exists() 函數,設置監視器。
ret = zoo_aexists(zkhandle, "/xyz", 1, zktest_stat_completion, "aexists");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "aexists");exit(EXIT_FAILURE);}
  • 調用 delete 函數,刪除 znode 節點。
ret = zoo_adelete(zkhandle, "/xyz", -1, zktest_void_completion, "adelete");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "adelete");exit(EXIT_FAILURE);}
  • 銷毀 zookeeper 句柄
zookeeper_close(zkhandle);

好了,至此本文大致講完了 Zookeeper C API 的分類和幾個基本函數的用法。之所以為 Zookeeper C API 分類是方便記憶,開發者可以迅速找到自己需要的 API;另外,本文還講了幾個基本函數的使用方法,包括 zookeeper_init(),zoo_acreate(), zoo_aexists(), zoo_adelete() 以及 zookeeper_close()。相信大家對 Zookeeper C API 也有了一個大致的了解,第五講我會給大家介紹 Zookeeper C API 中的同步調用的函數(即以 zoo_* 開頭的函數),然后第六講給大家介紹 Zookeeper C API 中的異步調用的函數(即以 zoo_a* 開頭的函數)。

上一講《Zookeeper C API 指南四(C API 概覽)》講了Zookeeper C API 的分類和幾個基本函數的用法,相信大家對 Zookeeper C API 也有了一個大致的了解,本文我會給大家介紹 Zookeeper C API 中的同步調用的函數(即以 zoo_* 開頭的函數)。

Zookeeper C API 中與訪問 Zookeeper 服務相關(比如創建、刪除 znode 節點,獲取子節點,設置 znode 數據等)的同步 API 如下:

ZOOAPI int zoo_add_auth(zhandle_t * zh, const char *scheme,const char *cert, int certLen,void_completion_t completion, const void *data);ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_set(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version);ZOOAPI int zoo_set2(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path,struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version,const struct ACL_vector *acl);ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results);

本文將以上同步 API 在此細分為一下幾類:(1). 創建、刪除 znode 節點,(2). 可設置 watch 的 API,(3). 訪問、設置節點 ACL 的 API,(4). 批處理 API

  • 創建、刪除 znode 節點(兩個)
ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);
  • 創建 znode 節點:
ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
value該節點保存的數據。
valuelen該節點保存數據的大小。如果 value 被設置為 NULL(該 znode 節點不包含數據),則 valuelen 應該設置為 -1。
acl該節點初始 ACL,ACL 不能為null 或空。
flags該參數可以設置為 0,或者創建標識符ZOO_EPHEMERAL,?ZOO_SEQUENCE 的組合或(OR)。
path_buffer用于保存返回節點新路徑(因為設置了ZOO_SEQUENCE 后 zoo_create 所創建的節點名稱與參數 path 提供的名稱不同,新的節點名稱后面填充了序號),path 字符串以 NULL 結束。path_buffer 可以設置為 NULL,此時 path_buffer_len 等于 0。
path_buffer_lenpath_buffer 的長度,如果新節點名稱的長度大于path_buffer_len,則節點名稱將會被截斷,而服務器端該節點的名稱不會截斷。
  • 刪除 znode 節點:
ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
version節點的版本號,如果該 znode 節點的實際版本號與該參數提供的版本號不一值,則刪除節點失敗,如果 version 為 -1,則不作版本檢查。

?

  • 可設置 watch 的 API(exists(兩個) + get(兩個) + get_children(四個) = 八個)
ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);
  • 檢查節點狀態 exists(兩個,分別是 zoo_exists() 和 zoo_wexists(),區別是后者可以指定單獨的 watcher_fn(監視器回調函數),而前者只能用 zookeeper_init() 設置的全局監視器回調函數,同時 get 和 get_children兩族函數也一樣,帶有zoo_w* 的函數可以指定單獨的 watcher_fn)。
ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
stat返回的 Stat 信息。

?

ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx,struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果不為 NULL 則會在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
stat返回的 Stat 信息。

?

  • 獲取節點數據 get(兩個)
ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。
buffer用于保存從 zookeeper 服務器獲取的節點數據。
buffer_lenbuffer 大小,一旦成功返回該值將會被設置為節點數據的實際大小,如果節點的數據為空,則數據大小為 -1,buffer_len 也為 -1。
stat如果非空,stat 指向的結構將會保存該節點的 Stat 信息。

?

ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果不為 NULL 則會在服務器端設置監視,當節點發生變化時客戶端會得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
buffer用于保存從 zookeeper 服務器獲取的節點數據。
buffer_lenbuffer 大小,一旦成功返回該值將會被設置為節點數據的實際大小,如果節點的數據為空,則數據大小為 -1,buffer_len 也為 -1。
stat如果非空,stat 指向的結構將會保存該節點的 Stat 信息。
  • 獲取子節點列表 get_children(四個)
ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。
strings返回各個子節點路徑

?

ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx,struct String_vector *strings);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果不為 NULL 則會在服務器端設置監視,當節點發生變化時客戶端會得到通知
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
strings回各個子節點路徑

?

ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path, int watch, struct String_vector *strings,struct Stat *stat);

該函數最早出現在 Zookeeper 3.3.0中,該函數功能與 zoo_get_children() 基本一致,但同時還會返回指定節點的 Stat 信息。

zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。
strings返回各個子節點路徑。
stat返回指定節點的 Stat 信息。

?

ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);

該函數最早出現在 Zookeeper 3.3.0中,該函數功能與 zoo_wget_children() 基本一致,但同時還會返回指定節點的 Stat 信息。

zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果不為 NULL 則會在服務器端設置監視,當節點發生變化時客戶端會得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
strings返回各個子節點路徑。
stat返回指定節點的 Stat 信息。
  • 訪問、設置節點 ACL (兩個)
ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path, struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version, const struct ACL_vector *acl);
  • 獲取節點 ACL 信息
ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path, struct ACL_vector *acl, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
acl該函數所返回的指定節點的 ACL 信息。
stat返回指定節點的 Stat 信息。
  • 設置節點 ACL
ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version, const struct ACL_vector *acl);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
version節點的版本號。
acl需要設置的 ACL 信息。
  • 批處理,即原子性地一次提交多個 Zookeeper 操作。
ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops, zoo_op_result_t * results);
zhzookeeper_init() 返回的 zookeeper 句柄。
count提交操作的個數。
ops包含所提交操作數組。
results包含操作所返回結果的數組。

其中 zoo_op_t 是各種操作(創建、刪除節點,設置節點數據和檢查節點狀態四種操作)一個封裝(聯合體),定義如下:

typedef struct zoo_op {int type;union {// CREATEstruct {const char *path;const char *data;int datalen;char *buf;int buflen;const struct ACL_vector *acl;int flags;} create_op;// DELETE struct {const char *path;int version;} delete_op;// SETstruct {const char *path;const char *data;int datalen;int version;struct Stat *stat;} set_op;// CHECKstruct {const char *path;int version;} check_op;}; } zoo_op_t;

zoo_op_t 一般由以下四個函數初始化:

void zoo_create_op_init(zoo_op_t * op, const char *path, const char *value,int valuelen, const struct ACL_vector *acl,int flags, char *path_buffer, int path_buffer_len);void zoo_delete_op_init(zoo_op_t * op, const char *path, int version);void zoo_set_op_init(zoo_op_t * op, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);void zoo_check_op_init(zoo_op_t * op, const char *path, int version);

zoo_op_result_t 用于保存 zoo_multi 或者 zoo_amulti 返回的其中一個結果,定義如下:

typedef struct zoo_op_result {int err;char *value;int valuelen;struct Stat *stat; } zoo_op_result_t;

?

以上內容是 Zookeeper? C API 中同步 API 的介紹,如有錯誤請留下您的想法和意見,本人會盡快更正;同時,我也將在后面的文章中列舉一些示例來說明上述 API 的用法,如有興趣請繼續關注,如果您需要了解 Zookeeper 異步 API,請移步第六講《Zookeeper C API 指南六(異步 API 介紹)》。

上一講《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);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
value該節點保存的數據。
valuelen該節點保存數據的大小。
acl該節點初始 ACL,ACL 不能為null 或空。
flags該參數可以設置為 0,或者創建標識符 ZOO_EPHEMERAL,?ZOO_SEQUENCE 的組合或(OR)。
completion當創建節點請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 父節點不存在;ZNODEEXISTS 節點已存在;ZNOAUTH 客戶端沒有權限創建節點。ZNOCHILDRENFOREPHEMERALS 臨時節點不能創建子節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。
  • 刪除 znode 節點
ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version,void_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
version期望的節點版本號,如果真實的版本號與期望的版本號不同則 zoo_delete() 調用失敗,-1 表示不不檢查版本號。
completion當刪除節點請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點;ZBADVERSION 版包號不匹配;ZNOTEMPTY 當前節點存在子節點,不能被刪除。
datacompletion 函數被調用時,傳遞給 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);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
completion當 zoo_aexists 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。

?

ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,stat_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
completionzoo_awexists 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。

?

  • 獲取節點數據 aget(兩個)
ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch,data_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。
completionzoo_aget 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。

?

ZOOAPI int zoo_awget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,data_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
completionzoo_awget 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。

?

  • 獲取子節點列表 aget_children (四個)
ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path,int watch,strings_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。
completion當 zoo_aget_children 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。

?

ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
completion當zoo_awget_children 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 completion 的數據。

?

ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path,int watch,strings_stat_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watch如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知。
completion當 zoo_aget_children2 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 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);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
watcher如果非 0,則在服務器端設置監視,當節點發生變化時客戶端會得到通知,即使當前指定的節點不存在也會設置監視,這樣該節點被創建時,客戶端也可以得到通知。
watcherCtx用戶指定的數據,將被傳入到監視器回調函數中,與由 zookeeper_init() 設置的全局監視器上下文不同,該函數設置的監視器上下文只與當前的監視器相關聯。
completion當zoo_awget_children2 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 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);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
completion當 zoo_aget_acl 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點。
datacompletion 函數被調用時,傳遞給 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);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節點路徑。
buffer保存需要設置的 ACL。
buflenbuffer 的長度。
completion當 zoo_aset_acl 請求完成時會調用該函數,該函數原型詳見第三講《回調函數》一節。同時傳遞給completion的rc參數為: ZOK 操作完成;ZNONODE 節點不存在;ZNOAUTH 客戶端沒有權限刪除節點;ZINVALIDACL 非法 ACL;ZBADVERSION 版本號不匹配。
datacompletion 函數被調用時,傳遞給 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 的用法,如有興趣請繼續關注。

在前面的文章中我們講了大部分 Zookeeper? C API,相信大家已經知道怎樣使用 Zookeeper? C API了吧。我曾在《Zookeeper C API 指南》系列文章的第四篇《Zookeeper C API 指南四(C API 概覽)》中也 Zookeeper C API 的分為了 5 類,他們分別是:(1)、初始化、銷毀 Zookeeper 句柄,(2)、與 zoo_multi() 和 zoo_amulti() 批量操作相關的 zoo_op_t 初始化函數,(3)、同步 API,(4)、異步 API,(5)、輔助函數。其中“(1)、初始化、銷毀 Zookeeper 句柄”已經在《Zookeeper C API 指南四(C API 概覽)》中介紹過了,并且在《Zookeeper C API 指南五(同步 API 介紹)》和《Zookeeper C API 指南六(異步 API 介紹)》中我們又分別講了“同步 API” 和 “異步 API”(其中也簡單地介紹了一下與 zoo_multi() 和 zoo_amulti() 批量操作相關的 zoo_op_t 初始化函數),所以接下來我們再來講講 Zookeeper C API 中的 “輔助函數”。

我們分類的 Zookeeper C API 中輔助函數如下:

ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);ZOOAPI void zoo_set_log_stream(FILE * logStream);ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);ZOOAPI int zoo_recv_timeout(zhandle_t * zh);ZOOAPI const void *zoo_get_context(zhandle_t * zh);ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);ZOOAPI int zookeeper_interest(zhandle_t * zh, int *fd, int *interest,struct timeval *tv);ZOOAPI int zookeeper_process(zhandle_t * zh, int events);ZOOAPI int zoo_state(zhandle_t * zh);ZOOAPI const char *zerror(int c);ZOOAPI int is_unrecoverable(zhandle_t * zh);ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);

下面我們來講講其中比較常用的幾個函數吧 :-)

  • ?設置日志等級
ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);

其中 logLevel 可以是ZOO_LOG_LEVEL_ERROR, ZOO_LOG_LEVEL_WARN,ZOO_LOG_LEVEL_INFO, ZOO_LOG_LEVEL_DEBUG四個取值。

?

  • 設置日志流
ZOOAPI void zoo_set_log_stream(FILE * logStream);

Zookeeper C API 默認的日志流是標準輸出,可以通過該函數設置 Zookeeper C API的日志流為文件。

?

  • 獲取客戶端的 session id,只有在客戶端的當前連接狀態有效時才可以。
ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);

?

  • 返回當前會話的超時時間,只有在客戶端的當前連接狀態有效時才可以。
ZOOAPI int zoo_recv_timeout(zhandle_t * zh);

?

  • 獲取 Zookeeper 句柄的上下文。
ZOOAPI const void *zoo_get_context(zhandle_t * zh);

?

  • 設置 Zookeeper 句柄的上下文。
ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);

?

  • 設置 Zookeeper 句柄的全局監視器回調函數,該函數返回全局監視器的舊回調函數。
ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);

?

  • 返回當前 Zookeeper 連接的套接字地址。
ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);

?

  • 獲取當前 Zookeeper 連接狀態。
ZOOAPI int zoo_state(zhandle_t * zh);

?

  • 返回某一錯誤碼的字符串表示。
ZOOAPI const char *zerror(int c);

?

  • 檢查當前 Zookeeper 連接是否為不可恢復的,如果不可恢復,則客戶端需要關閉連接,然后重連。
ZOOAPI int is_unrecoverable(zhandle_t * zh);

?

好了,Zookeeper 大部分的輔助函數就介紹到這里了,大家可以更多文檔可以在 zookeeper.h 中找到。:-)

前面七講我們基本上介紹完了 Zookeeper C API 的所有內容,本文將結合一個小例子講講如何在你的實際項目中使用 Zookeeper 服務。

設想如下場景:

假設程序 A 需要 7* 24 小時在線對外提供服務,但是 A 程序在生產環境下總是不穩定,時常崩潰,不過幸運的是解決方案很簡單,在 A 程序崩潰以后只需要重啟它就可以了。當然如此簡單的問題你可以提出多種解決方案,比方說自己實現一個服務程序,每隔一定時間去輪詢 A 的狀態,如果發現 A 崩潰了,立即重啟它,并向管理人員報告問題。不過我們并不打算這么做,畢竟本文主題是講 Zookeeper C API 的應用,所以我們采用 Zookeeper 服務來解決該問題。

若采用 Zookeeper 服務可以按照如下方案解決問題,程序 A 在啟動時創建一個臨時(ZOO_EPHEMERAL) znode 節點 /A,然后按照正常流程對外提供服務。另外監控程序對 /A 節點設置監視,當 /A 節點消失(說明 A 程序已經崩潰)時,重啟 A 程序。假設 A 的名稱是 QueryServer,即對外提供查詢服務的程序,具體提供什么查詢服務由應用自身決定,我們這里只是簡單地模擬一下。QueryServer 在啟動時創建一個 /QueryServer 的臨時節點(ZOO_EPHEMERAL),然后,程序 QueryServerd 監控 /QueryServer 節點,當 /QueryServer 節點消失(說明 A 程序已經崩潰)時,重啟?QueryServer 程序。

下面是 QueryServer 的實現代碼:

/** =============================================================================** Filename: QueryServer.c** Description: QueryServer** Created: 02/15/2013 08:48:49 PM** Author: Fu Haiping (forhappy), haipingf@gmail.com* Company: ICT ( Institute Of Computing Technology, CAS )** =============================================================================*/ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <zookeeper/zookeeper.h> #include <zookeeper/zookeeper_log.h>void QueryServer_watcher_g(zhandle_t* zh, int type, int state,const char* path, void* watcherCtx) {if (type == ZOO_SESSION_EVENT) {if (state == ZOO_CONNECTED_STATE) {printf("[[[QueryServer]]] Connected to zookeeper service successfully!\n");} else if (state == ZOO_EXPIRED_SESSION_STATE) { printf("Zookeeper session expired!\n");}} }void QueryServer_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);} }void QueryServer_accept_query() {printf("QueryServer is running...\n"); }int main(int argc, const char *argv[]) {const char* host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185";int timeout = 30000;zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);zhandle_t* zkhandle = zookeeper_init(host,QueryServer_watcher_g, timeout, 0, "hello zookeeper.", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}// struct ACL ALL_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};// struct ACL_vector ALL_PERMS = {1, ALL_ACL};int ret = zoo_acreate(zkhandle, "/QueryServer", "alive", 5,&ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL,QueryServer_string_completion, "zoo_acreate");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "acreate");exit(EXIT_FAILURE);}do {// 模擬 QueryServer 對外提供服務.// 為了簡單起見, 我們在此調用一個簡單的函數來模擬 QueryServer.// 然后休眠 5 秒,程序主動退出(即假設此時已經崩潰). QueryServer_accept_query();sleep(5);} while(false);zookeeper_close(zkhandle); }

Makefile如下:

all:QueryServerQueryServer:QueryServer.ogcc -L/usr/local/lib/ -lzookeeper_mt -o $@ $^ QueryServer.o:QueryServer.cgcc -DTHREADED -I/usr/local/include/zookeeper -o $@ -c $^.PHONY:cleanclean:rm QueryServer.o QueryServer

?

QueryServerd 代碼如下:

/** =============================================================================** Filename: QueryServerd.c** Description: QueryServer daemon using zookeeper. ** Created: 02/15/2013 08:48:49 PM** Author: Fu Haiping (forhappy), haipingf@gmail.com* Company: ICT ( Institute Of Computing Technology, CAS )** =============================================================================*/ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <zookeeper/zookeeper.h> #include <zookeeper/zookeeper_log.h>void QueryServerd_watcher_global(zhandle_t * zh, int type, int state,const char *path, void *watcherCtx); static void QueryServerd_dump_stat(const struct Stat *stat); void QueryServerd_stat_completion(int rc, const struct Stat *stat,const void *data); void QueryServerd_watcher_awexists(zhandle_t *zh, int type, int state,const char *path, void *watcherCtx); static void QueryServerd_awexists(zhandle_t *zh);void QueryServerd_watcher_global(zhandle_t * zh, int type, int state,const char *path, void *watcherCtx) {if (type == ZOO_SESSION_EVENT) {if (state == ZOO_CONNECTED_STATE) {printf("Connected to zookeeper service successfully!\n");} else if (state == ZOO_EXPIRED_SESSION_STATE) { printf("Zookeeper session expired!\n");}} }static void QueryServerd_dump_stat(const struct Stat *stat) {char tctimes[40];char tmtimes[40];time_t tctime;time_t tmtime;if (!stat) {fprintf(stderr, "null\n");return;}tctime = stat->ctime / 1000;tmtime = stat->mtime / 1000;ctime_r(&tmtime, tmtimes);ctime_r(&tctime, tctimes);fprintf(stderr, "\tctime = %s\tczxid=%llx\n""\tmtime=%s\tmzxid=%llx\n""\tversion=%x\taversion=%x\n""\tephemeralOwner = %llx\n",tctimes, stat->czxid,tmtimes, stat->mzxid,(unsigned int) stat->version, (unsigned int) stat->aversion,stat->ephemeralOwner); }void QueryServerd_stat_completion(int rc, const struct Stat *stat,const void *data) {// fprintf(stderr, "%s: rc = %d Stat:\n", (char *) data, rc);// QueryServerd_dump_stat(stat); }void QueryServerd_watcher_awexists(zhandle_t *zh, int type, int state,const char *path, void *watcherCtx) {if (state == ZOO_CONNECTED_STATE) {if (type == ZOO_DELETED_EVENT) {printf("QueryServer gone away, restart now...\n");// re-exists and set watch on /QueryServer again. QueryServerd_awexists(zh);pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Error when doing fork.\n");exit(EXIT_FAILURE);}if (pid == 0) { /* child process */// 重啟 QueryServer 服務.execl("/tmp/QueryServer/QueryServer", "QueryServer", NULL);exit(EXIT_SUCCESS);}sleep(1); /* sleep 1 second for purpose. */} else if (type == ZOO_CREATED_EVENT) {printf("QueryServer started...\n");}}// re-exists and set watch on /QueryServer again. QueryServerd_awexists(zh); }static void QueryServerd_awexists(zhandle_t *zh) {int ret =zoo_awexists(zh, "/QueryServer",QueryServerd_watcher_awexists,"QueryServerd_awexists.",QueryServerd_stat_completion,"zoo_awexists");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "aexists");exit(EXIT_FAILURE);} }int main(int argc, const char *argv[]) {const char *host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185";int timeout = 30000;zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);zhandle_t *zkhandle = zookeeper_init(host,QueryServerd_watcher_global,timeout,0, "QueryServerd", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}QueryServerd_awexists(zkhandle);// Wait for asynchronous zookeeper call done. getchar();zookeeper_close(zkhandle);return 0; }

?

Makefile 如下:

all:QueryServerdQueryServerd:QueryServerd.ogcc -L/usr/local/lib/ -lzookeeper_mt -o $@ $^ QueryServerd.o:QueryServerd.cgcc -g -DTHREADED -I/usr/local/include/zookeeper -o $@ -c $^.PHONY:cleanclean:rm QueryServerd.o QueryServerd

?

首先執行 QueryServerd,

forhappy@haiping-ict:/tmp/QueryServerd$ ./QueryServerd Connected to zookeeper service successfully!

然后執行 QueryServer,

forhappy@haiping-ict:/tmp/QueryServer$ ./QueryServer QueryServer is running... [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer

可見 Queryerver 創建了 /QueryServer 節點,5 秒后 QueryServer 模擬程序崩潰而退出,那么此時在 QueryServerd 端輸出如下:

Connected to zookeeper service successfully! QueryServer started... # QueryServerd 感知到 QueryServer 已正常啟動. QueryServer gone away, restart now... # 5 秒鐘后,QueryServer 崩潰,QueryServerd 準備重啟 QueryServer. QueryServer is running... #?QueryServer 正在運行,以下 3 行是 QueryServer 輸出結果。 [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer QueryServer started... #?QueryServerd 感知到 QueryServer 已正常啟動. QueryServer gone away, restart now...# 又過了 5 秒鐘后,QueryServer 崩潰,QueryServerd 準備重啟 QueryServer. QueryServer is running... #?QueryServer 再次運行,以下 3 行是 QueryServer 輸出結果。 [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer QueryServer started... #?QueryServerd 再次感知到 QueryServer 已正常啟動,如此反復. QueryServer gone away, restart now... QueryServer is running... [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer QueryServer started...

即 QueryServer 每 5 秒鐘崩潰一次,然后又被 QueryServerd 重啟,模擬了上面的應用場景。

好了 Zookeeper C API 的應用小示例講完了,可能應用場景選取的不好,不過大致可以一些說明問題吧,如果你想看 Zookeeper 更貼近現實的應用場景,可以參考淘寶的一篇文章《ZooKeeper典型應用場景一覽》和 IBM developerWorks 的一篇博文《分布式服務框架 Zookeeper -- 管理分布式環境中的數據》。


總結

以上是生活随笔為你收集整理的Zookeeper C API 指南的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

国产精品久久久久影院嫩草 | 国产精品毛多多水多 | 国产av一区二区精品久久凹凸 | 天堂久久天堂av色综合 | 亚洲阿v天堂在线 | 国产一精品一av一免费 | 亚洲国产精品无码久久久久高潮 | 2020久久香蕉国产线看观看 | 青青久在线视频免费观看 | 成人aaa片一区国产精品 | 国产无遮挡又黄又爽免费视频 | 一本色道久久综合狠狠躁 | 日本一卡2卡3卡四卡精品网站 | 欧美成人免费全部网站 | 99精品国产综合久久久久五月天 | 亚洲精品国产精品乱码视色 | 六月丁香婷婷色狠狠久久 | 天天做天天爱天天爽综合网 | 亚洲综合另类小说色区 | 377p欧洲日本亚洲大胆 | 18禁止看的免费污网站 | 国产亚洲精品精品国产亚洲综合 | 日本精品少妇一区二区三区 | 国产又粗又硬又大爽黄老大爷视 | 无套内谢的新婚少妇国语播放 | 中文久久乱码一区二区 | 久久99国产综合精品 | 免费人成网站视频在线观看 | 给我免费的视频在线观看 | 丰满人妻被黑人猛烈进入 | 日本丰满护士爆乳xxxx | 超碰97人人射妻 | 精品无码成人片一区二区98 | аⅴ资源天堂资源库在线 | 中文字幕乱码亚洲无线三区 | yw尤物av无码国产在线观看 | 人人澡人人妻人人爽人人蜜桃 | 少妇一晚三次一区二区三区 | 久久国语露脸国产精品电影 | 欧美 日韩 人妻 高清 中文 | 欧美一区二区三区 | 国产精品资源一区二区 | 丝袜 中出 制服 人妻 美腿 | 国内少妇偷人精品视频免费 | 国产成人综合在线女婷五月99播放 | 亚洲熟妇色xxxxx欧美老妇y | 曰韩无码二三区中文字幕 | 日韩av无码中文无码电影 | 黑人玩弄人妻中文在线 | 成人无码精品1区2区3区免费看 | 亚洲精品午夜国产va久久成人 | √天堂资源地址中文在线 | 色婷婷欧美在线播放内射 | 台湾无码一区二区 | 人妻aⅴ无码一区二区三区 | 精品人妻人人做人人爽 | 欧美精品一区二区精品久久 | 少妇厨房愉情理9仑片视频 | 久久精品人人做人人综合 | 国产在线精品一区二区三区直播 | 久久午夜夜伦鲁鲁片无码免费 | 大地资源网第二页免费观看 | 无码人妻丰满熟妇区毛片18 | 动漫av网站免费观看 | 精品无码成人片一区二区98 | 精品国产精品久久一区免费式 | 欧美日韩人成综合在线播放 | 兔费看少妇性l交大片免费 | 亚洲色欲色欲欲www在线 | 国产九九九九九九九a片 | 日韩精品乱码av一区二区 | 国产在线精品一区二区三区直播 | 欧美人与物videos另类 | 国产亚洲视频中文字幕97精品 | 黄网在线观看免费网站 | 国内少妇偷人精品视频 | 亚洲乱亚洲乱妇50p | 午夜福利一区二区三区在线观看 | 精品无码成人片一区二区98 | 人妻无码αv中文字幕久久琪琪布 | 男人扒开女人内裤强吻桶进去 | 国产一区二区三区日韩精品 | 99久久久无码国产aaa精品 | 亚洲综合精品香蕉久久网 | 亚洲国产精品成人久久蜜臀 | 一本色道婷婷久久欧美 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 日韩av激情在线观看 | 丝袜美腿亚洲一区二区 | 秋霞特色aa大片 | 麻豆国产丝袜白领秘书在线观看 | 水蜜桃亚洲一二三四在线 | 无套内谢的新婚少妇国语播放 | 亚洲一区二区三区偷拍女厕 | 国产精品久久久久久久9999 | 樱花草在线社区www | 国产精品18久久久久久麻辣 | aⅴ在线视频男人的天堂 | 大色综合色综合网站 | 偷窥日本少妇撒尿chinese | 少妇高潮喷潮久久久影院 | 久久精品国产一区二区三区 | 熟女体下毛毛黑森林 | 国产高清不卡无码视频 | 精品偷自拍另类在线观看 | 久久综合久久自在自线精品自 | 国产精品.xx视频.xxtv | 国产 精品 自在自线 | 无码帝国www无码专区色综合 | 天干天干啦夜天干天2017 | 午夜福利不卡在线视频 | 纯爱无遮挡h肉动漫在线播放 | 免费男性肉肉影院 | 国产明星裸体无码xxxx视频 | √8天堂资源地址中文在线 | 亚洲 高清 成人 动漫 | av在线亚洲欧洲日产一区二区 | 日韩精品久久久肉伦网站 | 无码成人精品区在线观看 | 国产av人人夜夜澡人人爽麻豆 | 国产精品二区一区二区aⅴ污介绍 | 欧美性猛交xxxx富婆 | 欧美成人午夜精品久久久 | 国产精品亚洲专区无码不卡 | 成人动漫在线观看 | 欧美 日韩 亚洲 在线 | 免费无码午夜福利片69 | 免费播放一区二区三区 | 国产特级毛片aaaaaaa高清 | 国产精品无套呻吟在线 | 亚洲va欧美va天堂v国产综合 | 久久综合久久自在自线精品自 | 久久精品一区二区三区四区 | 男女作爱免费网站 | 精品久久综合1区2区3区激情 | 国产内射爽爽大片视频社区在线 | 在线看片无码永久免费视频 | 久久精品人人做人人综合试看 | 影音先锋中文字幕无码 | 精品亚洲韩国一区二区三区 | 2020最新国产自产精品 | 国内精品人妻无码久久久影院蜜桃 | 亚洲aⅴ无码成人网站国产app | 日日天干夜夜狠狠爱 | 国产熟女一区二区三区四区五区 | 久久国产精品萌白酱免费 | 永久免费观看国产裸体美女 | 捆绑白丝粉色jk震动捧喷白浆 | 国产精品99久久精品爆乳 | 中文无码精品a∨在线观看不卡 | 露脸叫床粗话东北少妇 | 久久久久亚洲精品中文字幕 | 大地资源网第二页免费观看 | 亚洲精品www久久久 | 成人无码精品一区二区三区 | 丰满人妻被黑人猛烈进入 | 人妻与老人中文字幕 | 亚洲 激情 小说 另类 欧美 | 好男人www社区 | 国产精品亚洲а∨无码播放麻豆 | 国产猛烈高潮尖叫视频免费 | 亚洲中文无码av永久不收费 | 日韩无码专区 | 野狼第一精品社区 | 香港三级日本三级妇三级 | 亚洲综合色区中文字幕 | 国产午夜精品一区二区三区嫩草 | 日日碰狠狠躁久久躁蜜桃 | 国产精品人人妻人人爽 | 香港三级日本三级妇三级 | 青青草原综合久久大伊人精品 | 东京热一精品无码av | 99久久久无码国产aaa精品 | 美女扒开屁股让男人桶 | 麻豆精品国产精华精华液好用吗 | 图片区 小说区 区 亚洲五月 | 亚洲熟妇色xxxxx欧美老妇 | 又粗又大又硬毛片免费看 | 日韩少妇白浆无码系列 | 精品国产青草久久久久福利 | 久久无码专区国产精品s | 亚洲精品久久久久中文第一幕 | 亚洲精品国偷拍自产在线观看蜜桃 | 男女爱爱好爽视频免费看 | 亚洲国产成人av在线观看 | 红桃av一区二区三区在线无码av | 老熟女重囗味hdxx69 | 成人精品视频一区二区三区尤物 | 99精品国产综合久久久久五月天 | 丁香啪啪综合成人亚洲 | 六月丁香婷婷色狠狠久久 | 亚洲s码欧洲m码国产av | 中文字幕无码日韩欧毛 | 无码纯肉视频在线观看 | 午夜丰满少妇性开放视频 | 久久无码专区国产精品s | 亚洲区欧美区综合区自拍区 | av无码久久久久不卡免费网站 | 亚洲娇小与黑人巨大交 | 午夜成人1000部免费视频 | 国产精品无码久久av | 又大又黄又粗又爽的免费视频 | 波多野结衣av在线观看 | 久久久精品国产sm最大网站 | 亚洲毛片av日韩av无码 | 无码吃奶揉捏奶头高潮视频 | 影音先锋中文字幕无码 | 999久久久国产精品消防器材 | 丰满少妇熟乱xxxxx视频 | 久久久中文字幕日本无吗 | 色婷婷香蕉在线一区二区 | 亚洲精品综合一区二区三区在线 | 天下第一社区视频www日本 | 精品久久久久香蕉网 | 特大黑人娇小亚洲女 | aⅴ亚洲 日韩 色 图网站 播放 | 在线精品国产一区二区三区 | 国产福利视频一区二区 | 国产性生交xxxxx无码 | 东京一本一道一二三区 | 亚洲精品综合一区二区三区在线 | 人人爽人人爽人人片av亚洲 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 精品国精品国产自在久国产87 | 欧美乱妇无乱码大黄a片 | 国产成人无码a区在线观看视频app | 亚洲精品一区国产 | 色综合久久久无码网中文 | 7777奇米四色成人眼影 | 动漫av一区二区在线观看 | 亚洲国产精品无码一区二区三区 | 性欧美videos高清精品 | 中文字幕乱码人妻无码久久 | 99视频精品全部免费免费观看 | 日本饥渴人妻欲求不满 | 国产精品内射视频免费 | 国产精品毛片一区二区 | 日本熟妇人妻xxxxx人hd | 国产色xx群视频射精 | 成人无码精品1区2区3区免费看 | 狠狠噜狠狠狠狠丁香五月 | 亚洲色欲色欲天天天www | 国产两女互慰高潮视频在线观看 | 中文字幕乱码人妻二区三区 | 亚洲综合无码一区二区三区 | 国产精品成人av在线观看 | 久久国产精品萌白酱免费 | 久久国产精品萌白酱免费 | 兔费看少妇性l交大片免费 | 中国女人内谢69xxxxxa片 | 久久天天躁夜夜躁狠狠 | 全黄性性激高免费视频 | 一本久道久久综合婷婷五月 | 99精品国产综合久久久久五月天 | 亚洲理论电影在线观看 | 沈阳熟女露脸对白视频 | 婷婷丁香五月天综合东京热 | 亚洲综合精品香蕉久久网 | 亚洲成在人网站无码天堂 | 人人妻人人澡人人爽人人精品浪潮 | 红桃av一区二区三区在线无码av | 免费中文字幕日韩欧美 | 无码精品人妻一区二区三区av | 亚洲 高清 成人 动漫 | 免费人成网站视频在线观看 | 午夜福利试看120秒体验区 | 亚洲熟妇色xxxxx欧美老妇y | 国产精品久久久午夜夜伦鲁鲁 | 高清无码午夜福利视频 | 精品成在人线av无码免费看 | 蜜桃视频韩日免费播放 | 亚欧洲精品在线视频免费观看 | 国产xxx69麻豆国语对白 | 久久伊人色av天堂九九小黄鸭 | 精品无码成人片一区二区98 | 日本一本二本三区免费 | 无码纯肉视频在线观看 | 久久无码中文字幕免费影院蜜桃 | 色诱久久久久综合网ywww | 国产成人无码区免费内射一片色欲 | 青青青爽视频在线观看 | 欧美性生交活xxxxxdddd | 国产乱人伦偷精品视频 | 国产猛烈高潮尖叫视频免费 | 欧美日韩亚洲国产精品 | 色综合久久久无码中文字幕 | 亚洲爆乳大丰满无码专区 | 久久久久亚洲精品中文字幕 | 18精品久久久无码午夜福利 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产成人综合在线女婷五月99播放 | √8天堂资源地址中文在线 | 人妻少妇被猛烈进入中文字幕 | 亚洲日韩一区二区 | √天堂中文官网8在线 | 亚洲男人av天堂午夜在 | 中文字幕无码热在线视频 | 2020久久超碰国产精品最新 | 99久久无码一区人妻 | 亚洲精品鲁一鲁一区二区三区 | 麻豆国产人妻欲求不满谁演的 | 野外少妇愉情中文字幕 | 亚洲精品综合一区二区三区在线 | 天干天干啦夜天干天2017 | 国产精品久久精品三级 | 亚洲熟熟妇xxxx | 中文无码成人免费视频在线观看 | 一个人看的www免费视频在线观看 | 日韩少妇白浆无码系列 | 97资源共享在线视频 | 国产精品高潮呻吟av久久 | 精品国精品国产自在久国产87 | 桃花色综合影院 | 国产亚洲视频中文字幕97精品 | 久久熟妇人妻午夜寂寞影院 | 亚洲国产成人av在线观看 | 久久99热只有频精品8 | 精品无人国产偷自产在线 | 人人爽人人澡人人高潮 | 亚洲理论电影在线观看 | 四虎国产精品一区二区 | 人妻少妇被猛烈进入中文字幕 | 曰韩无码二三区中文字幕 | 99久久久无码国产aaa精品 | 伊人久久大香线焦av综合影院 | 成人片黄网站色大片免费观看 | 激情国产av做激情国产爱 | 99久久精品国产一区二区蜜芽 | www成人国产高清内射 | 色婷婷综合激情综在线播放 | 国产真实夫妇视频 | 妺妺窝人体色www在线小说 | 国产精品久久久久久亚洲影视内衣 | 男女猛烈xx00免费视频试看 | 国产精品久久久 | 精品人妻人人做人人爽夜夜爽 | 亚洲一区二区三区国产精华液 | 黑人玩弄人妻中文在线 | 亚洲一区二区三区香蕉 | 正在播放老肥熟妇露脸 | 欧美丰满熟妇xxxx性ppx人交 | 国产成人无码av片在线观看不卡 | 国产真人无遮挡作爱免费视频 | 久久成人a毛片免费观看网站 | 牲欲强的熟妇农村老妇女 | 在线播放无码字幕亚洲 | 午夜丰满少妇性开放视频 | 亚洲精品国偷拍自产在线麻豆 | 久久精品中文字幕大胸 | 日韩人妻无码一区二区三区久久99 | 精品无码成人片一区二区98 | 男人扒开女人内裤强吻桶进去 | 色窝窝无码一区二区三区色欲 | 欧洲美熟女乱又伦 | 欧美兽交xxxx×视频 | 波多野结衣高清一区二区三区 | 亚洲中文无码av永久不收费 | 精品国产一区二区三区四区在线看 | 国产欧美精品一区二区三区 | 久久国语露脸国产精品电影 | 狠狠色色综合网站 | 亚洲精品久久久久久久久久久 | 欧美肥老太牲交大战 | 亚洲成a人片在线观看无码 | 99久久精品无码一区二区毛片 | 一本色道久久综合亚洲精品不卡 | 亚洲大尺度无码无码专区 | 日日天日日夜日日摸 | 99精品无人区乱码1区2区3区 | 亚洲娇小与黑人巨大交 | 亚洲人亚洲人成电影网站色 | 精品国产aⅴ无码一区二区 | 欧美日韩人成综合在线播放 | 日韩精品无码一区二区中文字幕 | 午夜无码人妻av大片色欲 | 亚洲国产精华液网站w | 人妻少妇精品无码专区二区 | 亚洲日韩一区二区 | 日产国产精品亚洲系列 | 欧美精品无码一区二区三区 | 亚洲国产精品久久久天堂 | 人人妻人人澡人人爽人人精品 | 青青青爽视频在线观看 | 久久久久亚洲精品男人的天堂 | www成人国产高清内射 | 日韩亚洲欧美精品综合 | 国产精品国产三级国产专播 | 国产艳妇av在线观看果冻传媒 | 中文无码伦av中文字幕 | 国产亚洲精品久久久久久国模美 | 中文久久乱码一区二区 | 国产真人无遮挡作爱免费视频 | 色综合久久久无码网中文 | 亚洲色成人中文字幕网站 | 色窝窝无码一区二区三区色欲 | 国产精品久久久久无码av色戒 | 国产精品爱久久久久久久 | 全球成人中文在线 | 久久久久久久人妻无码中文字幕爆 | 精品无人国产偷自产在线 | 偷窥日本少妇撒尿chinese | 亚洲中文字幕在线无码一区二区 | 国产一区二区三区日韩精品 | 99久久精品日本一区二区免费 | 亚洲大尺度无码无码专区 | 精品国产麻豆免费人成网站 | 国产精品99爱免费视频 | 久久人人97超碰a片精品 | 免费看少妇作爱视频 | 特大黑人娇小亚洲女 | 久久综合九色综合欧美狠狠 | 性欧美牲交xxxxx视频 | 成人无码影片精品久久久 | 丰满人妻精品国产99aⅴ | 伊人久久大香线焦av综合影院 | 狠狠色丁香久久婷婷综合五月 | 国产熟妇高潮叫床视频播放 | 四虎影视成人永久免费观看视频 | 女人被男人爽到呻吟的视频 | 老司机亚洲精品影院无码 | 亚洲综合另类小说色区 | 5858s亚洲色大成网站www | 国产精品久久久久无码av色戒 | 99久久精品无码一区二区毛片 | 国产在线aaa片一区二区99 | 国产午夜无码视频在线观看 | 亚洲国产精华液网站w | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲爆乳无码专区 | 成年美女黄网站色大免费视频 | 中文字幕亚洲情99在线 | 国产9 9在线 | 中文 | 国内精品久久毛片一区二区 | 成熟女人特级毛片www免费 | 人人爽人人澡人人人妻 | 亚洲人成网站色7799 | 国产精品国产自线拍免费软件 | 国产精品久久久久无码av色戒 | 国产手机在线αⅴ片无码观看 | 国产97色在线 | 免 | 亚洲va中文字幕无码久久不卡 | 日本免费一区二区三区最新 | 99久久无码一区人妻 | 中文字幕无码热在线视频 | 日韩少妇内射免费播放 | 国产成人一区二区三区在线观看 | 中文字幕无码人妻少妇免费 | 国产午夜手机精彩视频 | 日韩亚洲欧美精品综合 | 国产精品久久久久久久9999 | 四虎国产精品免费久久 | 在线精品国产一区二区三区 | 久久精品国产亚洲精品 | 精品国产国产综合精品 | 波多野结衣乳巨码无在线观看 | 99久久亚洲精品无码毛片 | 国产午夜无码视频在线观看 | 最新国产麻豆aⅴ精品无码 | 日本免费一区二区三区最新 | 久久久久久久人妻无码中文字幕爆 | 亚洲欧洲日本无在线码 | 牲欲强的熟妇农村老妇女视频 | 国产乱子伦视频在线播放 | 亚洲日韩av一区二区三区中文 | 欧美熟妇另类久久久久久多毛 | 欧美日韩人成综合在线播放 | 国产成人精品三级麻豆 | 国产精品久久久久久亚洲影视内衣 | 中文字幕无码av波多野吉衣 | 99视频精品全部免费免费观看 | 性色欲网站人妻丰满中文久久不卡 | 久久久久久久久蜜桃 | 国产特级毛片aaaaaaa高清 | 一区二区三区乱码在线 | 欧洲 | 亚洲 欧美 激情 小说 另类 | 久久精品成人欧美大片 | 国产精品久久久久久亚洲影视内衣 | 又黄又爽又色的视频 | 欧美精品国产综合久久 | 亚洲一区av无码专区在线观看 | 久久久久久久久888 | 国产精品对白交换视频 | 国内精品一区二区三区不卡 | 国产97人人超碰caoprom | 国产精品a成v人在线播放 | 国产av无码专区亚洲awww | 日本爽爽爽爽爽爽在线观看免 | 自拍偷自拍亚洲精品10p | 精品偷拍一区二区三区在线看 | 国产亚洲tv在线观看 | 国产精品人人妻人人爽 | 亚洲欧洲日本无在线码 | 97久久国产亚洲精品超碰热 | 亚洲熟妇色xxxxx欧美老妇y | 狠狠色欧美亚洲狠狠色www | 台湾无码一区二区 | 领导边摸边吃奶边做爽在线观看 | 中文无码精品a∨在线观看不卡 | 国产成人无码av在线影院 | 少妇的肉体aa片免费 | 国产舌乚八伦偷品w中 | 国产精品第一区揄拍无码 | 久久国语露脸国产精品电影 | 国内少妇偷人精品视频免费 | 国产成人人人97超碰超爽8 | 欧美黑人乱大交 | 99久久亚洲精品无码毛片 | 人妻无码αv中文字幕久久琪琪布 | 国模大胆一区二区三区 | 国产艳妇av在线观看果冻传媒 | 欧美日韩一区二区综合 | 天天拍夜夜添久久精品大 | 国内精品久久毛片一区二区 | 国产三级久久久精品麻豆三级 | 日日摸日日碰夜夜爽av | 98国产精品综合一区二区三区 | 女人被爽到呻吟gif动态图视看 | 99国产精品白浆在线观看免费 | 国产明星裸体无码xxxx视频 | 奇米影视888欧美在线观看 | 水蜜桃亚洲一二三四在线 | 久久久久成人片免费观看蜜芽 | 国产欧美精品一区二区三区 | 青青草原综合久久大伊人精品 | 亚洲熟熟妇xxxx | 色欲人妻aaaaaaa无码 | 亚洲欧美中文字幕5发布 | 久久精品国产99精品亚洲 | 亚洲娇小与黑人巨大交 | 国内揄拍国内精品少妇国语 | 乱人伦人妻中文字幕无码久久网 | 狠狠噜狠狠狠狠丁香五月 | 国产成人久久精品流白浆 | 午夜精品一区二区三区的区别 | 免费乱码人妻系列无码专区 | 国产精品-区区久久久狼 | 少妇无码一区二区二三区 | 久久伊人色av天堂九九小黄鸭 | 国产亲子乱弄免费视频 | 久久国产精品萌白酱免费 | 激情爆乳一区二区三区 | 国产精品办公室沙发 | 亚洲乱码国产乱码精品精 | 国产精品亚洲综合色区韩国 | 又大又硬又黄的免费视频 | 性欧美牲交xxxxx视频 | 中文字幕无码日韩专区 | 成人性做爰aaa片免费看 | 成人欧美一区二区三区 | 欧美freesex黑人又粗又大 | 美女黄网站人色视频免费国产 | 国语自产偷拍精品视频偷 | 免费人成在线视频无码 | 西西人体www44rt大胆高清 | 久久99精品国产.久久久久 | 日韩人妻少妇一区二区三区 | 99久久婷婷国产综合精品青草免费 | 日韩av激情在线观看 | 亚洲の无码国产の无码影院 | 中文字幕+乱码+中文字幕一区 | 乌克兰少妇xxxx做受 | 无码人妻出轨黑人中文字幕 | 日本在线高清不卡免费播放 | 欧美老熟妇乱xxxxx | 黑人巨大精品欧美一区二区 | 国产精品对白交换视频 | 中文字幕无码视频专区 | 国产精品香蕉在线观看 | 亚洲一区二区三区 | 国产农村乱对白刺激视频 | 国产午夜无码精品免费看 | 精品无码国产一区二区三区av | 成人亚洲精品久久久久软件 | 国产两女互慰高潮视频在线观看 | 亚洲午夜福利在线观看 | 亚洲国产精华液网站w | 一个人免费观看的www视频 | 少妇人妻大乳在线视频 | 狠狠亚洲超碰狼人久久 | 久久精品成人欧美大片 | 亚洲国产欧美在线成人 | 乱人伦人妻中文字幕无码 | 一本加勒比波多野结衣 | 一个人看的www免费视频在线观看 | 国产美女极度色诱视频www | 精品国产一区二区三区av 性色 | 国产 精品 自在自线 | 熟妇人妻中文av无码 | 麻豆精品国产精华精华液好用吗 | 国产激情无码一区二区app | 内射欧美老妇wbb | 中文字幕亚洲情99在线 | 在线观看欧美一区二区三区 | 亚洲成色在线综合网站 | 四虎永久在线精品免费网址 | 亚洲精品中文字幕乱码 | 国产精品久久国产三级国 | 国产精品久久久久影院嫩草 | 亚洲日韩av片在线观看 | 特大黑人娇小亚洲女 | 亚洲精品一区二区三区婷婷月 | 国产免费久久久久久无码 | 亚洲国产欧美日韩精品一区二区三区 | 国产免费无码一区二区视频 | 久久亚洲国产成人精品性色 | www成人国产高清内射 | 成 人 免费观看网站 | 国产97在线 | 亚洲 | 一个人看的www免费视频在线观看 | 国产熟女一区二区三区四区五区 | 国产高清不卡无码视频 | 亚洲一区二区三区香蕉 | 全球成人中文在线 | www国产亚洲精品久久网站 | 黑人巨大精品欧美黑寡妇 | 国产精品99久久精品爆乳 | 天堂一区人妻无码 | 亚洲爆乳大丰满无码专区 | 国产成人精品无码播放 | 老熟妇乱子伦牲交视频 | 真人与拘做受免费视频 | 免费观看的无遮挡av | 人妻熟女一区 | av人摸人人人澡人人超碰下载 | 国精产品一品二品国精品69xx | 野狼第一精品社区 | 76少妇精品导航 | 色狠狠av一区二区三区 | 无码人妻久久一区二区三区不卡 | 日本爽爽爽爽爽爽在线观看免 | 99久久久国产精品无码免费 | 国产成人无码一二三区视频 | 久久久久亚洲精品男人的天堂 | 天天躁夜夜躁狠狠是什么心态 | 强辱丰满人妻hd中文字幕 | 男人和女人高潮免费网站 | 亚洲国产精品无码久久久久高潮 | 亚洲精品欧美二区三区中文字幕 | 成人性做爰aaa片免费看 | 中国大陆精品视频xxxx | 国产激情精品一区二区三区 | 午夜理论片yy44880影院 | 欧美人与牲动交xxxx | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 激情五月综合色婷婷一区二区 | 亚洲爆乳精品无码一区二区三区 | 亚洲国产成人a精品不卡在线 | а√天堂www在线天堂小说 | 天天爽夜夜爽夜夜爽 | 国产97色在线 | 免 | 国产精品嫩草久久久久 | 亚洲综合无码一区二区三区 | 牲欲强的熟妇农村老妇女 | 撕开奶罩揉吮奶头视频 | 久久精品国产99久久6动漫 | 免费无码一区二区三区蜜桃大 | 性史性农村dvd毛片 | 国产av无码专区亚洲a∨毛片 | 婷婷色婷婷开心五月四房播播 | 成人精品天堂一区二区三区 | 蜜桃视频插满18在线观看 | 色综合久久久无码网中文 | 日产精品高潮呻吟av久久 | 熟妇人妻激情偷爽文 | 99re在线播放 | 99久久婷婷国产综合精品青草免费 | 少妇激情av一区二区 | 欧美日韩色另类综合 | 国产亚洲精品久久久久久久久动漫 | 无码av免费一区二区三区试看 | 学生妹亚洲一区二区 | 99国产欧美久久久精品 | 1000部啪啪未满十八勿入下载 | 国产午夜亚洲精品不卡下载 | 大地资源网第二页免费观看 | 全黄性性激高免费视频 | 国产亚洲精品久久久久久 | 老太婆性杂交欧美肥老太 | 国产精品毛片一区二区 | 久久久久久久久888 | 久久国产精品_国产精品 | 无码人妻丰满熟妇区毛片18 | 鲁鲁鲁爽爽爽在线视频观看 | 澳门永久av免费网站 | 沈阳熟女露脸对白视频 | 蜜臀aⅴ国产精品久久久国产老师 | 狂野欧美性猛xxxx乱大交 | 欧美日韩一区二区免费视频 | 狠狠亚洲超碰狼人久久 | 日日躁夜夜躁狠狠躁 | 久久久www成人免费毛片 | 亚洲国产精品久久久久久 | 国产真实乱对白精彩久久 | 天堂а√在线中文在线 | 亚洲欧美日韩综合久久久 | 白嫩日本少妇做爰 | 欧美日韩亚洲国产精品 | 精品国产一区二区三区四区在线看 | 欧美野外疯狂做受xxxx高潮 | 亚洲精品中文字幕久久久久 | 精品少妇爆乳无码av无码专区 | 又色又爽又黄的美女裸体网站 | 荫蒂被男人添的好舒服爽免费视频 | 日日摸夜夜摸狠狠摸婷婷 | av无码电影一区二区三区 | 日日躁夜夜躁狠狠躁 | 色婷婷综合激情综在线播放 | 久热国产vs视频在线观看 | 最新国产乱人伦偷精品免费网站 | 成在人线av无码免观看麻豆 | 国产情侣作爱视频免费观看 | 免费看男女做好爽好硬视频 | 国产精品第一区揄拍无码 | 夫妻免费无码v看片 | 国产农村妇女高潮大叫 | 欧美激情综合亚洲一二区 | 国产精品久久久久久亚洲毛片 | 日韩av激情在线观看 | 99久久精品午夜一区二区 | 亚洲日本一区二区三区在线 | 99国产欧美久久久精品 | 欧美野外疯狂做受xxxx高潮 | 日韩 欧美 动漫 国产 制服 | 成人三级无码视频在线观看 | 日本一区二区三区免费高清 | 捆绑白丝粉色jk震动捧喷白浆 | 又紧又大又爽精品一区二区 | 久久精品中文闷骚内射 | 亚洲精品综合一区二区三区在线 | 欧美zoozzooz性欧美 | 日日摸日日碰夜夜爽av | 亚洲自偷自拍另类第1页 | 亚洲乱码日产精品bd | aⅴ亚洲 日韩 色 图网站 播放 | 天堂а√在线地址中文在线 | 欧美性生交xxxxx久久久 | 欧美人妻一区二区三区 | 激情内射亚州一区二区三区爱妻 | 亚洲无人区一区二区三区 | 大屁股大乳丰满人妻 | 小sao货水好多真紧h无码视频 | 国产香蕉尹人视频在线 | 国产精品丝袜黑色高跟鞋 | 日本熟妇浓毛 | 粉嫩少妇内射浓精videos | 久久国产36精品色熟妇 | 国产精品无套呻吟在线 | 国产人妻精品一区二区三区 | 蜜桃无码一区二区三区 | 88国产精品欧美一区二区三区 | 波多野结衣av在线观看 | 人妻插b视频一区二区三区 | 少妇一晚三次一区二区三区 | 国产av一区二区精品久久凹凸 | 麻花豆传媒剧国产免费mv在线 | 欧美丰满老熟妇xxxxx性 | 亚洲国产精品美女久久久久 | 亚洲人交乣女bbw | 久久久久亚洲精品中文字幕 | 久久视频在线观看精品 | 久久国语露脸国产精品电影 | 国产精品亚洲五月天高清 | 午夜福利不卡在线视频 | 欧美人与禽zoz0性伦交 | 两性色午夜免费视频 | 无码国产激情在线观看 | 日日躁夜夜躁狠狠躁 | 99久久久无码国产aaa精品 | 欧美熟妇另类久久久久久多毛 | av无码久久久久不卡免费网站 | 亚洲人成网站免费播放 | 自拍偷自拍亚洲精品被多人伦好爽 | 无套内谢老熟女 | 在线观看免费人成视频 | 好屌草这里只有精品 | 人妻少妇精品视频专区 | 初尝人妻少妇中文字幕 | 久久久久亚洲精品男人的天堂 | 女人被男人躁得好爽免费视频 | 亚洲最大成人网站 | 国产精品永久免费视频 | 成熟女人特级毛片www免费 | 成人欧美一区二区三区 | 最新国产麻豆aⅴ精品无码 | 日本精品久久久久中文字幕 | 国产绳艺sm调教室论坛 | 一本无码人妻在中文字幕免费 | 97se亚洲精品一区 | 国产成人精品久久亚洲高清不卡 | 成年女人永久免费看片 | 波多野结衣高清一区二区三区 | 99精品国产综合久久久久五月天 | av人摸人人人澡人人超碰下载 | 天天av天天av天天透 | 中文字幕人妻无码一夲道 | 人人妻人人澡人人爽精品欧美 | 蜜桃臀无码内射一区二区三区 | 无码人妻精品一区二区三区下载 | 亚洲色大成网站www | 久精品国产欧美亚洲色aⅴ大片 | 又粗又大又硬又长又爽 | 亚洲精品国产精品乱码不卡 | 中文无码成人免费视频在线观看 | 中文毛片无遮挡高清免费 | 一本加勒比波多野结衣 | 大屁股大乳丰满人妻 | 一本久道久久综合婷婷五月 | 欧美激情综合亚洲一二区 | 高潮毛片无遮挡高清免费视频 | 久久久国产一区二区三区 | 一个人免费观看的www视频 | 国产艳妇av在线观看果冻传媒 | 欧美精品无码一区二区三区 | 国产人妻久久精品二区三区老狼 | 伦伦影院午夜理论片 | 久久人人爽人人爽人人片av高清 | 性做久久久久久久久 | 色综合久久久无码网中文 | 亚洲s色大片在线观看 | 清纯唯美经典一区二区 | 午夜无码人妻av大片色欲 | 3d动漫精品啪啪一区二区中 | 免费国产成人高清在线观看网站 | 欧美兽交xxxx×视频 | 亚洲经典千人经典日产 | 亚洲成av人片天堂网无码】 | 国产精品国产三级国产专播 | 国产手机在线αⅴ片无码观看 | 国产成人精品视频ⅴa片软件竹菊 | 乱码午夜-极国产极内射 | 无码午夜成人1000部免费视频 | 国产免费久久久久久无码 | 性色欲网站人妻丰满中文久久不卡 | 成人av无码一区二区三区 | 无码国产激情在线观看 | 国产午夜精品一区二区三区嫩草 | 国产精品久久国产精品99 | 久久精品中文字幕一区 | 亚洲熟妇色xxxxx亚洲 | 曰本女人与公拘交酡免费视频 | 色诱久久久久综合网ywww | 日日躁夜夜躁狠狠躁 | 亚洲一区二区三区偷拍女厕 | 中文字幕无码日韩欧毛 | 亚洲欧洲无卡二区视頻 | 中文毛片无遮挡高清免费 | 国产成人av免费观看 | 人妻天天爽夜夜爽一区二区 | 丰满少妇弄高潮了www | 精品久久久无码人妻字幂 | 国产内射老熟女aaaa | 欧美 日韩 亚洲 在线 | 国产av无码专区亚洲awww | 对白脏话肉麻粗话av | 97久久国产亚洲精品超碰热 | 中文字幕乱码中文乱码51精品 | 熟女少妇在线视频播放 | 性开放的女人aaa片 | 一区二区传媒有限公司 | 中文字幕乱码人妻二区三区 | 亚洲人成网站免费播放 | 伊人久久大香线蕉亚洲 | 日日躁夜夜躁狠狠躁 | 装睡被陌生人摸出水好爽 | 两性色午夜视频免费播放 | 午夜无码区在线观看 | 内射巨臀欧美在线视频 | 无码av免费一区二区三区试看 | √天堂中文官网8在线 | 少妇激情av一区二区 | 男女作爱免费网站 | 国产莉萝无码av在线播放 | 亚洲啪av永久无码精品放毛片 | v一区无码内射国产 | 粉嫩少妇内射浓精videos | 精品偷自拍另类在线观看 | 国产成人无码av一区二区 | 少妇人妻大乳在线视频 | 国产精品久久国产三级国 | 精品人妻中文字幕有码在线 | 日日摸夜夜摸狠狠摸婷婷 | 日韩精品a片一区二区三区妖精 | 久久无码中文字幕免费影院蜜桃 | 人妻无码久久精品人妻 | 特级做a爰片毛片免费69 | 国产手机在线αⅴ片无码观看 | 亚洲中文字幕乱码av波多ji | 久久久久久久人妻无码中文字幕爆 | 奇米影视7777久久精品 | 成在人线av无码免观看麻豆 | 特级做a爰片毛片免费69 | 给我免费的视频在线观看 | 国产97人人超碰caoprom | 国产极品美女高潮无套在线观看 | 亚欧洲精品在线视频免费观看 | 精品无码国产自产拍在线观看蜜 | 99riav国产精品视频 | 蜜臀av无码人妻精品 | 欧美变态另类xxxx | 一本色道婷婷久久欧美 | 六十路熟妇乱子伦 | 国内精品久久久久久中文字幕 | 精品 日韩 国产 欧美 视频 | 性生交大片免费看女人按摩摩 | 麻豆蜜桃av蜜臀av色欲av | 少妇被粗大的猛进出69影院 | 成人影院yy111111在线观看 | 夜精品a片一区二区三区无码白浆 | 日本精品久久久久中文字幕 | 精品一区二区三区波多野结衣 | 亚洲の无码国产の无码影院 | 未满成年国产在线观看 | 国产在线精品一区二区高清不卡 | 一个人免费观看的www视频 | 精品国产一区二区三区四区在线看 | 性生交大片免费看女人按摩摩 | 性做久久久久久久免费看 | 女人高潮内射99精品 | 国产精品亚洲lv粉色 | 亚洲精品综合五月久久小说 | www国产亚洲精品久久网站 | 天天做天天爱天天爽综合网 | 国产亚洲精品久久久久久久久动漫 | 香蕉久久久久久av成人 | 日韩精品成人一区二区三区 | 狠狠色丁香久久婷婷综合五月 | 国模大胆一区二区三区 | 国产成人无码av一区二区 | 特黄特色大片免费播放器图片 | 免费无码的av片在线观看 | 51国偷自产一区二区三区 | 国产精品久久福利网站 | 色综合久久88色综合天天 | 国产三级久久久精品麻豆三级 | 日本丰满熟妇videos | 精品一区二区不卡无码av | 国产在线精品一区二区三区直播 | 色情久久久av熟女人妻网站 | 人妻与老人中文字幕 | 欧美激情一区二区三区成人 | 性欧美疯狂xxxxbbbb | 国产高潮视频在线观看 | 国产又爽又黄又刺激的视频 | 国产亚洲精品久久久久久久久动漫 | 激情内射日本一区二区三区 | 色综合久久88色综合天天 | 日本xxxx色视频在线观看免费 | 亚洲国产精品无码一区二区三区 | 丰满少妇女裸体bbw | 亚洲成a人一区二区三区 | 中文字幕无码免费久久99 | 日本护士xxxxhd少妇 | 啦啦啦www在线观看免费视频 | 国产精品丝袜黑色高跟鞋 | 午夜成人1000部免费视频 | 久久亚洲日韩精品一区二区三区 | 老子影院午夜伦不卡 | 亚洲一区av无码专区在线观看 | 亚洲欧洲日本无在线码 | 久久久久久av无码免费看大片 | 十八禁真人啪啪免费网站 | 超碰97人人做人人爱少妇 | 国产色精品久久人妻 | 亚洲成av人在线观看网址 | 成人试看120秒体验区 | 亚洲国产高清在线观看视频 | 漂亮人妻洗澡被公强 日日躁 | 黑森林福利视频导航 | 色综合天天综合狠狠爱 | 免费乱码人妻系列无码专区 | 久久国产36精品色熟妇 | 无套内谢老熟女 | 成人女人看片免费视频放人 | 国产卡一卡二卡三 | 99久久无码一区人妻 | 国产超级va在线观看视频 | a片免费视频在线观看 | 国产亚洲欧美在线专区 | 激情五月综合色婷婷一区二区 | 国产热a欧美热a在线视频 | 日韩无套无码精品 | 亚洲爆乳大丰满无码专区 | 日韩精品一区二区av在线 | 精品乱码久久久久久久 | 亚洲呦女专区 | 国产综合在线观看 | 狠狠色噜噜狠狠狠7777奇米 | 久久精品中文字幕一区 | 荡女精品导航 | 人妻无码久久精品人妻 | 亚洲成av人在线观看网址 | 色综合久久88色综合天天 | 国产精品.xx视频.xxtv | 国产精品毛多多水多 | 亚洲中文字幕在线观看 | 人人妻人人澡人人爽人人精品浪潮 | 免费人成网站视频在线观看 | 性欧美疯狂xxxxbbbb | 国产色xx群视频射精 | 无码精品国产va在线观看dvd | 日日天日日夜日日摸 | 欧美丰满老熟妇xxxxx性 | 国产九九九九九九九a片 | 丰满少妇人妻久久久久久 | 伊人色综合久久天天小片 | 欧美一区二区三区视频在线观看 | 高潮毛片无遮挡高清免费视频 | 人人妻人人澡人人爽人人精品 | 麻花豆传媒剧国产免费mv在线 | 无码任你躁久久久久久久 | 曰韩无码二三区中文字幕 | 久久久久久av无码免费看大片 | 久久久久99精品国产片 | 在线观看国产一区二区三区 | 精品一区二区不卡无码av | 午夜精品久久久内射近拍高清 | 亚洲乱亚洲乱妇50p | 国产日产欧产精品精品app | 中文字幕无码免费久久9一区9 | 国产va免费精品观看 | 国内综合精品午夜久久资源 | 97久久超碰中文字幕 | 蜜臀av无码人妻精品 | 人妻有码中文字幕在线 | 国产福利视频一区二区 | 性开放的女人aaa片 | 激情内射日本一区二区三区 | 波多野结衣av一区二区全免费观看 | 国产精品亚洲专区无码不卡 | 4hu四虎永久在线观看 | 亚洲精品国偷拍自产在线麻豆 | 98国产精品综合一区二区三区 | 亚洲欧洲日本无在线码 | 亚洲精品一区二区三区四区五区 | 久9re热视频这里只有精品 | 日日碰狠狠躁久久躁蜜桃 | 在线欧美精品一区二区三区 | 国产真人无遮挡作爱免费视频 | 久久成人a毛片免费观看网站 | 日韩精品乱码av一区二区 | 精品乱码久久久久久久 | 国产亚洲精品久久久ai换 | 亚洲成av人片天堂网无码】 | 国产做国产爱免费视频 | 精品国产一区二区三区四区在线看 | 婷婷五月综合缴情在线视频 | 欧美三级不卡在线观看 | 亚洲综合另类小说色区 | 人人澡人人妻人人爽人人蜜桃 | 国产精品亚洲五月天高清 | 日日天干夜夜狠狠爱 | 国产成人无码区免费内射一片色欲 | 亚洲欧美色中文字幕在线 | 亚洲精品美女久久久久久久 | 国产真实乱对白精彩久久 | 日本爽爽爽爽爽爽在线观看免 | 亚欧洲精品在线视频免费观看 | 亚洲男女内射在线播放 | 又大又硬又黄的免费视频 | 成人aaa片一区国产精品 | 天堂在线观看www | 欧美 亚洲 国产 另类 | 成人精品一区二区三区中文字幕 | 亚无码乱人伦一区二区 | 一本久道久久综合婷婷五月 | 一二三四在线观看免费视频 | 鲁鲁鲁爽爽爽在线视频观看 | 国产精品成人av在线观看 | 欧美性色19p | 亚洲欧美日韩综合久久久 | 在线观看国产午夜福利片 | 国产深夜福利视频在线 | 亚洲熟悉妇女xxx妇女av | 国产一区二区三区精品视频 | 特大黑人娇小亚洲女 | 亚洲 欧美 激情 小说 另类 | 亚洲成熟女人毛毛耸耸多 | 日韩av无码一区二区三区 | 亚洲狠狠色丁香婷婷综合 | 最新版天堂资源中文官网 | 男女猛烈xx00免费视频试看 | 久久午夜无码鲁丝片午夜精品 | 性色欲网站人妻丰满中文久久不卡 | 老司机亚洲精品影院无码 | 成 人 网 站国产免费观看 | 无码人妻av免费一区二区三区 | 色老头在线一区二区三区 | 熟妇女人妻丰满少妇中文字幕 | 水蜜桃亚洲一二三四在线 | 丰满人妻翻云覆雨呻吟视频 | 国产在线aaa片一区二区99 | 精品国产青草久久久久福利 | 日韩av激情在线观看 | 国产精品久免费的黄网站 | 亚洲国产一区二区三区在线观看 | 国产婷婷色一区二区三区在线 | 香蕉久久久久久av成人 | 久久午夜无码鲁丝片秋霞 | 人妻少妇精品无码专区动漫 | 亚洲午夜福利在线观看 | 日韩人妻无码一区二区三区久久99 | 高清不卡一区二区三区 | 久久99久久99精品中文字幕 | 欧美性色19p | 国产亚洲精品久久久ai换 | 丝袜人妻一区二区三区 | 国产一区二区三区四区五区加勒比 | 丰满护士巨好爽好大乳 | 无码纯肉视频在线观看 | 欧美人与物videos另类 | 天海翼激烈高潮到腰振不止 | 国产99久久精品一区二区 | yw尤物av无码国产在线观看 | av人摸人人人澡人人超碰下载 | 乱码av麻豆丝袜熟女系列 | 丰满少妇人妻久久久久久 | 免费无码肉片在线观看 | 久久亚洲国产成人精品性色 | 欧美freesex黑人又粗又大 | 中文字幕无码av激情不卡 | av人摸人人人澡人人超碰下载 | 精品国产一区av天美传媒 | 中文字幕日韩精品一区二区三区 | 国产成人无码av片在线观看不卡 | 久久久久免费精品国产 | 天堂а√在线地址中文在线 | 国产人妻精品一区二区三区不卡 | 中文字幕乱码人妻无码久久 | 荡女精品导航 | 99久久精品无码一区二区毛片 | 强开小婷嫩苞又嫩又紧视频 | 在线看片无码永久免费视频 | 乱人伦人妻中文字幕无码久久网 | 久久久成人毛片无码 | 鲁一鲁av2019在线 | 97久久精品无码一区二区 | 午夜性刺激在线视频免费 | 欧美老妇与禽交 | 中文字幕 人妻熟女 | 天天拍夜夜添久久精品 | 亚洲色欲久久久综合网东京热 | 国精产品一品二品国精品69xx | 少妇高潮一区二区三区99 | 国产人妻精品一区二区三区不卡 | 国产人妻久久精品二区三区老狼 | 波多野结衣 黑人 | 2019午夜福利不卡片在线 | 国产精品丝袜黑色高跟鞋 | 午夜成人1000部免费视频 | 久久国产36精品色熟妇 | 一本色道婷婷久久欧美 | 免费中文字幕日韩欧美 | 中文精品无码中文字幕无码专区 | 天堂亚洲2017在线观看 | 成人女人看片免费视频放人 | 久久久久久av无码免费看大片 | 乱码av麻豆丝袜熟女系列 | 成人欧美一区二区三区黑人免费 | 亚洲最大成人网站 | 色爱情人网站 | 自拍偷自拍亚洲精品10p | 国产69精品久久久久app下载 | 国产熟女一区二区三区四区五区 | 国产美女精品一区二区三区 | 久久精品人妻少妇一区二区三区 | 老子影院午夜伦不卡 | 亚洲中文字幕无码一久久区 | 久久99精品久久久久婷婷 | 欧美国产亚洲日韩在线二区 | 亚洲色大成网站www国产 | 中文字幕乱码亚洲无线三区 | 中文字幕人成乱码熟女app | 久久精品国产99精品亚洲 | 精品久久久久久人妻无码中文字幕 | 亚洲综合精品香蕉久久网 | 欧美激情综合亚洲一二区 | 国模大胆一区二区三区 | 国产成人无码a区在线观看视频app | 狠狠色色综合网站 | 色综合久久久无码网中文 | 久久精品女人的天堂av | 欧美性生交活xxxxxdddd | 男女作爱免费网站 | 亚洲一区二区三区播放 | 夜先锋av资源网站 | 国产av无码专区亚洲a∨毛片 | 亚洲色在线无码国产精品不卡 | 国产办公室秘书无码精品99 | 日本丰满熟妇videos | 四虎4hu永久免费 | 国产av一区二区三区最新精品 | 欧美精品在线观看 | 亚拍精品一区二区三区探花 | 性做久久久久久久免费看 | 黑人粗大猛烈进出高潮视频 | 波多野结衣一区二区三区av免费 | 午夜性刺激在线视频免费 | 午夜精品久久久久久久久 | 日本乱人伦片中文三区 | 午夜丰满少妇性开放视频 | 成人影院yy111111在线观看 | 国产精品理论片在线观看 | 大胆欧美熟妇xx | 极品嫩模高潮叫床 | 亚洲欧洲中文日韩av乱码 | 国产成人无码av在线影院 | 成人精品视频一区二区三区尤物 | 精品国产成人一区二区三区 | 亚洲天堂2017无码 | 无套内谢老熟女 | 国产亚洲欧美在线专区 | 国产精品久久精品三级 | 麻花豆传媒剧国产免费mv在线 | 人妻少妇精品无码专区动漫 | 国产精华av午夜在线观看 | 十八禁真人啪啪免费网站 | 动漫av一区二区在线观看 | 妺妺窝人体色www在线小说 | 任你躁国产自任一区二区三区 | 久久久国产精品无码免费专区 | 一区二区三区乱码在线 | 欧洲 | 亚洲经典千人经典日产 | 欧美国产日韩久久mv | 日产精品高潮呻吟av久久 | 亚洲一区二区三区香蕉 | 无码人妻丰满熟妇区五十路百度 | 男女性色大片免费网站 | 亚洲精品综合五月久久小说 | 久久视频在线观看精品 | 奇米影视888欧美在线观看 | 亚洲日本va中文字幕 | 久久精品国产亚洲精品 | 疯狂三人交性欧美 | 一本久久a久久精品vr综合 | 国产成人精品一区二区在线小狼 | 久久99精品久久久久久 | 国产真人无遮挡作爱免费视频 | 伊人久久大香线蕉亚洲 | 精品国产精品久久一区免费式 | 亚洲精品国产精品乱码不卡 | 在线 国产 欧美 亚洲 天堂 | 人妻体内射精一区二区三四 | 国产人妻精品午夜福利免费 | 国产成人精品优优av | 日韩精品无码一区二区中文字幕 | 亚洲熟妇自偷自拍另类 | 宝宝好涨水快流出来免费视频 | 中文字幕无码免费久久9一区9 | 97久久国产亚洲精品超碰热 | 亚洲日韩av一区二区三区四区 | 最近免费中文字幕中文高清百度 | 亚洲日本在线电影 | 日韩人妻无码一区二区三区久久99 | 网友自拍区视频精品 | yw尤物av无码国产在线观看 | 少妇无码av无码专区在线观看 | 少妇高潮一区二区三区99 | 少妇无码吹潮 | a在线亚洲男人的天堂 | 玩弄少妇高潮ⅹxxxyw | 四十如虎的丰满熟妇啪啪 | 一本加勒比波多野结衣 | 精品久久久无码人妻字幂 | 亚洲毛片av日韩av无码 | 久久精品人妻少妇一区二区三区 | 国产亚洲精品精品国产亚洲综合 | 在教室伦流澡到高潮hnp视频 | 国产无遮挡又黄又爽又色 | 国产成人精品必看 | 在线播放亚洲第一字幕 | 亚洲一区二区三区四区 | 国产精品永久免费视频 | 日韩av无码中文无码电影 | 欧洲极品少妇 | 成人女人看片免费视频放人 | 亚洲色大成网站www国产 | 国产成人精品一区二区在线小狼 | 国产黄在线观看免费观看不卡 | 欧美35页视频在线观看 | 国产在线精品一区二区三区直播 | 精品无码成人片一区二区98 | 亚洲国产午夜精品理论片 | 爆乳一区二区三区无码 | 国产人妻精品一区二区三区 | 激情国产av做激情国产爱 | 久久99精品久久久久久动态图 | 青青青手机频在线观看 | 1000部啪啪未满十八勿入下载 | 国产猛烈高潮尖叫视频免费 | 久久国产36精品色熟妇 | 国产成人一区二区三区在线观看 | 国内精品一区二区三区不卡 | 色老头在线一区二区三区 | 久久久久久亚洲精品a片成人 | 色综合久久久无码中文字幕 | 老熟妇乱子伦牲交视频 | 极品嫩模高潮叫床 | 日本大香伊一区二区三区 | 国产真实夫妇视频 | 欧美变态另类xxxx | 国产精品第一区揄拍无码 | 欧洲欧美人成视频在线 | 国内精品人妻无码久久久影院 | 久久国产精品萌白酱免费 | 少妇人妻大乳在线视频 | 午夜精品一区二区三区的区别 | 少妇性l交大片欧洲热妇乱xxx | 欧美性黑人极品hd | 丰满护士巨好爽好大乳 | 永久免费观看国产裸体美女 | 国产精品a成v人在线播放 | 天堂在线观看www | 在线 国产 欧美 亚洲 天堂 | 色综合久久88色综合天天 | 国产在线aaa片一区二区99 | 激情综合激情五月俺也去 | 国产色在线 | 国产 | 又粗又大又硬又长又爽 | 又粗又大又硬又长又爽 | 98国产精品综合一区二区三区 | 性欧美牲交在线视频 | 中文字幕乱码人妻二区三区 | 亚洲成熟女人毛毛耸耸多 | 国产真实乱对白精彩久久 | 一本久久a久久精品亚洲 | 中文字幕人妻无码一夲道 | 无码福利日韩神码福利片 | 亚洲成av人片在线观看无码不卡 | 激情五月综合色婷婷一区二区 | 亚欧洲精品在线视频免费观看 | 国产精品嫩草久久久久 | 日韩无码专区 | 久久亚洲精品中文字幕无男同 | 国产精品国产三级国产专播 | 亚洲一区二区三区香蕉 | 国产精品无码一区二区三区不卡 | 领导边摸边吃奶边做爽在线观看 | 亚洲 日韩 欧美 成人 在线观看 | 无码人妻黑人中文字幕 | 亚洲成色www久久网站 | 九九综合va免费看 | 亚洲区欧美区综合区自拍区 | 沈阳熟女露脸对白视频 | 久久人妻内射无码一区三区 | 国产亚洲精品久久久久久久 | 亚洲七七久久桃花影院 | 精品久久久中文字幕人妻 | 波多野结衣乳巨码无在线观看 | 日韩无码专区 | 色综合久久久久综合一本到桃花网 | 国产精品99久久精品爆乳 | 国产精品人人爽人人做我的可爱 | 亚洲无人区午夜福利码高清完整版 | 一本久久a久久精品vr综合 | 人人爽人人澡人人高潮 | 国产精华av午夜在线观看 | 帮老师解开蕾丝奶罩吸乳网站 | 日日碰狠狠躁久久躁蜜桃 | 一本久道久久综合婷婷五月 | 狂野欧美性猛xxxx乱大交 | 麻豆国产丝袜白领秘书在线观看 | 一本色道久久综合狠狠躁 | 亚洲一区二区三区国产精华液 | 又湿又紧又大又爽a视频国产 | 国产午夜福利100集发布 | 7777奇米四色成人眼影 | 久久久亚洲欧洲日产国码αv | 欧美成人高清在线播放 | 51国偷自产一区二区三区 | 久久久久久av无码免费看大片 | 免费看少妇作爱视频 | 水蜜桃av无码 | 精品国偷自产在线 | 亚洲色偷偷男人的天堂 | 欧美国产日韩亚洲中文 | 波多野42部无码喷潮在线 | 中文字幕 亚洲精品 第1页 | 日本饥渴人妻欲求不满 | 大肉大捧一进一出好爽视频 | 日韩欧美群交p片內射中文 | 自拍偷自拍亚洲精品被多人伦好爽 | 成人无码影片精品久久久 | 永久免费观看国产裸体美女 | 久久熟妇人妻午夜寂寞影院 | 成人无码影片精品久久久 | 亚洲中文字幕在线无码一区二区 | 伊人久久大香线蕉av一区二区 | 国产艳妇av在线观看果冻传媒 | 国产亚洲日韩欧美另类第八页 | 亚洲男人av香蕉爽爽爽爽 | 中文字幕人妻丝袜二区 | 丰满妇女强制高潮18xxxx | 女人被男人爽到呻吟的视频 | 国产成人人人97超碰超爽8 | 亚洲精品国产精品乱码不卡 | 99国产精品白浆在线观看免费 | 国产激情精品一区二区三区 | √天堂资源地址中文在线 | 黄网在线观看免费网站 | 国产又爽又黄又刺激的视频 | 无码人妻出轨黑人中文字幕 | 亚洲综合在线一区二区三区 | 99久久亚洲精品无码毛片 | 欧美日韩色另类综合 | 日本免费一区二区三区最新 | 99在线 | 亚洲 | 在线 国产 欧美 亚洲 天堂 | 国产凸凹视频一区二区 | 亚洲人亚洲人成电影网站色 | 人人澡人人透人人爽 | 男女下面进入的视频免费午夜 | 国产suv精品一区二区五 | 国产乱人伦偷精品视频 | 漂亮人妻洗澡被公强 日日躁 | 国产精品人人爽人人做我的可爱 | 国产精品无码一区二区三区不卡 | 亚洲区欧美区综合区自拍区 | 性色欲网站人妻丰满中文久久不卡 | 小sao货水好多真紧h无码视频 | 精品无码国产自产拍在线观看蜜 | 少妇一晚三次一区二区三区 | 国产美女极度色诱视频www | 天天av天天av天天透 | 免费播放一区二区三区 | 国内丰满熟女出轨videos | 无码av中文字幕免费放 | 国产麻豆精品精东影业av网站 | 51国偷自产一区二区三区 | 无码乱肉视频免费大全合集 | 正在播放老肥熟妇露脸 | 久久久久99精品成人片 | 亚洲综合久久一区二区 | 99视频精品全部免费免费观看 | 国产成人亚洲综合无码 | 欧美真人作爱免费视频 | 国产人妻久久精品二区三区老狼 | 亚洲日韩中文字幕在线播放 | 综合人妻久久一区二区精品 | 国产精品.xx视频.xxtv | 亚洲a无码综合a国产av中文 | 色五月丁香五月综合五月 | 波多野结衣一区二区三区av免费 | 在线a亚洲视频播放在线观看 | 国产高清不卡无码视频 | 精品乱码久久久久久久 | 国产又爽又猛又粗的视频a片 | 桃花色综合影院 | 国模大胆一区二区三区 | 丁香花在线影院观看在线播放 | 久久精品国产一区二区三区肥胖 | 久久综合网欧美色妞网 | 国产在线aaa片一区二区99 | 亚洲成色www久久网站 | 久久99精品久久久久婷婷 | 国产片av国语在线观看 | 国产精品久久久久无码av色戒 | 中文字幕无码日韩欧毛 | 亚洲熟妇色xxxxx欧美老妇 | 在线观看国产午夜福利片 | 少妇人妻大乳在线视频 | 国产精品久久久久久久9999 | 色五月五月丁香亚洲综合网 | 精品国产麻豆免费人成网站 | 精品成人av一区二区三区 | 亚洲日韩一区二区三区 | 国产成人无码a区在线观看视频app | 男女猛烈xx00免费视频试看 | 极品尤物被啪到呻吟喷水 | 无码国模国产在线观看 | 午夜熟女插插xx免费视频 | 精品无码一区二区三区的天堂 | 亚洲日韩av一区二区三区四区 | 人妻人人添人妻人人爱 | 精品无码国产自产拍在线观看蜜 | 亚洲爆乳精品无码一区二区三区 | 国产69精品久久久久app下载 | аⅴ资源天堂资源库在线 | 精品无人国产偷自产在线 | 暴力强奷在线播放无码 | 欧美放荡的少妇 | 亚洲一区二区三区四区 | 性欧美熟妇videofreesex | 国产亚洲精品久久久ai换 | 久久久久亚洲精品中文字幕 | 四虎影视成人永久免费观看视频 | 中国女人内谢69xxxx | 国产高清不卡无码视频 | 国产精品久久久一区二区三区 | 最新国产麻豆aⅴ精品无码 | 中文字幕无线码免费人妻 | 亚洲精品国产精品乱码不卡 | 午夜嘿嘿嘿影院 | 欧美性生交xxxxx久久久 | 亚洲精品无码人妻无码 | 久久熟妇人妻午夜寂寞影院 | 国产明星裸体无码xxxx视频 | 亚洲一区二区三区四区 | 国产 浪潮av性色四虎 | 在线观看欧美一区二区三区 | 夜夜躁日日躁狠狠久久av | 色婷婷综合激情综在线播放 | 人妻尝试又大又粗久久 | 性做久久久久久久久 | 亚洲另类伦春色综合小说 | 999久久久国产精品消防器材 | 欧美日韩在线亚洲综合国产人 | 日产精品99久久久久久 | 日韩人妻系列无码专区 | 色欲av亚洲一区无码少妇 | 免费中文字幕日韩欧美 | 亚洲成av人影院在线观看 | 国产激情一区二区三区 | 久久人人爽人人爽人人片ⅴ | 对白脏话肉麻粗话av | 国产精品办公室沙发 | av香港经典三级级 在线 | 狠狠色丁香久久婷婷综合五月 | 国产av人人夜夜澡人人爽麻豆 | 中文字幕乱码人妻无码久久 | 日本爽爽爽爽爽爽在线观看免 | 丁香花在线影院观看在线播放 | 暴力强奷在线播放无码 | 99久久婷婷国产综合精品青草免费 | 98国产精品综合一区二区三区 | 亚洲综合在线一区二区三区 | 日欧一片内射va在线影院 | 国产精品毛多多水多 | 对白脏话肉麻粗话av | 激情综合激情五月俺也去 | 丝袜美腿亚洲一区二区 | 骚片av蜜桃精品一区 | 亚拍精品一区二区三区探花 | 国产精品无码成人午夜电影 | 欧美日本免费一区二区三区 | 99精品无人区乱码1区2区3区 | 亚洲一区av无码专区在线观看 | 国产精品永久免费视频 | 日韩av无码一区二区三区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 黑人巨大精品欧美一区二区 | 99久久精品日本一区二区免费 | 亚洲欧美精品aaaaaa片 | 无码国产激情在线观看 | 久激情内射婷内射蜜桃人妖 | 久久无码专区国产精品s | 蜜臀av无码人妻精品 | www国产精品内射老师 | 极品嫩模高潮叫床 | 又紧又大又爽精品一区二区 | 一本久久a久久精品vr综合 | 国产香蕉尹人综合在线观看 | 亚洲色偷偷男人的天堂 | 国产明星裸体无码xxxx视频 | 国产精品久久久一区二区三区 | 97久久超碰中文字幕 | 色 综合 欧美 亚洲 国产 | 国产亚洲精品久久久久久久久动漫 | 夜夜影院未满十八勿进 | 中文字幕无线码 | 3d动漫精品啪啪一区二区中 | 亚洲天堂2017无码中文 | 精品夜夜澡人妻无码av蜜桃 | 亚洲国产日韩a在线播放 | 日本高清一区免费中文视频 | 日韩精品a片一区二区三区妖精 | 成人精品视频一区二区三区尤物 | 无码一区二区三区在线 | 精品偷拍一区二区三区在线看 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 欧美放荡的少妇 | 人妻熟女一区 | 欧美日本免费一区二区三区 | 国产精品久久久久影院嫩草 | 国产精品亚洲综合色区韩国 | 麻花豆传媒剧国产免费mv在线 | 性欧美牲交xxxxx视频 | 国产真实伦对白全集 | 亚洲乱码中文字幕在线 | 日韩精品a片一区二区三区妖精 | 全球成人中文在线 | 性欧美疯狂xxxxbbbb | 男女性色大片免费网站 | 国产真实乱对白精彩久久 | 亚洲无人区一区二区三区 | 亚洲经典千人经典日产 | 国产av一区二区精品久久凹凸 | 亚洲无人区午夜福利码高清完整版 | 亚洲娇小与黑人巨大交 | 一本色道久久综合亚洲精品不卡 | 999久久久国产精品消防器材 | 午夜时刻免费入口 | 色 综合 欧美 亚洲 国产 | 亚洲精品久久久久久一区二区 | 图片区 小说区 区 亚洲五月 | 樱花草在线播放免费中文 | 亚洲国产精华液网站w | 亚洲国产欧美日韩精品一区二区三区 | 亚洲乱码中文字幕在线 | 久久99精品久久久久久动态图 | av无码久久久久不卡免费网站 | 国内揄拍国内精品人妻 | 久久97精品久久久久久久不卡 | 国内揄拍国内精品人妻 | 国产深夜福利视频在线 | 国产精品亚洲综合色区韩国 | 色婷婷久久一区二区三区麻豆 | 大肉大捧一进一出好爽视频 | 久久伊人色av天堂九九小黄鸭 | 精品国产麻豆免费人成网站 | 国产精品久久久久久亚洲毛片 | 日日天干夜夜狠狠爱 | 精品厕所偷拍各类美女tp嘘嘘 | 麻豆成人精品国产免费 | 久久成人a毛片免费观看网站 | 色综合久久中文娱乐网 | 性欧美熟妇videofreesex | 俺去俺来也在线www色官网 | 丁香花在线影院观看在线播放 | 成人精品视频一区二区 | 国产激情综合五月久久 | 三上悠亚人妻中文字幕在线 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 三级4级全黄60分钟 | 成人精品天堂一区二区三区 | 强辱丰满人妻hd中文字幕 | 一本大道久久东京热无码av | 2019午夜福利不卡片在线 | 特大黑人娇小亚洲女 | 波多野结衣av一区二区全免费观看 | 日本成熟视频免费视频 | 亚洲精品成人av在线 | 国产精品久久国产三级国 | 免费人成在线观看网站 | 人妻插b视频一区二区三区 | 日本大乳高潮视频在线观看 | 暴力强奷在线播放无码 | 欧美喷潮久久久xxxxx | 国産精品久久久久久久 | 欧美国产亚洲日韩在线二区 | 日韩亚洲欧美精品综合 | 免费观看的无遮挡av | 国产人妻人伦精品1国产丝袜 | 久久久久久久人妻无码中文字幕爆 | 丰满肥臀大屁股熟妇激情视频 | 亚洲欧美色中文字幕在线 | 欧美丰满熟妇xxxx性ppx人交 | 夜精品a片一区二区三区无码白浆 | 免费国产黄网站在线观看 | 欧美三级不卡在线观看 | 国产色xx群视频射精 | 国产精品-区区久久久狼 | 日本一卡2卡3卡四卡精品网站 | 国产亚洲精品久久久ai换 | 一个人看的www免费视频在线观看 | 最新国产麻豆aⅴ精品无码 | 久久久国产一区二区三区 | 国产莉萝无码av在线播放 | 久久久www成人免费毛片 | 国产色精品久久人妻 | 美女扒开屁股让男人桶 | 偷窥日本少妇撒尿chinese | 亚洲aⅴ无码成人网站国产app | 东京热无码av男人的天堂 | 日本大乳高潮视频在线观看 | 两性色午夜免费视频 | 天堂а√在线中文在线 | 久久久国产精品无码免费专区 | 国产精品毛片一区二区 | 日日麻批免费40分钟无码 | 亚洲 日韩 欧美 成人 在线观看 | 18精品久久久无码午夜福利 | 国产精品美女久久久久av爽李琼 | 欧洲美熟女乱又伦 | 亚洲人交乣女bbw | 天下第一社区视频www日本 | 欧美成人午夜精品久久久 |