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