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