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