yc.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. // (C) 2013-2015 Cybozu.
  2. #include "yrmcds.h"
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <inttypes.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. static const uint16_t DEFAULT_PORT = 11211;
  11. static const char DEFAULT_SERVER[] = "localhost";
  12. static const size_t DEFAULT_COMPRESS = 16384;
  13. static int debug = 0;
  14. static int quiet = 0;
  15. static void version() {
  16. printf("yc with libyrmcds " LIBYRMCDS_VERSION "\n");
  17. }
  18. static void usage() {
  19. printf("Usage: yc "
  20. "[-h] [-v] [-d] [-t] [-s SERVER] [-p PORT] [-c COMPRESS] COMMAND ...\n\n"
  21. "Options:\n"
  22. " -h print help and exit.\n"
  23. " -v print version information.\n"
  24. " -d turn on debug messages.\n"
  25. " -t turn on text protocol mode.\n"
  26. " -q Use quiet commands, if possible.\n"
  27. " -s connect to SERVER. Default: localhost\n"
  28. " -p TCP port number. Default: 11211\n"
  29. " -c compression threshold. Default: 16384\n\n"
  30. "Commands:\n"
  31. " noop\n"
  32. " ping the server.\n"
  33. " get KEY\n"
  34. " get an object.\n"
  35. " getk KEY\n"
  36. " get an object with key.\n"
  37. " gat KEY EXPIRE\n"
  38. " get and touch an object.\n"
  39. " gatk KEY EXPIRE\n"
  40. " get and touch an object with key.\n"
  41. " lag KEY\n"
  42. " lock and get an object.\n"
  43. " lagk KEY\n"
  44. " lock and get an object with key.\n"
  45. " touch KEY EXPIRE\n"
  46. " touch an object.\n"
  47. " set KEY FILE [EXPIRE [FLAGS [CAS]]]\n"
  48. " store FILE data. If FILE is \"-\", stdin is used.\n"
  49. " replace KEY FILE [EXPIRE [FLAGS [CAS]]]\n"
  50. " update an existing object. FILE is the same as set.\n"
  51. " add KEY FILE [EXPIRE [FLAGS [CAS]]]\n"
  52. " create a new object. FILE is the same as set.\n"
  53. " rau KEY FILE [EXPIRE [FLAGS]]\n"
  54. " replace a locked object then unlock it.\n"
  55. " Since this command always fails, do not use this.\n"
  56. " incr KEY VALUE [INITIAL [EXPIRE]]\n"
  57. " increments an exiting object's value by VALUE.\n"
  58. " If INITIAL is given, new object is created when KEY\n"
  59. " is not found. EXPIRE is used only when an object is\n"
  60. " created.\n"
  61. " decr KEY VALUE [INITIAL [EXPIRE]]\n"
  62. " decrements an exiting object's value by VALUE.\n"
  63. " If INITIAL is given, new object is created when KEY\n"
  64. " is not found. EXPIRE is used only when an object is\n"
  65. " created.\n"
  66. " append KEY FILE\n"
  67. " append FILE data FILE is the same as set.\n"
  68. " prepend KEY FILE\n"
  69. " prepend FILE data FILE is the same as set.\n"
  70. " delete KEY\n"
  71. " delete an object.\n"
  72. " lock KEY\n"
  73. " locks an object.\n"
  74. " unlock KEY\n"
  75. " this command always fails. Do not use this.\n"
  76. " unlockall\n"
  77. " this command has no effect.\n"
  78. " flush [DELAY]\n"
  79. " flush all unlocked items immediately or after DELAY seconds.\n"
  80. " stat [settings|items|sizes]\n"
  81. " obtain general or specified statistics.\n"
  82. " keys [PREFIX]\n"
  83. " dump keys matching PREFIX.\n"
  84. " version\n"
  85. " shows the server version.\n"
  86. " quit\n"
  87. " just quits. Not much interesting.\n"
  88. );
  89. }
  90. static void print_response(const yrmcds_response* r) {
  91. fprintf(stderr, "dump response:\n"
  92. " serial: %u\n"
  93. " length: %lu\n"
  94. " status: 0x%04x\n"
  95. " command: 0x%02x\n"
  96. " cas: %" PRIu64 "\n"
  97. " flags: 0x%08x\n"
  98. " value: %" PRIu64 "\n",
  99. r->serial, (unsigned long)r->length, r->status, r->command,
  100. r->cas_unique, r->flags, r->value);
  101. if( r->key_len )
  102. fprintf(stderr, " key: %.*s (%lu bytes)\n",
  103. (int)r->key_len, r->key, (unsigned long)r->key_len);
  104. if( r->data_len )
  105. fprintf(stderr, " data: %.*s (%lu bytes)\n",
  106. (int)r->data_len, r->data, (unsigned long)r->data_len);
  107. }
  108. static void write_data(const yrmcds_response* r) {
  109. const char* p = r->data;
  110. size_t to_write = r->data_len;
  111. while( to_write > 0 ) {
  112. ssize_t n = write(STDOUT_FILENO, p, to_write);
  113. if( n == -1 ) return;
  114. p += n;
  115. to_write -= (size_t)n;
  116. }
  117. // writing a newline breaks data equality...
  118. //char nl = '\n';
  119. //write(STDOUT_FILENO, &nl, 1);
  120. }
  121. static size_t read_data(const char* filename, char** pdata) {
  122. int fd;
  123. if( strcmp(filename, "-") == 0 ) {
  124. fd = STDIN_FILENO;
  125. } else {
  126. fd = open(filename, O_RDONLY);
  127. if( fd == -1 ) return 0;
  128. }
  129. size_t data_len = 0;
  130. size_t capacity = 1 << 20;
  131. *pdata = (char*)malloc(capacity);
  132. if( *pdata == NULL ) return 0;
  133. while( 1 ) {
  134. if( (capacity - data_len) < (1 << 20) ) {
  135. char* new_data = (char*)realloc(*pdata, capacity * 2);
  136. if( new_data == NULL ) {
  137. free(*pdata);
  138. *pdata = NULL;
  139. return 0;
  140. }
  141. *pdata = new_data;
  142. capacity *= 2;
  143. }
  144. ssize_t n = read(fd, *pdata + data_len, 1 << 20);
  145. if( n == -1 ) {
  146. free(*pdata);
  147. *pdata = NULL;
  148. return 0;
  149. }
  150. if( n == 0 ) break;
  151. data_len += (size_t)n;
  152. }
  153. if( fd != STDIN_FILENO )
  154. close(fd);
  155. return data_len;
  156. }
  157. #define CHECK_ERROR(e) \
  158. if( e != 0 ) { \
  159. if( e == YRMCDS_SYSTEM_ERROR ) { \
  160. fprintf(stderr, "system error: %s\n", strerror(errno)); \
  161. } else { \
  162. fprintf(stderr, "yrmcds error: %s\n", yrmcds_strerror(e)); \
  163. } \
  164. return 2; \
  165. }
  166. #define CHECK_RESPONSE(r) \
  167. if( r->status != YRMCDS_STATUS_OK ) { \
  168. fprintf(stderr, "Command failed: 0x%04x %.*s\n", \
  169. r->status, (int)r->data_len, r->data); \
  170. return 3; \
  171. }
  172. int cmd_noop(int argc, char** argv, yrmcds* s) {
  173. yrmcds_response r[1];
  174. uint32_t serial;
  175. yrmcds_error e = yrmcds_noop(s, &serial);
  176. CHECK_ERROR(e);
  177. if( debug )
  178. fprintf(stderr, "request serial = %u\n", serial);
  179. e = yrmcds_recv(s, r);
  180. CHECK_ERROR(e);
  181. if( debug )
  182. print_response(r);
  183. CHECK_RESPONSE(r);
  184. printf("OK\n");
  185. return 0;
  186. }
  187. int cmd_get(int argc, char** argv, yrmcds* s) {
  188. if( argc != 1 ) {
  189. fprintf(stderr, "Wrong number of arguments.\n");
  190. return 1;
  191. }
  192. yrmcds_response r[1];
  193. uint32_t serial;
  194. yrmcds_error e = yrmcds_get(s, argv[0], strlen(argv[0]), quiet, &serial);
  195. CHECK_ERROR(e);
  196. if( quiet ) {
  197. e = yrmcds_noop(s, &serial);
  198. CHECK_ERROR(e);
  199. }
  200. if( debug )
  201. fprintf(stderr, "request serial = %u\n", serial);
  202. while( 1 ) {
  203. e = yrmcds_recv(s, r);
  204. CHECK_ERROR(e);
  205. if( debug )
  206. print_response(r);
  207. CHECK_RESPONSE(r);
  208. if( r->serial == serial )
  209. break;
  210. }
  211. write_data(r);
  212. return 0;
  213. }
  214. int cmd_getk(int argc, char** argv, yrmcds* s) {
  215. if( argc != 1 ) {
  216. fprintf(stderr, "Wrong number of arguments.\n");
  217. return 1;
  218. }
  219. yrmcds_response r[1];
  220. uint32_t serial;
  221. yrmcds_error e = yrmcds_getk(s, argv[0], strlen(argv[0]), quiet, &serial);
  222. CHECK_ERROR(e);
  223. if( quiet ) {
  224. e = yrmcds_noop(s, &serial);
  225. CHECK_ERROR(e);
  226. }
  227. if( debug )
  228. fprintf(stderr, "request serial = %u\n", serial);
  229. while( 1 ) {
  230. e = yrmcds_recv(s, r);
  231. CHECK_ERROR(e);
  232. if( debug )
  233. print_response(r);
  234. CHECK_RESPONSE(r);
  235. if( r->serial == serial )
  236. break;
  237. }
  238. write_data(r);
  239. return 0;
  240. }
  241. int cmd_gat(int argc, char** argv, yrmcds* s) {
  242. if( argc != 2 ) {
  243. fprintf(stderr, "Wrong number of arguments.\n");
  244. return 1;
  245. }
  246. const char* key = argv[0];
  247. uint32_t expire = (uint32_t)strtoull(argv[1], NULL, 0);
  248. yrmcds_response r[1];
  249. uint32_t serial;
  250. yrmcds_error e = yrmcds_get_touch(s, key, strlen(key), expire, quiet, &serial);
  251. CHECK_ERROR(e);
  252. if( quiet ) {
  253. e = yrmcds_noop(s, &serial);
  254. CHECK_ERROR(e);
  255. }
  256. if( debug )
  257. fprintf(stderr, "request serial = %u\n", serial);
  258. while( 1 ) {
  259. e = yrmcds_recv(s, r);
  260. CHECK_ERROR(e);
  261. if( debug )
  262. print_response(r);
  263. CHECK_RESPONSE(r);
  264. if( r->serial == serial )
  265. break;
  266. }
  267. write_data(r);
  268. return 0;
  269. }
  270. int cmd_gatk(int argc, char** argv, yrmcds* s) {
  271. if( argc != 2 ) {
  272. fprintf(stderr, "Wrong number of arguments.\n");
  273. return 1;
  274. }
  275. const char* key = argv[0];
  276. uint32_t expire = (uint32_t)strtoull(argv[1], NULL, 0);
  277. yrmcds_response r[1];
  278. uint32_t serial;
  279. yrmcds_error e = yrmcds_getk_touch(s, key, strlen(key), expire, quiet, &serial);
  280. CHECK_ERROR(e);
  281. if( quiet ) {
  282. e = yrmcds_noop(s, &serial);
  283. CHECK_ERROR(e);
  284. }
  285. if( debug )
  286. fprintf(stderr, "request serial = %u\n", serial);
  287. while( 1 ) {
  288. e = yrmcds_recv(s, r);
  289. CHECK_ERROR(e);
  290. if( debug )
  291. print_response(r);
  292. CHECK_RESPONSE(r);
  293. if( r->serial == serial )
  294. break;
  295. }
  296. write_data(r);
  297. return 0;
  298. }
  299. int cmd_lag(int argc, char** argv, yrmcds* s) {
  300. if( argc != 1 ) {
  301. fprintf(stderr, "Wrong number of arguments.\n");
  302. return 1;
  303. }
  304. yrmcds_response r[1];
  305. uint32_t serial;
  306. yrmcds_error e = yrmcds_lock_get(s, argv[0], strlen(argv[0]), quiet, &serial);
  307. CHECK_ERROR(e);
  308. if( quiet ) {
  309. e = yrmcds_noop(s, &serial);
  310. CHECK_ERROR(e);
  311. }
  312. if( debug )
  313. fprintf(stderr, "request serial = %u\n", serial);
  314. while( 1 ) {
  315. e = yrmcds_recv(s, r);
  316. CHECK_ERROR(e);
  317. if( debug )
  318. print_response(r);
  319. CHECK_RESPONSE(r);
  320. if( r->serial == serial )
  321. break;
  322. }
  323. write_data(r);
  324. fprintf(stderr, "Press enter to unlock.\n");
  325. getchar();
  326. return 0;
  327. }
  328. int cmd_lagk(int argc, char** argv, yrmcds* s) {
  329. if( argc != 1 ) {
  330. fprintf(stderr, "Wrong number of arguments.\n");
  331. return 1;
  332. }
  333. yrmcds_response r[1];
  334. uint32_t serial;
  335. yrmcds_error e = yrmcds_lock_getk(s, argv[0], strlen(argv[0]), quiet, &serial);
  336. CHECK_ERROR(e);
  337. if( quiet ) {
  338. e = yrmcds_noop(s, &serial);
  339. CHECK_ERROR(e);
  340. }
  341. if( debug )
  342. fprintf(stderr, "request serial = %u\n", serial);
  343. while( 1 ) {
  344. e = yrmcds_recv(s, r);
  345. CHECK_ERROR(e);
  346. if( debug )
  347. print_response(r);
  348. CHECK_RESPONSE(r);
  349. if( r->serial == serial )
  350. break;
  351. }
  352. write_data(r);
  353. fprintf(stderr, "Press enter to unlock.\n");
  354. getchar();
  355. return 0;
  356. }
  357. int cmd_touch(int argc, char** argv, yrmcds* s) {
  358. if( argc != 2 ) {
  359. fprintf(stderr, "Wrong number of arguments.\n");
  360. return 1;
  361. }
  362. const char* key = argv[0];
  363. uint32_t expire = (uint32_t)strtoull(argv[1], NULL, 0);
  364. yrmcds_response r[1];
  365. uint32_t serial;
  366. yrmcds_error e = yrmcds_touch(s, key, strlen(key), expire, quiet, &serial);
  367. CHECK_ERROR(e);
  368. if( quiet ) {
  369. e = yrmcds_noop(s, &serial);
  370. CHECK_ERROR(e);
  371. }
  372. if( debug )
  373. fprintf(stderr, "request serial = %u\n", serial);
  374. while( 1 ) {
  375. e = yrmcds_recv(s, r);
  376. CHECK_ERROR(e);
  377. if( debug )
  378. print_response(r);
  379. CHECK_RESPONSE(r);
  380. if( r->serial == serial )
  381. break;
  382. }
  383. return 0;
  384. }
  385. int cmd_set(int argc, char** argv, yrmcds* s) {
  386. if( argc < 2 || 5 < argc ) {
  387. fprintf(stderr, "Wrong number of arguments.\n");
  388. return 1;
  389. }
  390. const char* key = argv[0];
  391. char* data = NULL;
  392. size_t data_len = read_data(argv[1], &data);
  393. if( data == NULL ) {
  394. fprintf(stderr, "Failed to read data.\n");
  395. return 2;
  396. }
  397. uint32_t expire = 0;
  398. uint32_t flags = 0;
  399. uint64_t cas = 0;
  400. if( argc > 2 )
  401. expire = (uint32_t)strtoull(argv[2], NULL, 0);
  402. if( argc > 3 )
  403. flags = (uint32_t)strtoull(argv[3], NULL, 0);
  404. if( argc > 4 )
  405. cas = (uint64_t)strtoull(argv[4], NULL, 0);
  406. yrmcds_response r[1];
  407. uint32_t serial;
  408. yrmcds_error e = yrmcds_set(s, key, strlen(key), data, data_len,
  409. flags, expire, cas, quiet, &serial);
  410. free(data);
  411. CHECK_ERROR(e);
  412. if( quiet ) {
  413. e = yrmcds_noop(s, &serial);
  414. CHECK_ERROR(e);
  415. }
  416. if( debug )
  417. fprintf(stderr, "request serial = %u\n", serial);
  418. while( 1 ) {
  419. e = yrmcds_recv(s, r);
  420. CHECK_ERROR(e);
  421. if( debug )
  422. print_response(r);
  423. CHECK_RESPONSE(r);
  424. if( r->serial == serial )
  425. break;
  426. }
  427. return 0;
  428. }
  429. int cmd_replace(int argc, char** argv, yrmcds* s) {
  430. if( argc < 2 || 5 < argc ) {
  431. fprintf(stderr, "Wrong number of arguments.\n");
  432. return 1;
  433. }
  434. const char* key = argv[0];
  435. char* data = NULL;
  436. size_t data_len = read_data(argv[1], &data);
  437. if( data == NULL ) {
  438. fprintf(stderr, "Failed to read data.\n");
  439. return 2;
  440. }
  441. uint32_t expire = 0;
  442. uint32_t flags = 0;
  443. uint64_t cas = 0;
  444. if( argc > 2 )
  445. expire = (uint32_t)strtoull(argv[2], NULL, 0);
  446. if( argc > 3 )
  447. flags = (uint32_t)strtoull(argv[3], NULL, 0);
  448. if( argc > 4 )
  449. cas = (uint64_t)strtoull(argv[4], NULL, 0);
  450. yrmcds_response r[1];
  451. uint32_t serial;
  452. yrmcds_error e = yrmcds_replace(s, key, strlen(key), data, data_len,
  453. flags, expire, cas, quiet, &serial);
  454. free(data);
  455. CHECK_ERROR(e);
  456. if( quiet ) {
  457. e = yrmcds_noop(s, &serial);
  458. CHECK_ERROR(e);
  459. }
  460. if( debug )
  461. fprintf(stderr, "request serial = %u\n", serial);
  462. while( 1 ) {
  463. e = yrmcds_recv(s, r);
  464. CHECK_ERROR(e);
  465. if( debug )
  466. print_response(r);
  467. CHECK_RESPONSE(r);
  468. if( r->serial == serial )
  469. break;
  470. }
  471. return 0;
  472. }
  473. int cmd_add(int argc, char** argv, yrmcds* s) {
  474. if( argc < 2 || 5 < argc ) {
  475. fprintf(stderr, "Wrong number of arguments.\n");
  476. return 1;
  477. }
  478. const char* key = argv[0];
  479. char* data = NULL;
  480. size_t data_len = read_data(argv[1], &data);
  481. if( data == NULL ) {
  482. fprintf(stderr, "Failed to read data.\n");
  483. return 2;
  484. }
  485. uint32_t expire = 0;
  486. uint32_t flags = 0;
  487. uint64_t cas = 0;
  488. if( argc > 2 )
  489. expire = (uint32_t)strtoull(argv[2], NULL, 0);
  490. if( argc > 3 )
  491. flags = (uint32_t)strtoull(argv[3], NULL, 0);
  492. if( argc > 4 )
  493. cas = (uint64_t)strtoull(argv[4], NULL, 0);
  494. yrmcds_response r[1];
  495. uint32_t serial;
  496. yrmcds_error e = yrmcds_add(s, key, strlen(key), data, data_len,
  497. flags, expire, cas, quiet, &serial);
  498. free(data);
  499. CHECK_ERROR(e);
  500. if( quiet ) {
  501. e = yrmcds_noop(s, &serial);
  502. CHECK_ERROR(e);
  503. }
  504. if( debug )
  505. fprintf(stderr, "request serial = %u\n", serial);
  506. while( 1 ) {
  507. e = yrmcds_recv(s, r);
  508. CHECK_ERROR(e);
  509. if( debug )
  510. print_response(r);
  511. CHECK_RESPONSE(r);
  512. if( r->serial == serial )
  513. break;
  514. }
  515. return 0;
  516. }
  517. int cmd_rau(int argc, char** argv, yrmcds* s) {
  518. if( argc < 2 || 4 < argc ) {
  519. fprintf(stderr, "Wrong number of arguments.\n");
  520. return 1;
  521. }
  522. const char* key = argv[0];
  523. char* data = NULL;
  524. size_t data_len = read_data(argv[1], &data);
  525. if( data == NULL ) {
  526. fprintf(stderr, "Failed to read data.\n");
  527. return 2;
  528. }
  529. uint32_t expire = 0;
  530. uint32_t flags = 0;
  531. if( argc > 2 )
  532. expire = (uint32_t)strtoull(argv[2], NULL, 0);
  533. if( argc > 3 )
  534. flags = (uint32_t)strtoull(argv[3], NULL, 0);
  535. yrmcds_response r[1];
  536. uint32_t serial;
  537. yrmcds_error e = yrmcds_replace_unlock(s, key, strlen(key), data, data_len,
  538. flags, expire, quiet, &serial);
  539. free(data);
  540. CHECK_ERROR(e);
  541. if( quiet ) {
  542. e = yrmcds_noop(s, &serial);
  543. CHECK_ERROR(e);
  544. }
  545. if( debug )
  546. fprintf(stderr, "request serial = %u\n", serial);
  547. while( 1 ) {
  548. e = yrmcds_recv(s, r);
  549. CHECK_ERROR(e);
  550. if( debug )
  551. print_response(r);
  552. CHECK_RESPONSE(r);
  553. if( r->serial == serial )
  554. break;
  555. }
  556. return 0;
  557. }
  558. int cmd_incr(int argc, char** argv, yrmcds* s) {
  559. if( argc < 2 || 4 < argc ) {
  560. fprintf(stderr, "Wrong number of arguments.\n");
  561. return 1;
  562. }
  563. const char* key = argv[0];
  564. uint64_t value = (uint64_t)strtoull(argv[1], NULL, 0);
  565. uint64_t initial = 0;
  566. uint32_t expire = ~(uint32_t)0;
  567. if( argc > 2 ) {
  568. initial = (uint64_t)strtoull(argv[2], NULL, 0);
  569. expire = 0;
  570. }
  571. if( argc > 3 )
  572. expire = (uint32_t)strtoull(argv[3], NULL, 0);
  573. yrmcds_response r[1];
  574. uint32_t serial;
  575. yrmcds_error e;
  576. if( argc == 2 ) {
  577. e = yrmcds_incr(s, key, strlen(key), value, quiet, &serial);
  578. } else {
  579. e = yrmcds_incr2(s, key, strlen(key), value, initial, expire,
  580. quiet, &serial);
  581. }
  582. CHECK_ERROR(e);
  583. if( quiet ) {
  584. e = yrmcds_noop(s, &serial);
  585. CHECK_ERROR(e);
  586. }
  587. if( debug )
  588. fprintf(stderr, "request serial = %u\n", serial);
  589. while( 1 ) {
  590. e = yrmcds_recv(s, r);
  591. CHECK_ERROR(e);
  592. if( debug )
  593. print_response(r);
  594. CHECK_RESPONSE(r);
  595. if( r->serial == serial )
  596. break;
  597. }
  598. printf("%" PRIu64 "\n", r->value);
  599. return 0;
  600. }
  601. int cmd_decr(int argc, char** argv, yrmcds* s) {
  602. if( argc < 2 || 4 < argc ) {
  603. fprintf(stderr, "Wrong number of arguments.\n");
  604. return 1;
  605. }
  606. const char* key = argv[0];
  607. uint64_t value = (uint64_t)strtoull(argv[1], NULL, 0);
  608. uint64_t initial = 0;
  609. uint32_t expire = ~(uint32_t)0;
  610. if( argc > 2 ) {
  611. initial = (uint64_t)strtoull(argv[2], NULL, 0);
  612. expire = 0;
  613. }
  614. if( argc > 3 )
  615. expire = (uint32_t)strtoull(argv[3], NULL, 0);
  616. yrmcds_response r[1];
  617. uint32_t serial;
  618. yrmcds_error e;
  619. if( argc == 2 ) {
  620. e = yrmcds_decr(s, key, strlen(key), value, quiet, &serial);
  621. } else {
  622. e = yrmcds_decr2(s, key, strlen(key), value, initial, expire,
  623. quiet, &serial);
  624. }
  625. CHECK_ERROR(e);
  626. if( quiet ) {
  627. e = yrmcds_noop(s, &serial);
  628. CHECK_ERROR(e);
  629. }
  630. if( debug )
  631. fprintf(stderr, "request serial = %u\n", serial);
  632. while( 1 ) {
  633. e = yrmcds_recv(s, r);
  634. CHECK_ERROR(e);
  635. if( debug )
  636. print_response(r);
  637. CHECK_RESPONSE(r);
  638. if( r->serial == serial )
  639. break;
  640. }
  641. printf("%" PRIu64 "\n", r->value);
  642. return 0;
  643. }
  644. int cmd_append(int argc, char** argv, yrmcds* s) {
  645. if( argc != 2 ) {
  646. fprintf(stderr, "Wrong number of arguments.\n");
  647. return 1;
  648. }
  649. const char* key = argv[0];
  650. char* data = NULL;
  651. size_t data_len = read_data(argv[1], &data);
  652. if( data == NULL ) {
  653. fprintf(stderr, "Failed to read data.\n");
  654. return 2;
  655. }
  656. yrmcds_response r[1];
  657. uint32_t serial;
  658. yrmcds_error e = yrmcds_append(s, key, strlen(key),
  659. data, data_len, quiet, &serial);
  660. free(data);
  661. CHECK_ERROR(e);
  662. if( quiet ) {
  663. e = yrmcds_noop(s, &serial);
  664. CHECK_ERROR(e);
  665. }
  666. if( debug )
  667. fprintf(stderr, "request serial = %u\n", serial);
  668. while( 1 ) {
  669. e = yrmcds_recv(s, r);
  670. CHECK_ERROR(e);
  671. if( debug )
  672. print_response(r);
  673. CHECK_RESPONSE(r);
  674. if( r->serial == serial )
  675. break;
  676. }
  677. return 0;
  678. }
  679. int cmd_prepend(int argc, char** argv, yrmcds* s) {
  680. if( argc != 2 ) {
  681. fprintf(stderr, "Wrong number of arguments.\n");
  682. return 1;
  683. }
  684. const char* key = argv[0];
  685. char* data = NULL;
  686. size_t data_len = read_data(argv[1], &data);
  687. if( data == NULL ) {
  688. fprintf(stderr, "Failed to read data.\n");
  689. return 2;
  690. }
  691. yrmcds_response r[1];
  692. uint32_t serial;
  693. yrmcds_error e = yrmcds_prepend(s, key, strlen(key),
  694. data, data_len, quiet, &serial);
  695. free(data);
  696. CHECK_ERROR(e);
  697. if( quiet ) {
  698. e = yrmcds_noop(s, &serial);
  699. CHECK_ERROR(e);
  700. }
  701. if( debug )
  702. fprintf(stderr, "request serial = %u\n", serial);
  703. while( 1 ) {
  704. e = yrmcds_recv(s, r);
  705. CHECK_ERROR(e);
  706. if( debug )
  707. print_response(r);
  708. CHECK_RESPONSE(r);
  709. if( r->serial == serial )
  710. break;
  711. }
  712. return 0;
  713. }
  714. int cmd_delete(int argc, char** argv, yrmcds* s) {
  715. if( argc != 1 ) {
  716. fprintf(stderr, "Wrong number of arguments.\n");
  717. return 1;
  718. }
  719. yrmcds_response r[1];
  720. uint32_t serial;
  721. yrmcds_error e = yrmcds_remove(s, argv[0], strlen(argv[0]), quiet, &serial);
  722. CHECK_ERROR(e);
  723. if( quiet ) {
  724. e = yrmcds_noop(s, &serial);
  725. CHECK_ERROR(e);
  726. }
  727. if( debug )
  728. fprintf(stderr, "request serial = %u\n", serial);
  729. while( 1 ) {
  730. e = yrmcds_recv(s, r);
  731. CHECK_ERROR(e);
  732. if( debug )
  733. print_response(r);
  734. CHECK_RESPONSE(r);
  735. if( r->serial == serial )
  736. break;
  737. }
  738. write_data(r);
  739. return 0;
  740. }
  741. int cmd_lock(int argc, char** argv, yrmcds* s) {
  742. if( argc != 1 ) {
  743. fprintf(stderr, "Wrong number of arguments.\n");
  744. return 1;
  745. }
  746. yrmcds_response r[1];
  747. uint32_t serial;
  748. yrmcds_error e = yrmcds_lock(s, argv[0], strlen(argv[0]), quiet, &serial);
  749. CHECK_ERROR(e);
  750. if( quiet ) {
  751. e = yrmcds_noop(s, &serial);
  752. CHECK_ERROR(e);
  753. }
  754. if( debug )
  755. fprintf(stderr, "request serial = %u\n", serial);
  756. while( 1 ) {
  757. e = yrmcds_recv(s, r);
  758. CHECK_ERROR(e);
  759. if( debug )
  760. print_response(r);
  761. CHECK_RESPONSE(r);
  762. if( r->serial == serial )
  763. break;
  764. }
  765. fprintf(stderr, "Press enter to unlock.\n");
  766. getchar();
  767. return 0;
  768. }
  769. int cmd_unlock(int argc, char** argv, yrmcds* s) {
  770. if( argc != 1 ) {
  771. fprintf(stderr, "Wrong number of arguments.\n");
  772. return 1;
  773. }
  774. yrmcds_response r[1];
  775. uint32_t serial;
  776. yrmcds_error e = yrmcds_unlock(s, argv[0], strlen(argv[0]), quiet, &serial);
  777. CHECK_ERROR(e);
  778. if( quiet ) {
  779. e = yrmcds_noop(s, &serial);
  780. CHECK_ERROR(e);
  781. }
  782. if( debug )
  783. fprintf(stderr, "request serial = %u\n", serial);
  784. while( 1 ) {
  785. e = yrmcds_recv(s, r);
  786. CHECK_ERROR(e);
  787. if( debug )
  788. print_response(r);
  789. CHECK_RESPONSE(r);
  790. if( r->serial == serial )
  791. break;
  792. }
  793. return 0;
  794. }
  795. int cmd_unlockall(int argc, char** argv, yrmcds* s) {
  796. yrmcds_response r[1];
  797. uint32_t serial;
  798. yrmcds_error e = yrmcds_unlockall(s, quiet, &serial);
  799. CHECK_ERROR(e);
  800. if( quiet ) {
  801. e = yrmcds_noop(s, &serial);
  802. CHECK_ERROR(e);
  803. }
  804. if( debug )
  805. fprintf(stderr, "request serial = %u\n", serial);
  806. while( 1 ) {
  807. e = yrmcds_recv(s, r);
  808. CHECK_ERROR(e);
  809. if( debug )
  810. print_response(r);
  811. CHECK_RESPONSE(r);
  812. if( r->serial == serial )
  813. break;
  814. }
  815. return 0;
  816. }
  817. int cmd_flush(int argc, char** argv, yrmcds* s) {
  818. uint32_t delay = 0;
  819. if( argc == 1 )
  820. delay = (uint32_t)strtoull(argv[0], NULL, 0);
  821. yrmcds_response r[1];
  822. uint32_t serial;
  823. yrmcds_error e = yrmcds_flush(s, delay, quiet, &serial);
  824. CHECK_ERROR(e);
  825. if( quiet ) {
  826. e = yrmcds_noop(s, &serial);
  827. CHECK_ERROR(e);
  828. }
  829. if( debug )
  830. fprintf(stderr, "request serial = %u\n", serial);
  831. while( 1 ) {
  832. e = yrmcds_recv(s, r);
  833. CHECK_ERROR(e);
  834. if( debug )
  835. print_response(r);
  836. CHECK_RESPONSE(r);
  837. if( r->serial == serial )
  838. break;
  839. }
  840. return 0;
  841. }
  842. int cmd_stat(int argc, char** argv, yrmcds* s) {
  843. yrmcds_response r[1];
  844. uint32_t serial;
  845. yrmcds_error e;
  846. if( argc > 0 ) {
  847. if( strcmp(argv[0], "settings") == 0 ) {
  848. e = yrmcds_stat_settings(s, &serial);
  849. } else if( strcmp(argv[0], "items") == 0 ) {
  850. e = yrmcds_stat_items(s, &serial);
  851. } else if( strcmp(argv[0], "sizes") == 0 ) {
  852. e = yrmcds_stat_sizes(s, &serial);
  853. } else {
  854. fprintf(stderr, "No such statistics.\n");
  855. return 1;
  856. }
  857. } else {
  858. e = yrmcds_stat_general(s, &serial);
  859. }
  860. CHECK_ERROR(e);
  861. while( 1 ) {
  862. e = yrmcds_recv(s, r);
  863. CHECK_ERROR(e);
  864. if( debug )
  865. print_response(r);
  866. CHECK_RESPONSE(r);
  867. if( r->key_len == 0 )
  868. break;
  869. if( r->data_len == 0 )
  870. continue;
  871. printf("%.*s: %.*s\n", (int)r->key_len, r->key,
  872. (int)r->data_len, r->data);
  873. }
  874. return 0;
  875. }
  876. int cmd_keys(int argc, char** argv, yrmcds* s) {
  877. const char* prefix = NULL;
  878. size_t prefix_len = 0;
  879. if( argc == 1 ) {
  880. prefix = argv[0];
  881. prefix_len = strlen(prefix);
  882. }
  883. yrmcds_response r[1];
  884. uint32_t serial;
  885. yrmcds_error e = yrmcds_keys(s, prefix, prefix_len, &serial);
  886. CHECK_ERROR(e);
  887. if( debug )
  888. fprintf(stderr, "request serial = %u\n", serial);
  889. while( 1 ) {
  890. e = yrmcds_recv(s, r);
  891. CHECK_ERROR(e);
  892. if( debug )
  893. print_response(r);
  894. CHECK_RESPONSE(r);
  895. if( r->serial != serial )
  896. continue;
  897. if( r->key_len == 0 )
  898. break;
  899. printf("%.*s\n", (int)r->key_len, r->key);
  900. }
  901. return 0;
  902. }
  903. int cmd_version(int argc, char** argv, yrmcds* s) {
  904. yrmcds_response r[1];
  905. uint32_t serial;
  906. yrmcds_error e = yrmcds_version(s, &serial);
  907. CHECK_ERROR(e);
  908. e = yrmcds_recv(s, r);
  909. CHECK_ERROR(e);
  910. if( debug )
  911. print_response(r);
  912. CHECK_RESPONSE(r);
  913. printf("%.*s\n", (int)r->data_len, r->data);
  914. return 0;
  915. }
  916. int cmd_quit(int argc, char** argv, yrmcds* s) {
  917. yrmcds_response r[1];
  918. uint32_t serial;
  919. yrmcds_error e = yrmcds_quit(s, quiet, &serial);
  920. CHECK_ERROR(e);
  921. if( debug )
  922. fprintf(stderr, "request serial = %u\n", serial);
  923. if( ! quiet ) {
  924. e = yrmcds_recv(s, r);
  925. CHECK_ERROR(e);
  926. if( debug )
  927. print_response(r);
  928. CHECK_RESPONSE(r);
  929. }
  930. return 0;
  931. }
  932. //int main(int argc, char** argv) {
  933. // const char* server = DEFAULT_SERVER;
  934. // uint16_t port = DEFAULT_PORT;
  935. // size_t compression = DEFAULT_COMPRESS;
  936. // int text_mode = 0;
  937. //
  938. // while( 1 ) {
  939. // int n;
  940. // int c = getopt(argc, argv, "s:p:c:dtqvh");
  941. // if( c == -1 ) break;
  942. // switch( c ) {
  943. // case 's':
  944. // server = optarg;
  945. // break;
  946. // case 'p':
  947. // n = atoi(optarg);
  948. // if( n <= 0 || n > 65535 ) {
  949. // fprintf(stderr, "Invalid TCP port.\n");
  950. // return 1;
  951. // }
  952. // port = (uint16_t)n;
  953. // break;
  954. // case 'c':
  955. // n = atoi(optarg);
  956. // if( n <= 0 ) {
  957. // fprintf(stderr, "Invalid compression thoreshold.\n");
  958. // return 1;
  959. // }
  960. // compression = (size_t)n;
  961. // break;
  962. // case 'd':
  963. // debug = 1;
  964. // break;
  965. // case 't':
  966. // text_mode = 1;
  967. // break;
  968. // case 'q':
  969. // quiet = 1;
  970. // break;
  971. // case 'v':
  972. // version();
  973. // return 0;
  974. // case 'h':
  975. // usage();
  976. // return 0;
  977. // default:
  978. // return 1;
  979. // }
  980. // }
  981. //
  982. // if( optind == argc ) {
  983. // usage();
  984. // return 0;
  985. // }
  986. //
  987. // const char* cmd = argv[optind];
  988. // argc -= optind + 1;
  989. // argv += optind + 1;
  990. //
  991. // yrmcds s[1];
  992. // yrmcds_error e = yrmcds_connect(s, server, port);
  993. // CHECK_ERROR(e);
  994. // if( text_mode ) {
  995. // e = yrmcds_text_mode(s);
  996. // CHECK_ERROR(e);
  997. // }
  998. // e = yrmcds_set_compression(s, compression);
  999. // if( e != 0 && e != YRMCDS_NOT_IMPLEMENTED ) {
  1000. // yrmcds_close(s);
  1001. // CHECK_ERROR(e);
  1002. // }
  1003. //
  1004. // int ret = 1;
  1005. //#define do_cmd(name) \
  1006. // if( strcmp(cmd, #name) == 0 ) { \
  1007. // ret = cmd_##name(argc, argv, s); \
  1008. // goto OUT; \
  1009. // }
  1010. //
  1011. // do_cmd(noop);
  1012. // do_cmd(get);
  1013. // do_cmd(getk);
  1014. // do_cmd(gat);
  1015. // do_cmd(gatk);
  1016. // do_cmd(lag);
  1017. // do_cmd(lagk);
  1018. // do_cmd(touch);
  1019. // do_cmd(set);
  1020. // do_cmd(replace);
  1021. // do_cmd(add);
  1022. // do_cmd(rau);
  1023. // do_cmd(incr);
  1024. // do_cmd(decr);
  1025. // do_cmd(append);
  1026. // do_cmd(prepend);
  1027. // do_cmd(delete);
  1028. // do_cmd(lock);
  1029. // do_cmd(unlock);
  1030. // do_cmd(unlockall);
  1031. // do_cmd(flush);
  1032. // do_cmd(stat);
  1033. // do_cmd(keys);
  1034. // do_cmd(version);
  1035. // do_cmd(quit);
  1036. //
  1037. // fprintf(stderr, "No such command: %s\n", cmd);
  1038. //
  1039. // OUT:
  1040. // yrmcds_close(s);
  1041. // return ret;
  1042. //}