1
2 // vim:ai:sw=2:ts=8
3
4 /*
5 * Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
6 * See COPYRIGHT.txt for details.
7 */
8
9 #include "EXTERN.h"
10 #include "perl.h"
11 #include "XSUB.h"
12
13 #include "ppport.h"
14
15 #include "hstcpcli.hpp"
16
17 #define DBG(x)
18
19 static SV *
arr_get_entry(AV * av,I32 avmax,I32 idx)20 arr_get_entry(AV *av, I32 avmax, I32 idx)
21 {
22 if (idx > avmax) {
23 DBG(fprintf(stderr, "arr_get_entry1 %d %d\n", avmax, idx));
24 return 0;
25 }
26 SV **const ev = av_fetch(av, idx, 0);
27 if (ev == 0) {
28 DBG(fprintf(stderr, "arr_get_entry2 %d %d\n", avmax, idx));
29 return 0;
30 }
31 return *ev;
32 }
33
34 static int
35 arr_get_intval(AV *av, I32 avmax, I32 idx, int default_val = 0)
36 {
37 SV *const e = arr_get_entry(av, avmax, idx);
38 if (e == 0) {
39 return default_val;
40 }
41 return SvIV(e);
42 }
43
44 static const char *
sv_get_strval(SV * sv)45 sv_get_strval(SV *sv)
46 {
47 if (sv == 0 || !SvPOK(sv)) {
48 DBG(fprintf(stderr, "sv_get_strval\n"));
49 return 0;
50 }
51 return SvPV_nolen(sv);
52 }
53
54 static const char *
arr_get_strval(AV * av,I32 avmax,I32 idx)55 arr_get_strval(AV *av, I32 avmax, I32 idx)
56 {
57 SV *const e = arr_get_entry(av, avmax, idx);
58 return sv_get_strval(e);
59 }
60
61 static AV *
sv_get_arrval(SV * sv)62 sv_get_arrval(SV *sv)
63 {
64 if (sv == 0 || !SvROK(sv)) {
65 DBG(fprintf(stderr, "sv_get_arrval1\n"));
66 return 0;
67 }
68 SV *const svtarget = SvRV(sv);
69 if (svtarget == 0 || SvTYPE(svtarget) != SVt_PVAV) {
70 DBG(fprintf(stderr, "sv_get_arrval2\n"));
71 return 0;
72 }
73 return (AV *)svtarget;
74 }
75
76 static AV *
arr_get_arrval(AV * av,I32 avmax,I32 idx)77 arr_get_arrval(AV *av, I32 avmax, I32 idx)
78 {
79 SV *const e = arr_get_entry(av, avmax, idx);
80 if (e == 0) {
81 DBG(fprintf(stderr, "arr_get_arrval1\n"));
82 return 0;
83 }
84 return sv_get_arrval(e);
85 }
86
87 static void
hv_to_strmap(HV * hv,std::map<std::string,std::string> & m_r)88 hv_to_strmap(HV *hv, std::map<std::string, std::string>& m_r)
89 {
90 if (hv == 0) {
91 return;
92 }
93 hv_iterinit(hv);
94 HE *hent = 0;
95 while ((hent = hv_iternext(hv)) != 0) {
96 I32 klen = 0;
97 char *const k = hv_iterkey(hent, &klen);
98 DBG(fprintf(stderr, "k=%s\n", k));
99 const std::string key(k, klen);
100 SV *const vsv = hv_iterval(hv, hent);
101 STRLEN vlen = 0;
102 char *const v = SvPV(vsv, vlen);
103 DBG(fprintf(stderr, "v=%s\n", v));
104 const std::string val(v, vlen);
105 m_r[key] = val;
106 }
107 }
108
109 static void
strrefarr_push_back(std::vector<dena::string_ref> & a_r,SV * sv)110 strrefarr_push_back(std::vector<dena::string_ref>& a_r, SV *sv)
111 {
112 if (sv == 0 || SvTYPE(sv) == SVt_NULL) { /* !SvPOK()? */
113 DBG(fprintf(stderr, "strrefarr_push_back: null\n"));
114 return a_r.push_back(dena::string_ref());
115 }
116 STRLEN vlen = 0;
117 char *const v = SvPV(sv, vlen);
118 DBG(fprintf(stderr, "strrefarr_push_back: %s\n", v));
119 a_r.push_back(dena::string_ref(v, vlen));
120 }
121
122 static void
av_to_strrefarr(AV * av,std::vector<dena::string_ref> & a_r)123 av_to_strrefarr(AV *av, std::vector<dena::string_ref>& a_r)
124 {
125 if (av == 0) {
126 return;
127 }
128 const I32 len = av_len(av) + 1;
129 for (I32 i = 0; i < len; ++i) {
130 SV **const ev = av_fetch(av, i, 0);
131 strrefarr_push_back(a_r, ev ? *ev : 0);
132 }
133 }
134
135 static dena::string_ref
sv_get_string_ref(SV * sv)136 sv_get_string_ref(SV *sv)
137 {
138 if (sv == 0 || SvTYPE(sv) == SVt_NULL) { /* !SvPOK()? */
139 return dena::string_ref();
140 }
141 STRLEN vlen = 0;
142 char *const v = SvPV(sv, vlen);
143 return dena::string_ref(v, vlen);
144 }
145
146 static IV
sv_get_iv(SV * sv)147 sv_get_iv(SV *sv)
148 {
149 if (sv == 0 || ( !SvIOK(sv) && !SvPOK(sv) ) ) {
150 return 0;
151 }
152 return SvIV(sv);
153 }
154
155 static void
av_to_filters(AV * av,std::vector<dena::hstcpcli_filter> & f_r)156 av_to_filters(AV *av, std::vector<dena::hstcpcli_filter>& f_r)
157 {
158 DBG(fprintf(stderr, "av_to_filters: %p\n", av));
159 if (av == 0) {
160 return;
161 }
162 const I32 len = av_len(av) + 1;
163 DBG(fprintf(stderr, "av_to_filters: len=%d\n", (int)len));
164 for (I32 i = 0; i < len; ++i) {
165 AV *const earr = arr_get_arrval(av, len, i);
166 if (earr == 0) {
167 continue;
168 }
169 const I32 earrlen = av_len(earr) + 1;
170 dena::hstcpcli_filter fe;
171 fe.filter_type = sv_get_string_ref(arr_get_entry(earr, earrlen, 0));
172 fe.op = sv_get_string_ref(arr_get_entry(earr, earrlen, 1));
173 fe.ff_offset = sv_get_iv(arr_get_entry(earr, earrlen, 2));
174 fe.val = sv_get_string_ref(arr_get_entry(earr, earrlen, 3));
175 f_r.push_back(fe);
176 DBG(fprintf(stderr, "av_to_filters: %s %s %d %s\n",
177 fe.filter_action.begin(), fe.filter_op.begin(), (int)fe.ff_offset,
178 fe.value.begin()));
179 }
180 }
181
182 static void
set_process_verbose_level(const std::map<std::string,std::string> & m)183 set_process_verbose_level(const std::map<std::string, std::string>& m)
184 {
185 std::map<std::string, std::string>::const_iterator iter = m.find("verbose");
186 if (iter != m.end()) {
187 dena::verbose_level = atoi(iter->second.c_str());
188 }
189 }
190
191 static AV *
execute_internal(SV * obj,int id,const char * op,AV * keys,int limit,int skip,const char * modop,AV * modvals,AV * filters,int invalues_keypart,AV * invalues)192 execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
193 int skip, const char *modop, AV *modvals, AV *filters, int invalues_keypart,
194 AV *invalues)
195 {
196 AV *retval = (AV *)&PL_sv_undef;
197 dena::hstcpcli_i *const ptr =
198 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
199 do {
200 std::vector<dena::string_ref> keyarr, mvarr;
201 std::vector<dena::hstcpcli_filter> farr;
202 std::vector<dena::string_ref> ivs;
203 av_to_strrefarr(keys, keyarr);
204 dena::string_ref modop_ref;
205 if (modop != 0) {
206 modop_ref = dena::string_ref(modop, strlen(modop));
207 av_to_strrefarr(modvals, mvarr);
208 }
209 if (filters != 0) {
210 av_to_filters(filters, farr);
211 }
212 if (invalues_keypart >= 0 && invalues != 0) {
213 av_to_strrefarr(invalues, ivs);
214 }
215 ptr->request_buf_exec_generic(id, dena::string_ref(op, strlen(op)),
216 &keyarr[0], keyarr.size(), limit, skip, modop_ref, &mvarr[0],
217 mvarr.size(), &farr[0], farr.size(), invalues_keypart, &ivs[0],
218 ivs.size());
219 AV *const av = newAV();
220 retval = av;
221 if (ptr->request_send() != 0) {
222 break;
223 }
224 size_t nflds = 0;
225 ptr->response_recv(nflds);
226 const int e = ptr->get_error_code();
227 DBG(fprintf(stderr, "e=%d nflds=%zu\n", e, nflds));
228 av_push(av, newSViv(e));
229 if (e != 0) {
230 const std::string s = ptr->get_error();
231 av_push(av, newSVpvn(s.data(), s.size()));
232 } else {
233 const dena::string_ref *row = 0;
234 while ((row = ptr->get_next_row()) != 0) {
235 DBG(fprintf(stderr, "row=%p\n", row));
236 for (size_t i = 0; i < nflds; ++i) {
237 const dena::string_ref& v = row[i];
238 DBG(fprintf(stderr, "FLD %zu v=%s vbegin=%p\n", i,
239 std::string(v.begin(), v.size())
240 .c_str(), v.begin()));
241 if (v.begin() != 0) {
242 SV *const e = newSVpvn(
243 v.begin(), v.size());
244 av_push(av, e);
245 } else {
246 av_push(av, &PL_sv_undef);
247 }
248 }
249 }
250 }
251 if (e >= 0) {
252 ptr->response_buf_remove();
253 }
254 } while (0);
255 return retval;
256 }
257
258 struct execute_arg {
259 int id;
260 const char *op;
261 AV *keys;
262 int limit;
263 int skip;
264 const char *modop;
265 AV *modvals;
266 AV *filters;
267 int invalues_keypart;
268 AV *invalues;
execute_argexecute_arg269 execute_arg() : id(0), op(0), keys(0), limit(0), skip(0), modop(0),
270 modvals(0), filters(0), invalues_keypart(-1), invalues(0) { }
271 };
272
273 static AV *
execute_multi_internal(SV * obj,const execute_arg * args,size_t num_args)274 execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args)
275 {
276 dena::hstcpcli_i *const ptr =
277 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
278 /* appends multiple requests to the send buffer */
279 for (size_t i = 0; i < num_args; ++i) {
280 std::vector<dena::string_ref> keyarr, mvarr;
281 std::vector<dena::hstcpcli_filter> farr;
282 std::vector<dena::string_ref> ivs;
283 const execute_arg& arg = args[i];
284 av_to_strrefarr(arg.keys, keyarr);
285 dena::string_ref modop_ref;
286 if (arg.modop != 0) {
287 modop_ref = dena::string_ref(arg.modop, strlen(arg.modop));
288 av_to_strrefarr(arg.modvals, mvarr);
289 }
290 if (arg.filters != 0) {
291 av_to_filters(arg.filters, farr);
292 }
293 if (arg.invalues_keypart >= 0 && arg.invalues != 0) {
294 av_to_strrefarr(arg.invalues, ivs);
295 }
296 ptr->request_buf_exec_generic(arg.id,
297 dena::string_ref(arg.op, strlen(arg.op)), &keyarr[0], keyarr.size(),
298 arg.limit, arg.skip, modop_ref, &mvarr[0], mvarr.size(), &farr[0],
299 farr.size(), arg.invalues_keypart, &ivs[0], ivs.size());
300 }
301 AV *const retval = newAV();
302 /* sends the requests */
303 if (ptr->request_send() < 0) {
304 /* IO error */
305 AV *const av_respent = newAV();
306 av_push(retval, newRV_noinc((SV *)av_respent));
307 av_push(av_respent, newSViv(ptr->get_error_code()));
308 const std::string& s = ptr->get_error();
309 av_push(av_respent, newSVpvn(s.data(), s.size()));
310 return retval; /* retval : [ [ err_code, err_message ] ] */
311 }
312 /* receives responses */
313 for (size_t i = 0; i < num_args; ++i) {
314 AV *const av_respent = newAV();
315 av_push(retval, newRV_noinc((SV *)av_respent));
316 size_t nflds = 0;
317 const int e = ptr->response_recv(nflds);
318 av_push(av_respent, newSViv(e));
319 if (e != 0) {
320 const std::string& s = ptr->get_error();
321 av_push(av_respent, newSVpvn(s.data(), s.size()));
322 } else {
323 const dena::string_ref *row = 0;
324 while ((row = ptr->get_next_row()) != 0) {
325 for (size_t i = 0; i < nflds; ++i) {
326 const dena::string_ref& v = row[i];
327 DBG(fprintf(stderr, "%zu %s\n", i,
328 std::string(v.begin(), v.size()).c_str()));
329 if (v.begin() != 0) {
330 av_push(av_respent, newSVpvn(v.begin(), v.size()));
331 } else {
332 /* null */
333 av_push(av_respent, &PL_sv_undef);
334 }
335 }
336 }
337 }
338 if (e >= 0) {
339 ptr->response_buf_remove();
340 }
341 if (e < 0) {
342 return retval;
343 }
344 }
345 return retval;
346 }
347
348 MODULE = Net::HandlerSocket PACKAGE = Net::HandlerSocket
349
350 SV *
351 new(klass, args)
352 char *klass
353 HV *args
354 CODE:
355 RETVAL = &PL_sv_undef;
356 dena::config conf;
357 hv_to_strmap(args, conf);
358 set_process_verbose_level(conf);
359 dena::socket_args sargs;
360 sargs.set(conf);
361 dena::hstcpcli_ptr p = dena::hstcpcli_i::create(sargs);
362 SV *const objref = newSViv(0);
363 SV *const obj = newSVrv(objref, klass);
364 dena::hstcpcli_i *const ptr = p.get();
365 sv_setiv(obj, reinterpret_cast<IV>(ptr));
366 p.release();
367 SvREADONLY_on(obj);
368 RETVAL = objref;
369 OUTPUT:
370 RETVAL
371
372 void
373 DESTROY(obj)
374 SV *obj
375 CODE:
376 dena::hstcpcli_i *const ptr =
377 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
378 delete ptr;
379
380 void
381 close(obj)
382 SV *obj
383 CODE:
384 dena::hstcpcli_i *const ptr =
385 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
386 ptr->close();
387
388 int
389 reconnect(obj)
390 SV *obj
391 CODE:
392 RETVAL = 0;
393 dena::hstcpcli_i *const ptr =
394 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
395 RETVAL = ptr->reconnect();
396 OUTPUT:
397 RETVAL
398
399 int
400 stable_point(obj)
401 SV *obj
402 CODE:
403 RETVAL = 0;
404 dena::hstcpcli_i *const ptr =
405 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
406 const bool rv = ptr->stable_point();
407 RETVAL = static_cast<int>(rv);
408 OUTPUT:
409 RETVAL
410
411 int
412 get_error_code(obj)
413 SV *obj
414 CODE:
415 RETVAL = 0;
416 dena::hstcpcli_i *const ptr =
417 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
418 RETVAL = ptr->get_error_code();
419 OUTPUT:
420 RETVAL
421
422 SV *
423 get_error(obj)
424 SV *obj
425 CODE:
426 RETVAL = &PL_sv_undef;
427 dena::hstcpcli_i *const ptr =
428 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
429 const std::string s = ptr->get_error();
430 RETVAL = newSVpvn(s.data(), s.size());
431 OUTPUT:
432 RETVAL
433
434 int
435 auth(obj, key, typ = 0)
436 SV *obj
437 const char *key
438 const char *typ
439 CODE:
440 RETVAL = 0;
441 dena::hstcpcli_i *const ptr =
442 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
443 do {
444 ptr->request_buf_auth(key, typ);
445 if (ptr->request_send() != 0) {
446 break;
447 }
448 size_t nflds = 0;
449 ptr->response_recv(nflds);
450 const int e = ptr->get_error_code();
451 DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
452 if (e >= 0) {
453 ptr->response_buf_remove();
454 }
455 DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
456 } while (0);
457 RETVAL = ptr->get_error_code();
458 OUTPUT:
459 RETVAL
460
461
462 int
463 open_index(obj, id, db, table, index, fields, ffields = 0)
464 SV *obj
465 int id
466 const char *db
467 const char *table
468 const char *index
469 const char *fields
470 SV *ffields
471 CODE:
472 const char *const ffields_str = sv_get_strval(ffields);
473 RETVAL = 0;
474 dena::hstcpcli_i *const ptr =
475 reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
476 do {
477 ptr->request_buf_open_index(id, db, table, index, fields, ffields_str);
478 if (ptr->request_send() != 0) {
479 break;
480 }
481 size_t nflds = 0;
482 ptr->response_recv(nflds);
483 const int e = ptr->get_error_code();
484 DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
485 if (e >= 0) {
486 ptr->response_buf_remove();
487 }
488 DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
489 } while (0);
490 RETVAL = ptr->get_error_code();
491 OUTPUT:
492 RETVAL
493
494 AV *
495 execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0, ivkeypart = -1, ivs = 0)
496 SV *obj
497 int id
498 const char *op
499 AV *keys
500 int limit
501 int skip
502 SV *mop
503 SV *mvs
504 SV *fils
505 int ivkeypart
506 SV *ivs
507 CODE:
508 const char *const mop_str = sv_get_strval(mop);
509 AV *const mvs_av = sv_get_arrval(mvs);
510 AV *const fils_av = sv_get_arrval(fils);
511 AV *const ivs_av = sv_get_arrval(ivs);
512 RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
513 fils_av, ivkeypart, ivs_av);
514 sv_2mortal((SV *)RETVAL);
515 OUTPUT:
516 RETVAL
517
518 AV *
519 execute_multi(obj, cmds)
520 SV *obj
521 AV *cmds
522 CODE:
523 DBG(fprintf(stderr, "execute_multi0\n"));
524 const I32 cmdsmax = av_len(cmds);
525 execute_arg args[cmdsmax + 1]; /* GNU */
526 for (I32 i = 0; i <= cmdsmax; ++i) {
527 AV *const avtarget = arr_get_arrval(cmds, cmdsmax, i);
528 if (avtarget == 0) {
529 DBG(fprintf(stderr, "execute_multi1 %d\n", i));
530 continue;
531 }
532 const I32 argmax = av_len(avtarget);
533 if (argmax < 2) {
534 DBG(fprintf(stderr, "execute_multi2 %d\n", i));
535 continue;
536 }
537 execute_arg& ag = args[i];
538 ag.id = arr_get_intval(avtarget, argmax, 0);
539 ag.op = arr_get_strval(avtarget, argmax, 1);
540 ag.keys = arr_get_arrval(avtarget, argmax, 2);
541 ag.limit = arr_get_intval(avtarget, argmax, 3);
542 ag.skip = arr_get_intval(avtarget, argmax, 4);
543 ag.modop = arr_get_strval(avtarget, argmax, 5);
544 ag.modvals = arr_get_arrval(avtarget, argmax, 6);
545 ag.filters = arr_get_arrval(avtarget, argmax, 7);
546 ag.invalues_keypart = arr_get_intval(avtarget, argmax, 8, -1);
547 ag.invalues = arr_get_arrval(avtarget, argmax, 9);
548 DBG(fprintf(stderr, "execute_multi3 %d: %d %s %p %d %d %s %p %p %d %p\n",
549 i, ag.id, ag.op, ag.keys, ag.limit, ag.skip, ag.modop, ag.modvals,
550 ag.filters, ag.invalues_keypart, ag.invalues));
551 }
552 RETVAL = execute_multi_internal(obj, args, cmdsmax + 1);
553 sv_2mortal((SV *)RETVAL);
554 OUTPUT:
555 RETVAL
556
557 AV *
558 execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0, ivkeypart = -1, ivs = 0)
559 SV *obj
560 int id
561 const char *op
562 AV *keys
563 int limit
564 int skip
565 SV *mop
566 SV *mvs
567 SV *fils
568 int ivkeypart
569 SV *ivs
570 CODE:
571 const char *const mop_str = sv_get_strval(mop);
572 AV *const mvs_av = sv_get_arrval(mvs);
573 AV *const fils_av = sv_get_arrval(fils);
574 AV *const ivs_av = sv_get_arrval(ivs);
575 RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
576 fils_av, ivkeypart, ivs_av);
577 sv_2mortal((SV *)RETVAL);
578 OUTPUT:
579 RETVAL
580
581 AV *
582 execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0, ivkeypart = -1, ivs = 0)
583 SV *obj
584 int id
585 const char *op
586 AV *keys
587 int limit
588 int skip
589 AV *modvals
590 SV *fils
591 int ivkeypart
592 SV *ivs
593 CODE:
594 AV *const fils_av = sv_get_arrval(fils);
595 AV *const ivs_av = sv_get_arrval(ivs);
596 RETVAL = execute_internal(obj, id, op, keys, limit, skip, "U",
597 modvals, fils_av, ivkeypart, ivs_av);
598 sv_2mortal((SV *)RETVAL);
599 OUTPUT:
600 RETVAL
601
602 AV *
603 execute_delete(obj, id, op, keys, limit, skip, fils = 0, ivkeypart = -1, ivs = 0)
604 SV *obj
605 int id
606 const char *op
607 AV *keys
608 int limit
609 int skip
610 SV *fils
611 int ivkeypart
612 SV *ivs
613 CODE:
614 AV *const fils_av = sv_get_arrval(fils);
615 AV *const ivs_av = sv_get_arrval(ivs);
616 RETVAL = execute_internal(obj, id, op, keys, limit, skip, "D", 0, fils_av,
617 ivkeypart, ivs_av);
618 sv_2mortal((SV *)RETVAL);
619 OUTPUT:
620 RETVAL
621
622 AV *
623 execute_insert(obj, id, fvals)
624 SV *obj
625 int id
626 AV *fvals
627 CODE:
628 RETVAL = execute_internal(obj, id, "+", fvals, 0, 0, 0, 0, 0, -1, 0);
629 sv_2mortal((SV *)RETVAL);
630 OUTPUT:
631 RETVAL
632
633