Merge lp://staging/~posulliv/libmemcached/cpp-interface into lp://staging/~tangent-org/libmemcached/trunk
- cpp-interface
- Merge into 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 |
Related bugs: | |
Related blueprints: |
Libmemcached C++ Interface
(Medium)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brian Aker | Pending | ||
Review via email:
|
This proposal supersedes a proposal from 2009-09-19.
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Padraig O'Sullivan (posulliv) wrote : Posted in a previous version of this proposal | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2009-09-16 07:41:38 +0000 |
3 | +++ ChangeLog 2009-09-19 23:59:36 +0000 |
4 | @@ -3,7 +3,9 @@ |
5 | it is set to zero. |
6 | * Added Twitter's memcached_server_error() functions. |
7 | * Fix for OSX compiles in development builds. |
8 | - * Updated C++ interface. |
9 | + * Updated C++ interface. Added basic support for C++ exceptions. Added |
10 | + multiple constructors the memcached client object. The C++ interface |
11 | + now takes parameters which are C++ types (such as std::string). |
12 | * Updated memcached_mget and memcached_mget_by_key to take a size_t |
13 | as a parameter instead of an unsigned int for number_of_keys. |
14 | |
15 | |
16 | === modified file 'libmemcached/Makefile.am' |
17 | --- libmemcached/Makefile.am 2009-07-27 02:51:32 +0000 |
18 | +++ libmemcached/Makefile.am 2009-09-17 19:14:07 +0000 |
19 | @@ -12,6 +12,7 @@ |
20 | |
21 | pkginclude_HEADERS= memcached.h \ |
22 | memcached.hpp \ |
23 | + exception.hpp \ |
24 | memcached_configure.h \ |
25 | memcached_constants.h \ |
26 | memcached_get.h \ |
27 | |
28 | === added file 'libmemcached/exception.hpp' |
29 | --- libmemcached/exception.hpp 1970-01-01 00:00:00 +0000 |
30 | +++ libmemcached/exception.hpp 2009-09-19 23:53:48 +0000 |
31 | @@ -0,0 +1,63 @@ |
32 | +/* |
33 | + * Summary: Exceptions for the C++ interface |
34 | + * |
35 | + * Copy: See Copyright for the status of this software. |
36 | + * |
37 | + */ |
38 | + |
39 | +/** |
40 | + * @file |
41 | + * @brief Exception declarations |
42 | + */ |
43 | + |
44 | +#ifndef LIBMEMACHED_EXCEPTION_HPP |
45 | +#define LIBMEMACHED_EXCEPTION_HPP |
46 | + |
47 | +#include <stdexcept> |
48 | +#include <string> |
49 | + |
50 | +namespace memcache |
51 | +{ |
52 | + class Exception : public std::runtime_error |
53 | + { |
54 | + public: |
55 | + Exception(const std::string& msg, int in_errno) |
56 | + : |
57 | + std::runtime_error(msg), |
58 | + _errno(in_errno) |
59 | + {} |
60 | + |
61 | + Exception(const char *msg, int in_errno) |
62 | + : |
63 | + std::runtime_error(std::string(msg)), |
64 | + _errno(in_errno) {} |
65 | + |
66 | + virtual ~Exception() throw() {} |
67 | + |
68 | + int getErrno() const |
69 | + { |
70 | + return _errno; |
71 | + } |
72 | + |
73 | + private: |
74 | + int _errno; |
75 | + }; |
76 | + |
77 | + class Warning : public Exception |
78 | + { |
79 | + public: |
80 | + Warning(const std::string& msg, int in_errno) : Exception(msg, in_errno) {} |
81 | + Warning(const char *msg, int in_errno) : Exception(msg, in_errno) {} |
82 | + }; |
83 | + |
84 | + class Error : public Exception |
85 | + { |
86 | + public: |
87 | + Error(const std::string& msg, int in_errno) : Exception(msg, in_errno) {} |
88 | + Error(const char *msg, int in_errno) : Exception(msg, in_errno) {} |
89 | + virtual ~Error() throw() {} |
90 | + }; |
91 | + |
92 | +} /* namespace libmemcached */ |
93 | + |
94 | +#endif /* LIBMEMACHED_EXCEPTION_HPP */ |
95 | |
96 | === modified file 'libmemcached/memcached.hpp' |
97 | --- libmemcached/memcached.hpp 2009-07-27 02:39:31 +0000 |
98 | +++ libmemcached/memcached.hpp 2009-09-19 23:36:57 +0000 |
99 | @@ -16,9 +16,11 @@ |
100 | #define LIBMEMCACHEDPP_H |
101 | |
102 | #include <libmemcached/memcached.h> |
103 | +#include <libmemcached/exception.hpp> |
104 | |
105 | #include <string.h> |
106 | |
107 | +#include <sstream> |
108 | #include <string> |
109 | #include <vector> |
110 | #include <map> |
111 | @@ -36,15 +38,49 @@ |
112 | |
113 | Memcache() |
114 | : |
115 | - memc(), |
116 | - result() |
117 | - { |
118 | - memcached_create(&memc); |
119 | + servers_list(), |
120 | + memc(), |
121 | + servers(NULL), |
122 | + result() |
123 | + { |
124 | + memcached_create(&memc); |
125 | + } |
126 | + |
127 | + Memcache(const std::string &in_servers_list) |
128 | + : |
129 | + servers_list(in_servers_list), |
130 | + memc(), |
131 | + servers(NULL), |
132 | + result() |
133 | + { |
134 | + memcached_create(&memc); |
135 | + servers= memcached_servers_parse(servers_list.c_str()); |
136 | + memcached_server_push(&memc, servers); |
137 | + } |
138 | + |
139 | + Memcache(const std::string &hostname, |
140 | + unsigned int port) |
141 | + : |
142 | + servers_list(), |
143 | + memc(), |
144 | + servers(NULL), |
145 | + result() |
146 | + { |
147 | + memcached_create(&memc); |
148 | + servers_list.append(hostname); |
149 | + servers_list.append(":"); |
150 | + std::ostringstream strsmt; |
151 | + strsmt << port; |
152 | + servers_list.append(strsmt.str()); |
153 | + servers= memcached_servers_parse(servers_list.c_str()); |
154 | + memcached_server_push(&memc, servers); |
155 | } |
156 | |
157 | Memcache(memcached_st *clone) |
158 | : |
159 | + servers_list(), |
160 | memc(), |
161 | + servers(NULL), |
162 | result() |
163 | { |
164 | memcached_clone(&memc, clone); |
165 | @@ -52,15 +88,31 @@ |
166 | |
167 | Memcache(const Memcache &rhs) |
168 | : |
169 | + servers_list(rhs.servers_list), |
170 | memc(), |
171 | + servers(NULL), |
172 | result() |
173 | { |
174 | memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl())); |
175 | + servers= memcached_servers_parse(servers_list.c_str()); |
176 | + memcached_server_push(&memc, servers); |
177 | + } |
178 | + |
179 | + Memcache &operator=(const Memcache &rhs) |
180 | + { |
181 | + if (this != &rhs) |
182 | + { |
183 | + memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl())); |
184 | + servers= memcached_servers_parse(servers_list.c_str()); |
185 | + memcached_server_push(&memc, servers); |
186 | + } |
187 | + return *this; |
188 | } |
189 | |
190 | ~Memcache() |
191 | { |
192 | memcached_free(&memc); |
193 | + memcached_server_list_free(servers); |
194 | } |
195 | |
196 | /** |
197 | @@ -92,6 +144,53 @@ |
198 | } |
199 | |
200 | /** |
201 | + * Return the string which contains the list of memcached servers being |
202 | + * used. |
203 | + * |
204 | + * @return a std::string containing the list of memcached servers |
205 | + */ |
206 | + const std::string getServersList() const |
207 | + { |
208 | + return servers_list; |
209 | + } |
210 | + |
211 | + /** |
212 | + * Set the list of memcached servers to use. |
213 | + * |
214 | + * @param[in] in_servers_list list of servers |
215 | + * @return true on success; false otherwise |
216 | + */ |
217 | + bool setServers(const std::string &in_servers_list) |
218 | + { |
219 | + servers_list.assign(in_servers_list); |
220 | + servers= memcached_servers_parse(in_servers_list.c_str()); |
221 | + return (servers == NULL); |
222 | + } |
223 | + |
224 | + /** |
225 | + * Add a server to the list of memcached servers to use. |
226 | + * |
227 | + * @param[in] server_name name of the server to add |
228 | + * @param[in[ port port number of server to add |
229 | + * @return true on success; false otherwise |
230 | + */ |
231 | + bool addServer(const std::string &server_name, unsigned int port) |
232 | + { |
233 | + memcached_return rc; |
234 | + std::ostringstream strstm; |
235 | + servers_list.append(","); |
236 | + servers_list.append(server_name); |
237 | + servers_list.append(":"); |
238 | + strstm << port; |
239 | + servers_list.append(strstm.str()); |
240 | + servers= memcached_server_list_append(servers, |
241 | + server_name.c_str(), |
242 | + port, |
243 | + &rc); |
244 | + return (rc == MEMCACHED_SUCCESS); |
245 | + } |
246 | + |
247 | + /** |
248 | * Fetches an individual value from the server. mget() must always |
249 | * be called before using this method. |
250 | * |
251 | @@ -127,7 +226,7 @@ |
252 | * @return true on success; false otherwise |
253 | */ |
254 | bool get(const std::string &key, |
255 | - std::vector<char> &ret_val) |
256 | + std::vector<char> &ret_val) throw (Error) |
257 | { |
258 | uint32_t flags= 0; |
259 | memcached_return rc; |
260 | @@ -135,7 +234,7 @@ |
261 | |
262 | if (key.empty()) |
263 | { |
264 | - return false; |
265 | + throw(Error("the key supplied is empty!", false)); |
266 | } |
267 | char *value= memcached_get(&memc, key.c_str(), key.length(), |
268 | &value_length, &flags, &rc); |
269 | @@ -162,7 +261,7 @@ |
270 | */ |
271 | bool getByKey(const std::string &master_key, |
272 | const std::string &key, |
273 | - std::vector<char> &ret_val) |
274 | + std::vector<char> &ret_val) throw(Error) |
275 | { |
276 | uint32_t flags= 0; |
277 | memcached_return rc; |
278 | @@ -170,10 +269,10 @@ |
279 | |
280 | if (master_key.empty() || key.empty()) |
281 | { |
282 | - return false; |
283 | + throw(Error("the master key or key supplied is empty!", false)); |
284 | } |
285 | - char *value= memcached_get_by_key(&memc, |
286 | - master_key.c_str(), master_key.length(), |
287 | + char *value= memcached_get_by_key(&memc, |
288 | + master_key.c_str(), master_key.length(), |
289 | key.c_str(), key.length(), |
290 | &value_length, &flags, &rc); |
291 | if (value) |
292 | @@ -239,16 +338,16 @@ |
293 | * @param[in] flags flags to store with the object |
294 | * @return true on succcess; false otherwise |
295 | */ |
296 | - bool set(const std::string &key, |
297 | + bool set(const std::string &key, |
298 | const std::vector<char> &value, |
299 | time_t expiration, |
300 | - uint32_t flags) |
301 | + uint32_t flags) throw(Error) |
302 | { |
303 | if (key.empty() || value.empty()) |
304 | { |
305 | - return false; |
306 | + throw(Error("the key or value supplied is empty!", false)); |
307 | } |
308 | - memcached_return rc= memcached_set(&memc, |
309 | + memcached_return rc= memcached_set(&memc, |
310 | key.c_str(), key.length(), |
311 | &value[0], value.size(), |
312 | expiration, flags); |
313 | @@ -270,13 +369,13 @@ |
314 | const std::string &key, |
315 | const std::vector<char> &value, |
316 | time_t expiration, |
317 | - uint32_t flags) |
318 | + uint32_t flags) throw(Error) |
319 | { |
320 | if (master_key.empty() || |
321 | key.empty() || |
322 | value.empty()) |
323 | { |
324 | - return false; |
325 | + throw(Error("the key or value supplied is empty!", false)); |
326 | } |
327 | memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(), |
328 | master_key.length(), |
329 | @@ -300,11 +399,11 @@ |
330 | bool setAll(std::vector<std::string> &keys, |
331 | std::vector< std::vector<char> *> &values, |
332 | time_t expiration, |
333 | - uint32_t flags) |
334 | + uint32_t flags) throw(Error) |
335 | { |
336 | if (keys.size() != values.size()) |
337 | { |
338 | - return false; |
339 | + throw(Error("The number of keys and values do not match!", false)); |
340 | } |
341 | bool retval= true; |
342 | std::vector<std::string>::iterator key_it= keys.begin(); |
343 | @@ -333,11 +432,11 @@ |
344 | */ |
345 | bool setAll(std::map<const std::string, std::vector<char> > &key_value_map, |
346 | time_t expiration, |
347 | - uint32_t flags) |
348 | + uint32_t flags) throw(Error) |
349 | { |
350 | if (key_value_map.empty()) |
351 | { |
352 | - return false; |
353 | + throw(Error("The key/values are not properly set!", false)); |
354 | } |
355 | bool retval= true; |
356 | std::map<const std::string, std::vector<char> >::iterator it= |
357 | @@ -347,7 +446,9 @@ |
358 | retval= set(it->first, it->second, expiration, flags); |
359 | if (retval == false) |
360 | { |
361 | - return false; |
362 | + std::string err_buff("There was an error setting the key "); |
363 | + err_buff.append(it->first); |
364 | + throw(Error(err_buff, false)); |
365 | } |
366 | ++it; |
367 | } |
368 | @@ -364,11 +465,11 @@ |
369 | * @param[out] value store the result of the increment here |
370 | * @return true on success; false otherwise |
371 | */ |
372 | - bool increment(const std::string &key, uint32_t offset, uint64_t *value) |
373 | + bool increment(const std::string &key, uint32_t offset, uint64_t *value) throw(Error) |
374 | { |
375 | if (key.empty()) |
376 | { |
377 | - return false; |
378 | + throw(Error("the key supplied is empty!", false)); |
379 | } |
380 | memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(), |
381 | offset, value); |
382 | @@ -386,10 +487,11 @@ |
383 | * @return true on success; false otherwise |
384 | */ |
385 | bool decrement(const std::string &key, uint32_t offset, uint64_t *value) |
386 | + throw(Error) |
387 | { |
388 | if (key.empty()) |
389 | { |
390 | - return false; |
391 | + throw(Error("the key supplied is empty!", false)); |
392 | } |
393 | memcached_return rc= memcached_decrement(&memc, key.c_str(), |
394 | key.length(), |
395 | @@ -407,10 +509,11 @@ |
396 | * @return true on success; false otherwise |
397 | */ |
398 | bool add(const std::string &key, const std::vector<char> &value) |
399 | + throw(Error) |
400 | { |
401 | if (key.empty() || value.empty()) |
402 | { |
403 | - return false; |
404 | + throw(Error("the key or value supplied is empty!", false)); |
405 | } |
406 | memcached_return rc= memcached_add(&memc, key.c_str(), key.length(), |
407 | &value[0], value.size(), 0, 0); |
408 | @@ -429,13 +532,13 @@ |
409 | */ |
410 | bool addByKey(const std::string &master_key, |
411 | const std::string &key, |
412 | - const std::vector<char> &value) |
413 | + const std::vector<char> &value) throw(Error) |
414 | { |
415 | if (master_key.empty() || |
416 | key.empty() || |
417 | value.empty()) |
418 | { |
419 | - return false; |
420 | + throw(Error("the master key or key supplied is empty!", false)); |
421 | } |
422 | memcached_return rc= memcached_add_by_key(&memc, |
423 | master_key.c_str(), |
424 | @@ -456,12 +559,12 @@ |
425 | * @param[in[ value value to replace object with |
426 | * @return true on success; false otherwise |
427 | */ |
428 | - bool replace(const std::string &key, const std::vector<char> &value) |
429 | + bool replace(const std::string &key, const std::vector<char> &value) throw(Error) |
430 | { |
431 | if (key.empty() || |
432 | value.empty()) |
433 | { |
434 | - return false; |
435 | + throw(Error("the key or value supplied is empty!", false)); |
436 | } |
437 | memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(), |
438 | &value[0], value.size(), |
439 | @@ -487,7 +590,7 @@ |
440 | key.empty() || |
441 | value.empty()) |
442 | { |
443 | - return false; |
444 | + throw(Error("the master key or key supplied is empty!", false)); |
445 | } |
446 | memcached_return rc= memcached_replace_by_key(&memc, |
447 | master_key.c_str(), |
448 | @@ -508,10 +611,11 @@ |
449 | * @return true on success; false otherwise |
450 | */ |
451 | bool prepend(const std::string &key, const std::vector<char> &value) |
452 | + throw(Error) |
453 | { |
454 | if (key.empty() || value.empty()) |
455 | { |
456 | - return false; |
457 | + throw(Error("the key or value supplied is empty!", false)); |
458 | } |
459 | memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(), |
460 | &value[0], value.size(), 0, 0); |
461 | @@ -531,19 +635,20 @@ |
462 | bool prependByKey(const std::string &master_key, |
463 | const std::string &key, |
464 | const std::vector<char> &value) |
465 | + throw(Error) |
466 | { |
467 | if (master_key.empty() || |
468 | key.empty() || |
469 | value.empty()) |
470 | { |
471 | - return false; |
472 | + throw(Error("the master key or key supplied is empty!", false)); |
473 | } |
474 | - memcached_return rc= memcached_prepend_by_key(&memc, |
475 | - master_key.c_str(), |
476 | + memcached_return rc= memcached_prepend_by_key(&memc, |
477 | + master_key.c_str(), |
478 | master_key.length(), |
479 | - key.c_str(), |
480 | + key.c_str(), |
481 | key.length(), |
482 | - &value[0], |
483 | + &value[0], |
484 | value.size(), |
485 | 0, |
486 | 0); |
487 | @@ -558,16 +663,17 @@ |
488 | * @return true on success; false otherwise |
489 | */ |
490 | bool append(const std::string &key, const std::vector<char> &value) |
491 | + throw(Error) |
492 | { |
493 | if (key.empty() || value.empty()) |
494 | { |
495 | - return false; |
496 | + throw(Error("the key or value supplied is empty!", false)); |
497 | } |
498 | - memcached_return rc= memcached_append(&memc, |
499 | - key.c_str(), |
500 | + memcached_return rc= memcached_append(&memc, |
501 | + key.c_str(), |
502 | key.length(), |
503 | - &value[0], |
504 | - value.size(), |
505 | + &value[0], |
506 | + value.size(), |
507 | 0, 0); |
508 | return (rc == MEMCACHED_SUCCESS); |
509 | } |
510 | @@ -582,15 +688,16 @@ |
511 | * @param[in] value data to append to object's value |
512 | * @return true on success; false otherwise |
513 | */ |
514 | - bool appendByKey(const std::string &master_key, |
515 | - const std::string &key, |
516 | + bool appendByKey(const std::string &master_key, |
517 | + const std::string &key, |
518 | const std::vector<char> &value) |
519 | + throw(Error) |
520 | { |
521 | if (master_key.empty() || |
522 | key.empty() || |
523 | value.empty()) |
524 | { |
525 | - return false; |
526 | + throw(Error("the master key or key supplied is empty!", false)); |
527 | } |
528 | memcached_return rc= memcached_append_by_key(&memc, |
529 | master_key.c_str(), |
530 | @@ -613,11 +720,11 @@ |
531 | */ |
532 | bool cas(const std::string &key, |
533 | const std::vector<char> &value, |
534 | - uint64_t cas_arg) |
535 | + uint64_t cas_arg) throw(Error) |
536 | { |
537 | if (key.empty() || value.empty()) |
538 | { |
539 | - return false; |
540 | + throw(Error("the key or value supplied is empty!", false)); |
541 | } |
542 | memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(), |
543 | &value[0], value.size(), |
544 | @@ -638,13 +745,13 @@ |
545 | bool casByKey(const std::string &master_key, |
546 | const std::string &key, |
547 | const std::vector<char> &value, |
548 | - uint64_t cas_arg) |
549 | + uint64_t cas_arg) throw(Error) |
550 | { |
551 | if (master_key.empty() || |
552 | key.empty() || |
553 | value.empty()) |
554 | { |
555 | - return false; |
556 | + throw(Error("the master key, key or value supplied is empty!", false)); |
557 | } |
558 | memcached_return rc= memcached_cas_by_key(&memc, |
559 | master_key.c_str(), |
560 | @@ -663,11 +770,11 @@ |
561 | * @param[in] key key of object to delete |
562 | * @return true on success; false otherwise |
563 | */ |
564 | - bool remove(const std::string &key) |
565 | + bool remove(const std::string &key) throw(Error) |
566 | { |
567 | if (key.empty()) |
568 | { |
569 | - return false; |
570 | + throw(Error("the key supplied is empty!", false)); |
571 | } |
572 | memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0); |
573 | return (rc == MEMCACHED_SUCCESS); |
574 | @@ -681,15 +788,15 @@ |
575 | * @return true on success; false otherwise |
576 | */ |
577 | bool remove(const std::string &key, |
578 | - time_t expiration) |
579 | + time_t expiration) throw(Error) |
580 | { |
581 | if (key.empty()) |
582 | { |
583 | - return false; |
584 | + throw(Error("the key supplied is empty!", false)); |
585 | } |
586 | - memcached_return rc= memcached_delete(&memc, |
587 | - key.c_str(), |
588 | - key.length(), |
589 | + memcached_return rc= memcached_delete(&memc, |
590 | + key.c_str(), |
591 | + key.length(), |
592 | expiration); |
593 | return (rc == MEMCACHED_SUCCESS); |
594 | } |
595 | @@ -701,18 +808,18 @@ |
596 | * @param[in] key key of object to delete |
597 | * @return true on success; false otherwise |
598 | */ |
599 | - bool removeByKey(const std::string &master_key, |
600 | - const std::string &key) |
601 | + bool removeByKey(const std::string &master_key, |
602 | + const std::string &key) throw(Error) |
603 | { |
604 | if (master_key.empty() || key.empty()) |
605 | { |
606 | - return false; |
607 | + throw(Error("the master key or key supplied is empty!", false)); |
608 | } |
609 | - memcached_return rc= memcached_delete_by_key(&memc, |
610 | - master_key.c_str(), |
611 | + memcached_return rc= memcached_delete_by_key(&memc, |
612 | + master_key.c_str(), |
613 | master_key.length(), |
614 | - key.c_str(), |
615 | - key.length(), |
616 | + key.c_str(), |
617 | + key.length(), |
618 | 0); |
619 | return (rc == MEMCACHED_SUCCESS); |
620 | } |
621 | @@ -727,11 +834,11 @@ |
622 | */ |
623 | bool removeByKey(const std::string &master_key, |
624 | const std::string &key, |
625 | - time_t expiration) |
626 | + time_t expiration) throw(Error) |
627 | { |
628 | if (master_key.empty() || key.empty()) |
629 | { |
630 | - return false; |
631 | + throw(Error("the master key or key supplied is empty!", false)); |
632 | } |
633 | memcached_return rc= memcached_delete_by_key(&memc, |
634 | master_key.c_str(), |
635 | @@ -789,7 +896,9 @@ |
636 | |
637 | private: |
638 | |
639 | + std::string servers_list; |
640 | memcached_st memc; |
641 | + memcached_server_st *servers; |
642 | memcached_result_st result; |
643 | }; |
644 | |
645 | |
646 | === added file 'tests/cpp_example.cc' |
647 | --- tests/cpp_example.cc 1970-01-01 00:00:00 +0000 |
648 | +++ tests/cpp_example.cc 2009-09-19 23:36:57 +0000 |
649 | @@ -0,0 +1,202 @@ |
650 | +/* |
651 | + * An example file showing the usage of the C++ libmemcached interface. |
652 | + */ |
653 | + |
654 | +#include <vector> |
655 | +#include <string> |
656 | +#include <iostream> |
657 | +#include <algorithm> |
658 | + |
659 | +#include <string.h> |
660 | + |
661 | +#include <libmemcached/memcached.hpp> |
662 | + |
663 | +using namespace std; |
664 | +using namespace memcache; |
665 | + |
666 | +class DeletePtrs |
667 | +{ |
668 | +public: |
669 | + template<typename T> |
670 | + inline void operator()(const T *ptr) const |
671 | + { |
672 | + delete ptr; |
673 | + } |
674 | +}; |
675 | + |
676 | +class MyCache |
677 | +{ |
678 | +public: |
679 | + |
680 | + static const uint32_t num_of_clients= 10; |
681 | + |
682 | + static MyCache &singleton() |
683 | + { |
684 | + static MyCache instance; |
685 | + return instance; |
686 | + } |
687 | + |
688 | + void set(const string &key, |
689 | + const vector<char> &value) |
690 | + { |
691 | + time_t expiry= 0; |
692 | + uint32_t flags= 0; |
693 | + getCache()->set(key, value, expiry, flags); |
694 | + } |
695 | + |
696 | + vector<char> get(const string &key) |
697 | + { |
698 | + vector<char> ret_value; |
699 | + getCache()->get(key, ret_value); |
700 | + return ret_value; |
701 | + } |
702 | + |
703 | + void remove(const string &key) |
704 | + { |
705 | + getCache()->remove(key); |
706 | + } |
707 | + |
708 | + Memcache *getCache() |
709 | + { |
710 | + /* |
711 | + * pick a random element from the vector of clients. Obviously, this is |
712 | + * not very random but suffices as an example! |
713 | + */ |
714 | + uint32_t index= rand() % num_of_clients; |
715 | + return clients[index]; |
716 | + } |
717 | + |
718 | +private: |
719 | + |
720 | + /* |
721 | + * A vector of clients. |
722 | + */ |
723 | + std::vector<Memcache *> clients; |
724 | + |
725 | + MyCache() |
726 | + : |
727 | + clients() |
728 | + { |
729 | + /* create clients and add them to the vector */ |
730 | + for (uint32_t i= 0; i < num_of_clients; i++) |
731 | + { |
732 | + Memcache *client= new Memcache("127.0.0.1:11211"); |
733 | + clients.push_back(client); |
734 | + } |
735 | + } |
736 | + |
737 | + ~MyCache() |
738 | + { |
739 | + for_each(clients.begin(), clients.end(), DeletePtrs()); |
740 | + clients.clear(); |
741 | + } |
742 | + |
743 | + MyCache(const MyCache&); |
744 | + |
745 | +}; |
746 | + |
747 | +class Product |
748 | +{ |
749 | +public: |
750 | + |
751 | + Product(int in_id, double in_price) |
752 | + : |
753 | + id(in_id), |
754 | + price(in_price) |
755 | + {} |
756 | + |
757 | + Product() |
758 | + : |
759 | + id(0), |
760 | + price(0.0) |
761 | + {} |
762 | + |
763 | + int getId() const |
764 | + { |
765 | + return id; |
766 | + } |
767 | + |
768 | + double getPrice() const |
769 | + { |
770 | + return price; |
771 | + } |
772 | + |
773 | +private: |
774 | + |
775 | + int id; |
776 | + double price; |
777 | + |
778 | +}; |
779 | + |
780 | +void setAllProducts(vector<Product> &products) |
781 | +{ |
782 | + vector<char> raw_products(products.size() * sizeof(Product)); |
783 | + memcpy(&raw_products[0], &products[0], products.size() * sizeof(Product)); |
784 | + MyCache::singleton().set("AllProducts", raw_products); |
785 | +} |
786 | + |
787 | +vector<Product> getAllProducts() |
788 | +{ |
789 | + vector<char> raw_products = MyCache::singleton().get("AllProducts"); |
790 | + vector<Product> products(raw_products.size() / sizeof(Product)); |
791 | + memcpy(&products[0], &raw_products[0], raw_products.size()); |
792 | + return products; |
793 | +} |
794 | + |
795 | +Product getProduct(const string &key) |
796 | +{ |
797 | + vector<char> raw_product= MyCache::singleton().get(key); |
798 | + Product ret; |
799 | + if (! raw_product.empty()) |
800 | + { |
801 | + memcpy(&ret, &raw_product[0], sizeof(Product)); |
802 | + } |
803 | + else |
804 | + { |
805 | + /* retrieve it from the persistent store */ |
806 | + } |
807 | + return ret; |
808 | +} |
809 | + |
810 | +void setProduct(const string &key, const Product &product) |
811 | +{ |
812 | + vector<char> raw_product(sizeof(Product)); |
813 | + memcpy(&raw_product[0], &product, sizeof(Product)); |
814 | + MyCache::singleton().set(key, raw_product); |
815 | +} |
816 | + |
817 | +int main() |
818 | +{ |
819 | +#if 0 |
820 | + Product pad(1, 5.0); |
821 | + const string key("padraig"); |
822 | + cout << "Going to set an object in the cache..." << endl; |
823 | + setProduct(key, pad); |
824 | + cout << "Now retrieve that key..." << endl; |
825 | + Product test= getProduct(key); |
826 | + double price= test.getPrice(); |
827 | + cout << "Price of retrieve object: " << price << endl; |
828 | + Product next(2, 10.0); |
829 | + vector<Product> products; |
830 | + products.push_back(pad); |
831 | + products.push_back(next); |
832 | + cout << "going to set a vector of products..." << endl; |
833 | + setAllProducts(products); |
834 | + cout << "now retrieve those products..." << endl; |
835 | + vector<Product> got= getAllProducts(); |
836 | + cout << "size of retrieved vector: " << got.size() << endl; |
837 | + vector<Product>::iterator iter= got.begin(); |
838 | + while (iter != got.end()) |
839 | + { |
840 | + cout << "product " << (*iter).getId() << " costs " << (*iter).getPrice() << endl; |
841 | + ++iter; |
842 | + } |
843 | +#endif |
844 | + Memcache first_client("127.0.0.1:11211"); |
845 | + Memcache second_client("127.0.0.1", 11211); |
846 | + //first_client.set("key", some_vector_of_chars, expiry, flags); |
847 | + //first_client.get("key", vector_to_fill_with_data); |
848 | + //first_client.remove("key"); |
849 | + first_client.addServer("192.168.1.1", 11211); |
850 | + return 0; |
851 | +} |
852 | |
853 | === modified file 'tests/plus.cpp' |
854 | --- tests/plus.cpp 2009-07-27 02:29:44 +0000 |
855 | +++ tests/plus.cpp 2009-09-17 19:14:07 +0000 |
856 | @@ -17,6 +17,7 @@ |
857 | #include "test.h" |
858 | |
859 | #include <string> |
860 | +#include <iostream> |
861 | |
862 | using namespace std; |
863 | using namespace memcache; |
864 | @@ -63,7 +64,20 @@ |
865 | |
866 | assert((memcmp(&test_value[0], &value[0], test_value.size()) == 0)); |
867 | |
868 | - return TEST_SUCCESS; |
869 | + /* |
870 | + * Simple test of the exceptions here...this should throw an exception |
871 | + * saying that the key is empty. |
872 | + */ |
873 | + try |
874 | + { |
875 | + foo.set("", value, 0, 0); |
876 | + } |
877 | + catch (Error &err) |
878 | + { |
879 | + return TEST_SUCCESS; |
880 | + } |
881 | + |
882 | + return TEST_FAILURE; |
883 | } |
884 | |
885 | test_return increment_test(memcached_st *memc) |
This branch adds some more constructors to the libmemcached C++ api which will make it easier to use. I also created a sample C++ file which demonstrates some sample usage of the C++ api. I added this file (cpp_example.cc) under the tests directory.
-Padraig