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