cli.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. /**
  19. * cli.c is a example/sample C client shell for ZooKeeper. It contains
  20. * basic shell functionality which exercises some of the features of
  21. * the ZooKeeper C client API. It is not a full fledged client and is
  22. * not meant for production usage - see the Java client shell for a
  23. * fully featured shell.
  24. */
  25. #include <zookeeper.h>
  26. #include <proto.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #ifndef WIN32
  31. #include <sys/time.h>
  32. #include <unistd.h>
  33. #include <sys/select.h>
  34. #else
  35. #include "winport.h"
  36. //#include <io.h> <-- can't include, conflicting definitions of close()
  37. int read(int _FileHandle, void * _DstBuf, unsigned int _MaxCharCount);
  38. int write(int _Filehandle, const void * _Buf, unsigned int _MaxCharCount);
  39. #define ctime_r(tctime, buffer) ctime_s (buffer, 40, tctime)
  40. #endif
  41. #include <time.h>
  42. #include <errno.h>
  43. #include <assert.h>
  44. #ifdef YCA
  45. #include <yca/yca.h>
  46. #endif
  47. #define _LL_CAST_ (long long)
  48. static zhandle_t *zh;
  49. static clientid_t myid;
  50. static const char *clientIdFile = 0;
  51. struct timeval startTime;
  52. static char cmd[1024];
  53. static int batchMode=0;
  54. static int to_send=0;
  55. static int sent=0;
  56. static int recvd=0;
  57. static int shutdownThisThing=0;
  58. static __attribute__ ((unused)) void
  59. printProfileInfo(struct timeval start, struct timeval end, int thres,
  60. const char* msg)
  61. {
  62. int delay=(end.tv_sec*1000+end.tv_usec/1000)-
  63. (start.tv_sec*1000+start.tv_usec/1000);
  64. if(delay>thres)
  65. fprintf(stderr,"%s: execution time=%dms\n",msg,delay);
  66. }
  67. static const char* state2String(int state){
  68. if (state == 0)
  69. return "CLOSED_STATE";
  70. if (state == ZOO_CONNECTING_STATE)
  71. return "CONNECTING_STATE";
  72. if (state == ZOO_ASSOCIATING_STATE)
  73. return "ASSOCIATING_STATE";
  74. if (state == ZOO_CONNECTED_STATE)
  75. return "CONNECTED_STATE";
  76. if (state == ZOO_READONLY_STATE)
  77. return "READONLY_STATE";
  78. if (state == ZOO_EXPIRED_SESSION_STATE)
  79. return "EXPIRED_SESSION_STATE";
  80. if (state == ZOO_AUTH_FAILED_STATE)
  81. return "AUTH_FAILED_STATE";
  82. return "INVALID_STATE";
  83. }
  84. static const char* type2String(int state){
  85. if (state == ZOO_CREATED_EVENT)
  86. return "CREATED_EVENT";
  87. if (state == ZOO_DELETED_EVENT)
  88. return "DELETED_EVENT";
  89. if (state == ZOO_CHANGED_EVENT)
  90. return "CHANGED_EVENT";
  91. if (state == ZOO_CHILD_EVENT)
  92. return "CHILD_EVENT";
  93. if (state == ZOO_SESSION_EVENT)
  94. return "SESSION_EVENT";
  95. if (state == ZOO_NOTWATCHING_EVENT)
  96. return "NOTWATCHING_EVENT";
  97. return "UNKNOWN_EVENT_TYPE";
  98. }
  99. void watcher(zhandle_t *zzh, int type, int state, const char *path,
  100. void* context)
  101. {
  102. /* Be careful using zh here rather than zzh - as this may be mt code
  103. * the client lib may call the watcher before zookeeper_init returns */
  104. fprintf(stderr, "Watcher %s state = %s", type2String(type), state2String(state));
  105. if (path && strlen(path) > 0) {
  106. fprintf(stderr, " for path %s", path);
  107. }
  108. fprintf(stderr, "\n");
  109. if (type == ZOO_SESSION_EVENT) {
  110. if (state == ZOO_CONNECTED_STATE) {
  111. const clientid_t *id = zoo_client_id(zzh);
  112. if (myid.client_id == 0 || myid.client_id != id->client_id) {
  113. myid = *id;
  114. fprintf(stderr, "Got a new session id: 0x%llx\n",
  115. _LL_CAST_ myid.client_id);
  116. if (clientIdFile) {
  117. FILE *fh = fopen(clientIdFile, "w");
  118. if (!fh) {
  119. perror(clientIdFile);
  120. } else {
  121. int rc = fwrite(&myid, sizeof(myid), 1, fh);
  122. if (rc != sizeof(myid)) {
  123. perror("writing client id");
  124. }
  125. fclose(fh);
  126. }
  127. }
  128. }
  129. } else if (state == ZOO_AUTH_FAILED_STATE) {
  130. fprintf(stderr, "Authentication failure. Shutting down...\n");
  131. zookeeper_close(zzh);
  132. shutdownThisThing=1;
  133. zh=0;
  134. } else if (state == ZOO_EXPIRED_SESSION_STATE) {
  135. fprintf(stderr, "Session expired. Shutting down...\n");
  136. zookeeper_close(zzh);
  137. shutdownThisThing=1;
  138. zh=0;
  139. }
  140. }
  141. }
  142. void dumpStat(const struct Stat *stat) {
  143. char tctimes[40];
  144. char tmtimes[40];
  145. time_t tctime;
  146. time_t tmtime;
  147. if (!stat) {
  148. fprintf(stderr,"null\n");
  149. return;
  150. }
  151. tctime = stat->ctime/1000;
  152. tmtime = stat->mtime/1000;
  153. ctime_r(&tmtime, tmtimes);
  154. ctime_r(&tctime, tctimes);
  155. fprintf(stderr, "\tctime = %s\tczxid=%llx\n"
  156. "\tmtime=%s\tmzxid=%llx\n"
  157. "\tversion=%x\taversion=%x\n"
  158. "\tephemeralOwner = %llx\n",
  159. tctimes, _LL_CAST_ stat->czxid, tmtimes,
  160. _LL_CAST_ stat->mzxid,
  161. (unsigned int)stat->version, (unsigned int)stat->aversion,
  162. _LL_CAST_ stat->ephemeralOwner);
  163. }
  164. void my_string_completion(int rc, const char *name, const void *data) {
  165. fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc);
  166. if (!rc) {
  167. fprintf(stderr, "\tname = %s\n", name);
  168. }
  169. if(batchMode)
  170. shutdownThisThing=1;
  171. }
  172. void my_string_completion_free_data(int rc, const char *name, const void *data) {
  173. my_string_completion(rc, name, data);
  174. free((void*)data);
  175. }
  176. void my_string_stat_completion(int rc, const char *name, const struct Stat *stat,
  177. const void *data) {
  178. my_string_completion(rc, name, data);
  179. dumpStat(stat);
  180. }
  181. void my_string_stat_completion_free_data(int rc, const char *name,
  182. const struct Stat *stat, const void *data) {
  183. my_string_stat_completion(rc, name, stat, data);
  184. free((void*)data);
  185. }
  186. void my_data_completion(int rc, const char *value, int value_len,
  187. const struct Stat *stat, const void *data) {
  188. struct timeval tv;
  189. int sec;
  190. int usec;
  191. gettimeofday(&tv, 0);
  192. sec = tv.tv_sec - startTime.tv_sec;
  193. usec = tv.tv_usec - startTime.tv_usec;
  194. fprintf(stderr, "time = %d msec\n", sec*1000 + usec/1000);
  195. fprintf(stderr, "%s: rc = %d\n", (char*)data, rc);
  196. if (value) {
  197. fprintf(stderr, " value_len = %d\n", value_len);
  198. assert(write(2, value, value_len) == value_len);
  199. }
  200. fprintf(stderr, "\nStat:\n");
  201. dumpStat(stat);
  202. free((void*)data);
  203. if(batchMode)
  204. shutdownThisThing=1;
  205. }
  206. void my_silent_data_completion(int rc, const char *value, int value_len,
  207. const struct Stat *stat, const void *data) {
  208. recvd++;
  209. fprintf(stderr, "Data completion %s rc = %d\n",(char*)data,rc);
  210. free((void*)data);
  211. if (recvd==to_send) {
  212. fprintf(stderr,"Recvd %d responses for %d requests sent\n",recvd,to_send);
  213. if(batchMode)
  214. shutdownThisThing=1;
  215. }
  216. }
  217. void my_strings_completion(int rc, const struct String_vector *strings,
  218. const void *data) {
  219. struct timeval tv;
  220. int sec;
  221. int usec;
  222. int i;
  223. gettimeofday(&tv, 0);
  224. sec = tv.tv_sec - startTime.tv_sec;
  225. usec = tv.tv_usec - startTime.tv_usec;
  226. fprintf(stderr, "time = %d msec\n", sec*1000 + usec/1000);
  227. fprintf(stderr, "%s: rc = %d\n", (char*)data, rc);
  228. if (strings)
  229. for (i=0; i < strings->count; i++) {
  230. fprintf(stderr, "\t%s\n", strings->data[i]);
  231. }
  232. free((void*)data);
  233. gettimeofday(&tv, 0);
  234. sec = tv.tv_sec - startTime.tv_sec;
  235. usec = tv.tv_usec - startTime.tv_usec;
  236. fprintf(stderr, "time = %d msec\n", sec*1000 + usec/1000);
  237. if(batchMode)
  238. shutdownThisThing=1;
  239. }
  240. void my_strings_stat_completion(int rc, const struct String_vector *strings,
  241. const struct Stat *stat, const void *data) {
  242. my_strings_completion(rc, strings, data);
  243. dumpStat(stat);
  244. if(batchMode)
  245. shutdownThisThing=1;
  246. }
  247. void my_void_completion(int rc, const void *data) {
  248. fprintf(stderr, "%s: rc = %d\n", (char*)data, rc);
  249. free((void*)data);
  250. if(batchMode)
  251. shutdownThisThing=1;
  252. }
  253. void my_stat_completion(int rc, const struct Stat *stat, const void *data) {
  254. fprintf(stderr, "%s: rc = %d Stat:\n", (char*)data, rc);
  255. dumpStat(stat);
  256. free((void*)data);
  257. if(batchMode)
  258. shutdownThisThing=1;
  259. }
  260. void my_silent_stat_completion(int rc, const struct Stat *stat,
  261. const void *data) {
  262. // fprintf(stderr, "State completion: [%s] rc = %d\n", (char*)data, rc);
  263. sent++;
  264. free((void*)data);
  265. }
  266. static void sendRequest(const char* data) {
  267. zoo_aset(zh, "/od", data, strlen(data), -1, my_silent_stat_completion,
  268. strdup("/od"));
  269. zoo_aget(zh, "/od", 1, my_silent_data_completion, strdup("/od"));
  270. }
  271. void od_completion(int rc, const struct Stat *stat, const void *data) {
  272. int i;
  273. fprintf(stderr, "od command response: rc = %d Stat:\n", rc);
  274. dumpStat(stat);
  275. // send a whole bunch of requests
  276. recvd=0;
  277. sent=0;
  278. to_send=200;
  279. for (i=0; i<to_send; i++) {
  280. char buf[4096*16];
  281. memset(buf, -1, sizeof(buf)-1);
  282. buf[sizeof(buf)-1]=0;
  283. sendRequest(buf);
  284. }
  285. }
  286. int startsWith(const char *line, const char *prefix) {
  287. int len = strlen(prefix);
  288. return strncmp(line, prefix, len) == 0;
  289. }
  290. static const char *hostPort;
  291. static int verbose = 0;
  292. void processline(char *line) {
  293. int rc;
  294. int async = ((line[0] == 'a') && !(startsWith(line, "addauth ")));
  295. if (async) {
  296. line++;
  297. }
  298. if (startsWith(line, "help")) {
  299. fprintf(stderr, " create [+[e|s]] <path>\n");
  300. fprintf(stderr, " create2 [+[e|s]] <path>\n");
  301. fprintf(stderr, " delete <path>\n");
  302. fprintf(stderr, " set <path> <data>\n");
  303. fprintf(stderr, " get <path>\n");
  304. fprintf(stderr, " ls <path>\n");
  305. fprintf(stderr, " ls2 <path>\n");
  306. fprintf(stderr, " sync <path>\n");
  307. fprintf(stderr, " exists <path>\n");
  308. fprintf(stderr, " wexists <path>\n");
  309. fprintf(stderr, " myid\n");
  310. fprintf(stderr, " verbose\n");
  311. fprintf(stderr, " addauth <id> <scheme>\n");
  312. fprintf(stderr, " config\n");
  313. fprintf(stderr, " reconfig [-file <path> | -members <serverId=host:port1:port2;port3>,... | "
  314. " -add <serverId=host:port1:port2;port3>,... | -remove <serverId>,...] [-version <version>]\n");
  315. fprintf(stderr, " quit\n");
  316. fprintf(stderr, "\n");
  317. fprintf(stderr, " prefix the command with the character 'a' to run the command asynchronously.\n");
  318. fprintf(stderr, " run the 'verbose' command to toggle verbose logging.\n");
  319. fprintf(stderr, " i.e. 'aget /foo' to get /foo asynchronously\n");
  320. } else if (startsWith(line, "verbose")) {
  321. if (verbose) {
  322. verbose = 0;
  323. zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
  324. fprintf(stderr, "logging level set to WARN\n");
  325. } else {
  326. verbose = 1;
  327. zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
  328. fprintf(stderr, "logging level set to DEBUG\n");
  329. }
  330. } else if (startsWith(line, "get ")) {
  331. line += 4;
  332. if (line[0] != '/') {
  333. fprintf(stderr, "Path must start with /, found: %s\n", line);
  334. return;
  335. }
  336. rc = zoo_aget(zh, line, 1, my_data_completion, strdup(line));
  337. if (rc) {
  338. fprintf(stderr, "Error %d for %s\n", rc, line);
  339. }
  340. } else if (strcmp(line, "config") == 0) {
  341. gettimeofday(&startTime, 0);
  342. rc = zoo_agetconfig(zh, 1, my_data_completion, strdup(ZOO_CONFIG_NODE));
  343. if (rc) {
  344. fprintf(stderr, "Error %d for %s\n", rc, line);
  345. }
  346. } else if (startsWith(line, "reconfig ")) {
  347. int syntaxError = 0;
  348. char* p = NULL;
  349. char* joining = NULL;
  350. char* leaving = NULL;
  351. char* members = NULL;
  352. size_t members_size = 0;
  353. int mode = 0; // 0 = not set, 1 = incremental, 2 = non-incremental
  354. int64_t version = -1;
  355. line += 9;
  356. p = strtok (strdup(line)," ");
  357. while (p != NULL) {
  358. if (strcmp(p, "-add")==0) {
  359. p = strtok (NULL," ");
  360. if (mode == 2 || p == NULL) {
  361. syntaxError = 1;
  362. break;
  363. }
  364. mode = 1;
  365. joining = strdup(p);
  366. } else if (strcmp(p, "-remove")==0){
  367. p = strtok (NULL," ");
  368. if (mode == 2 || p == NULL) {
  369. syntaxError = 1;
  370. break;
  371. }
  372. mode = 1;
  373. leaving = strdup(p);
  374. } else if (strcmp(p, "-members")==0) {
  375. p = strtok (NULL," ");
  376. if (mode == 1 || p == NULL) {
  377. syntaxError = 1;
  378. break;
  379. }
  380. mode = 2;
  381. members = strdup(p);
  382. } else if (strcmp(p, "-file")==0){
  383. FILE *fp = NULL;
  384. p = strtok (NULL," ");
  385. if (mode == 1 || p == NULL) {
  386. syntaxError = 1;
  387. break;
  388. }
  389. mode = 2;
  390. fp = fopen(p, "r");
  391. if (fp == NULL) {
  392. fprintf(stderr, "Error reading file: %s\n", p);
  393. syntaxError = 1;
  394. break;
  395. }
  396. fseek(fp, 0L, SEEK_END); /* Position to end of file */
  397. members_size = ftell(fp); /* Get file length */
  398. rewind(fp); /* Back to start of file */
  399. members = calloc(members_size + 1, sizeof(char));
  400. if(members == NULL )
  401. {
  402. fprintf(stderr, "\nInsufficient memory to read file: %s\n", p);
  403. syntaxError = 1;
  404. fclose(fp);
  405. break;
  406. }
  407. /* Read the entire file into members
  408. * NOTE: -- fread returns number of items successfully read
  409. * not the number of bytes. We're requesting one item of
  410. * members_size bytes. So we expect the return value here
  411. * to be 1.
  412. */
  413. if (fread(members, members_size, 1, fp) != 1){
  414. fprintf(stderr, "Error reading file: %s\n", p);
  415. syntaxError = 1;
  416. fclose(fp);
  417. break;
  418. }
  419. fclose(fp);
  420. } else if (strcmp(p, "-version")==0){
  421. p = strtok (NULL," ");
  422. if (version != -1 || p == NULL){
  423. syntaxError = 1;
  424. break;
  425. }
  426. #ifdef WIN32
  427. version = _strtoui64(p, NULL, 16);
  428. #else
  429. version = strtoull(p, NULL, 16);
  430. #endif
  431. if (version < 0) {
  432. syntaxError = 1;
  433. break;
  434. }
  435. } else {
  436. syntaxError = 1;
  437. break;
  438. }
  439. p = strtok (NULL," ");
  440. }
  441. if (syntaxError) return;
  442. rc = zoo_areconfig(zh, joining, leaving, members, version, my_data_completion, strdup(line));
  443. free(joining);
  444. free(leaving);
  445. free(members);
  446. if (rc) {
  447. fprintf(stderr, "Error %d for %s\n", rc, line);
  448. }
  449. } else if (startsWith(line, "set ")) {
  450. char *ptr;
  451. line += 4;
  452. if (line[0] != '/') {
  453. fprintf(stderr, "Path must start with /, found: %s\n", line);
  454. return;
  455. }
  456. ptr = strchr(line, ' ');
  457. if (!ptr) {
  458. fprintf(stderr, "No data found after path\n");
  459. return;
  460. }
  461. *ptr = '\0';
  462. ptr++;
  463. rc = zoo_aset(zh, line, ptr, strlen(ptr), -1, my_stat_completion,
  464. strdup(line));
  465. if (rc) {
  466. fprintf(stderr, "Error %d for %s\n", rc, line);
  467. }
  468. } else if (startsWith(line, "ls ")) {
  469. line += 3;
  470. if (line[0] != '/') {
  471. fprintf(stderr, "Path must start with /, found: %s\n", line);
  472. return;
  473. }
  474. gettimeofday(&startTime, 0);
  475. rc= zoo_aget_children(zh, line, 1, my_strings_completion, strdup(line));
  476. if (rc) {
  477. fprintf(stderr, "Error %d for %s\n", rc, line);
  478. }
  479. } else if (startsWith(line, "ls2 ")) {
  480. line += 4;
  481. if (line[0] != '/') {
  482. fprintf(stderr, "Path must start with /, found: %s\n", line);
  483. return;
  484. }
  485. gettimeofday(&startTime, 0);
  486. rc= zoo_aget_children2(zh, line, 1, my_strings_stat_completion, strdup(line));
  487. if (rc) {
  488. fprintf(stderr, "Error %d for %s\n", rc, line);
  489. }
  490. } else if (startsWith(line, "create ") || startsWith(line, "create2 ")) {
  491. int flags = 0;
  492. int is_create2 = startsWith(line, "create2 ");
  493. line += is_create2 ? 8 : 7;
  494. if (line[0] == '+') {
  495. line++;
  496. if (line[0] == 'e') {
  497. flags |= ZOO_EPHEMERAL;
  498. line++;
  499. }
  500. if (line[0] == 's') {
  501. flags |= ZOO_SEQUENCE;
  502. line++;
  503. }
  504. line++;
  505. }
  506. if (line[0] != '/') {
  507. fprintf(stderr, "Path must start with /, found: %s\n", line);
  508. return;
  509. }
  510. fprintf(stderr, "Creating [%s] node\n", line);
  511. // {
  512. // struct ACL _CREATE_ONLY_ACL_ACL[] = {{ZOO_PERM_CREATE, ZOO_ANYONE_ID_UNSAFE}};
  513. // struct ACL_vector CREATE_ONLY_ACL = {1,_CREATE_ONLY_ACL_ACL};
  514. // rc = zoo_acreate(zh, line, "new", 3, &CREATE_ONLY_ACL, flags,
  515. // my_string_completion, strdup(line));
  516. // }
  517. if (is_create2) {
  518. rc = zoo_acreate2(zh, line, "new", 3, &ZOO_OPEN_ACL_UNSAFE, flags,
  519. my_string_stat_completion_free_data, strdup(line));
  520. } else {
  521. rc = zoo_acreate(zh, line, "new", 3, &ZOO_OPEN_ACL_UNSAFE, flags,
  522. my_string_completion_free_data, strdup(line));
  523. }
  524. if (rc) {
  525. fprintf(stderr, "Error %d for %s\n", rc, line);
  526. }
  527. } else if (startsWith(line, "delete ")) {
  528. line += 7;
  529. if (line[0] != '/') {
  530. fprintf(stderr, "Path must start with /, found: %s\n", line);
  531. return;
  532. }
  533. rc = zoo_adelete(zh, line, -1, my_void_completion, strdup(line));
  534. if (rc) {
  535. fprintf(stderr, "Error %d for %s\n", rc, line);
  536. }
  537. } else if (startsWith(line, "sync ")) {
  538. line += 5;
  539. if (line[0] != '/') {
  540. fprintf(stderr, "Path must start with /, found: %s\n", line);
  541. return;
  542. }
  543. rc = zoo_async(zh, line, my_string_completion_free_data, strdup(line));
  544. if (rc) {
  545. fprintf(stderr, "Error %d for %s\n", rc, line);
  546. }
  547. } else if (startsWith(line, "wexists ")) {
  548. #ifdef THREADED
  549. struct Stat stat;
  550. #endif
  551. line += 8;
  552. if (line[0] != '/') {
  553. fprintf(stderr, "Path must start with /, found: %s\n", line);
  554. return;
  555. }
  556. #ifndef THREADED
  557. rc = zoo_awexists(zh, line, watcher, (void*) 0, my_stat_completion, strdup(line));
  558. #else
  559. rc = zoo_wexists(zh, line, watcher, (void*) 0, &stat);
  560. #endif
  561. if (rc) {
  562. fprintf(stderr, "Error %d for %s\n", rc, line);
  563. }
  564. } else if (startsWith(line, "exists ")) {
  565. #ifdef THREADED
  566. struct Stat stat;
  567. #endif
  568. line += 7;
  569. if (line[0] != '/') {
  570. fprintf(stderr, "Path must start with /, found: %s\n", line);
  571. return;
  572. }
  573. #ifndef THREADED
  574. rc = zoo_aexists(zh, line, 1, my_stat_completion, strdup(line));
  575. #else
  576. rc = zoo_exists(zh, line, 1, &stat);
  577. #endif
  578. if (rc) {
  579. fprintf(stderr, "Error %d for %s\n", rc, line);
  580. }
  581. } else if (strcmp(line, "myid") == 0) {
  582. printf("session Id = %llx\n", _LL_CAST_ zoo_client_id(zh)->client_id);
  583. } else if (strcmp(line, "reinit") == 0) {
  584. zookeeper_close(zh);
  585. // we can't send myid to the server here -- zookeeper_close() removes
  586. // the session on the server. We must start anew.
  587. zh = zookeeper_init(hostPort, watcher, 30000, 0, 0, 0);
  588. } else if (startsWith(line, "quit")) {
  589. fprintf(stderr, "Quitting...\n");
  590. shutdownThisThing=1;
  591. } else if (startsWith(line, "od")) {
  592. const char val[]="fire off";
  593. fprintf(stderr, "Overdosing...\n");
  594. rc = zoo_aset(zh, "/od", val, sizeof(val)-1, -1, od_completion, 0);
  595. if (rc)
  596. fprintf(stderr, "od command failed: %d\n", rc);
  597. } else if (startsWith(line, "addauth ")) {
  598. char *ptr;
  599. line += 8;
  600. ptr = strchr(line, ' ');
  601. if (ptr) {
  602. *ptr = '\0';
  603. ptr++;
  604. }
  605. zoo_add_auth(zh, line, ptr, ptr ? strlen(ptr) : 0, NULL, NULL);
  606. }
  607. }
  608. int main(int argc, char **argv) {
  609. #ifndef THREADED
  610. fd_set rfds, wfds, efds;
  611. int processed=0;
  612. #endif
  613. char buffer[4096];
  614. char p[2048];
  615. #ifdef YCA
  616. char *cert=0;
  617. char appId[64];
  618. #endif
  619. int bufoff = 0;
  620. int flags, i;
  621. FILE *fh;
  622. if (argc < 2) {
  623. fprintf(stderr,
  624. "USAGE %s zookeeper_host_list [clientid_file|cmd:(ls|ls2|create|create2|od|...)]\n",
  625. argv[0]);
  626. fprintf(stderr,
  627. "Version: ZooKeeper cli (c client) version %d.%d.%d\n",
  628. ZOO_MAJOR_VERSION,
  629. ZOO_MINOR_VERSION,
  630. ZOO_PATCH_VERSION);
  631. return 2;
  632. }
  633. if (argc > 2) {
  634. if(strncmp("cmd:",argv[2],4)==0){
  635. size_t cmdlen = strlen(argv[2]);
  636. if (cmdlen > sizeof(cmd)) {
  637. fprintf(stderr,
  638. "Command length %zu exceeds max length of %zu\n",
  639. cmdlen,
  640. sizeof(cmd));
  641. return 2;
  642. }
  643. strncpy(cmd, argv[2]+4, sizeof(cmd));
  644. batchMode=1;
  645. fprintf(stderr,"Batch mode: %s\n",cmd);
  646. }else{
  647. clientIdFile = argv[2];
  648. fh = fopen(clientIdFile, "r");
  649. if (fh) {
  650. if (fread(&myid, sizeof(myid), 1, fh) != sizeof(myid)) {
  651. memset(&myid, 0, sizeof(myid));
  652. }
  653. fclose(fh);
  654. }
  655. }
  656. }
  657. flags = 0;
  658. for (i = 1; i < argc; ++i) {
  659. if (strcmp("-r", argv[i]) == 0) {
  660. flags = ZOO_READONLY;
  661. break;
  662. }
  663. }
  664. #ifdef YCA
  665. strcpy(appId,"yahoo.example.yca_test");
  666. cert = yca_get_cert_once(appId);
  667. if(cert!=0) {
  668. fprintf(stderr,"Certificate for appid [%s] is [%s]\n",appId,cert);
  669. strncpy(p,cert,sizeof(p)-1);
  670. free(cert);
  671. } else {
  672. fprintf(stderr,"Certificate for appid [%s] not found\n",appId);
  673. strcpy(p,"dummy");
  674. }
  675. #else
  676. strcpy(p, "dummy");
  677. #endif
  678. verbose = 0;
  679. zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
  680. zoo_deterministic_conn_order(1); // enable deterministic order
  681. hostPort = argv[1];
  682. zh = zookeeper_init(hostPort, watcher, 30000, &myid, NULL, flags);
  683. if (!zh) {
  684. return errno;
  685. }
  686. #ifdef YCA
  687. if(zoo_add_auth(zh,"yca",p,strlen(p),0,0)!=ZOK)
  688. return 2;
  689. #endif
  690. #ifdef THREADED
  691. while(!shutdownThisThing) {
  692. int rc;
  693. int len = sizeof(buffer) - bufoff -1;
  694. if (len <= 0) {
  695. fprintf(stderr, "Can't handle lines that long!\n");
  696. exit(2);
  697. }
  698. rc = read(0, buffer+bufoff, len);
  699. if (rc <= 0) {
  700. fprintf(stderr, "bye\n");
  701. shutdownThisThing=1;
  702. break;
  703. }
  704. bufoff += rc;
  705. buffer[bufoff] = '\0';
  706. while (strchr(buffer, '\n')) {
  707. char *ptr = strchr(buffer, '\n');
  708. *ptr = '\0';
  709. processline(buffer);
  710. ptr++;
  711. memmove(buffer, ptr, strlen(ptr)+1);
  712. bufoff = 0;
  713. }
  714. }
  715. #else
  716. FD_ZERO(&rfds);
  717. FD_ZERO(&wfds);
  718. FD_ZERO(&efds);
  719. while (!shutdownThisThing) {
  720. int fd;
  721. int interest;
  722. int events;
  723. struct timeval tv;
  724. int rc;
  725. zookeeper_interest(zh, &fd, &interest, &tv);
  726. if (fd != -1) {
  727. if (interest&ZOOKEEPER_READ) {
  728. FD_SET(fd, &rfds);
  729. } else {
  730. FD_CLR(fd, &rfds);
  731. }
  732. if (interest&ZOOKEEPER_WRITE) {
  733. FD_SET(fd, &wfds);
  734. } else {
  735. FD_CLR(fd, &wfds);
  736. }
  737. } else {
  738. fd = 0;
  739. }
  740. FD_SET(0, &rfds);
  741. rc = select(fd+1, &rfds, &wfds, &efds, &tv);
  742. events = 0;
  743. if (rc > 0) {
  744. if (FD_ISSET(fd, &rfds)) {
  745. events |= ZOOKEEPER_READ;
  746. }
  747. if (FD_ISSET(fd, &wfds)) {
  748. events |= ZOOKEEPER_WRITE;
  749. }
  750. }
  751. if(batchMode && processed==0){
  752. //batch mode
  753. processline(cmd);
  754. processed=1;
  755. }
  756. if (!processed && FD_ISSET(0, &rfds)) {
  757. int rc;
  758. int len = sizeof(buffer) - bufoff -1;
  759. if (len <= 0) {
  760. fprintf(stderr, "Can't handle lines that long!\n");
  761. exit(2);
  762. }
  763. rc = read(0, buffer+bufoff, len);
  764. if (rc <= 0) {
  765. fprintf(stderr, "bye\n");
  766. break;
  767. }
  768. bufoff += rc;
  769. buffer[bufoff] = '\0';
  770. while (strchr(buffer, '\n')) {
  771. char *ptr = strchr(buffer, '\n');
  772. *ptr = '\0';
  773. processline(buffer);
  774. ptr++;
  775. memmove(buffer, ptr, strlen(ptr)+1);
  776. bufoff = 0;
  777. }
  778. }
  779. zookeeper_process(zh, events);
  780. }
  781. #endif
  782. if (to_send!=0)
  783. fprintf(stderr,"Recvd %d responses for %d requests sent\n",recvd,sent);
  784. zookeeper_close(zh);
  785. return 0;
  786. }