Merge Trond.
[m6w6/libmemcached] / libmemcached / memcached.hpp
1 /*
2 * Summary: C++ interface for memcached server
3 *
4 * Copy: See Copyright for the status of this software.
5 *
6 * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
7 * Patrick Galbraith <patg@patg.net>
8 */
9
10 /**
11 * @file memcached.hpp
12 * @brief Libmemcached C++ interface
13 */
14
15 #ifndef LIBMEMCACHEDPP_H
16 #define LIBMEMCACHEDPP_H
17
18 #include <libmemcached/memcached.h>
19
20 #include <string.h>
21
22 #include <string>
23 #include <vector>
24 #include <map>
25
26 namespace memcache
27 {
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 Memcache
34 {
35 public:
36
37 Memcache()
38 :
39 memc(),
40 result()
41 {
42 memcached_create(&memc);
43 }
44
45 Memcache(memcached_st *clone)
46 :
47 memc(),
48 result()
49 {
50 memcached_clone(&memc, clone);
51 }
52
53 Memcache(const Memcache &rhs)
54 :
55 memc(),
56 result()
57 {
58 memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl()));
59 }
60
61 ~Memcache()
62 {
63 memcached_free(&memc);
64 }
65
66 /**
67 * Get the internal memcached_st *
68 */
69 memcached_st &getImpl()
70 {
71 return memc;
72 }
73
74 /**
75 * Get the internal memcached_st *
76 */
77 const memcached_st &getImpl() const
78 {
79 return memc;
80 }
81
82 /**
83 * Return an error string for the given return structure.
84 *
85 * @param[in] rc a memcached_return structure
86 * @return error string corresponding to given return code in the library.
87 */
88 const std::string getError(memcached_return rc) const
89 {
90 /* first parameter to strerror is unused */
91 return memcached_strerror(NULL, rc);
92 }
93
94 /**
95 * Fetches an individual value from the server. mget() must always
96 * be called before using this method.
97 *
98 * @param[in] key key of object to fetch
99 * @param[out] ret_val store returned object in this vector
100 * @return a memcached return structure
101 */
102 memcached_return fetch(std::string &key,
103 std::vector<char> &ret_val)
104 {
105 char ret_key[MEMCACHED_MAX_KEY];
106 size_t value_length= 0;
107 size_t key_length= 0;
108 memcached_return rc;
109 uint32_t flags= 0;
110 char *value= memcached_fetch(&memc, ret_key, &key_length,
111 &value_length, &flags, &rc);
112 if (value && ret_val.empty())
113 {
114 ret_val.reserve(value_length);
115 ret_val.assign(value, value + value_length);
116 key.assign(ret_key);
117 }
118 return rc;
119 }
120
121 /**
122 * Fetches an individual value from the server.
123 *
124 * @param[in] key key of object whose value to get
125 * @param[out] ret_val object that is retrieved is stored in
126 * this vector
127 * @return true on success; false otherwise
128 */
129 bool get(const std::string &key,
130 std::vector<char> &ret_val)
131 {
132 uint32_t flags= 0;
133 memcached_return rc;
134 size_t value_length= 0;
135
136 if (key.empty())
137 {
138 return false;
139 }
140 char *value= memcached_get(&memc, key.c_str(), key.length(),
141 &value_length, &flags, &rc);
142 if (value != NULL && ret_val.empty())
143 {
144 ret_val.reserve(value_length);
145 ret_val.assign(value, value + value_length);
146 return true;
147 }
148 return false;
149 }
150
151 /**
152 * Fetches an individual from a server which is specified by
153 * the master_key parameter that is used for determining which
154 * server an object was stored in if key partitioning was
155 * used for storage.
156 *
157 * @param[in] master_key key that specifies server object is stored on
158 * @param[in] key key of object whose value to get
159 * @param[out] ret_val object that is retrieved is stored in
160 * this vector
161 * @return true on success; false otherwise
162 */
163 bool getByKey(const std::string &master_key,
164 const std::string &key,
165 std::vector<char> &ret_val)
166 {
167 uint32_t flags= 0;
168 memcached_return rc;
169 size_t value_length= 0;
170
171 if (master_key.empty() || key.empty())
172 {
173 return false;
174 }
175 char *value= memcached_get_by_key(&memc,
176 master_key.c_str(), master_key.length(),
177 key.c_str(), key.length(),
178 &value_length, &flags, &rc);
179 if (value)
180 {
181 ret_val.reserve(value_length);
182 ret_val.assign(value, value + value_length);
183 return true;
184 }
185 return false;
186 }
187
188 /**
189 * Selects multiple keys at once. This method always
190 * works asynchronously.
191 *
192 * @param[in] keys vector of keys to select
193 * @return true if all keys are found
194 */
195 bool mget(std::vector<std::string> &keys)
196 {
197 std::vector<const char *> real_keys;
198 std::vector<size_t> key_len;
199 /*
200 * Construct an array which will contain the length
201 * of each of the strings in the input vector. Also, to
202 * interface with the memcached C API, we need to convert
203 * the vector of std::string's to a vector of char *.
204 */
205 real_keys.reserve(keys.size());
206 key_len.reserve(keys.size());
207
208 std::vector<std::string>::iterator it= keys.begin();
209
210 while (it != keys.end())
211 {
212 real_keys.push_back(const_cast<char *>((*it).c_str()));
213 key_len.push_back((*it).length());
214 ++it;
215 }
216
217 /*
218 * If the std::vector of keys is empty then we cannot
219 * call memcached_mget as we will get undefined behavior.
220 */
221 if (! real_keys.empty())
222 {
223 memcached_return rc= memcached_mget(&memc, &real_keys[0], &key_len[0],
224 real_keys.size());
225 return (rc == MEMCACHED_SUCCESS);
226 }
227
228 return false;
229 }
230
231 /**
232 * Writes an object to the server. If the object already exists, it will
233 * overwrite the existing object. This method always returns true
234 * when using non-blocking mode unless a network error occurs.
235 *
236 * @param[in] key key of object to write to server
237 * @param[in] value value of object to write to server
238 * @param[in] expiration time to keep the object stored in the server for
239 * @param[in] flags flags to store with the object
240 * @return true on succcess; false otherwise
241 */
242 bool set(const std::string &key,
243 const std::vector<char> &value,
244 time_t expiration,
245 uint32_t flags)
246 {
247 if (key.empty() || value.empty())
248 {
249 return false;
250 }
251 memcached_return rc= memcached_set(&memc,
252 key.c_str(), key.length(),
253 &value[0], value.size(),
254 expiration, flags);
255 return (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
256 }
257
258 /**
259 * Writes an object to a server specified by the master_key parameter.
260 * If the object already exists, it will overwrite the existing object.
261 *
262 * @param[in] master_key key that specifies server to write to
263 * @param[in] key key of object to write to server
264 * @param[in] value value of object to write to server
265 * @param[in] expiration time to keep the object stored in the server for
266 * @param[in] flags flags to store with the object
267 * @return true on succcess; false otherwise
268 */
269 bool setByKey(const std::string &master_key,
270 const std::string &key,
271 const std::vector<char> &value,
272 time_t expiration,
273 uint32_t flags)
274 {
275 if (master_key.empty() ||
276 key.empty() ||
277 value.empty())
278 {
279 return false;
280 }
281 memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
282 master_key.length(),
283 key.c_str(), key.length(),
284 &value[0], value.size(),
285 expiration,
286 flags);
287 return (rc == MEMCACHED_SUCCESS);
288 }
289
290 /**
291 * Writes a list of objects to the server. Objects are specified by
292 * 2 vectors - 1 vector of keys and 1 vector of values.
293 *
294 * @param[in] keys vector of keys of objects to write to server
295 * @param[in] values vector of values of objects to write to server
296 * @param[in] expiration time to keep the objects stored in server for
297 * @param[in] flags flags to store with the objects
298 * @return true on success; false otherwise
299 */
300 bool setAll(std::vector<std::string> &keys,
301 std::vector< std::vector<char> *> &values,
302 time_t expiration,
303 uint32_t flags)
304 {
305 if (keys.size() != values.size())
306 {
307 return false;
308 }
309 bool retval= true;
310 std::vector<std::string>::iterator key_it= keys.begin();
311 std::vector< std::vector<char> *>::iterator val_it= values.begin();
312 while (key_it != keys.end())
313 {
314 retval= set((*key_it), *(*val_it), expiration, flags);
315 if (retval == false)
316 {
317 return retval;
318 }
319 ++key_it;
320 ++val_it;
321 }
322 return retval;
323 }
324
325 /**
326 * Writes a list of objects to the server. Objects are specified by
327 * a map of keys to values.
328 *
329 * @param[in] key_value_map map of keys and values to store in server
330 * @param[in] expiration time to keep the objects stored in server for
331 * @param[in] flags flags to store with the objects
332 * @return true on success; false otherwise
333 */
334 bool setAll(std::map<const std::string, std::vector<char> > &key_value_map,
335 time_t expiration,
336 uint32_t flags)
337 {
338 if (key_value_map.empty())
339 {
340 return false;
341 }
342 bool retval= true;
343 std::map<const std::string, std::vector<char> >::iterator it=
344 key_value_map.begin();
345 while (it != key_value_map.end())
346 {
347 retval= set(it->first, it->second, expiration, flags);
348 if (retval == false)
349 {
350 return false;
351 }
352 ++it;
353 }
354 return true;
355 }
356
357 /**
358 * Increment the value of the object associated with the specified
359 * key by the offset given. The resulting value is saved in the value
360 * parameter.
361 *
362 * @param[in] key key of object in server whose value to increment
363 * @param[in] offset amount to increment object's value by
364 * @param[out] value store the result of the increment here
365 * @return true on success; false otherwise
366 */
367 bool increment(const std::string &key, uint32_t offset, uint64_t *value)
368 {
369 if (key.empty())
370 {
371 return false;
372 }
373 memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(),
374 offset, value);
375 return (rc == MEMCACHED_SUCCESS);
376 }
377
378 /**
379 * Decrement the value of the object associated with the specified
380 * key by the offset given. The resulting value is saved in the value
381 * parameter.
382 *
383 * @param[in] key key of object in server whose value to decrement
384 * @param[in] offset amount to increment object's value by
385 * @param[out] value store the result of the decrement here
386 * @return true on success; false otherwise
387 */
388 bool decrement(const std::string &key, uint32_t offset, uint64_t *value)
389 {
390 if (key.empty())
391 {
392 return false;
393 }
394 memcached_return rc= memcached_decrement(&memc, key.c_str(),
395 key.length(),
396 offset, value);
397 return (rc == MEMCACHED_SUCCESS);
398 }
399
400
401 /**
402 * Add an object with the specified key and value to the server. This
403 * function returns false if the object already exists on the server.
404 *
405 * @param[in] key key of object to add
406 * @param[in] value of object to add
407 * @return true on success; false otherwise
408 */
409 bool add(const std::string &key, const std::vector<char> &value)
410 {
411 if (key.empty() || value.empty())
412 {
413 return false;
414 }
415 memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
416 &value[0], value.size(), 0, 0);
417 return (rc == MEMCACHED_SUCCESS);
418 }
419
420 /**
421 * Add an object with the specified key and value to the server. This
422 * function returns false if the object already exists on the server. The
423 * server to add the object to is specified by the master_key parameter.
424 *
425 * @param[in[ master_key key of server to add object to
426 * @param[in] key key of object to add
427 * @param[in] value of object to add
428 * @return true on success; false otherwise
429 */
430 bool addByKey(const std::string &master_key,
431 const std::string &key,
432 const std::vector<char> &value)
433 {
434 if (master_key.empty() ||
435 key.empty() ||
436 value.empty())
437 {
438 return false;
439 }
440 memcached_return rc= memcached_add_by_key(&memc,
441 master_key.c_str(),
442 master_key.length(),
443 key.c_str(),
444 key.length(),
445 &value[0],
446 value.size(),
447 0, 0);
448 return (rc == MEMCACHED_SUCCESS);
449 }
450
451 /**
452 * Replaces an object on the server. This method only succeeds
453 * if the object is already present on the server.
454 *
455 * @param[in] key key of object to replace
456 * @param[in[ value value to replace object with
457 * @return true on success; false otherwise
458 */
459 bool replace(const std::string &key, const std::vector<char> &value)
460 {
461 if (key.empty() ||
462 value.empty())
463 {
464 return false;
465 }
466 memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
467 &value[0], value.size(),
468 0, 0);
469 return (rc == MEMCACHED_SUCCESS);
470 }
471
472 /**
473 * Replaces an object on the server. This method only succeeds
474 * if the object is already present on the server. The server
475 * to replace the object on is specified by the master_key param.
476 *
477 * @param[in] master_key key of server to replace object on
478 * @param[in] key key of object to replace
479 * @param[in[ value value to replace object with
480 * @return true on success; false otherwise
481 */
482 bool replaceByKey(const std::string &master_key,
483 const std::string &key,
484 const std::vector<char> &value)
485 {
486 if (master_key.empty() ||
487 key.empty() ||
488 value.empty())
489 {
490 return false;
491 }
492 memcached_return rc= memcached_replace_by_key(&memc,
493 master_key.c_str(),
494 master_key.length(),
495 key.c_str(),
496 key.length(),
497 &value[0],
498 value.size(),
499 0, 0);
500 return (rc == MEMCACHED_SUCCESS);
501 }
502
503 /**
504 * Places a segment of data before the last piece of data stored.
505 *
506 * @param[in] key key of object whose value we will prepend data to
507 * @param[in] value data to prepend to object's value
508 * @return true on success; false otherwise
509 */
510 bool prepend(const std::string &key, const std::vector<char> &value)
511 {
512 if (key.empty() || value.empty())
513 {
514 return false;
515 }
516 memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
517 &value[0], value.size(), 0, 0);
518 return (rc == MEMCACHED_SUCCESS);
519 }
520
521 /**
522 * Places a segment of data before the last piece of data stored. The
523 * server on which the object where we will be prepending data is stored
524 * on is specified by the master_key parameter.
525 *
526 * @param[in] master_key key of server where object is stored
527 * @param[in] key key of object whose value we will prepend data to
528 * @param[in] value data to prepend to object's value
529 * @return true on success; false otherwise
530 */
531 bool prependByKey(const std::string &master_key,
532 const std::string &key,
533 const std::vector<char> &value)
534 {
535 if (master_key.empty() ||
536 key.empty() ||
537 value.empty())
538 {
539 return false;
540 }
541 memcached_return rc= memcached_prepend_by_key(&memc,
542 master_key.c_str(),
543 master_key.length(),
544 key.c_str(),
545 key.length(),
546 &value[0],
547 value.size(),
548 0,
549 0);
550 return (rc == MEMCACHED_SUCCESS);
551 }
552
553 /**
554 * Places a segment of data at the end of the last piece of data stored.
555 *
556 * @param[in] key key of object whose value we will append data to
557 * @param[in] value data to append to object's value
558 * @return true on success; false otherwise
559 */
560 bool append(const std::string &key, const std::vector<char> &value)
561 {
562 if (key.empty() || value.empty())
563 {
564 return false;
565 }
566 memcached_return rc= memcached_append(&memc,
567 key.c_str(),
568 key.length(),
569 &value[0],
570 value.size(),
571 0, 0);
572 return (rc == MEMCACHED_SUCCESS);
573 }
574
575 /**
576 * Places a segment of data at the end of the last piece of data stored. The
577 * server on which the object where we will be appending data is stored
578 * on is specified by the master_key parameter.
579 *
580 * @param[in] master_key key of server where object is stored
581 * @param[in] key key of object whose value we will append data to
582 * @param[in] value data to append to object's value
583 * @return true on success; false otherwise
584 */
585 bool appendByKey(const std::string &master_key,
586 const std::string &key,
587 const std::vector<char> &value)
588 {
589 if (master_key.empty() ||
590 key.empty() ||
591 value.empty())
592 {
593 return false;
594 }
595 memcached_return rc= memcached_append_by_key(&memc,
596 master_key.c_str(),
597 master_key.length(),
598 key.c_str(),
599 key.length(),
600 &value[0],
601 value.size(),
602 0, 0);
603 return (rc == MEMCACHED_SUCCESS);
604 }
605
606 /**
607 * Overwrite data in the server as long as the cas_arg value
608 * is still the same in the server.
609 *
610 * @param[in] key key of object in server
611 * @param[in] value value to store for object in server
612 * @param[in] cas_arg "cas" value
613 */
614 bool cas(const std::string &key,
615 const std::vector<char> &value,
616 uint64_t cas_arg)
617 {
618 if (key.empty() || value.empty())
619 {
620 return false;
621 }
622 memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
623 &value[0], value.size(),
624 0, 0, cas_arg);
625 return (rc == MEMCACHED_SUCCESS);
626 }
627
628 /**
629 * Overwrite data in the server as long as the cas_arg value
630 * is still the same in the server. The server to use is
631 * specified by the master_key parameter.
632 *
633 * @param[in] master_key specifies server to operate on
634 * @param[in] key key of object in server
635 * @param[in] value value to store for object in server
636 * @param[in] cas_arg "cas" value
637 */
638 bool casByKey(const std::string &master_key,
639 const std::string &key,
640 const std::vector<char> &value,
641 uint64_t cas_arg)
642 {
643 if (master_key.empty() ||
644 key.empty() ||
645 value.empty())
646 {
647 return false;
648 }
649 memcached_return rc= memcached_cas_by_key(&memc,
650 master_key.c_str(),
651 master_key.length(),
652 key.c_str(),
653 key.length(),
654 &value[0],
655 value.size(),
656 0, 0, cas_arg);
657 return (rc == MEMCACHED_SUCCESS);
658 }
659
660 /**
661 * Delete an object from the server specified by the key given.
662 *
663 * @param[in] key key of object to delete
664 * @return true on success; false otherwise
665 */
666 bool remove(const std::string &key)
667 {
668 if (key.empty())
669 {
670 return false;
671 }
672 memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
673 return (rc == MEMCACHED_SUCCESS);
674 }
675
676 /**
677 * Delete an object from the server specified by the key given.
678 *
679 * @param[in] key key of object to delete
680 * @param[in] expiration time to delete the object after
681 * @return true on success; false otherwise
682 */
683 bool remove(const std::string &key,
684 time_t expiration)
685 {
686 if (key.empty())
687 {
688 return false;
689 }
690 memcached_return rc= memcached_delete(&memc,
691 key.c_str(),
692 key.length(),
693 expiration);
694 return (rc == MEMCACHED_SUCCESS);
695 }
696
697 /**
698 * Delete an object from the server specified by the key given.
699 *
700 * @param[in] master_key specifies server to remove object from
701 * @param[in] key key of object to delete
702 * @return true on success; false otherwise
703 */
704 bool removeByKey(const std::string &master_key,
705 const std::string &key)
706 {
707 if (master_key.empty() || key.empty())
708 {
709 return false;
710 }
711 memcached_return rc= memcached_delete_by_key(&memc,
712 master_key.c_str(),
713 master_key.length(),
714 key.c_str(),
715 key.length(),
716 0);
717 return (rc == MEMCACHED_SUCCESS);
718 }
719
720 /**
721 * Delete an object from the server specified by the key given.
722 *
723 * @param[in] master_key specifies server to remove object from
724 * @param[in] key key of object to delete
725 * @param[in] expiration time to delete the object after
726 * @return true on success; false otherwise
727 */
728 bool removeByKey(const std::string &master_key,
729 const std::string &key,
730 time_t expiration)
731 {
732 if (master_key.empty() || key.empty())
733 {
734 return false;
735 }
736 memcached_return rc= memcached_delete_by_key(&memc,
737 master_key.c_str(),
738 master_key.length(),
739 key.c_str(),
740 key.length(),
741 expiration);
742 return (rc == MEMCACHED_SUCCESS);
743 }
744
745 /**
746 * Wipe the contents of memcached servers.
747 *
748 * @param[in] expiration time to wait until wiping contents of
749 * memcached servers
750 * @return true on success; false otherwise
751 */
752 bool flush(time_t expiration)
753 {
754 memcached_return rc= memcached_flush(&memc, expiration);
755 return (rc == MEMCACHED_SUCCESS);
756 }
757
758 /**
759 * Callback function for result sets. It passes the result
760 * sets to the list of functions provided.
761 *
762 * @param[in] callback list of callback functions
763 * @param[in] context pointer to memory reference that is
764 * supplied to the calling function
765 * @param[in] num_of_callbacks number of callback functions
766 * @return true on success; false otherwise
767 */
768 bool fetchExecute(memcached_execute_function *callback,
769 void *context,
770 unsigned int num_of_callbacks)
771 {
772 memcached_return rc= memcached_fetch_execute(&memc,
773 callback,
774 context,
775 num_of_callbacks);
776 return (rc == MEMCACHED_SUCCESS);
777 }
778
779 /**
780 * Get the library version string.
781 * @return std::string containing a copy of the library version string.
782 */
783 const std::string libVersion() const
784 {
785 const char *ver= memcached_lib_version();
786 const std::string version(ver);
787 return version;
788 }
789
790 private:
791
792 memcached_st memc;
793 memcached_result_st result;
794 };
795
796 }
797
798 #endif /* LIBMEMCACHEDPP_H */