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