Merge lp://staging/~posulliv/libmemcached/cpp-interface into lp://staging/~tangent-org/libmemcached/trunk

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

This patch continues the work of improving the libmemcached C++ interface. In this patch, I modified the following:

* used std::vector<char> instead of std::string for values
* removed un-needed parameters from some API calls in the C++ interface
* used camel case on C++ interface
* added some doxygen comments (much more will be added in later patches)
* modified test cases accordingly

Work still needs to be done on this interface but I plan on doing it in small increments with small patches that are easier to review.

-Padraig

566. By Brian Aker <brian@gaz>

Merge Padraig

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-15 18:26:30 +0000
3+++ libmemcached/memcached.hh 2009-07-18 20:56:38 +0000
4@@ -1,8 +1,31 @@
5+/*
6+ * Summary: C++ interface for memcached server
7+ *
8+ * Copy: See Copyright for the status of this software.
9+ *
10+ * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
11+ * Patrick Galbraith <patg@patg.net>
12+ */
13+
14+/**
15+ * @file memcached.hh
16+ * @brief Libmemcached C++ interface
17+ */
18+
19+#ifndef LIBMEMCACHEDPP_H
20+#define LIBMEMCACHEDPP_H
21+
22 #include <libmemcached/memcached.h>
23
24+#include <string.h>
25+
26 #include <string>
27 #include <vector>
28
29+/**
30+ * This is the core memcached library (if later, other objects
31+ * are needed, they will be created from this class).
32+ */
33 class Memcached
34 {
35 public:
36@@ -23,59 +46,100 @@
37 memcached_clone(&memc, clone);
38 }
39
40+ Memcached(const Memcached &rhs)
41+ :
42+ memc(),
43+ result()
44+ {
45+ memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl()));
46+ }
47+
48 ~Memcached()
49 {
50 memcached_free(&memc);
51 }
52
53+ /**
54+ * Get the internal memcached_st *
55+ */
56+ memcached_st &getImpl()
57+ {
58+ return memc;
59+ }
60+
61+ /**
62+ * Get the internal memcached_st *
63+ */
64+ const memcached_st &getImpl() const
65+ {
66+ return memc;
67+ }
68+
69+ /**
70+ * Return an error string for the given return structure.
71+ *
72+ * @param[in] rc a memcached_return structure
73+ * @return error string corresponding to given return code in the library.
74+ */
75+ const std::string getError(memcached_return rc) const
76+ {
77+ /* first parameter to strerror is unused */
78+ return memcached_strerror(NULL, rc);
79+ }
80+
81 bool fetch(std::string &key,
82- std::string &ret_val,
83- size_t *key_length,
84- size_t *value_length,
85+ std::vector<char> &ret_val,
86 uint32_t *flags,
87 memcached_return *rc)
88 {
89 char ret_key[MEMCACHED_MAX_KEY];
90- char *value= memcached_fetch(&memc, ret_key, key_length,
91- value_length, flags, rc);
92+ size_t value_length= 0;
93+ size_t key_length= 0;
94+ char *value= memcached_fetch(&memc, ret_key, &key_length,
95+ &value_length, flags, rc);
96 if (value)
97 {
98- ret_val.assign(value);
99+ ret_val.reserve(value_length);
100+ memcpy(&*ret_val.begin(), value, value_length);
101 key.assign(ret_key);
102 return true;
103 }
104 return false;
105 }
106
107- std::string get(const std::string &key, size_t *value_length)
108+ std::vector<char> &get(const std::string &key,
109+ std::vector<char> &ret_val)
110 {
111- uint32_t flags;
112+ uint32_t flags= 0;
113 memcached_return rc;
114- std::string ret_val;
115+ size_t value_length= 0;
116
117 char *value= memcached_get(&memc, key.c_str(), key.length(),
118- value_length, &flags, &rc);
119- if (value)
120+ &value_length, &flags, &rc);
121+ if (value != NULL)
122 {
123- ret_val.assign(value);
124+ ret_val.reserve(value_length);
125+ memcpy(&ret_val[0], value, value_length);
126 }
127 return ret_val;
128 }
129
130- std::string get_by_key(const std::string &master_key,
131- const std::string &key,
132- size_t *value_length)
133+ std::vector<char> &getByKey(const std::string &master_key,
134+ const std::string &key,
135+ std::vector<char> &ret_val)
136 {
137- uint32_t flags;
138+ uint32_t flags= 0;
139 memcached_return rc;
140- std::string ret_val;
141+ size_t value_length= 0;
142
143- char *value= memcached_get_by_key(&memc, master_key.c_str(), master_key.length(),
144+ char *value= memcached_get_by_key(&memc,
145+ master_key.c_str(), master_key.length(),
146 key.c_str(), key.length(),
147- value_length, &flags, &rc);
148+ &value_length, &flags, &rc);
149 if (value)
150 {
151- ret_val.assign(value);
152+ ret_val.reserve(value_length);
153+ memcpy(&*ret_val.begin(), value, value_length);
154 }
155 return ret_val;
156 }
157@@ -117,21 +181,21 @@
158 }
159
160 bool set(const std::string &key,
161- const std::string &value,
162+ const std::vector<char> &value,
163 time_t expiration,
164 uint32_t flags)
165 {
166 memcached_return rc= memcached_set(&memc,
167 key.c_str(), key.length(),
168- value.c_str(), value.length(),
169+ &value[0], value.size(),
170 expiration, flags);
171 return (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
172 }
173
174- bool set_all(std::vector<std::string> &keys,
175- std::vector<std::string> &values,
176- time_t expiration,
177- uint32_t flags)
178+ bool setAll(std::vector<std::string> &keys,
179+ std::vector< std::vector<char> > &values,
180+ time_t expiration,
181+ uint32_t flags)
182 {
183 if (keys.size() != values.size())
184 {
185@@ -139,7 +203,7 @@
186 }
187 bool retval= true;
188 std::vector<std::string>::iterator key_it= keys.begin();
189- std::vector<std::string>::iterator val_it= values.begin();
190+ std::vector< std::vector<char> >::iterator val_it= values.begin();
191 while (key_it != keys.end())
192 {
193 retval= set((*key_it), (*val_it), expiration, flags);
194@@ -153,16 +217,16 @@
195 return retval;
196 }
197
198- bool set_by_key(const std::string &master_key,
199- const std::string &key,
200- const std::string &value,
201- time_t expiration,
202- uint32_t flags)
203+ bool setByKey(const std::string &master_key,
204+ const std::string &key,
205+ const std::vector<char> &value,
206+ time_t expiration,
207+ uint32_t flags)
208 {
209 memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
210 master_key.length(),
211 key.c_str(), key.length(),
212- value.c_str(), value.length(),
213+ &value[0], value.size(),
214 expiration,
215 flags);
216 return (rc == MEMCACHED_SUCCESS);
217@@ -184,135 +248,134 @@
218 }
219
220
221- bool add(const std::string &key, const std::string &value)
222+ bool add(const std::string &key, const std::vector<char> &value)
223 {
224 memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
225- value.c_str(), value.length(), 0, 0);
226+ &value[0], value.size(), 0, 0);
227 return (rc == MEMCACHED_SUCCESS);
228 }
229
230- bool add_by_key(const std::string &master_key,
231- const std::string &key,
232- const std::string &value)
233+ bool addByKey(const std::string &master_key,
234+ const std::string &key,
235+ const std::vector<char> &value)
236 {
237 memcached_return rc= memcached_add_by_key(&memc,
238 master_key.c_str(),
239 master_key.length(),
240 key.c_str(),
241 key.length(),
242- value.c_str(),
243- value.length(),
244+ &value[0],
245+ value.size(),
246 0, 0);
247 return (rc == MEMCACHED_SUCCESS);
248 }
249
250- bool replace(const std::string &key, const std::string &value)
251+ bool replace(const std::string &key, const std::vector<char> &value)
252 {
253 memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
254- value.c_str(), value.length(),
255+ &value[0], value.size(),
256 0, 0);
257 return (rc == MEMCACHED_SUCCESS);
258 }
259
260- bool replace_by_key(const std::string &master_key,
261- const std::string &key,
262- const std::string &value)
263+ bool replaceByKey(const std::string &master_key,
264+ const std::string &key,
265+ const std::vector<char> &value)
266 {
267 memcached_return rc= memcached_replace_by_key(&memc,
268 master_key.c_str(),
269 master_key.length(),
270 key.c_str(),
271 key.length(),
272- value.c_str(),
273- value.length(),
274+ &value[0],
275+ value.size(),
276 0, 0);
277 return (rc == MEMCACHED_SUCCESS);
278 }
279
280- bool prepend(const std::string &key, const std::string &value)
281+ bool prepend(const std::string &key, const std::vector<char> &value)
282 {
283 memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
284- value.c_str(), value.length(), 0, 0);
285+ &value[0], value.size(), 0, 0);
286 return (rc == MEMCACHED_SUCCESS);
287 }
288
289- bool prepend_by_key(const std::string &master_key,
290- const std::string &key,
291- const std::string &value)
292+ bool prependByKey(const std::string &master_key,
293+ const std::string &key,
294+ const std::vector<char> &value)
295 {
296 memcached_return rc= memcached_prepend_by_key(&memc,
297 master_key.c_str(),
298 master_key.length(),
299 key.c_str(),
300 key.length(),
301- value.c_str(),
302- value.length(),
303+ &value[0],
304+ value.size(),
305 0,
306 0);
307 return (rc == MEMCACHED_SUCCESS);
308 }
309
310- bool append(const std::string &key, const std::string &value)
311+ bool append(const std::string &key, const std::vector<char> &value)
312 {
313 memcached_return rc= memcached_append(&memc,
314 key.c_str(),
315 key.length(),
316- value.c_str(),
317- value.length(),
318+ &value[0],
319+ value.size(),
320 0, 0);
321 return (rc == MEMCACHED_SUCCESS);
322 }
323
324- bool append_by_key(const std::string &master_key,
325- const std::string &key,
326- const std::string &value)
327+ bool appendByKey(const std::string &master_key,
328+ const std::string &key,
329+ const std::vector<char> &value)
330 {
331 memcached_return rc= memcached_append_by_key(&memc,
332 master_key.c_str(),
333 master_key.length(),
334 key.c_str(),
335 key.length(),
336- value.c_str(),
337- value.length(),
338+ &value[0],
339+ value.size(),
340 0, 0);
341 return (rc == MEMCACHED_SUCCESS);
342 }
343
344 bool cas(const std::string &key,
345- const std::string &value,
346+ const std::vector<char> &value,
347 uint64_t cas_arg)
348 {
349 memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
350- value.c_str(), value.length(),
351+ &value[0], value.size(),
352 0, 0, cas_arg);
353 return (rc == MEMCACHED_SUCCESS);
354 }
355
356- bool cas_by_key(const std::string &master_key,
357- const std::string &key,
358- const std::string &value,
359- uint64_t cas_arg)
360+ bool casByKey(const std::string &master_key,
361+ const std::string &key,
362+ const std::vector<char> &value,
363+ uint64_t cas_arg)
364 {
365 memcached_return rc= memcached_cas_by_key(&memc,
366 master_key.c_str(),
367 master_key.length(),
368 key.c_str(),
369 key.length(),
370- value.c_str(),
371- value.length(),
372+ &value[0],
373+ value.size(),
374 0, 0, cas_arg);
375 return (rc == MEMCACHED_SUCCESS);
376 }
377
378- // using 'remove' vs. 'delete' since 'delete' is a keyword
379 bool remove(const std::string &key)
380 {
381 memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
382 return (rc == MEMCACHED_SUCCESS);
383 }
384
385- bool delete_by_key(const std::string &master_key,
386- const std::string &key)
387+ bool removeByKey(const std::string &master_key,
388+ const std::string &key)
389 {
390 memcached_return rc= memcached_delete_by_key(&memc,
391 master_key.c_str(),
392@@ -329,9 +392,9 @@
393 return (rc == MEMCACHED_SUCCESS);
394 }
395
396- bool fetch_execute(memcached_execute_function *callback,
397- void *context,
398- unsigned int num_of_callbacks)
399+ bool fetchExecute(memcached_execute_function *callback,
400+ void *context,
401+ unsigned int num_of_callbacks)
402 {
403 memcached_return rc= memcached_fetch_execute(&memc,
404 callback,
405@@ -340,7 +403,11 @@
406 return (rc == MEMCACHED_SUCCESS);
407 }
408
409- const std::string lib_version() const
410+ /**
411+ * Get the library version string.
412+ * @return std::string containing a copy of the library version string.
413+ */
414+ const std::string libVersion() const
415 {
416 const char *ver= memcached_lib_version();
417 const std::string version(ver);
418@@ -348,6 +415,9 @@
419 }
420
421 private:
422+
423 memcached_st memc;
424 memcached_result_st result;
425 };
426+
427+#endif /* LIBMEMCACHEDPP_H */
428
429=== modified file 'tests/plus.cpp'
430--- tests/plus.cpp 2009-07-15 18:45:15 +0000
431+++ tests/plus.cpp 2009-07-18 20:35:03 +0000
432@@ -33,17 +33,36 @@
433 void world_destroy(void *p);
434 }
435
436+static void populate_vector(vector<char> &vec, const string &str)
437+{
438+ vec.reserve(str.length());
439+ memcpy(&*vec.begin(), str.c_str(), str.length());
440+}
441+
442+static void copy_vec_to_string(vector<char> &vec, string &str)
443+{
444+ str.clear();
445+ char *tmp= static_cast<char *>(malloc(vec.size() * sizeof(char)));
446+ if (!vec.empty())
447+ {
448+ memcpy(tmp, &vec[0], vec.size());
449+ str.assign(tmp);
450+ }
451+}
452+
453 test_return basic_test(memcached_st *memc)
454 {
455 Memcached foo(memc);
456 const string value_set("This is some data");
457- string value;
458- size_t value_length;
459-
460- foo.set("mine", value_set, 0, 0);
461- value= foo.get("mine", &value_length);
462-
463- assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));
464+ std::vector<char> value;
465+ std::vector<char> test_value;
466+
467+ populate_vector(value, value_set);
468+
469+ foo.set("mine", value, 0, 0);
470+ test_value= foo.get("mine", test_value);
471+
472+ assert((memcmp(&test_value[0], &value[0], test_value.size()) == 0));
473
474 return TEST_SUCCESS;
475 }
476@@ -52,18 +71,32 @@
477 {
478 Memcached mcach(memc);
479 bool rc;
480- const string key("inctest");
481+ const string key("blah");
482 const string inc_value("1");
483- string ret_value;
484+ std::vector<char> inc_val;
485+ vector<char> ret_value;
486+ string ret_string;
487 uint64_t int_inc_value;
488 uint64_t int_ret_value;
489- size_t value_length;
490-
491- mcach.set(key, inc_value, 0, 0);
492- ret_value= mcach.get(key, &value_length);
493- printf("\nretvalue %s\n",ret_value.c_str());
494+
495+ populate_vector(inc_val, inc_value);
496+
497+ rc= mcach.set(key, inc_val, 0, 0);
498+ if (rc == false)
499+ {
500+ return TEST_FAILURE;
501+ }
502+ ret_value= mcach.get(key, ret_value);
503+ if (ret_value.empty())
504+ {
505+ return TEST_FAILURE;
506+ }
507+ copy_vec_to_string(ret_value, ret_string);
508+
509+ printf("string is: %s\n", ret_string.c_str());
510+
511 int_inc_value= uint64_t(atol(inc_value.c_str()));
512- int_ret_value= uint64_t(atol(ret_value.c_str()));
513+ int_ret_value= uint64_t(atol(ret_string.c_str()));
514 assert(int_ret_value == int_inc_value);
515
516 rc= mcach.increment(key, 1, &int_ret_value);
517@@ -85,19 +118,23 @@
518 {
519 Memcached foo(memc);
520 const string value_set("Data for server A");
521+ vector<char> value;
522+ vector<char> test_value;
523 const string master_key_a("server-a");
524 const string master_key_b("server-b");
525 const string key("xyz");
526- string value;
527- size_t value_length;
528-
529- foo.set_by_key(master_key_a, key, value_set, 0, 0);
530- value= foo.get_by_key(master_key_a, key, &value_length);
531-
532- assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));
533-
534- value= foo.get_by_key(master_key_b, key, &value_length);
535- assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));
536+
537+ populate_vector(value, value_set);
538+
539+ foo.setByKey(master_key_a, key, value, 0, 0);
540+ test_value= foo.getByKey(master_key_a, key, test_value);
541+
542+ assert((memcmp(&value[0], &test_value[0], value.size()) == 0));
543+
544+ test_value.clear();
545+
546+ test_value= foo.getByKey(master_key_b, key, test_value);
547+ assert((memcmp(&value[0], &test_value[0], value.size()) == 0));
548
549 return TEST_SUCCESS;
550 }
551@@ -122,16 +159,27 @@
552 string key2("son");
553 string key3("food");
554 vector<string> keys;
555+ vector< vector<char> > values;
556+ vector<char> val1;
557+ vector<char> val2;
558+ vector<char> val3;
559+ populate_vector(val1, key1);
560+ populate_vector(val2, key2);
561+ populate_vector(val3, key3);
562 keys.reserve(3);
563 keys.push_back(key1);
564 keys.push_back(key2);
565 keys.push_back(key3);
566+ values.reserve(3);
567+ values.push_back(val1);
568+ values.push_back(val2);
569+ values.push_back(val3);
570 unsigned int counter;
571 memcached_execute_function callbacks[1];
572
573 /* We need to empty the server before we continue the test */
574 rc= mc.flush(0);
575- rc= mc.set_all(keys, keys, 50, 9);
576+ rc= mc.setAll(keys, values, 50, 9);
577 assert(rc == true);
578
579 rc= mc.mget(keys);
580@@ -139,7 +187,7 @@
581
582 callbacks[0]= &callback_counter;
583 counter= 0;
584- rc= mc.fetch_execute(callbacks, static_cast<void *>(&counter), 1);
585+ rc= mc.fetchExecute(callbacks, static_cast<void *>(&counter), 1);
586
587 assert(counter == 3);
588
589@@ -152,16 +200,25 @@
590 bool rc;
591 memcached_return mc_rc;
592 vector<string> keys;
593+ vector< vector<char> > values;
594 keys.reserve(3);
595 keys.push_back("fudge");
596 keys.push_back("son");
597 keys.push_back("food");
598+ vector<char> val1;
599+ vector<char> val2;
600+ vector<char> val3;
601+ populate_vector(val1, "fudge");
602+ populate_vector(val2, "son");
603+ populate_vector(val3, "food");
604+ values.reserve(3);
605+ values.push_back(val1);
606+ values.push_back(val2);
607+ values.push_back(val3);
608 uint32_t flags;
609
610 string return_key;
611- size_t return_key_length;
612- string return_value;
613- size_t return_value_length;
614+ vector<char> return_value;
615
616 /* We need to empty the server before we continue the test */
617 rc= mc.flush(0);
618@@ -170,27 +227,26 @@
619 rc= mc.mget(keys);
620 assert(rc == true);
621
622- while (mc.fetch(return_key, return_value, &return_key_length,
623- &return_value_length, &flags, &mc_rc))
624+ while (mc.fetch(return_key, return_value,
625+ &flags, &mc_rc))
626 {
627- assert(return_value.length() != 0);
628+ assert(return_value.size() != 0);
629+ return_value.clear();
630 }
631- assert(return_value_length == 0);
632 assert(mc_rc == MEMCACHED_END);
633
634- rc= mc.set_all(keys, keys, 50, 9);
635+ rc= mc.setAll(keys, values, 50, 9);
636 assert(rc == true);
637
638 rc= mc.mget(keys);
639 assert(rc == true);
640
641- while ((mc.fetch(return_key, return_value, &return_key_length,
642- &return_value_length, &flags, &mc_rc)))
643+ while ((mc.fetch(return_key, return_value,
644+ &flags, &mc_rc)))
645 {
646- assert(return_value.length() != 0);
647 assert(mc_rc == MEMCACHED_SUCCESS);
648- assert(return_key_length == return_value_length);
649- assert(!memcmp(return_value.c_str(), return_key.c_str(), return_value_length));
650+ assert(return_key.length() == return_value.size());
651+ assert(!memcmp(&return_value[0], return_key.c_str(), return_value.size()));
652 }
653
654 return TEST_SUCCESS;

Subscribers

People subscribed via source and target branches