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 Memcache()76 Memcache() 77 { 78 memc_= memcached(NULL, 0); 79 } 80 Memcache(const std::string & config)81 Memcache(const std::string &config) 82 { 83 memc_= memcached(config.c_str(), config.size()); 84 } 85 Memcache(const std::string & hostname,in_port_t port)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 Memcache(memcached_st * clone)95 Memcache(memcached_st *clone) 96 { 97 memc_= memcached_clone(NULL, clone); 98 } 99 Memcache(const Memcache & rhs)100 Memcache(const Memcache &rhs) 101 { 102 memc_= memcached_clone(NULL, rhs.getImpl()); 103 } 104 operator =(const Memcache & rhs)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 ~Memcache()116 ~Memcache() 117 { 118 memcached_free(memc_); 119 } 120 121 /** 122 * Get the internal memcached_st * 123 */ getImpl() const124 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 */ getError(memcached_return_t rc) const135 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 error(std::string & error_message) const141 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 error() const152 bool error() const 153 { 154 if (memcached_failed(memcached_last_error(memc_))) 155 { 156 return true; 157 } 158 159 return false; 160 } 161 error(memcached_return_t & arg) const162 bool error(memcached_return_t& arg) const 163 { 164 arg= memcached_last_error(memc_); 165 return memcached_failed(arg); 166 } 167 setBehavior(memcached_behavior_t flag,uint64_t data)168 bool setBehavior(memcached_behavior_t flag, uint64_t data) 169 { 170 return (memcached_success(memcached_behavior_set(memc_, flag, data))); 171 } 172 getBehavior(memcached_behavior_t flag)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 */ configure(const std::string & configuration)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 */ addServer(const std::string & server_name,in_port_t port)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 */ removeServer(const std::string & server_name,in_port_t port)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 */ fetch(std::string & key,std::vector<char> & ret_val,uint32_t & flags,uint64_t & cas_value)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 fetch(std::string & key,std::vector<char> & ret_val)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 */ get(const std::string & key,std::vector<char> & ret_val)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 */ getByKey(const std::string & master_key,const std::string & key,std::vector<char> & ret_val)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 */ mget(const std::vector<std::string> & keys)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 */ set(const std::string & key,const std::vector<char> & value,time_t expiration,uint32_t flags)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 set(const std::string & key,const char * value,const size_t value_length,time_t expiration,uint32_t flags)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 */ setByKey(const std::string & master_key,const std::string & key,const std::vector<char> & value,time_t expiration,uint32_t flags)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 */ setAll(const std::vector<std::string> & keys,const std::vector<std::vector<char> * > & values,time_t expiration,uint32_t flags)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 */ setAll(const std::map<const std::string,std::vector<char>> & key_value_map,time_t expiration,uint32_t flags)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 */ increment(const std::string & key,uint32_t offset,uint64_t * value)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 */ decrement(const std::string & key,uint32_t offset,uint64_t * value)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 */ add(const std::string & key,const std::vector<char> & value)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 */ addByKey(const std::string & master_key,const std::string & key,const std::vector<char> & value)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 */ replace(const std::string & key,const std::vector<char> & value)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 */ replaceByKey(const std::string & master_key,const std::string & key,const std::vector<char> & value)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 */ prepend(const std::string & key,const std::vector<char> & value)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 */ prependByKey(const std::string & master_key,const std::string & key,const std::vector<char> & value)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 */ append(const std::string & key,const std::vector<char> & value)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 */ appendByKey(const std::string & master_key,const std::string & key,const std::vector<char> & value)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 */ cas(const std::string & key,const std::vector<char> & value,uint64_t cas_arg)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 */ casByKey(const std::string & master_key,const std::string & key,const std::vector<char> & value,uint64_t cas_arg)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 */ remove(const std::string & key)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 */ remove(const std::string & key,time_t expiration)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 */ removeByKey(const std::string & master_key,const std::string & key)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 */ removeByKey(const std::string & master_key,const std::string & key,time_t expiration)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 */ flush(time_t expiration=0)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 */ libVersion() const816 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 */ getStats(std::map<std::string,std::map<std::string,std::string>> & stats_map)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 } 879