Merge lp:~posulliv/libmemcached/c++-interface into lp:~tangent-org/libmemcached/trunk

Proposed by Padraig O'Sullivan
Status: Merged
Merged at revision: not available
Proposed branch: lp:~posulliv/libmemcached/c++-interface
Merge into: lp:~tangent-org/libmemcached/trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~posulliv/libmemcached/c++-interface
Reviewer Review Type Date Requested Status
Libmemcached-developers Pending
Review via email: mp+8617@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Padraig O'Sullivan (posulliv) wrote :

So I was thinking that when we actually port the memcached UDF's to Drizzle, we should use the libmemcached C++ interface since Drizzle is a C++ project. Thus, to enable that, I did some refactoring of the libmemcached C++ interface wrapper.

Basically, all I did was the following:

* replace parameters as char * with references to std::string
* use std::vector in places where arrays of pointers were being passed
* modified the return types of numerous API function to be bool instead of memcached_return
* added more test cases to the C++ API test file

I'm just proposing this for merging to get some feedback on the approach I've taken. I can easily keep the existing interface by just overloading those API functions if that is wanted.

-Padraig

Revision history for this message
Brian Aker (brianaker) wrote :

Thanks!

This is a huge improvement over the current interface (which I am sure no one is using).

Revision history for this message
Brian Aker (brianaker) wrote :

Looking through the code.. mget() going to be quite slow I suspect because of the memory allocation that will be done because of it.

I modified mget() to not do a malloc, and instead use a vector for the key sizes.

I suspect we could look at the lower level interfaces and find a way of getting the advantages of mget() without doing the vector overhead. Probably just a matter of flipping the bit for pipelining requests and sending down directly the bits from the std:string.

Code is now in trunk.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libmemcached/memcached.hh'
2--- libmemcached/memcached.hh 2009-07-07 21:57:24 +0000
3+++ libmemcached/memcached.hh 2009-07-11 19:10:39 +0000
4@@ -1,175 +1,354 @@
5-#include "libmemcached/memcached.h"
6-#include <string.h>
7-#include <stdio.h>
8+#include <libmemcached/memcached.h>
9+
10+#include <string>
11+#include <vector>
12
13 class Memcached
14 {
15- memcached_st memc;
16- memcached_result_st result;
17-
18 public:
19
20- Memcached() : memc(), result()
21+ Memcached()
22+ :
23+ memc(),
24+ result()
25 {
26 memcached_create(&memc);
27 }
28
29- Memcached(memcached_st *clone) : memc(), result()
30+ Memcached(memcached_st *clone)
31+ :
32+ memc(),
33+ result()
34 {
35 memcached_clone(&memc, clone);
36 }
37- char *fetch (char *key, size_t *key_length, size_t *value_length)
38- {
39- uint32_t flags;
40- memcached_return rc;
41-
42- return memcached_fetch(&memc, key, key_length,
43- value_length, &flags, &rc);
44- }
45- char *get(const char *key, size_t *value_length)
46- {
47- uint32_t flags;
48- memcached_return rc;
49-
50- return memcached_get(&memc, key, strlen(key),
51- value_length, &flags, &rc);
52- }
53-
54- char *get_by_key(const char *master_key, const char *key,
55- size_t *value_length)
56- {
57- uint32_t flags;
58- memcached_return rc;
59-
60- return memcached_get_by_key(&memc, master_key, strlen(master_key),
61- key, strlen(key),
62- value_length, &flags, &rc);
63- }
64-
65- memcached_return mget(char **keys, size_t *key_length,
66- unsigned int number_of_keys)
67- {
68-
69- return memcached_mget(&memc, keys, key_length, number_of_keys);
70- }
71-
72- memcached_return set(const char *key, const char *value, size_t value_length)
73- {
74- return memcached_set(&memc, key, strlen(key),
75- value, value_length,
76- time_t(0), uint32_t(0));
77- }
78-
79- memcached_return set_by_key(const char *master_key, const char *key,
80- const char *value, size_t value_length)
81- {
82- return memcached_set_by_key(&memc, master_key, strlen(master_key),
83- key, strlen(key),
84- value, value_length,
85- time_t(0),
86- uint32_t(0) );
87- }
88- memcached_return
89- increment(const char *key, unsigned int offset, uint64_t *value)
90- {
91- return memcached_increment(&memc, key, strlen(key),
92- offset, value);
93- }
94- memcached_return
95- decrement(const char *key, unsigned int offset, uint64_t *value)
96- {
97- return memcached_decrement(&memc, key, strlen(key),
98- offset, value);
99- }
100-
101-
102- memcached_return add(const char *key, const char *value, size_t value_length)
103- {
104- return memcached_add(&memc, key, strlen(key), value, value_length, 0, 0);
105- }
106- memcached_return add_by_key(const char *master_key, const char *key,
107- const char *value, size_t value_length)
108- {
109- return memcached_add_by_key(&memc, master_key, strlen(master_key),
110- key, strlen(key),
111- value, value_length,
112- 0, 0);
113- }
114-
115- memcached_return replace(const char *key, const char *value,
116- size_t value_length)
117- {
118- return memcached_replace(&memc, key, strlen(key),
119- value, value_length,
120- 0, 0);
121- }
122- memcached_return replace_by_key(const char *master_key, const char *key,
123- const char *value, size_t value_length)
124- {
125- return memcached_replace_by_key(&memc, master_key, strlen(master_key),
126- key, strlen(key),
127- value, value_length, 0, 0);
128- }
129-
130- memcached_return prepend(const char *key, const char *value,
131- size_t value_length)
132- {
133- return memcached_prepend(&memc, key, strlen(key),
134- value, value_length, 0, 0);
135- }
136- memcached_return prepend_by_key(const char *master_key, const char *key,
137- const char *value, size_t value_length)
138- {
139- return memcached_prepend_by_key(&memc, master_key, strlen(master_key),
140- key, strlen(key),
141- value, value_length,
142- 0,
143- 0);
144- }
145-
146- memcached_return append(const char *key, const char *value,
147- size_t value_length)
148- {
149- return memcached_append(&memc, key, strlen(key),
150- value, value_length, 0, 0);
151- }
152- memcached_return append_by_key(const char *master_key, const char *key,
153- const char *value, size_t value_length)
154- {
155- return memcached_append_by_key(&memc,
156- master_key, strlen(master_key),
157- key, strlen(key),
158- value, value_length, 0, 0);
159- }
160- memcached_return cas(const char *key, const char *value,
161- size_t value_length, uint64_t cas_arg)
162- {
163- return memcached_cas(&memc, key, strlen(key),
164- value, value_length, 0, 0, cas_arg);
165- }
166- memcached_return cas_by_key(const char *master_key, const char *key,
167- const char *value, size_t value_length,
168- uint64_t cas_arg)
169- {
170- return memcached_cas_by_key(&memc,
171- master_key, strlen(master_key),
172- key, strlen(key),
173- value, value_length,
174- 0, 0, cas_arg);
175- }
176- // using 'remove' vs. 'delete' since 'delete' is a keyword
177- memcached_return remove(const char *key)
178- {
179- return memcached_delete (&memc, key, strlen(key), 0);
180-
181- }
182- memcached_return delete_by_key(const char *master_key, const char *key)
183- {
184- return memcached_delete_by_key(&memc, master_key, strlen(master_key),
185- key, strlen(key), 0);
186- }
187+
188 ~Memcached()
189 {
190 memcached_free(&memc);
191 }
192+
193+ bool fetch(std::string &key,
194+ std::string &ret_val,
195+ size_t *key_length,
196+ size_t *value_length,
197+ uint32_t *flags,
198+ memcached_return *rc)
199+ {
200+ char ret_key[MEMCACHED_MAX_KEY];
201+ char *value= memcached_fetch(&memc, ret_key, key_length,
202+ value_length, flags, rc);
203+ if (value)
204+ {
205+ ret_val.assign(value);
206+ key.assign(ret_key);
207+ return true;
208+ }
209+ return false;
210+ }
211+
212+ std::string get(const std::string &key, size_t *value_length)
213+ {
214+ uint32_t flags;
215+ memcached_return rc;
216+ std::string ret_val;
217+
218+ char *value= memcached_get(&memc, key.c_str(), key.length(),
219+ value_length, &flags, &rc);
220+ if (value)
221+ {
222+ ret_val.assign(value);
223+ }
224+ return ret_val;
225+ }
226+
227+ std::string get_by_key(const std::string &master_key,
228+ const std::string &key,
229+ size_t *value_length)
230+ {
231+ uint32_t flags;
232+ memcached_return rc;
233+ std::string ret_val;
234+
235+ char *value= memcached_get_by_key(&memc, master_key.c_str(), master_key.length(),
236+ key.c_str(), key.length(),
237+ value_length, &flags, &rc);
238+ if (value)
239+ {
240+ ret_val.assign(value);
241+ }
242+ return ret_val;
243+ }
244+
245+ bool mget(std::vector<std::string> &keys)
246+ {
247+ /*
248+ * Construct an array which will contain the length
249+ * of each of the strings in the input vector. Also, to
250+ * interface with the memcached C API, we need to convert
251+ * the vector of std::string's to a vector of char *.
252+ */
253+ size_t *key_len= static_cast<size_t *>(malloc(keys.size() * sizeof(size_t)));
254+ if (key_len == NULL)
255+ {
256+ return false;
257+ }
258+ std::vector<char *> real_keys;
259+ std::vector<std::string>::iterator it= keys.begin();
260+ int i= 0;
261+ while (it != keys.end())
262+ {
263+ real_keys.push_back(const_cast<char *>((*it).c_str()));
264+ key_len[i++]= (*it).length();
265+ ++it;
266+ }
267+
268+ /*
269+ * If the std::vector of keys is empty then we cannot
270+ * call memcached_mget as we will get undefined behavior.
271+ */
272+ if (!real_keys.empty())
273+ {
274+ memcached_return rc= memcached_mget(&memc, &real_keys[0], key_len,
275+ static_cast<unsigned int>(real_keys.size()));
276+ return (rc == MEMCACHED_SUCCESS);
277+ }
278+
279+ return false;
280+ }
281+
282+ bool set(const std::string &key,
283+ const std::string &value,
284+ time_t expiration,
285+ uint32_t flags)
286+ {
287+ memcached_return rc= memcached_set(&memc,
288+ key.c_str(), key.length(),
289+ value.c_str(), value.length(),
290+ expiration, flags);
291+ return (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
292+ }
293+
294+ bool set_all(std::vector<std::string> &keys,
295+ std::vector<std::string> &values,
296+ time_t expiration,
297+ uint32_t flags)
298+ {
299+ if (keys.size() != values.size())
300+ {
301+ return false;
302+ }
303+ bool retval= true;
304+ std::vector<std::string>::iterator key_it= keys.begin();
305+ std::vector<std::string>::iterator val_it= values.begin();
306+ while (key_it != keys.end())
307+ {
308+ retval= set((*key_it), (*val_it), expiration, flags);
309+ if (retval == false)
310+ {
311+ return retval;
312+ }
313+ ++key_it;
314+ ++val_it;
315+ }
316+ return retval;
317+ }
318+
319+ bool set_by_key(const std::string &master_key,
320+ const std::string &key,
321+ const std::string &value,
322+ time_t expiration,
323+ uint32_t flags)
324+ {
325+ memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
326+ master_key.length(),
327+ key.c_str(), key.length(),
328+ value.c_str(), value.length(),
329+ expiration,
330+ flags);
331+ return (rc == MEMCACHED_SUCCESS);
332+ }
333+
334+ bool increment(const std::string &key, unsigned int offset, uint64_t *value)
335+ {
336+ memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(),
337+ offset, value);
338+ return (rc == MEMCACHED_SUCCESS);
339+ }
340+
341+ bool decrement(const std::string &key, unsigned int offset, uint64_t *value)
342+ {
343+ memcached_return rc= memcached_decrement(&memc, key.c_str(),
344+ key.length(),
345+ offset, value);
346+ return (rc == MEMCACHED_SUCCESS);
347+ }
348+
349+
350+ bool add(const std::string &key, const std::string &value)
351+ {
352+ memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
353+ value.c_str(), value.length(), 0, 0);
354+ return (rc == MEMCACHED_SUCCESS);
355+ }
356+
357+ bool add_by_key(const std::string &master_key,
358+ const std::string &key,
359+ const std::string &value)
360+ {
361+ memcached_return rc= memcached_add_by_key(&memc,
362+ master_key.c_str(),
363+ master_key.length(),
364+ key.c_str(),
365+ key.length(),
366+ value.c_str(),
367+ value.length(),
368+ 0, 0);
369+ return (rc == MEMCACHED_SUCCESS);
370+ }
371+
372+ bool replace(const std::string &key, const std::string &value)
373+ {
374+ memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
375+ value.c_str(), value.length(),
376+ 0, 0);
377+ return (rc == MEMCACHED_SUCCESS);
378+ }
379+
380+ bool replace_by_key(const std::string &master_key,
381+ const std::string &key,
382+ const std::string &value)
383+ {
384+ memcached_return rc= memcached_replace_by_key(&memc,
385+ master_key.c_str(),
386+ master_key.length(),
387+ key.c_str(),
388+ key.length(),
389+ value.c_str(),
390+ value.length(),
391+ 0, 0);
392+ return (rc == MEMCACHED_SUCCESS);
393+ }
394+
395+ bool prepend(const std::string &key, const std::string &value)
396+ {
397+ memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
398+ value.c_str(), value.length(), 0, 0);
399+ return (rc == MEMCACHED_SUCCESS);
400+ }
401+
402+ bool prepend_by_key(const std::string &master_key,
403+ const std::string &key,
404+ const std::string &value)
405+ {
406+ memcached_return rc= memcached_prepend_by_key(&memc,
407+ master_key.c_str(),
408+ master_key.length(),
409+ key.c_str(),
410+ key.length(),
411+ value.c_str(),
412+ value.length(),
413+ 0,
414+ 0);
415+ return (rc == MEMCACHED_SUCCESS);
416+ }
417+
418+ bool append(const std::string &key, const std::string &value)
419+ {
420+ memcached_return rc= memcached_append(&memc,
421+ key.c_str(),
422+ key.length(),
423+ value.c_str(),
424+ value.length(),
425+ 0, 0);
426+ return (rc == MEMCACHED_SUCCESS);
427+ }
428+
429+ bool append_by_key(const std::string &master_key,
430+ const std::string &key,
431+ const std::string &value)
432+ {
433+ memcached_return rc= memcached_append_by_key(&memc,
434+ master_key.c_str(),
435+ master_key.length(),
436+ key.c_str(),
437+ key.length(),
438+ value.c_str(),
439+ value.length(),
440+ 0, 0);
441+ return (rc == MEMCACHED_SUCCESS);
442+ }
443+
444+ bool cas(const std::string &key,
445+ const std::string &value,
446+ uint64_t cas_arg)
447+ {
448+ memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
449+ value.c_str(), value.length(),
450+ 0, 0, cas_arg);
451+ return (rc == MEMCACHED_SUCCESS);
452+ }
453+
454+ bool cas_by_key(const std::string &master_key,
455+ const std::string &key,
456+ const std::string &value,
457+ uint64_t cas_arg)
458+ {
459+ memcached_return rc= memcached_cas_by_key(&memc,
460+ master_key.c_str(),
461+ master_key.length(),
462+ key.c_str(),
463+ key.length(),
464+ value.c_str(),
465+ value.length(),
466+ 0, 0, cas_arg);
467+ return (rc == MEMCACHED_SUCCESS);
468+ }
469+
470+ // using 'remove' vs. 'delete' since 'delete' is a keyword
471+ bool remove(const std::string &key)
472+ {
473+ memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
474+ return (rc == MEMCACHED_SUCCESS);
475+ }
476+
477+ bool delete_by_key(const std::string &master_key,
478+ const std::string &key)
479+ {
480+ memcached_return rc= memcached_delete_by_key(&memc,
481+ master_key.c_str(),
482+ master_key.length(),
483+ key.c_str(),
484+ key.length(),
485+ 0);
486+ return (rc == MEMCACHED_SUCCESS);
487+ }
488+
489+ bool flush(time_t expiration)
490+ {
491+ memcached_return rc= memcached_flush(&memc, expiration);
492+ return (rc == MEMCACHED_SUCCESS);
493+ }
494+
495+ bool fetch_execute(memcached_execute_function *callback,
496+ void *context,
497+ unsigned int num_of_callbacks)
498+ {
499+ memcached_return rc= memcached_fetch_execute(&memc,
500+ callback,
501+ context,
502+ num_of_callbacks);
503+ return (rc == MEMCACHED_SUCCESS);
504+ }
505+
506+ const std::string lib_version() const
507+ {
508+ const char *ver= memcached_lib_version();
509+ const std::string version(ver);
510+ return version;
511+ }
512+
513+private:
514+ memcached_st memc;
515+ memcached_result_st result;
516 };
517
518=== modified file 'tests/plus.cpp'
519--- tests/plus.cpp 2009-07-07 21:57:24 +0000
520+++ tests/plus.cpp 2009-07-11 19:10:39 +0000
521@@ -16,87 +16,184 @@
522
523 #include "test.h"
524
525+#include <string>
526+
527+using namespace std;
528+
529 extern "C" {
530- test_return basic_test(memcached_st *memc);
531- uint8_t increment_test(memcached_st *memc);
532- test_return basic_master_key_test(memcached_st *memc);
533 void *world_create(void);
534 void world_destroy(void *p);
535 }
536
537-test_return basic_test(memcached_st *memc)
538+static test_return basic_test(memcached_st *memc)
539 {
540 Memcached foo(memc);
541- const char *value_set= "This is some data";
542- char *value;
543+ const string value_set("This is some data");
544+ string value;
545 size_t value_length;
546
547- foo.set("mine", value_set, strlen(value_set));
548+ foo.set("mine", value_set, 0, 0);
549 value= foo.get("mine", &value_length);
550
551- assert((memcmp(value, value_set, value_length) == 0));
552+ assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));
553
554 return TEST_SUCCESS;
555 }
556
557-uint8_t increment_test(memcached_st *memc)
558+static test_return increment_test(memcached_st *memc)
559 {
560 Memcached mcach(memc);
561- memcached_return rc;
562- const char *key= "inctest";
563- const char *inc_value= "1";
564- char *ret_value;
565+ bool rc;
566+ const string key("inctest");
567+ const string inc_value("1");
568+ string ret_value;
569 uint64_t int_inc_value;
570 uint64_t int_ret_value;
571 size_t value_length;
572
573- mcach.set(key, inc_value, strlen(inc_value));
574+ mcach.set(key, inc_value, 0, 0);
575 ret_value= mcach.get(key, &value_length);
576- printf("\nretvalue %s\n",ret_value);
577- int_inc_value= uint64_t(atol(inc_value));
578- int_ret_value= uint64_t(atol(ret_value));
579+ printf("\nretvalue %s\n",ret_value.c_str());
580+ int_inc_value= uint64_t(atol(inc_value.c_str()));
581+ int_ret_value= uint64_t(atol(ret_value.c_str()));
582 assert(int_ret_value == int_inc_value);
583
584 rc= mcach.increment(key, 1, &int_ret_value);
585- assert(rc == MEMCACHED_SUCCESS);
586+ assert(rc == true);
587 assert(int_ret_value == 2);
588
589 rc= mcach.increment(key, 1, &int_ret_value);
590- assert(rc == MEMCACHED_SUCCESS);
591+ assert(rc == true);
592 assert(int_ret_value == 3);
593
594 rc= mcach.increment(key, 5, &int_ret_value);
595- assert(rc == MEMCACHED_SUCCESS);
596+ assert(rc == true);
597 assert(int_ret_value == 8);
598
599- return 0;
600+ return TEST_SUCCESS;
601 }
602
603-test_return basic_master_key_test(memcached_st *memc)
604+static test_return basic_master_key_test(memcached_st *memc)
605 {
606- Memcached foo(memc);
607- const char *value_set= "Data for server A";
608- const char *master_key_a= "server-a";
609- const char *master_key_b= "server-b";
610- const char *key= "xyz";
611- char *value;
612+ Memcached foo(memc);
613+ const string value_set("Data for server A");
614+ const string master_key_a("server-a");
615+ const string master_key_b("server-b");
616+ const string key("xyz");
617+ string value;
618 size_t value_length;
619
620- foo.set_by_key(master_key_a, key, value_set, strlen(value_set));
621+ foo.set_by_key(master_key_a, key, value_set, 0, 0);
622 value= foo.get_by_key(master_key_a, key, &value_length);
623
624- assert((memcmp(value, value_set, value_length) == 0));
625+ assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));
626
627 value= foo.get_by_key(master_key_b, key, &value_length);
628- assert((memcmp(value, value_set, value_length) == 0));
629-
630- return TEST_SUCCESS;
631-}
632-
633+ assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));
634+
635+ return TEST_SUCCESS;
636+}
637+
638+/* Count the results */
639+static memcached_return callback_counter(memcached_st *ptr __attribute__((unused)),
640+ memcached_result_st *result __attribute__((unused)),
641+ void *context)
642+{
643+ unsigned int *counter= static_cast<unsigned int *>(context);
644+
645+ *counter= *counter + 1;
646+
647+ return MEMCACHED_SUCCESS;
648+}
649+
650+static test_return mget_result_function(memcached_st *memc)
651+{
652+ Memcached mc(memc);
653+ bool rc;
654+ string key1("fudge");
655+ string key2("son");
656+ string key3("food");
657+ vector<string> keys;
658+ keys.reserve(3);
659+ keys.push_back(key1);
660+ keys.push_back(key2);
661+ keys.push_back(key3);
662+ unsigned int counter;
663+ memcached_execute_function callbacks[1];
664+
665+ /* We need to empty the server before we continue the test */
666+ rc= mc.flush(0);
667+ rc= mc.set_all(keys, keys, 50, 9);
668+ assert(rc == true);
669+
670+ rc= mc.mget(keys);
671+ assert(rc == true);
672+
673+ callbacks[0]= &callback_counter;
674+ counter= 0;
675+ rc= mc.fetch_execute(callbacks, static_cast<void *>(&counter), 1);
676+
677+ assert(counter == 3);
678+
679+ return TEST_SUCCESS;
680+}
681+
682+static test_return mget_test(memcached_st *memc)
683+{
684+ Memcached mc(memc);
685+ bool rc;
686+ memcached_return mc_rc;
687+ vector<string> keys;
688+ keys.reserve(3);
689+ keys.push_back("fudge");
690+ keys.push_back("son");
691+ keys.push_back("food");
692+ uint32_t flags;
693+
694+ string return_key;
695+ size_t return_key_length;
696+ string return_value;
697+ size_t return_value_length;
698+
699+ /* We need to empty the server before we continue the test */
700+ rc= mc.flush(0);
701+ assert(rc == true);
702+
703+ rc= mc.mget(keys);
704+ assert(rc == true);
705+
706+ while (mc.fetch(return_key, return_value, &return_key_length,
707+ &return_value_length, &flags, &mc_rc))
708+ {
709+ assert(return_value.length() != 0);
710+ }
711+ assert(return_value_length == 0);
712+ assert(mc_rc == MEMCACHED_END);
713+
714+ rc= mc.set_all(keys, keys, 50, 9);
715+ assert(rc == true);
716+
717+ rc= mc.mget(keys);
718+ assert(rc == true);
719+
720+ while ((mc.fetch(return_key, return_value, &return_key_length,
721+ &return_value_length, &flags, &mc_rc)))
722+ {
723+ assert(return_value.length() != 0);
724+ assert(mc_rc == MEMCACHED_SUCCESS);
725+ assert(return_key_length == return_value_length);
726+ assert(!memcmp(return_value.c_str(), return_key.c_str(), return_value_length));
727+ }
728+
729+ return TEST_SUCCESS;
730+}
731
732 test_st tests[] ={
733- {"basic", 0, basic_test },
734- {"basic_master_key", 0, basic_master_key_test },
735+ { "basic", 0, basic_test },
736+ { "basic_master_key", 0, basic_master_key_test },
737+ { "increment_test", 0, increment_test },
738+ { "mget", 1, mget_test },
739+ { "mget_result_function", 1, mget_result_function },
740 {0, 0, 0}
741 };
742

Subscribers

People subscribed via source and target branches