ZooKeeper.xs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664
  1. /* Net::ZooKeeper - Perl extension for Apache ZooKeeper
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. #define PERL_NO_GET_CONTEXT
  20. #include "EXTERN.h"
  21. #include "perl.h"
  22. #include "XSUB.h"
  23. #include <pthread.h> /* pthread_mutex_lock(), etc. */
  24. #include <string.h> /* memset(), etc. */
  25. #include <limits.h> /* CHAR_BIT */
  26. #include <sys/time.h> /* gettimeofday() */
  27. #include <zookeeper/zookeeper.h>
  28. #include "build/check_zk_version.h"
  29. #define PACKAGE_NAME "Net::ZooKeeper"
  30. #define PACKAGE_SIGNATURE 19631123
  31. #define STAT_PACKAGE_NAME "Net::ZooKeeper::Stat"
  32. #define STAT_PACKAGE_SIGNATURE 19960512
  33. #define WATCH_PACKAGE_NAME "Net::ZooKeeper::Watch"
  34. #define WATCH_PACKAGE_SIGNATURE 20050326
  35. #define MAX_KEY_NAME_LEN 16 /* "children_version" */
  36. #define NUM_ACL_ENTRY_KEYS 3
  37. #define NUM_KEYS 7
  38. #define NUM_STAT_KEYS 11
  39. #define NUM_WATCH_KEYS 3
  40. #define DEFAULT_RECV_TIMEOUT_MSEC 10000
  41. #define DEFAULT_DATA_BUF_LEN 1023
  42. #define DEFAULT_PATH_BUF_LEN 1023
  43. #define DEFAULT_WATCH_TIMEOUT 60000
  44. #define ZOO_LOG_LEVEL_OFF 0
  45. #ifndef strcaseEQ
  46. #define strcaseEQ(a,b) (!strcasecmp((a),(b)))
  47. #endif
  48. typedef struct Stat zk_stat_t;
  49. typedef HV* Net__ZooKeeper__Stat;
  50. typedef struct zk_watch_t zk_watch_t;
  51. struct zk_watch_t {
  52. pthread_mutex_t mutex;
  53. pthread_cond_t cond;
  54. int done;
  55. int ret;
  56. int event_type;
  57. int event_state;
  58. unsigned int timeout;
  59. zk_watch_t *prev;
  60. zk_watch_t *next;
  61. int ref_count;
  62. };
  63. typedef HV* Net__ZooKeeper__Watch;
  64. typedef struct {
  65. zhandle_t *handle;
  66. zk_watch_t *first_watch;
  67. int data_buf_len;
  68. int path_buf_len;
  69. unsigned int watch_timeout;
  70. const char *hosts;
  71. int hosts_len;
  72. int last_ret;
  73. int last_errno;
  74. } zk_t;
  75. typedef HV* Net__ZooKeeper;
  76. typedef struct {
  77. I32 signature;
  78. union {
  79. zk_t *zk;
  80. zk_stat_t *stat;
  81. zk_watch_t *watch;
  82. } handle;
  83. } zk_handle_t;
  84. typedef struct {
  85. const char name[MAX_KEY_NAME_LEN + 1];
  86. U32 name_len;
  87. size_t offset;
  88. size_t size;
  89. U32 hash;
  90. } zk_key_t;
  91. static zk_key_t zk_acl_entry_keys[NUM_ACL_ENTRY_KEYS] = {
  92. {"perms", 0, 0, 0, 0},
  93. {"scheme", 0, 0, 0, 0},
  94. {"id", 0, 0, 0, 0}
  95. };
  96. static zk_key_t zk_keys[NUM_KEYS] = {
  97. {"data_read_len", 0, 0, 0, 0},
  98. {"path_read_len", 0, 0, 0, 0},
  99. {"watch_timeout", 0, 0, 0, 0},
  100. {"hosts", 0, 0, 0, 0},
  101. {"session_timeout", 0, 0, 0, 0},
  102. {"session_id", 0, 0, 0, 0},
  103. {"pending_watches", 0, 0, 0, 0}
  104. };
  105. static zk_key_t zk_stat_keys[NUM_STAT_KEYS] = {
  106. {"czxid", 0, offsetof(struct Stat, czxid),
  107. sizeof(((struct Stat*) 0)->czxid), 0},
  108. {"mzxid", 0, offsetof(struct Stat, mzxid),
  109. sizeof(((struct Stat*) 0)->mzxid), 0},
  110. {"ctime", 0, offsetof(struct Stat, ctime),
  111. sizeof(((struct Stat*) 0)->ctime), 0},
  112. {"mtime", 0, offsetof(struct Stat, mtime),
  113. sizeof(((struct Stat*) 0)->mtime), 0},
  114. {"version", 0, offsetof(struct Stat, version),
  115. sizeof(((struct Stat*) 0)->version), 0},
  116. {"children_version", 0, offsetof(struct Stat, cversion),
  117. sizeof(((struct Stat*) 0)->cversion), 0},
  118. {"acl_version", 0, offsetof(struct Stat, aversion),
  119. sizeof(((struct Stat*) 0)->aversion), 0},
  120. {"ephemeral_owner", 0, offsetof(struct Stat, ephemeralOwner),
  121. sizeof(((struct Stat*) 0)->ephemeralOwner), 0},
  122. {"data_len", 0, offsetof(struct Stat, dataLength),
  123. sizeof(((struct Stat*) 0)->dataLength), 0},
  124. {"num_children", 0, offsetof(struct Stat, numChildren),
  125. sizeof(((struct Stat*) 0)->numChildren), 0},
  126. {"children_zxid", 0, offsetof(struct Stat, pzxid),
  127. sizeof(((struct Stat*) 0)->pzxid), 0}
  128. };
  129. static zk_key_t zk_watch_keys[NUM_WATCH_KEYS] = {
  130. {"timeout", 0, 0, 0, 0},
  131. {"event", 0, 0, 0, 0},
  132. {"state", 0, 0, 0, 0}
  133. };
  134. static void _zk_watcher(zhandle_t *handle, int type, int state,
  135. const char *path, void *context)
  136. {
  137. zk_watch_t *watch_ctx = context;
  138. pthread_mutex_lock(&watch_ctx->mutex);
  139. watch_ctx->event_type = type;
  140. watch_ctx->event_state = state;
  141. watch_ctx->done = 1;
  142. pthread_cond_signal(&watch_ctx->cond);
  143. pthread_mutex_unlock(&watch_ctx->mutex);
  144. return;
  145. }
  146. static void _zk_auth_completion(int ret, const void *data)
  147. {
  148. zk_watch_t *watch_ctx = (zk_watch_t*) data;
  149. pthread_mutex_lock(&watch_ctx->mutex);
  150. watch_ctx->ret = ret;
  151. watch_ctx->done = 1;
  152. pthread_cond_signal(&watch_ctx->cond);
  153. pthread_mutex_unlock(&watch_ctx->mutex);
  154. return;
  155. }
  156. static zk_watch_t *_zk_create_watch(pTHX)
  157. {
  158. zk_watch_t *watch;
  159. Newxz(watch, 1, zk_watch_t);
  160. if (pthread_mutex_init(&watch->mutex, NULL)) {
  161. int save_errno = errno;
  162. Safefree(watch);
  163. errno = save_errno;
  164. return NULL;
  165. }
  166. if (pthread_cond_init(&watch->cond, NULL)) {
  167. int save_errno = errno;
  168. pthread_mutex_destroy(&watch->mutex);
  169. Safefree(watch);
  170. errno = save_errno;
  171. return NULL;
  172. }
  173. return watch;
  174. }
  175. static void _zk_destroy_watch(pTHX_ zk_watch_t *watch)
  176. {
  177. pthread_cond_destroy(&watch->cond);
  178. pthread_mutex_destroy(&watch->mutex);
  179. Safefree(watch);
  180. return;
  181. }
  182. static zk_watch_t *_zk_acquire_watch(pTHX)
  183. {
  184. zk_watch_t *watch = _zk_create_watch(aTHX);
  185. if (watch) {
  186. watch->ref_count = 1;
  187. }
  188. return watch;
  189. }
  190. static void _zk_release_watch(pTHX_ zk_watch_t *watch, int list)
  191. {
  192. if (list) {
  193. if (watch->prev) {
  194. watch->prev->next = watch->next;
  195. }
  196. if (watch->next) {
  197. watch->next->prev = watch->prev;
  198. }
  199. watch->prev = NULL;
  200. watch->next = NULL;
  201. }
  202. if (--watch->ref_count == 0) {
  203. _zk_destroy_watch(aTHX_ watch);
  204. }
  205. return;
  206. }
  207. static unsigned int _zk_release_watches(pTHX_ zk_watch_t *first_watch,
  208. int final)
  209. {
  210. zk_watch_t *watch = first_watch->next;
  211. unsigned int pending_watches = 0;
  212. while (watch) {
  213. zk_watch_t *next_watch = watch->next;
  214. int done = final;
  215. if (!final) {
  216. pthread_mutex_lock(&watch->mutex);
  217. done = watch->done;
  218. pthread_mutex_unlock(&watch->mutex);
  219. }
  220. if (done) {
  221. _zk_release_watch(aTHX_ watch, 1);
  222. }
  223. else {
  224. ++pending_watches;
  225. }
  226. watch = next_watch;
  227. }
  228. return pending_watches;
  229. }
  230. static void _zk_replace_watch(pTHX_ zk_handle_t *handle,
  231. zk_watch_t *first_watch,
  232. zk_watch_t *old_watch, zk_watch_t *new_watch)
  233. {
  234. zk_watch_t *next_watch;
  235. new_watch->timeout = old_watch->timeout;
  236. _zk_release_watch(aTHX_ old_watch, 0);
  237. /* cleanup any completed watches not tied to a handle */
  238. _zk_release_watches(aTHX_ first_watch, 0);
  239. next_watch = first_watch->next;
  240. new_watch->prev = first_watch;
  241. new_watch->next = next_watch;
  242. if (next_watch) {
  243. next_watch->prev = new_watch;
  244. }
  245. first_watch->next = new_watch;
  246. ++new_watch->ref_count;
  247. handle->handle.watch = new_watch;
  248. return;
  249. }
  250. static void _zk_free_acl(pTHX_ struct ACL_vector *acl)
  251. {
  252. if (acl->data) {
  253. Safefree(acl->data);
  254. }
  255. return;
  256. }
  257. static const char *_zk_fill_acl(pTHX_ AV *acl_arr, struct ACL_vector *acl)
  258. {
  259. I32 num_acl_entries = av_len(acl_arr) + 1;
  260. int i;
  261. Zero(acl, 1, struct ACL_vector);
  262. if (num_acl_entries <= 0) {
  263. return NULL;
  264. }
  265. else if (num_acl_entries > PERL_INT_MAX) {
  266. num_acl_entries = PERL_INT_MAX;
  267. }
  268. Newx(acl->data, num_acl_entries, struct ACL);
  269. for (i = 0; i < num_acl_entries; ++i) {
  270. SV **acl_entry_ptr;
  271. HV *acl_entry_hash;
  272. zk_key_t *key;
  273. SV **val_ptr;
  274. struct ACL acl_entry;
  275. acl_entry_ptr = av_fetch(acl_arr, i, 0);
  276. if (!acl_entry_ptr) {
  277. continue;
  278. }
  279. if (!SvROK(*acl_entry_ptr) ||
  280. SvTYPE(SvRV(*acl_entry_ptr)) != SVt_PVHV) {
  281. _zk_free_acl(aTHX_ acl);
  282. return "invalid ACL entry hash reference";
  283. }
  284. acl_entry_hash = (HV*) SvRV(*acl_entry_ptr);
  285. key = &zk_acl_entry_keys[0];
  286. val_ptr = hv_fetch(acl_entry_hash, key->name, key->name_len, 0);
  287. if (!val_ptr) {
  288. _zk_free_acl(aTHX_ acl);
  289. return "no ACL entry perms element";
  290. }
  291. acl_entry.perms = SvIV(*val_ptr);
  292. if (!acl_entry.perms || (acl_entry.perms & ~ZOO_PERM_ALL)) {
  293. _zk_free_acl(aTHX_ acl);
  294. return "invalid ACL entry perms";
  295. }
  296. key = &zk_acl_entry_keys[1];
  297. val_ptr = hv_fetch(acl_entry_hash, key->name, key->name_len, 0);
  298. if (!val_ptr) {
  299. _zk_free_acl(aTHX_ acl);
  300. return "no ACL entry scheme element";
  301. }
  302. acl_entry.id.scheme = SvPV_nolen(*val_ptr);
  303. key = &zk_acl_entry_keys[2];
  304. val_ptr = hv_fetch(acl_entry_hash, key->name, key->name_len, 0);
  305. if (!val_ptr) {
  306. _zk_free_acl(aTHX_ acl);
  307. return "no ACL entry id element";
  308. }
  309. acl_entry.id.id = SvPV_nolen(*val_ptr);
  310. ++acl->count;
  311. acl->data[i] = acl_entry;
  312. }
  313. return NULL;
  314. }
  315. static void _zk_fill_acl_entry_hash(pTHX_ struct ACL *acl_entry,
  316. HV *acl_entry_hash)
  317. {
  318. zk_key_t *key;
  319. SV *val;
  320. key = &zk_acl_entry_keys[0];
  321. val = newSViv(acl_entry->perms);
  322. if (!hv_store(acl_entry_hash, key->name, key->name_len, val, key->hash)) {
  323. SvREFCNT_dec(val);
  324. }
  325. key = &zk_acl_entry_keys[1];
  326. val = newSVpv(acl_entry->id.scheme, 0);
  327. if (!hv_store(acl_entry_hash, key->name, key->name_len, val, key->hash)) {
  328. SvREFCNT_dec(val);
  329. }
  330. key = &zk_acl_entry_keys[2];
  331. val = newSVpv(acl_entry->id.id, 0);
  332. if (!hv_store(acl_entry_hash, key->name, key->name_len, val, key->hash)) {
  333. SvREFCNT_dec(val);
  334. }
  335. return;
  336. }
  337. static zk_handle_t *_zk_check_handle_inner(pTHX_ HV *attr_hash,
  338. I32 package_signature)
  339. {
  340. zk_handle_t *handle = NULL;
  341. if (SvRMAGICAL(attr_hash)) {
  342. MAGIC *magic = mg_find((SV*) attr_hash, PERL_MAGIC_ext);
  343. if (magic) {
  344. handle = (zk_handle_t*) magic->mg_ptr;
  345. if (handle->signature != package_signature) {
  346. handle = NULL;
  347. }
  348. }
  349. }
  350. return handle;
  351. }
  352. static zk_handle_t *_zk_check_handle_outer(pTHX_ HV *hash, HV **attr_hash_ptr,
  353. const char *package_name,
  354. I32 package_signature)
  355. {
  356. zk_handle_t *handle = NULL;
  357. if (attr_hash_ptr) {
  358. *attr_hash_ptr = NULL;
  359. }
  360. if (SvRMAGICAL((SV*) hash)) {
  361. MAGIC *magic = mg_find((SV*) hash, PERL_MAGIC_tied);
  362. if (magic) {
  363. SV *attr = magic->mg_obj;
  364. if (SvROK(attr) && SvTYPE(SvRV(attr)) == SVt_PVHV &&
  365. sv_derived_from(attr, package_name)) {
  366. HV *attr_hash = (HV*) SvRV(attr);
  367. handle = _zk_check_handle_inner(aTHX_ attr_hash,
  368. package_signature);
  369. if (handle && attr_hash_ptr) {
  370. *attr_hash_ptr = attr_hash;
  371. }
  372. }
  373. }
  374. }
  375. return handle;
  376. }
  377. static zk_t *_zk_get_handle_inner(pTHX_ Net__ZooKeeper attr_hash)
  378. {
  379. zk_handle_t *handle;
  380. handle = _zk_check_handle_inner(aTHX_ attr_hash, PACKAGE_SIGNATURE);
  381. return handle ? handle->handle.zk : NULL;
  382. }
  383. static zk_t *_zk_get_handle_outer(pTHX_ Net__ZooKeeper zkh)
  384. {
  385. zk_handle_t *handle;
  386. handle = _zk_check_handle_outer(aTHX_ zkh, NULL, PACKAGE_NAME,
  387. PACKAGE_SIGNATURE);
  388. return handle ? handle->handle.zk : NULL;
  389. }
  390. static zk_stat_t *_zks_get_handle_inner(pTHX_ Net__ZooKeeper__Stat attr_hash)
  391. {
  392. zk_handle_t *handle;
  393. handle = _zk_check_handle_inner(aTHX_ attr_hash, STAT_PACKAGE_SIGNATURE);
  394. return handle ? handle->handle.stat : NULL;
  395. }
  396. static zk_stat_t *_zks_get_handle_outer(pTHX_ Net__ZooKeeper__Stat zksh)
  397. {
  398. zk_handle_t *handle;
  399. handle = _zk_check_handle_outer(aTHX_ zksh, NULL, STAT_PACKAGE_NAME,
  400. STAT_PACKAGE_SIGNATURE);
  401. return handle ? handle->handle.stat : NULL;
  402. }
  403. static zk_watch_t *_zkw_get_handle_inner(pTHX_ Net__ZooKeeper__Watch attr_hash)
  404. {
  405. zk_handle_t *handle;
  406. handle = _zk_check_handle_inner(aTHX_ attr_hash, WATCH_PACKAGE_SIGNATURE);
  407. return handle ? handle->handle.watch : NULL;
  408. }
  409. static zk_watch_t *_zkw_get_handle_outer(pTHX_ Net__ZooKeeper__Watch zkwh,
  410. zk_handle_t **handle_ptr)
  411. {
  412. zk_handle_t *handle;
  413. handle = _zk_check_handle_outer(aTHX_ zkwh, NULL, WATCH_PACKAGE_NAME,
  414. WATCH_PACKAGE_SIGNATURE);
  415. if (handle_ptr) {
  416. *handle_ptr = handle;
  417. }
  418. return handle ? handle->handle.watch : NULL;
  419. }
  420. MODULE = Net::ZooKeeper PACKAGE = Net::ZooKeeper PREFIX = zk_
  421. REQUIRE: 1.9508
  422. PROTOTYPES: ENABLE
  423. BOOT:
  424. {
  425. int i;
  426. for (i = 0; i < NUM_ACL_ENTRY_KEYS; ++i) {
  427. zk_key_t *key = &zk_acl_entry_keys[i];
  428. key->name_len = strlen(key->name);
  429. PERL_HASH(key->hash, key->name, key->name_len);
  430. }
  431. for (i = 0; i < NUM_KEYS; ++i) {
  432. zk_keys[i].name_len = strlen(zk_keys[i].name);
  433. }
  434. for (i = 0; i < NUM_STAT_KEYS; ++i) {
  435. zk_stat_keys[i].name_len = strlen(zk_stat_keys[i].name);
  436. }
  437. for (i = 0; i < NUM_WATCH_KEYS; ++i) {
  438. zk_watch_keys[i].name_len = strlen(zk_watch_keys[i].name);
  439. }
  440. zoo_set_log_stream(NULL);
  441. zoo_set_debug_level(0);
  442. }
  443. I32
  444. zk_constant(alias=Nullch)
  445. char *alias
  446. ALIAS:
  447. ZOK = ZOK
  448. ZSYSTEMERROR = ZSYSTEMERROR
  449. ZRUNTIMEINCONSISTENCY = ZRUNTIMEINCONSISTENCY
  450. ZDATAINCONSISTENCY = ZDATAINCONSISTENCY
  451. ZCONNECTIONLOSS = ZCONNECTIONLOSS
  452. ZMARSHALLINGERROR = ZMARSHALLINGERROR
  453. ZUNIMPLEMENTED = ZUNIMPLEMENTED
  454. ZOPERATIONTIMEOUT = ZOPERATIONTIMEOUT
  455. ZBADARGUMENTS = ZBADARGUMENTS
  456. ZINVALIDSTATE = ZINVALIDSTATE
  457. ZAPIERROR = ZAPIERROR
  458. ZNONODE = ZNONODE
  459. ZNOAUTH = ZNOAUTH
  460. ZBADVERSION = ZBADVERSION
  461. ZNOCHILDRENFOREPHEMERALS = ZNOCHILDRENFOREPHEMERALS
  462. ZNODEEXISTS = ZNODEEXISTS
  463. ZNOTEMPTY = ZNOTEMPTY
  464. ZSESSIONEXPIRED = ZSESSIONEXPIRED
  465. ZINVALIDCALLBACK = ZINVALIDCALLBACK
  466. ZINVALIDACL = ZINVALIDACL
  467. ZAUTHFAILED = ZAUTHFAILED
  468. ZCLOSING = ZCLOSING
  469. ZNOTHING = ZNOTHING
  470. ZOO_EPHEMERAL = ZOO_EPHEMERAL
  471. ZOO_SEQUENCE = ZOO_SEQUENCE
  472. ZOO_PERM_READ = ZOO_PERM_READ
  473. ZOO_PERM_WRITE = ZOO_PERM_WRITE
  474. ZOO_PERM_CREATE = ZOO_PERM_CREATE
  475. ZOO_PERM_DELETE = ZOO_PERM_DELETE
  476. ZOO_PERM_ADMIN = ZOO_PERM_ADMIN
  477. ZOO_PERM_ALL = ZOO_PERM_ALL
  478. ZOO_CREATED_EVENT = ZOO_CREATED_EVENT
  479. ZOO_DELETED_EVENT = ZOO_DELETED_EVENT
  480. ZOO_CHANGED_EVENT = ZOO_CHANGED_EVENT
  481. ZOO_CHILD_EVENT = ZOO_CHILD_EVENT
  482. ZOO_SESSION_EVENT = ZOO_SESSION_EVENT
  483. ZOO_NOTWATCHING_EVENT = ZOO_NOTWATCHING_EVENT
  484. ZOO_EXPIRED_SESSION_STATE = ZOO_EXPIRED_SESSION_STATE
  485. ZOO_AUTH_FAILED_STATE = ZOO_AUTH_FAILED_STATE
  486. ZOO_CONNECTING_STATE = ZOO_CONNECTING_STATE
  487. ZOO_ASSOCIATING_STATE = ZOO_ASSOCIATING_STATE
  488. ZOO_CONNECTED_STATE = ZOO_CONNECTED_STATE
  489. ZOO_LOG_LEVEL_OFF = ZOO_LOG_LEVEL_OFF
  490. ZOO_LOG_LEVEL_ERROR = ZOO_LOG_LEVEL_ERROR
  491. ZOO_LOG_LEVEL_WARN = ZOO_LOG_LEVEL_WARN
  492. ZOO_LOG_LEVEL_INFO = ZOO_LOG_LEVEL_INFO
  493. ZOO_LOG_LEVEL_DEBUG = ZOO_LOG_LEVEL_DEBUG
  494. CODE:
  495. if (!ix) {
  496. if (!alias) {
  497. alias = GvNAME(CvGV(cv));
  498. }
  499. if (strEQ(alias, "ZOK")) {
  500. RETVAL = ZOK;
  501. }
  502. else if (strEQ(alias, "ZOO_LOG_LEVEL_OFF")) {
  503. RETVAL = ZOO_LOG_LEVEL_OFF;
  504. }
  505. else {
  506. Perl_croak(aTHX_ "unknown " PACKAGE_NAME " constant: %s",
  507. alias);
  508. }
  509. }
  510. else {
  511. RETVAL = ix;
  512. }
  513. OUTPUT:
  514. RETVAL
  515. AV *
  516. zk_acl_constant(alias=Nullch)
  517. char *alias
  518. ALIAS:
  519. ZOO_OPEN_ACL_UNSAFE = 1
  520. ZOO_READ_ACL_UNSAFE = 2
  521. ZOO_CREATOR_ALL_ACL = 3
  522. PREINIT:
  523. struct ACL_vector acl;
  524. AV *acl_arr;
  525. int i;
  526. PPCODE:
  527. if (!ix && !alias) {
  528. alias = GvNAME(CvGV(cv));
  529. }
  530. if (ix == 1 || (alias != NULL && strEQ(alias, "ZOO_OPEN_ACL_UNSAFE"))) {
  531. acl = ZOO_OPEN_ACL_UNSAFE;
  532. }
  533. else if (ix == 2 || (alias != NULL && strEQ(alias, "ZOO_READ_ACL_UNSAFE"))) {
  534. acl = ZOO_READ_ACL_UNSAFE;
  535. }
  536. else if (ix == 3 || (alias != NULL && strEQ(alias, "ZOO_CREATOR_ALL_ACL"))) {
  537. acl = ZOO_CREATOR_ALL_ACL;
  538. }
  539. else {
  540. Perl_croak(aTHX_ "unknown " PACKAGE_NAME " constant: %s", alias);
  541. }
  542. acl_arr = newAV();
  543. av_extend(acl_arr, acl.count);
  544. for (i = 0; i < acl.count; ++i) {
  545. HV *acl_entry_hash = newHV();
  546. SV *val;
  547. _zk_fill_acl_entry_hash(aTHX_ &acl.data[i], acl_entry_hash);
  548. val = newRV_noinc((SV*) acl_entry_hash);
  549. if (!av_store(acl_arr, i, val)) {
  550. SvREFCNT_dec(val);
  551. }
  552. }
  553. ST(0) = sv_2mortal(newRV_noinc((SV*) acl_arr));
  554. XSRETURN(1);
  555. void
  556. zk_set_log_level(level)
  557. int level
  558. PPCODE:
  559. if (level < ZOO_LOG_LEVEL_OFF || level > ZOO_LOG_LEVEL_DEBUG) {
  560. Perl_croak(aTHX_ "invalid log level: %d", level);
  561. }
  562. zoo_set_debug_level(level);
  563. XSRETURN_EMPTY;
  564. void
  565. zk_set_deterministic_conn_order(flag)
  566. bool flag
  567. PPCODE:
  568. zoo_deterministic_conn_order(!!flag);
  569. XSRETURN_EMPTY;
  570. void
  571. zk_new(package, hosts, ...)
  572. char *package
  573. char *hosts
  574. PREINIT:
  575. int recv_timeout = DEFAULT_RECV_TIMEOUT_MSEC;
  576. const clientid_t *client_id = NULL;
  577. zk_t *zk;
  578. zk_handle_t *handle;
  579. HV *stash, *zk_hash, *attr_hash;
  580. SV *attr;
  581. int i;
  582. PPCODE:
  583. if (items > 2 && items % 2) {
  584. Perl_croak(aTHX_ "invalid number of arguments");
  585. }
  586. for (i = 2; i < items; i += 2) {
  587. char *key = SvPV_nolen(ST(i));
  588. if (strcaseEQ(key, "session_timeout")) {
  589. recv_timeout = SvIV(ST(i + 1));
  590. /* NOTE: would be nice if requirement in zookeeper_interest()
  591. * that recv_timeout*2 be non-negative was documented
  592. */
  593. if (recv_timeout < 0 || recv_timeout > (PERL_INT_MAX >> 1)) {
  594. Perl_croak(aTHX_ "invalid session timeout: %d",
  595. recv_timeout);
  596. }
  597. }
  598. else if (strcaseEQ(key, "session_id")) {
  599. STRLEN client_id_len;
  600. client_id = (const clientid_t*) SvPV(ST(i + 1), client_id_len);
  601. if (client_id_len != sizeof(clientid_t)) {
  602. Perl_croak(aTHX_ "invalid session ID");
  603. }
  604. }
  605. }
  606. Newxz(zk, 1, zk_t);
  607. zk->handle = zookeeper_init(hosts, NULL, recv_timeout,
  608. client_id, NULL, 0);
  609. if (!zk->handle) {
  610. Safefree(zk);
  611. XSRETURN_UNDEF;
  612. }
  613. Newxz(zk->first_watch, 1, zk_watch_t);
  614. zk->data_buf_len = DEFAULT_DATA_BUF_LEN;
  615. zk->path_buf_len = DEFAULT_PATH_BUF_LEN;
  616. zk->watch_timeout = DEFAULT_WATCH_TIMEOUT;
  617. zk->hosts_len = strlen(hosts);
  618. zk->hosts = savepvn(hosts, zk->hosts_len);
  619. Newx(handle, 1, zk_handle_t);
  620. handle->signature = PACKAGE_SIGNATURE;
  621. handle->handle.zk = zk;
  622. /* We use several tricks from DBI here. The attr_hash is our
  623. * empty inner hash; we attach extra magic to it in the form of
  624. * our zk_handle_t structure. Then we tie attr_hash to zk_hash,
  625. * our outer hash. This is what is passed around (by reference) by
  626. * callers.
  627. *
  628. * Most methods use _zk_get_handle_outer() which finds our inner
  629. * handle, then returns the zk_t structure from its extra magic
  630. * pointer.
  631. *
  632. * However, the tied hash methods, FETCH(), STORE(), and so forth,
  633. * receive an already-dereferenced inner handle hash. This is
  634. * because we bless both inner and outer handles into this class,
  635. * so when a caller's code references a hash element in our
  636. * outer handle, Perl detects its tied magic, looks up the
  637. * tied object (our inner handle) and invokes the tied hash methods
  638. * in its class on it. Since we blessed it into the same class
  639. * as the outer handle, these methods simply reside in our package.
  640. */
  641. stash = gv_stashpv(package, GV_ADDWARN);
  642. attr_hash = newHV();
  643. sv_magic((SV*) attr_hash, Nullsv, PERL_MAGIC_ext,
  644. (const char*) handle, 0);
  645. attr = sv_bless(newRV_noinc((SV*) attr_hash), stash);
  646. zk_hash = newHV();
  647. sv_magic((SV*) zk_hash, attr, PERL_MAGIC_tied, Nullch, 0);
  648. SvREFCNT_dec(attr);
  649. ST(0) = sv_bless(sv_2mortal(newRV_noinc((SV*) zk_hash)), stash);
  650. XSRETURN(1);
  651. void
  652. zk_DESTROY(zkh)
  653. Net::ZooKeeper zkh
  654. PREINIT:
  655. zk_handle_t *handle;
  656. HV *attr_hash;
  657. int ret = ZBADARGUMENTS;
  658. PPCODE:
  659. handle = _zk_check_handle_outer(aTHX_ zkh, &attr_hash,
  660. PACKAGE_NAME, PACKAGE_SIGNATURE);
  661. if (!handle) {
  662. handle = _zk_check_handle_inner(aTHX_ zkh, PACKAGE_SIGNATURE);
  663. if (handle) {
  664. attr_hash = zkh;
  665. zkh = NULL;
  666. }
  667. }
  668. if (handle) {
  669. zk_t *zk = handle->handle.zk;
  670. ret = zookeeper_close(zk->handle);
  671. /* detach all now-inactive watches still tied to handles */
  672. _zk_release_watches(aTHX_ zk->first_watch, 1);
  673. Safefree(zk->first_watch);
  674. Safefree(zk->hosts);
  675. Safefree(zk);
  676. Safefree(handle);
  677. sv_unmagic((SV*) attr_hash, PERL_MAGIC_ext);
  678. }
  679. if (zkh && attr_hash) {
  680. sv_unmagic((SV*) zkh, PERL_MAGIC_tied);
  681. }
  682. if (GIMME_V == G_VOID) {
  683. XSRETURN_EMPTY;
  684. }
  685. else if (ret == ZOK) {
  686. XSRETURN_YES;
  687. }
  688. else {
  689. XSRETURN_NO;
  690. }
  691. void
  692. zk_CLONE(package)
  693. char *package
  694. PPCODE:
  695. XSRETURN_EMPTY;
  696. void
  697. zk_CLONE_SKIP(package)
  698. char *package
  699. PPCODE:
  700. XSRETURN_YES;
  701. void
  702. zk_TIEHASH(package, ...)
  703. char *package
  704. PPCODE:
  705. Perl_croak(aTHX_ "tying hashes of class "
  706. PACKAGE_NAME " not supported");
  707. void
  708. zk_UNTIE(attr_hash, ref_count)
  709. Net::ZooKeeper attr_hash
  710. IV ref_count
  711. PPCODE:
  712. Perl_croak(aTHX_ "untying hashes of class "
  713. PACKAGE_NAME " not supported");
  714. void
  715. zk_FIRSTKEY(attr_hash)
  716. Net::ZooKeeper attr_hash
  717. PREINIT:
  718. zk_t *zk;
  719. PPCODE:
  720. zk = _zk_get_handle_inner(aTHX_ attr_hash);
  721. if (!zk) {
  722. Perl_croak(aTHX_ "invalid handle");
  723. }
  724. ST(0) = sv_2mortal(newSVpvn(zk_keys[0].name, zk_keys[0].name_len));
  725. XSRETURN(1);
  726. void
  727. zk_NEXTKEY(attr_hash, attr_key)
  728. Net::ZooKeeper attr_hash
  729. SV *attr_key
  730. PREINIT:
  731. zk_t *zk;
  732. char *key;
  733. int i;
  734. PPCODE:
  735. zk = _zk_get_handle_inner(aTHX_ attr_hash);
  736. if (!zk) {
  737. Perl_croak(aTHX_ "invalid handle");
  738. }
  739. key = SvPV_nolen(attr_key);
  740. for (i = 0; i < NUM_KEYS; ++i) {
  741. if (strcaseEQ(key, zk_keys[i].name)) {
  742. ++i;
  743. break;
  744. }
  745. }
  746. if (i < NUM_KEYS) {
  747. ST(0) = sv_2mortal(newSVpvn(zk_keys[i].name, zk_keys[i].name_len));
  748. XSRETURN(1);
  749. }
  750. else {
  751. XSRETURN_EMPTY;
  752. }
  753. void
  754. zk_SCALAR(attr_hash)
  755. Net::ZooKeeper attr_hash
  756. PPCODE:
  757. XSRETURN_YES;
  758. void
  759. zk_FETCH(attr_hash, attr_key)
  760. Net::ZooKeeper attr_hash
  761. SV *attr_key
  762. PREINIT:
  763. zk_t *zk;
  764. char *key;
  765. SV *val = NULL;
  766. PPCODE:
  767. zk = _zk_get_handle_inner(aTHX_ attr_hash);
  768. if (!zk) {
  769. Perl_croak(aTHX_ "invalid handle");
  770. }
  771. key = SvPV_nolen(attr_key);
  772. if (strcaseEQ(key, "data_read_len")) {
  773. val = newSViv(zk->data_buf_len);
  774. }
  775. else if (strcaseEQ(key, "path_read_len")) {
  776. val = newSViv(zk->path_buf_len);
  777. }
  778. else if (strcaseEQ(key, "watch_timeout")) {
  779. val = newSVuv(zk->watch_timeout);
  780. }
  781. else if (strcaseEQ(key, "hosts")) {
  782. val = newSVpvn(zk->hosts, zk->hosts_len);
  783. }
  784. else if (strcaseEQ(key, "session_timeout")) {
  785. val = newSViv(zoo_recv_timeout(zk->handle));
  786. }
  787. else if (strcaseEQ(key, "session_id")) {
  788. const clientid_t *client_id;
  789. clientid_t null_client_id;
  790. client_id = zoo_client_id(zk->handle);
  791. memset(&null_client_id, 0, sizeof(clientid_t));
  792. if (!memcmp(client_id, &null_client_id, sizeof(clientid_t))) {
  793. val = newSVpv("", 0);
  794. }
  795. else {
  796. val = newSVpvn((const char*) client_id, sizeof(clientid_t));
  797. }
  798. }
  799. else if (strcaseEQ(key, "pending_watches")) {
  800. /* cleanup any completed watches not tied to a handle */
  801. val = newSVuv(_zk_release_watches(aTHX_ zk->first_watch, 0));
  802. }
  803. if (val) {
  804. ST(0) = sv_2mortal(val);
  805. XSRETURN(1);
  806. }
  807. Perl_warn(aTHX_ "invalid element: %s", key);
  808. XSRETURN_UNDEF;
  809. void
  810. zk_STORE(attr_hash, attr_key, attr_val)
  811. Net::ZooKeeper attr_hash
  812. SV *attr_key
  813. SV *attr_val
  814. PREINIT:
  815. zk_t *zk;
  816. char *key;
  817. PPCODE:
  818. zk = _zk_get_handle_inner(aTHX_ attr_hash);
  819. if (!zk) {
  820. Perl_croak(aTHX_ "invalid handle");
  821. }
  822. key = SvPV_nolen(attr_key);
  823. if (strcaseEQ(key, "data_read_len")) {
  824. int val = SvIV(attr_val);
  825. if (val < 0) {
  826. Perl_croak(aTHX_ "invalid data read length: %d", val);
  827. }
  828. zk->data_buf_len = val;
  829. }
  830. else if (strcaseEQ(key, "path_read_len")) {
  831. int val = SvIV(attr_val);
  832. if (val < 0) {
  833. Perl_croak(aTHX_ "invalid path read length: %d", val);
  834. }
  835. zk->path_buf_len = val;
  836. }
  837. else if (strcaseEQ(key, "watch_timeout")) {
  838. zk->watch_timeout = SvUV(attr_val);
  839. }
  840. else {
  841. int i;
  842. for (i = 0; i < NUM_KEYS; ++i) {
  843. if (strcaseEQ(key, zk_keys[i].name)) {
  844. Perl_warn(aTHX_ "read-only element: %s", key);
  845. XSRETURN_EMPTY;
  846. }
  847. }
  848. Perl_warn(aTHX_ "invalid element: %s", key);
  849. }
  850. XSRETURN_EMPTY;
  851. void
  852. zk_EXISTS(attr_hash, attr_key)
  853. Net::ZooKeeper attr_hash
  854. SV *attr_key
  855. PREINIT:
  856. zk_t *zk;
  857. char *key;
  858. int i;
  859. PPCODE:
  860. zk = _zk_get_handle_inner(aTHX_ attr_hash);
  861. if (!zk) {
  862. Perl_croak(aTHX_ "invalid handle");
  863. }
  864. key = SvPV_nolen(attr_key);
  865. for (i = 0; i < NUM_KEYS; ++i) {
  866. if (strcaseEQ(key, zk_keys[i].name)) {
  867. XSRETURN_YES;
  868. }
  869. }
  870. XSRETURN_NO;
  871. void
  872. zk_DELETE(attr_hash, attr_key)
  873. Net::ZooKeeper attr_hash
  874. SV *attr_key
  875. PPCODE:
  876. Perl_warn(aTHX_ "deleting elements from hashes of class "
  877. PACKAGE_NAME " not supported");
  878. XSRETURN_EMPTY;
  879. void
  880. zk_CLEAR(attr_hash)
  881. Net::ZooKeeper attr_hash
  882. PPCODE:
  883. Perl_warn(aTHX_ "clearing hashes of class "
  884. PACKAGE_NAME " not supported");
  885. XSRETURN_EMPTY;
  886. SV *
  887. zk_get_error(zkh)
  888. Net::ZooKeeper zkh
  889. PREINIT:
  890. zk_t *zk;
  891. CODE:
  892. zk = _zk_get_handle_outer(aTHX_ zkh);
  893. if (!zk) {
  894. Perl_croak(aTHX_ "invalid handle");
  895. }
  896. RETVAL = newSViv(zk->last_ret);
  897. errno = zk->last_errno;
  898. OUTPUT:
  899. RETVAL
  900. void
  901. zk_add_auth(zkh, scheme, cert)
  902. Net::ZooKeeper zkh
  903. char *scheme
  904. char *cert; cert = (char *) SvPV($arg, cert_len);
  905. PREINIT:
  906. zk_t *zk;
  907. STRLEN cert_len;
  908. zk_watch_t *watch;
  909. int ret;
  910. PPCODE:
  911. zk = _zk_get_handle_outer(aTHX_ zkh);
  912. if (!zk) {
  913. Perl_croak(aTHX_ "invalid handle");
  914. }
  915. zk->last_ret = ZOK;
  916. zk->last_errno = 0;
  917. if (cert_len > PERL_INT_MAX) {
  918. Perl_croak(aTHX_ "invalid certificate length: %u", cert_len);
  919. }
  920. watch = _zk_create_watch(aTHX);
  921. if (!watch) {
  922. /* errno will be set */
  923. zk->last_ret = ZSYSTEMERROR;
  924. zk->last_errno = errno;
  925. XSRETURN_NO;
  926. }
  927. errno = 0;
  928. ret = zoo_add_auth(zk->handle, scheme, cert, cert_len,
  929. _zk_auth_completion, watch);
  930. zk->last_ret = ret;
  931. zk->last_errno = errno;
  932. if (ret == ZOK) {
  933. pthread_mutex_lock(&watch->mutex);
  934. while (!watch->done) {
  935. pthread_cond_wait(&watch->cond, &watch->mutex);
  936. }
  937. pthread_mutex_unlock(&watch->mutex);
  938. if (watch->done) {
  939. ret = watch->ret;
  940. }
  941. else {
  942. ret = ZINVALIDSTATE;
  943. }
  944. /* errno may be set while we waited */
  945. zk->last_ret = ret;
  946. zk->last_errno = errno;
  947. }
  948. _zk_destroy_watch(aTHX_ watch);
  949. if (ret == ZOK) {
  950. XSRETURN_YES;
  951. }
  952. else {
  953. XSRETURN_NO;
  954. }
  955. void
  956. zk_create(zkh, path, buf, ...)
  957. Net::ZooKeeper zkh
  958. char *path
  959. char *buf; buf = (char *) SvPV($arg, buf_len);
  960. PREINIT:
  961. zk_t *zk;
  962. STRLEN buf_len;
  963. int flags = 0;
  964. char *path_buf;
  965. int path_buf_len;
  966. AV *acl_arr = NULL;
  967. struct ACL_vector acl;
  968. int i, ret;
  969. PPCODE:
  970. zk = _zk_get_handle_outer(aTHX_ zkh);
  971. if (!zk) {
  972. Perl_croak(aTHX_ "invalid handle");
  973. }
  974. zk->last_ret = ZOK;
  975. zk->last_errno = 0;
  976. if (items > 3 && !(items % 2)) {
  977. Perl_croak(aTHX_ "invalid number of arguments");
  978. }
  979. if (buf_len > PERL_INT_MAX) {
  980. Perl_croak(aTHX_ "invalid data length: %u", buf_len);
  981. }
  982. path_buf_len = zk->path_buf_len;
  983. for (i = 3; i < items; i += 2) {
  984. char *key = SvPV_nolen(ST(i));
  985. if (strcaseEQ(key, "path_read_len")) {
  986. path_buf_len = SvIV(ST(i + 1));
  987. if (path_buf_len < 2) {
  988. Perl_croak(aTHX_ "invalid path read length: %d",
  989. path_buf_len);
  990. }
  991. }
  992. else if (strcaseEQ(key, "flags")) {
  993. flags = SvIV(ST(i + 1));
  994. if (flags & ~(ZOO_SEQUENCE | ZOO_EPHEMERAL)) {
  995. Perl_croak(aTHX_ "invalid create flags: %d", flags);
  996. }
  997. }
  998. else if (strcaseEQ(key, "acl")) {
  999. const char *err;
  1000. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVAV) {
  1001. Perl_croak(aTHX_ "invalid ACL array reference");
  1002. }
  1003. acl_arr = (AV*) SvRV(ST(i + 1));
  1004. err = _zk_fill_acl(aTHX_ acl_arr, &acl);
  1005. if (err) {
  1006. Perl_croak(aTHX_ err);
  1007. }
  1008. }
  1009. }
  1010. /* NOTE: would be nice to be able to rely on null-terminated string */
  1011. ++path_buf_len;
  1012. Newxz(path_buf, path_buf_len, char);
  1013. errno = 0;
  1014. ret = zoo_create(zk->handle, path, buf, buf_len,
  1015. (acl_arr ? &acl : NULL), flags,
  1016. path_buf, path_buf_len);
  1017. zk->last_ret = ret;
  1018. zk->last_errno = errno;
  1019. if (acl_arr) {
  1020. _zk_free_acl(aTHX_ &acl);
  1021. }
  1022. if (ret == ZOK) {
  1023. ST(0) = sv_newmortal();
  1024. #ifdef SV_HAS_TRAILING_NUL
  1025. sv_usepvn_flags(ST(0), path_buf, strlen(path_buf),
  1026. SV_HAS_TRAILING_NUL);
  1027. #else
  1028. sv_usepvn(ST(0), path_buf, strlen(path_buf));
  1029. #endif
  1030. SvCUR_set(ST(0), strlen(path_buf));
  1031. XSRETURN(1);
  1032. }
  1033. Safefree(path_buf);
  1034. XSRETURN_UNDEF;
  1035. void
  1036. zk_delete(zkh, path, ...)
  1037. Net::ZooKeeper zkh
  1038. char *path
  1039. PREINIT:
  1040. zk_t *zk;
  1041. int version = -1;
  1042. int i, ret;
  1043. PPCODE:
  1044. zk = _zk_get_handle_outer(aTHX_ zkh);
  1045. if (!zk) {
  1046. Perl_croak(aTHX_ "invalid handle");
  1047. }
  1048. zk->last_ret = ZOK;
  1049. zk->last_errno = 0;
  1050. if (items > 2 && items % 2) {
  1051. Perl_croak(aTHX_ "invalid number of arguments");
  1052. }
  1053. for (i = 2; i < items; i += 2) {
  1054. char *key = SvPV_nolen(ST(i));
  1055. if (strcaseEQ(key, "version")) {
  1056. version = SvIV(ST(i + 1));
  1057. if (version < 0) {
  1058. Perl_croak(aTHX_ "invalid version requirement: %d",
  1059. version);
  1060. }
  1061. }
  1062. }
  1063. errno = 0;
  1064. ret = zoo_delete(zk->handle, path, version);
  1065. zk->last_ret = ret;
  1066. zk->last_errno = errno;
  1067. if (ret == ZOK) {
  1068. XSRETURN_YES;
  1069. }
  1070. else {
  1071. XSRETURN_NO;
  1072. }
  1073. void
  1074. zk_exists(zkh, path, ...)
  1075. Net::ZooKeeper zkh
  1076. char *path
  1077. PREINIT:
  1078. zk_t *zk;
  1079. zk_stat_t *stat = NULL;
  1080. zk_watch_t *old_watch = NULL;
  1081. zk_handle_t *watch_handle = NULL;
  1082. watcher_fn watcher = NULL;
  1083. zk_watch_t *new_watch = NULL;
  1084. int i, ret;
  1085. PPCODE:
  1086. zk = _zk_get_handle_outer(aTHX_ zkh);
  1087. if (!zk) {
  1088. Perl_croak(aTHX_ "invalid handle");
  1089. }
  1090. zk->last_ret = ZOK;
  1091. zk->last_errno = 0;
  1092. if (items > 2 && items % 2) {
  1093. Perl_croak(aTHX_ "invalid number of arguments");
  1094. }
  1095. for (i = 2; i < items; i += 2) {
  1096. char *key = SvPV_nolen(ST(i));
  1097. if (strcaseEQ(key, "stat")) {
  1098. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1099. !sv_derived_from(ST(i + 1), STAT_PACKAGE_NAME)) {
  1100. Perl_croak(aTHX_ "stat is not a hash reference of "
  1101. "type " STAT_PACKAGE_NAME);
  1102. }
  1103. stat = _zks_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)));
  1104. if (!stat) {
  1105. Perl_croak(aTHX_ "invalid stat handle");
  1106. }
  1107. }
  1108. else if (strcaseEQ(key, "watch")) {
  1109. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1110. !sv_derived_from(ST(i + 1), WATCH_PACKAGE_NAME)) {
  1111. Perl_croak(aTHX_ "watch is not a hash reference of "
  1112. "type " WATCH_PACKAGE_NAME);
  1113. }
  1114. old_watch = _zkw_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)),
  1115. &watch_handle);
  1116. if (!old_watch) {
  1117. Perl_croak(aTHX_ "invalid watch handle");
  1118. }
  1119. }
  1120. }
  1121. if (watch_handle) {
  1122. new_watch = _zk_acquire_watch(aTHX);
  1123. if (!new_watch) {
  1124. /* errno will be set */
  1125. zk->last_ret = ZSYSTEMERROR;
  1126. zk->last_errno = errno;
  1127. XSRETURN_NO;
  1128. }
  1129. watcher = _zk_watcher;
  1130. }
  1131. errno = 0;
  1132. ret = zoo_wexists(zk->handle, path, watcher, new_watch, stat);
  1133. zk->last_ret = ret;
  1134. zk->last_errno = errno;
  1135. if (watch_handle) {
  1136. _zk_replace_watch(aTHX_ watch_handle, zk->first_watch,
  1137. old_watch, new_watch);
  1138. }
  1139. if (ret == ZOK) {
  1140. XSRETURN_YES;
  1141. }
  1142. else {
  1143. XSRETURN_NO;
  1144. }
  1145. void
  1146. zk_get_children(zkh, path, ...)
  1147. Net::ZooKeeper zkh
  1148. char *path
  1149. PREINIT:
  1150. zk_t *zk;
  1151. zk_watch_t *old_watch = NULL;
  1152. zk_handle_t *watch_handle = NULL;
  1153. watcher_fn watcher = NULL;
  1154. zk_watch_t *new_watch = NULL;
  1155. struct String_vector strings;
  1156. int i, ret;
  1157. PPCODE:
  1158. zk = _zk_get_handle_outer(aTHX_ zkh);
  1159. if (!zk) {
  1160. Perl_croak(aTHX_ "invalid handle");
  1161. }
  1162. zk->last_ret = ZOK;
  1163. zk->last_errno = 0;
  1164. if (items > 2 && items % 2) {
  1165. Perl_croak(aTHX_ "invalid number of arguments");
  1166. }
  1167. for (i = 2; i < items; i += 2) {
  1168. char *key = SvPV_nolen(ST(i));
  1169. if (strcaseEQ(key, "watch")) {
  1170. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1171. !sv_derived_from(ST(i + 1), WATCH_PACKAGE_NAME)) {
  1172. Perl_croak(aTHX_ "watch is not a hash reference of "
  1173. "type " WATCH_PACKAGE_NAME);
  1174. }
  1175. old_watch = _zkw_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)),
  1176. &watch_handle);
  1177. if (!old_watch) {
  1178. Perl_croak(aTHX_ "invalid watch handle");
  1179. }
  1180. }
  1181. }
  1182. if (watch_handle) {
  1183. new_watch = _zk_acquire_watch(aTHX);
  1184. if (!new_watch) {
  1185. /* errno will be set */
  1186. zk->last_ret = ZSYSTEMERROR;
  1187. zk->last_errno = errno;
  1188. if (GIMME_V == G_ARRAY) {
  1189. XSRETURN_EMPTY;
  1190. }
  1191. else {
  1192. XSRETURN_UNDEF;
  1193. }
  1194. }
  1195. watcher = _zk_watcher;
  1196. }
  1197. Zero(&strings, 1, struct String_vector);
  1198. errno = 0;
  1199. ret = zoo_wget_children(zk->handle, path, watcher, new_watch,
  1200. &strings);
  1201. zk->last_ret = ret;
  1202. zk->last_errno = errno;
  1203. if (watch_handle) {
  1204. _zk_replace_watch(aTHX_ watch_handle, zk->first_watch,
  1205. old_watch, new_watch);
  1206. }
  1207. if (ret == ZOK) {
  1208. int num_children;
  1209. num_children =
  1210. (strings.count > PERL_INT_MAX) ? PERL_INT_MAX : strings.count;
  1211. if (GIMME_V == G_ARRAY && num_children > 0) {
  1212. EXTEND(SP, num_children);
  1213. for (i = 0; i < num_children; ++i) {
  1214. ST(i) = sv_2mortal(newSVpv(strings.data[i], 0));
  1215. }
  1216. }
  1217. /* NOTE: would be nice if this were documented as required */
  1218. deallocate_String_vector(&strings);
  1219. if (GIMME_V == G_ARRAY) {
  1220. if (num_children == 0) {
  1221. XSRETURN_EMPTY;
  1222. }
  1223. XSRETURN(num_children);
  1224. }
  1225. else {
  1226. ST(0) = sv_2mortal(newSViv(num_children));
  1227. XSRETURN(1);
  1228. }
  1229. }
  1230. else {
  1231. if (GIMME_V == G_ARRAY) {
  1232. XSRETURN_EMPTY;
  1233. }
  1234. else {
  1235. XSRETURN_UNDEF;
  1236. }
  1237. }
  1238. void
  1239. zk_get(zkh, path, ...)
  1240. Net::ZooKeeper zkh
  1241. char *path
  1242. PREINIT:
  1243. zk_t *zk;
  1244. int buf_len;
  1245. zk_stat_t *stat = NULL;
  1246. zk_watch_t *old_watch = NULL;
  1247. zk_handle_t *watch_handle = NULL;
  1248. char *buf;
  1249. watcher_fn watcher = NULL;
  1250. zk_watch_t *new_watch = NULL;
  1251. int i, ret;
  1252. PPCODE:
  1253. zk = _zk_get_handle_outer(aTHX_ zkh);
  1254. if (!zk) {
  1255. Perl_croak(aTHX_ "invalid handle");
  1256. }
  1257. zk->last_ret = ZOK;
  1258. zk->last_errno = 0;
  1259. if (items > 2 && items % 2) {
  1260. Perl_croak(aTHX_ "invalid number of arguments");
  1261. }
  1262. buf_len = zk->data_buf_len;
  1263. for (i = 2; i < items; i += 2) {
  1264. char *key = SvPV_nolen(ST(i));
  1265. if (strcaseEQ(key, "data_read_len")) {
  1266. buf_len = SvIV(ST(i + 1));
  1267. if (buf_len < 0) {
  1268. Perl_croak(aTHX_ "invalid data read length: %d",
  1269. buf_len);
  1270. }
  1271. }
  1272. else if (strcaseEQ(key, "stat")) {
  1273. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1274. !sv_derived_from(ST(i + 1), STAT_PACKAGE_NAME)) {
  1275. Perl_croak(aTHX_ "stat is not a hash reference of "
  1276. "type " STAT_PACKAGE_NAME);
  1277. }
  1278. stat = _zks_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)));
  1279. if (!stat) {
  1280. Perl_croak(aTHX_ "invalid stat handle");
  1281. }
  1282. }
  1283. else if (strcaseEQ(key, "watch")) {
  1284. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1285. !sv_derived_from(ST(i + 1), WATCH_PACKAGE_NAME)) {
  1286. Perl_croak(aTHX_ "watch is not a hash reference of "
  1287. "type " WATCH_PACKAGE_NAME);
  1288. }
  1289. old_watch = _zkw_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)),
  1290. &watch_handle);
  1291. if (!old_watch) {
  1292. Perl_croak(aTHX_ "invalid watch handle");
  1293. }
  1294. }
  1295. }
  1296. if (watch_handle) {
  1297. new_watch = _zk_acquire_watch(aTHX);
  1298. if (!new_watch) {
  1299. /* errno will be set */
  1300. zk->last_ret = ZSYSTEMERROR;
  1301. zk->last_errno = errno;
  1302. XSRETURN_UNDEF;
  1303. }
  1304. watcher = _zk_watcher;
  1305. }
  1306. Newx(buf, buf_len + 1, char);
  1307. errno = 0;
  1308. ret = zoo_wget(zk->handle, path, watcher, new_watch,
  1309. buf, &buf_len, stat);
  1310. zk->last_ret = ret;
  1311. zk->last_errno = errno;
  1312. if (watch_handle) {
  1313. _zk_replace_watch(aTHX_ watch_handle, zk->first_watch,
  1314. old_watch, new_watch);
  1315. }
  1316. if (ret == ZOK && buf_len != -1) {
  1317. ST(0) = sv_newmortal();
  1318. #ifdef SV_HAS_TRAILING_NUL
  1319. buf[buf_len] = '\0';
  1320. sv_usepvn_flags(ST(0), buf, buf_len, SV_HAS_TRAILING_NUL);
  1321. #else
  1322. sv_usepvn(ST(0), buf, buf_len);
  1323. #endif
  1324. XSRETURN(1);
  1325. }
  1326. else {
  1327. Safefree(buf);
  1328. XSRETURN_UNDEF;
  1329. }
  1330. void
  1331. zk_set(zkh, path, buf, ...)
  1332. Net::ZooKeeper zkh
  1333. char *path
  1334. char *buf; buf = (char *) SvPV($arg, buf_len);
  1335. PREINIT:
  1336. zk_t *zk;
  1337. int version = -1;
  1338. zk_stat_t *stat = NULL;
  1339. STRLEN buf_len;
  1340. int i, ret;
  1341. PPCODE:
  1342. zk = _zk_get_handle_outer(aTHX_ zkh);
  1343. if (!zk) {
  1344. Perl_croak(aTHX_ "invalid handle");
  1345. }
  1346. zk->last_ret = ZOK;
  1347. zk->last_errno = 0;
  1348. if (items > 3 && !(items % 2)) {
  1349. Perl_croak(aTHX_ "invalid number of arguments");
  1350. }
  1351. if (buf_len > PERL_INT_MAX) {
  1352. Perl_croak(aTHX_ "invalid data length: %u", buf_len);
  1353. }
  1354. for (i = 3; i < items; i += 2) {
  1355. char *key = SvPV_nolen(ST(i));
  1356. if (strcaseEQ(key, "version")) {
  1357. version = SvIV(ST(i + 1));
  1358. if (version < 0) {
  1359. Perl_croak(aTHX_ "invalid version requirement: %d",
  1360. version);
  1361. }
  1362. }
  1363. else if (strcaseEQ(key, "stat")) {
  1364. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1365. !sv_derived_from(ST(i + 1), STAT_PACKAGE_NAME)) {
  1366. Perl_croak(aTHX_ "stat is not a hash reference of "
  1367. "type " STAT_PACKAGE_NAME);
  1368. }
  1369. stat = _zks_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)));
  1370. if (!stat) {
  1371. Perl_croak(aTHX_ "invalid stat handle");
  1372. }
  1373. }
  1374. }
  1375. errno = 0;
  1376. ret = zoo_set2(zk->handle, path, buf, buf_len, version, stat);
  1377. zk->last_ret = ret;
  1378. zk->last_errno = errno;
  1379. if (ret == ZOK) {
  1380. XSRETURN_YES;
  1381. }
  1382. else {
  1383. XSRETURN_NO;
  1384. }
  1385. void
  1386. zk_get_acl(zkh, path, ...)
  1387. Net::ZooKeeper zkh
  1388. char *path
  1389. PREINIT:
  1390. zk_t *zk;
  1391. zk_stat_t *stat = NULL;
  1392. struct ACL_vector acl;
  1393. int i, ret;
  1394. PPCODE:
  1395. zk = _zk_get_handle_outer(aTHX_ zkh);
  1396. if (!zk) {
  1397. Perl_croak(aTHX_ "invalid handle");
  1398. }
  1399. zk->last_ret = ZOK;
  1400. zk->last_errno = 0;
  1401. if (items > 2 && items % 2) {
  1402. Perl_croak(aTHX_ "invalid number of arguments");
  1403. }
  1404. for (i = 2; i < items; i += 2) {
  1405. char *key = SvPV_nolen(ST(i));
  1406. if (strcaseEQ(key, "stat")) {
  1407. if (!SvROK(ST(i + 1)) || SvTYPE(SvRV(ST(i + 1))) != SVt_PVHV ||
  1408. !sv_derived_from(ST(i + 1), STAT_PACKAGE_NAME)) {
  1409. Perl_croak(aTHX_ "stat is not a hash reference of "
  1410. "type " STAT_PACKAGE_NAME);
  1411. }
  1412. stat = _zks_get_handle_outer(aTHX_ (HV*) SvRV(ST(i + 1)));
  1413. if (!stat) {
  1414. Perl_croak(aTHX_ "invalid stat handle");
  1415. }
  1416. }
  1417. }
  1418. errno = 0;
  1419. ret = zoo_get_acl(zk->handle, path, &acl, stat);
  1420. zk->last_ret = ret;
  1421. zk->last_errno = errno;
  1422. if (ret == ZOK) {
  1423. int num_acl_entries;
  1424. num_acl_entries =
  1425. (acl.count > PERL_INT_MAX) ? PERL_INT_MAX : acl.count;
  1426. if (GIMME_V == G_ARRAY && num_acl_entries > 0) {
  1427. EXTEND(SP, num_acl_entries);
  1428. for (i = 0; i < num_acl_entries; ++i) {
  1429. HV *acl_entry_hash = newHV();
  1430. _zk_fill_acl_entry_hash(aTHX_ &acl.data[i],
  1431. acl_entry_hash);
  1432. ST(i) = sv_2mortal(newRV_noinc((SV*) acl_entry_hash));
  1433. }
  1434. }
  1435. /* NOTE: would be nice if this were documented as required */
  1436. deallocate_ACL_vector(&acl);
  1437. if (GIMME_V == G_ARRAY) {
  1438. if (num_acl_entries == 0) {
  1439. XSRETURN_EMPTY;
  1440. }
  1441. XSRETURN(num_acl_entries);
  1442. }
  1443. else {
  1444. ST(0) = sv_2mortal(newSViv(num_acl_entries));
  1445. XSRETURN(1);
  1446. }
  1447. }
  1448. else {
  1449. if (GIMME_V == G_ARRAY) {
  1450. XSRETURN_EMPTY;
  1451. }
  1452. else {
  1453. XSRETURN_UNDEF;
  1454. }
  1455. }
  1456. void
  1457. zk_set_acl(zkh, path, acl_arr, ...)
  1458. Net::ZooKeeper zkh
  1459. char *path
  1460. AV *acl_arr
  1461. PREINIT:
  1462. zk_t *zk;
  1463. const char *err;
  1464. int version = -1;
  1465. struct ACL_vector acl;
  1466. int i, ret;
  1467. PPCODE:
  1468. zk = _zk_get_handle_outer(aTHX_ zkh);
  1469. if (!zk) {
  1470. Perl_croak(aTHX_ "invalid handle");
  1471. }
  1472. zk->last_ret = ZOK;
  1473. zk->last_errno = 0;
  1474. if (items > 3 && !(items % 2)) {
  1475. Perl_croak(aTHX_ "invalid number of arguments");
  1476. }
  1477. err = _zk_fill_acl(aTHX_ acl_arr, &acl);
  1478. if (err) {
  1479. Perl_croak(aTHX_ err);
  1480. }
  1481. for (i = 3; i < items; i += 2) {
  1482. char *key = SvPV_nolen(ST(i));
  1483. if (strcaseEQ(key, "version")) {
  1484. version = SvIV(ST(i + 1));
  1485. if (version < 0) {
  1486. Perl_croak(aTHX_ "invalid version requirement: %d",
  1487. version);
  1488. }
  1489. }
  1490. }
  1491. errno = 0;
  1492. ret = zoo_set_acl(zk->handle, path, version, &acl);
  1493. zk->last_ret = ret;
  1494. zk->last_errno = errno;
  1495. _zk_free_acl(aTHX_ &acl);
  1496. if (ret == ZOK) {
  1497. XSRETURN_YES;
  1498. }
  1499. else {
  1500. XSRETURN_NO;
  1501. }
  1502. void
  1503. zk_stat(zkh)
  1504. Net::ZooKeeper zkh
  1505. PREINIT:
  1506. zk_t *zk;
  1507. zk_handle_t *handle;
  1508. HV *stash, *stat_hash, *attr_hash;
  1509. SV *attr;
  1510. PPCODE:
  1511. zk = _zk_get_handle_outer(aTHX_ zkh);
  1512. if (!zk) {
  1513. Perl_croak(aTHX_ "invalid handle");
  1514. }
  1515. zk->last_ret = ZOK;
  1516. zk->last_errno = 0;
  1517. Newx(handle, 1, zk_handle_t);
  1518. handle->signature = STAT_PACKAGE_SIGNATURE;
  1519. Newxz(handle->handle.stat, 1, zk_stat_t);
  1520. /* As in zk_new(), we use two levels of magic here. */
  1521. stash = gv_stashpv(STAT_PACKAGE_NAME, GV_ADDWARN);
  1522. attr_hash = newHV();
  1523. sv_magic((SV*) attr_hash, Nullsv, PERL_MAGIC_ext,
  1524. (const char*) handle, 0);
  1525. attr = sv_bless(newRV_noinc((SV*) attr_hash), stash);
  1526. stat_hash = newHV();
  1527. sv_magic((SV*) stat_hash, attr, PERL_MAGIC_tied, Nullch, 0);
  1528. SvREFCNT_dec(attr);
  1529. ST(0) = sv_bless(sv_2mortal(newRV_noinc((SV*) stat_hash)), stash);
  1530. XSRETURN(1);
  1531. void
  1532. zk_watch(zkh, ...)
  1533. Net::ZooKeeper zkh
  1534. PREINIT:
  1535. zk_t *zk;
  1536. unsigned int timeout;
  1537. zk_watch_t *watch;
  1538. zk_handle_t *handle;
  1539. HV *stash, *watch_hash, *attr_hash;
  1540. SV *attr;
  1541. int i;
  1542. PPCODE:
  1543. zk = _zk_get_handle_outer(aTHX_ zkh);
  1544. if (!zk) {
  1545. Perl_croak(aTHX_ "invalid handle");
  1546. }
  1547. zk->last_ret = ZOK;
  1548. zk->last_errno = 0;
  1549. if (items > 1 && !(items % 2)) {
  1550. Perl_croak(aTHX_ "invalid number of arguments");
  1551. }
  1552. timeout = zk->watch_timeout;
  1553. for (i = 1; i < items; i += 2) {
  1554. char *key = SvPV_nolen(ST(i));
  1555. if (strcaseEQ(key, "timeout")) {
  1556. timeout = SvUV(ST(i + 1));
  1557. }
  1558. }
  1559. watch = _zk_acquire_watch(aTHX);
  1560. if (!watch) {
  1561. /* errno will be set */
  1562. zk->last_ret = ZSYSTEMERROR;
  1563. zk->last_errno = errno;
  1564. XSRETURN_UNDEF;
  1565. }
  1566. Newx(handle, 1, zk_handle_t);
  1567. handle->signature = WATCH_PACKAGE_SIGNATURE;
  1568. handle->handle.watch = watch;
  1569. /* As in zk_new(), we use two levels of magic here. */
  1570. stash = gv_stashpv(WATCH_PACKAGE_NAME, GV_ADDWARN);
  1571. attr_hash = newHV();
  1572. watch->timeout = timeout;
  1573. sv_magic((SV*) attr_hash, Nullsv, PERL_MAGIC_ext,
  1574. (const char*) handle, 0);
  1575. attr = sv_bless(newRV_noinc((SV*) attr_hash), stash);
  1576. watch_hash = newHV();
  1577. sv_magic((SV*) watch_hash, attr, PERL_MAGIC_tied, Nullch, 0);
  1578. SvREFCNT_dec(attr);
  1579. ST(0) = sv_bless(sv_2mortal(newRV_noinc((SV*) watch_hash)), stash);
  1580. XSRETURN(1);
  1581. MODULE = Net::ZooKeeper PACKAGE = Net::ZooKeeper::Stat PREFIX = zks_
  1582. void
  1583. zks_DESTROY(zksh)
  1584. Net::ZooKeeper::Stat zksh
  1585. PREINIT:
  1586. zk_handle_t *handle;
  1587. HV *attr_hash;
  1588. int ret = ZBADARGUMENTS;
  1589. PPCODE:
  1590. handle = _zk_check_handle_outer(aTHX_ zksh, &attr_hash,
  1591. STAT_PACKAGE_NAME,
  1592. STAT_PACKAGE_SIGNATURE);
  1593. if (!handle) {
  1594. handle = _zk_check_handle_inner(aTHX_ zksh,
  1595. STAT_PACKAGE_SIGNATURE);
  1596. if (handle) {
  1597. attr_hash = zksh;
  1598. zksh = NULL;
  1599. }
  1600. }
  1601. if (handle) {
  1602. ret = ZOK;
  1603. Safefree(handle->handle.stat);
  1604. Safefree(handle);
  1605. sv_unmagic((SV*) attr_hash, PERL_MAGIC_ext);
  1606. }
  1607. if (zksh && attr_hash) {
  1608. sv_unmagic((SV*) zksh, PERL_MAGIC_tied);
  1609. }
  1610. if (GIMME_V == G_VOID) {
  1611. XSRETURN_EMPTY;
  1612. }
  1613. else if (ret == ZOK) {
  1614. XSRETURN_YES;
  1615. }
  1616. else {
  1617. XSRETURN_NO;
  1618. }
  1619. void
  1620. zks_CLONE(package)
  1621. char *package
  1622. PPCODE:
  1623. XSRETURN_EMPTY;
  1624. void
  1625. zks_CLONE_SKIP(package)
  1626. char *package
  1627. PPCODE:
  1628. XSRETURN_YES;
  1629. void
  1630. zks_TIEHASH(package, ...)
  1631. char *package
  1632. PPCODE:
  1633. Perl_croak(aTHX_ "tying hashes of class "
  1634. STAT_PACKAGE_NAME " not supported");
  1635. void
  1636. zks_UNTIE(attr_hash, ref_count)
  1637. Net::ZooKeeper::Stat attr_hash
  1638. IV ref_count
  1639. PPCODE:
  1640. Perl_croak(aTHX_ "untying hashes of class "
  1641. STAT_PACKAGE_NAME " not supported");
  1642. void
  1643. zks_FIRSTKEY(attr_hash)
  1644. Net::ZooKeeper::Stat attr_hash
  1645. PREINIT:
  1646. zk_stat_t *stat;
  1647. PPCODE:
  1648. stat = _zks_get_handle_inner(aTHX_ attr_hash);
  1649. if (!stat) {
  1650. Perl_croak(aTHX_ "invalid handle");
  1651. }
  1652. ST(0) = sv_2mortal(newSVpvn(zk_stat_keys[0].name,
  1653. zk_stat_keys[0].name_len));
  1654. XSRETURN(1);
  1655. void
  1656. zks_NEXTKEY(attr_hash, attr_key)
  1657. Net::ZooKeeper::Stat attr_hash
  1658. SV *attr_key
  1659. PREINIT:
  1660. zk_stat_t *stat;
  1661. char *key;
  1662. int i;
  1663. PPCODE:
  1664. stat = _zks_get_handle_inner(aTHX_ attr_hash);
  1665. if (!stat) {
  1666. Perl_croak(aTHX_ "invalid handle");
  1667. }
  1668. key = SvPV_nolen(attr_key);
  1669. for (i = 0; i < NUM_STAT_KEYS; ++i) {
  1670. if (strcaseEQ(key, zk_stat_keys[i].name)) {
  1671. ++i;
  1672. break;
  1673. }
  1674. }
  1675. if (i < NUM_STAT_KEYS) {
  1676. ST(0) = sv_2mortal(newSVpvn(zk_stat_keys[i].name,
  1677. zk_stat_keys[i].name_len));
  1678. XSRETURN(1);
  1679. }
  1680. else {
  1681. XSRETURN_EMPTY;
  1682. }
  1683. void
  1684. zks_SCALAR(attr_hash)
  1685. Net::ZooKeeper::Stat attr_hash
  1686. PPCODE:
  1687. XSRETURN_YES;
  1688. void
  1689. zks_FETCH(attr_hash, attr_key)
  1690. Net::ZooKeeper::Stat attr_hash
  1691. SV *attr_key
  1692. PREINIT:
  1693. zk_stat_t *stat;
  1694. char *key;
  1695. SV *val = NULL;
  1696. int i;
  1697. PPCODE:
  1698. stat = _zks_get_handle_inner(aTHX_ attr_hash);
  1699. if (!stat) {
  1700. Perl_croak(aTHX_ "invalid handle");
  1701. }
  1702. key = SvPV_nolen(attr_key);
  1703. for (i = 0; i < NUM_STAT_KEYS; ++i) {
  1704. if (strcaseEQ(key, zk_stat_keys[i].name)) {
  1705. if (zk_stat_keys[i].size * CHAR_BIT == 32) {
  1706. val = newSViv(*((int32_t*) (((char*) stat) +
  1707. zk_stat_keys[i].offset)));
  1708. }
  1709. else {
  1710. /* NOTE: %lld is inconsistent, so cast to a double */
  1711. val = newSVpvf("%.0f", (double)
  1712. *((int64_t*) (((char*) stat) +
  1713. zk_stat_keys[i].offset)));
  1714. }
  1715. break;
  1716. }
  1717. }
  1718. if (val) {
  1719. ST(0) = sv_2mortal(val);
  1720. XSRETURN(1);
  1721. }
  1722. Perl_warn(aTHX_ "invalid element: %s", key);
  1723. XSRETURN_UNDEF;
  1724. void
  1725. zks_STORE(attr_hash, attr_key, attr_val)
  1726. Net::ZooKeeper::Stat attr_hash
  1727. SV *attr_key
  1728. SV *attr_val
  1729. PREINIT:
  1730. zk_stat_t *stat;
  1731. char *key;
  1732. int i;
  1733. PPCODE:
  1734. stat = _zks_get_handle_inner(aTHX_ attr_hash);
  1735. if (!stat) {
  1736. Perl_croak(aTHX_ "invalid handle");
  1737. }
  1738. key = SvPV_nolen(attr_key);
  1739. for (i = 0; i < NUM_STAT_KEYS; ++i) {
  1740. if (strcaseEQ(key, zk_stat_keys[i].name)) {
  1741. Perl_warn(aTHX_ "read-only element: %s", key);
  1742. XSRETURN_EMPTY;
  1743. }
  1744. }
  1745. Perl_warn(aTHX_ "invalid element: %s", key);
  1746. XSRETURN_EMPTY;
  1747. void
  1748. zks_EXISTS(attr_hash, attr_key)
  1749. Net::ZooKeeper::Stat attr_hash
  1750. SV *attr_key
  1751. PREINIT:
  1752. zk_stat_t *stat;
  1753. char *key;
  1754. int i;
  1755. PPCODE:
  1756. stat = _zks_get_handle_inner(aTHX_ attr_hash);
  1757. if (!stat) {
  1758. Perl_croak(aTHX_ "invalid handle");
  1759. }
  1760. key = SvPV_nolen(attr_key);
  1761. for (i = 0; i < NUM_STAT_KEYS; ++i) {
  1762. if (strcaseEQ(key, zk_stat_keys[i].name)) {
  1763. XSRETURN_YES;
  1764. }
  1765. }
  1766. XSRETURN_NO;
  1767. void
  1768. zks_DELETE(attr_hash, attr_key)
  1769. Net::ZooKeeper::Stat attr_hash
  1770. SV *attr_key
  1771. PPCODE:
  1772. Perl_warn(aTHX_ "deleting elements from hashes of class "
  1773. STAT_PACKAGE_NAME " not supported");
  1774. XSRETURN_EMPTY;
  1775. void
  1776. zks_CLEAR(attr_hash)
  1777. Net::ZooKeeper::Stat attr_hash
  1778. PPCODE:
  1779. Perl_warn(aTHX_ "clearing hashes of class "
  1780. STAT_PACKAGE_NAME " not supported");
  1781. XSRETURN_EMPTY;
  1782. MODULE = Net::ZooKeeper PACKAGE = Net::ZooKeeper::Watch PREFIX = zkw_
  1783. void
  1784. zkw_DESTROY(zkwh)
  1785. Net::ZooKeeper::Watch zkwh
  1786. PREINIT:
  1787. zk_handle_t *handle;
  1788. HV *attr_hash;
  1789. int ret = ZBADARGUMENTS;
  1790. PPCODE:
  1791. handle = _zk_check_handle_outer(aTHX_ zkwh, &attr_hash,
  1792. WATCH_PACKAGE_NAME,
  1793. WATCH_PACKAGE_SIGNATURE);
  1794. if (!handle) {
  1795. handle = _zk_check_handle_inner(aTHX_ zkwh,
  1796. WATCH_PACKAGE_SIGNATURE);
  1797. if (handle) {
  1798. attr_hash = zkwh;
  1799. zkwh = NULL;
  1800. }
  1801. }
  1802. if (handle) {
  1803. ret = ZOK;
  1804. _zk_release_watch(aTHX_ handle->handle.watch, 0);
  1805. Safefree(handle);
  1806. sv_unmagic((SV*) attr_hash, PERL_MAGIC_ext);
  1807. }
  1808. if (zkwh && attr_hash) {
  1809. sv_unmagic((SV*) zkwh, PERL_MAGIC_tied);
  1810. }
  1811. if (GIMME_V == G_VOID) {
  1812. XSRETURN_EMPTY;
  1813. }
  1814. else if (ret == ZOK) {
  1815. XSRETURN_YES;
  1816. }
  1817. else {
  1818. XSRETURN_NO;
  1819. }
  1820. void
  1821. zkw_CLONE(package)
  1822. char *package
  1823. PPCODE:
  1824. XSRETURN_EMPTY;
  1825. void
  1826. zkw_CLONE_SKIP(package)
  1827. char *package
  1828. PPCODE:
  1829. XSRETURN_YES;
  1830. void
  1831. zkw_TIEHASH(package, ...)
  1832. char *package
  1833. PPCODE:
  1834. Perl_croak(aTHX_ "tying hashes of class "
  1835. WATCH_PACKAGE_NAME " not supported");
  1836. void
  1837. zkw_UNTIE(attr_hash, ref_count)
  1838. Net::ZooKeeper::Watch attr_hash
  1839. IV ref_count
  1840. PPCODE:
  1841. Perl_croak(aTHX_ "untying hashes of class "
  1842. WATCH_PACKAGE_NAME " not supported");
  1843. void
  1844. zkw_FIRSTKEY(attr_hash)
  1845. Net::ZooKeeper::Watch attr_hash
  1846. PREINIT:
  1847. zk_watch_t *watch;
  1848. PPCODE:
  1849. watch = _zkw_get_handle_inner(aTHX_ attr_hash);
  1850. if (!watch) {
  1851. Perl_croak(aTHX_ "invalid handle");
  1852. }
  1853. ST(0) = sv_2mortal(newSVpvn(zk_watch_keys[0].name,
  1854. zk_watch_keys[0].name_len));
  1855. XSRETURN(1);
  1856. void
  1857. zkw_NEXTKEY(attr_hash, attr_key)
  1858. Net::ZooKeeper::Watch attr_hash
  1859. SV *attr_key
  1860. PREINIT:
  1861. zk_watch_t *watch;
  1862. char *key;
  1863. int i;
  1864. PPCODE:
  1865. watch = _zkw_get_handle_inner(aTHX_ attr_hash);
  1866. if (!watch) {
  1867. Perl_croak(aTHX_ "invalid handle");
  1868. }
  1869. key = SvPV_nolen(attr_key);
  1870. for (i = 0; i < NUM_WATCH_KEYS; ++i) {
  1871. if (strcaseEQ(key, zk_watch_keys[i].name)) {
  1872. ++i;
  1873. break;
  1874. }
  1875. }
  1876. if (i < NUM_WATCH_KEYS) {
  1877. ST(0) = sv_2mortal(newSVpvn(zk_watch_keys[i].name,
  1878. zk_watch_keys[i].name_len));
  1879. XSRETURN(1);
  1880. }
  1881. else {
  1882. XSRETURN_EMPTY;
  1883. }
  1884. void
  1885. zkw_SCALAR(attr_hash)
  1886. Net::ZooKeeper::Watch attr_hash
  1887. PPCODE:
  1888. XSRETURN_YES;
  1889. void
  1890. zkw_FETCH(attr_hash, attr_key)
  1891. Net::ZooKeeper::Watch attr_hash
  1892. SV *attr_key
  1893. PREINIT:
  1894. zk_watch_t *watch;
  1895. char *key;
  1896. SV *val = NULL;
  1897. PPCODE:
  1898. watch = _zkw_get_handle_inner(aTHX_ attr_hash);
  1899. if (!watch) {
  1900. Perl_croak(aTHX_ "invalid handle");
  1901. }
  1902. key = SvPV_nolen(attr_key);
  1903. if (strcaseEQ(key, "timeout")) {
  1904. val = newSVuv(watch->timeout);
  1905. }
  1906. else if (strcaseEQ(key, "event")) {
  1907. val = newSViv(watch->event_type);
  1908. }
  1909. else if (strcaseEQ(key, "state")) {
  1910. val = newSViv(watch->event_state);
  1911. }
  1912. if (val) {
  1913. ST(0) = sv_2mortal(val);
  1914. XSRETURN(1);
  1915. }
  1916. Perl_warn(aTHX_ "invalid element: %s", key);
  1917. XSRETURN_UNDEF;
  1918. void
  1919. zkw_STORE(attr_hash, attr_key, attr_val)
  1920. Net::ZooKeeper::Watch attr_hash
  1921. SV *attr_key
  1922. SV *attr_val
  1923. PREINIT:
  1924. zk_watch_t *watch;
  1925. char *key;
  1926. PPCODE:
  1927. watch = _zkw_get_handle_inner(aTHX_ attr_hash);
  1928. if (!watch) {
  1929. Perl_croak(aTHX_ "invalid handle");
  1930. }
  1931. key = SvPV_nolen(attr_key);
  1932. if (strcaseEQ(key, "timeout")) {
  1933. watch->timeout = SvUV(attr_val);
  1934. }
  1935. else {
  1936. int i;
  1937. for (i = 0; i < NUM_WATCH_KEYS; ++i) {
  1938. if (strcaseEQ(key, zk_watch_keys[i].name)) {
  1939. Perl_warn(aTHX_ "read-only element: %s", key);
  1940. XSRETURN_EMPTY;
  1941. }
  1942. }
  1943. Perl_warn(aTHX_ "invalid element: %s", key);
  1944. }
  1945. XSRETURN_EMPTY;
  1946. void
  1947. zkw_EXISTS(attr_hash, attr_key)
  1948. Net::ZooKeeper::Watch attr_hash
  1949. SV *attr_key
  1950. PREINIT:
  1951. zk_watch_t *watch;
  1952. char *key;
  1953. int i;
  1954. PPCODE:
  1955. watch = _zkw_get_handle_inner(aTHX_ attr_hash);
  1956. if (!watch) {
  1957. Perl_croak(aTHX_ "invalid handle");
  1958. }
  1959. key = SvPV_nolen(attr_key);
  1960. for (i = 0; i < NUM_WATCH_KEYS; ++i) {
  1961. if (strcaseEQ(key, zk_watch_keys[i].name)) {
  1962. XSRETURN_YES;
  1963. }
  1964. }
  1965. XSRETURN_NO;
  1966. void
  1967. zkw_DELETE(attr_hash, attr_key)
  1968. Net::ZooKeeper::Watch attr_hash
  1969. SV *attr_key
  1970. PPCODE:
  1971. Perl_warn(aTHX_ "deleting elements from hashes of class "
  1972. WATCH_PACKAGE_NAME " not supported");
  1973. XSRETURN_EMPTY;
  1974. void
  1975. zkw_CLEAR(attr_hash)
  1976. Net::ZooKeeper::Watch attr_hash
  1977. PPCODE:
  1978. Perl_warn(aTHX_ "clearing hashes of class "
  1979. WATCH_PACKAGE_NAME " not supported");
  1980. XSRETURN_EMPTY;
  1981. void
  1982. zkw_wait(zkwh, ...)
  1983. Net::ZooKeeper::Watch zkwh
  1984. PREINIT:
  1985. zk_watch_t *watch;
  1986. unsigned int timeout;
  1987. struct timeval end_timeval;
  1988. int i, done;
  1989. struct timespec wait_timespec;
  1990. PPCODE:
  1991. watch = _zkw_get_handle_outer(aTHX_ zkwh, NULL);
  1992. if (!watch) {
  1993. Perl_croak(aTHX_ "invalid handle");
  1994. }
  1995. if (items > 1 && !(items % 2)) {
  1996. Perl_croak(aTHX_ "invalid number of arguments");
  1997. }
  1998. timeout = watch->timeout;
  1999. for (i = 1; i < items; i += 2) {
  2000. char *key = SvPV_nolen(ST(i));
  2001. if (strcaseEQ(key, "timeout")) {
  2002. timeout = SvUV(ST(i + 1));
  2003. }
  2004. }
  2005. gettimeofday(&end_timeval, NULL);
  2006. end_timeval.tv_sec += timeout / 1000;
  2007. end_timeval.tv_usec += (timeout % 1000) * 1000;
  2008. wait_timespec.tv_sec = end_timeval.tv_sec;
  2009. wait_timespec.tv_nsec = end_timeval.tv_usec * 1000;
  2010. pthread_mutex_lock(&watch->mutex);
  2011. while (!watch->done) {
  2012. struct timeval curr_timeval;
  2013. gettimeofday(&curr_timeval, NULL);
  2014. if (end_timeval.tv_sec < curr_timeval.tv_sec ||
  2015. (end_timeval.tv_sec == curr_timeval.tv_sec &&
  2016. end_timeval.tv_usec <= curr_timeval.tv_usec)) {
  2017. break;
  2018. }
  2019. pthread_cond_timedwait(&watch->cond, &watch->mutex,
  2020. &wait_timespec);
  2021. }
  2022. done = watch->done;
  2023. pthread_mutex_unlock(&watch->mutex);
  2024. if (done) {
  2025. XSRETURN_YES;
  2026. }
  2027. else {
  2028. XSRETURN_NO;
  2029. }