ZooKeeper.xs 67 KB

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