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