docs/linkcheck/
docs/text
example/memcached_light
-libhashkit/configure.h
+libhashkit-1.0/configure.h
libmemcached-?.??/
-libmemcached/configure.h
+libmemcached-1.0/configure.h
libmemcached/dtrace_probes.h
libmemcached/generated_probes.h
libmemcached/memcached_configure.h
tests/memcat
clients/memexist
tests/memexist
+libmemcached/configure.h
+clients/memtouch
+tests/memtouch
+
+* Dropped libmemcached/memcached_util.h (undocumented header file)
+
0.53 Mon Sep 26 20:50:33 PDT 2011
* Fix for FreeBSD/OpenBSD and -lm
* Added memcached_exist()
libmemcached_libmemcached_la_LDFLAGS=
+include libtest/include.am
+
+include libhashkit-1.0/include.am
+include libmemcached-1.0/include.am
+include libmemcachedprotocol-0.0/include.am
+include libmemcachedutil-1.0/include.am
+
include clients/include.am
include docs/include.am
include example/include.am
include libhashkit/include.am
include libmemcached/include.am
-include libmemcached/util/include.am
-include libmemcached/protocol/include.am
+include libmemcachedutil/include.am
+include libmemcachedprotocol/include.am
include libmemcachedinternal/include.am
include libmemcachedinternal/util/include.am
-include libtest/include.am
include poll/include.am
include support/include.am
include tests/include.am
clients/memdump \
clients/memerror \
clients/memexist \
+ clients/memtouch \
clients/memflush \
clients/memparse \
clients/memping \
clients_memexist_SOURCES= clients/memexist.cc
clients_memexist_LDADD= $(CLIENTS_LDADDS)
+clients_memtouch_SOURCES= clients/memtouch.cc
+clients_memtouch_LDADD= $(CLIENTS_LDADDS)
+
clients_memflush_SOURCES= clients/memflush.cc
clients_memflush_LDADD= $(CLIENTS_LDADDS)
--- /dev/null
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include <config.h>
+
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+#include <libmemcached/memcached.h>
+
+#include "utilities.h"
+
+#define PROGRAM_NAME "memtouch"
+#define PROGRAM_DESCRIPTION "Update the expiration value of an alreasy existing value in the sever"
+
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+time_t expiration= 0;
+
+int main(int argc, char *argv[])
+{
+ int return_code= EXIT_SUCCESS;
+
+ options_parse(argc, argv);
+ initialize_sockets();
+
+ if (opt_servers == NULL)
+ {
+ char *temp;
+
+ if ((temp= getenv("MEMCACHED_SERVERS")))
+ {
+ opt_servers= strdup(temp);
+ }
+ else
+ {
+ std::cerr << "No Servers provided" << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ memcached_st *memc= memcached_create(NULL);
+ process_hash_option(memc, opt_hash);
+
+ memcached_server_st *servers= memcached_servers_parse(opt_servers);
+
+ memcached_server_push(memc, servers);
+ memcached_server_list_free(servers);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+ (uint64_t)opt_binary);
+
+ if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+ {
+ memcached_free(memc);
+ std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (opt_username)
+ {
+ memcached_return_t ret;
+ if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+ {
+ std::cerr << memcached_last_error_message(memc) << std::endl;
+ memcached_free(memc);
+ return EXIT_FAILURE;
+ }
+ }
+
+ while (optind < argc)
+ {
+ memcached_return_t rc= memcached_touch(memc, argv[optind], strlen(argv[optind]), expiration);
+ if (rc == MEMCACHED_NOTFOUND)
+ {
+ if (opt_verbose)
+ {
+ std::cout << "Could not find key \"" << argv[optind] << "\"" << std::endl;
+ }
+
+ return_code= EXIT_FAILURE;
+ }
+ else if (memcached_failed(rc))
+ {
+ if (opt_verbose)
+ {
+ std::cerr << "Fatal error for key \"" << argv[optind] << "\" :" << memcached_last_error_message(memc) << std::endl;
+ }
+
+ return_code= EXIT_FAILURE;
+ }
+ else // success
+ {
+ if (opt_verbose)
+ {
+ std::cout << "Found key " << argv[optind] << std::endl;
+ }
+ }
+
+ optind++;
+ }
+
+ memcached_free(memc);
+
+ if (opt_servers)
+ {
+ free(opt_servers);
+ }
+
+ if (opt_hash)
+ {
+ free(opt_hash);
+ }
+
+ return return_code;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+ memcached_programs_help_st help_options[]=
+ {
+ {0},
+ };
+
+ static struct option long_options[]=
+ {
+ {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+ {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+ {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+ {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+ {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+ {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+ {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+ {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+ {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+ {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+ {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+ {0, 0, 0, 0},
+ };
+
+ bool opt_version= false;
+ bool opt_help= false;
+ int option_index= 0;
+
+ while (1)
+ {
+ int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+ if (option_rv == -1)
+ {
+ break;
+ }
+
+ switch (option_rv)
+ {
+ case 0:
+ break;
+
+ case OPT_BINARY:
+ opt_binary = true;
+ break;
+
+ case OPT_VERBOSE: /* --verbose or -v */
+ opt_verbose = OPT_VERBOSE;
+ break;
+
+ case OPT_DEBUG: /* --debug or -d */
+ opt_verbose = OPT_DEBUG;
+ break;
+
+ case OPT_VERSION: /* --version or -V */
+ opt_version= true;
+ break;
+
+ case OPT_HELP: /* --help or -h */
+ opt_help= true;
+ break;
+
+ case OPT_SERVERS: /* --servers or -s */
+ opt_servers= strdup(optarg);
+ break;
+
+ case OPT_HASH:
+ opt_hash= strdup(optarg);
+ break;
+
+ case OPT_USERNAME:
+ opt_username= optarg;
+ break;
+
+ case OPT_PASSWD:
+ opt_passwd= optarg;
+ break;
+
+ case OPT_EXPIRE:
+ expiration= time_t(strtoul(optarg, (char **)NULL, 10));
+ break;
+
+ case OPT_QUIET:
+ close_stdio();
+ break;
+
+ case '?':
+ /* getopt_long already printed an error message. */
+ exit(EXIT_FAILURE);
+
+ default:
+ abort();
+ }
+ }
+
+ if (opt_version)
+ {
+ version_command(PROGRAM_NAME);
+ exit(EXIT_SUCCESS);
+ }
+
+ if (opt_help)
+ {
+ help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+ exit(EXIT_SUCCESS);
+ }
+}
#include <clients/utilities.h>
#include <cstdio>
+#include <cassert>
#include <cstdlib>
#include <cstring>
#include <ctype.h>
case OPT_PASSWD: return "Password to use for SASL authentication";
case OPT_FILE: return "Path to file in which to save result";
case OPT_STAT_ARGS: return "Argument for statistics";
- default: WATCHPOINT_ASSERT(0);
+ default:
+ break;
};
- WATCHPOINT_ASSERT(0);
+ assert(0);
return "forgot to document this function :)";
}
#pragma once
#include <getopt.h>
-#include <libmemcached/memcached.h>
-#include "libmemcached/watchpoint.h"
-#include "client_options.h"
+#include <libmemcached-1.0/memcached.h>
+#include "clients/client_options.h"
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
AC_CONFIG_FILES([
Makefile
docs/conf.py
- libhashkit/configure.h
- libmemcached/configure.h
+ libhashkit-1.0/configure.h
+ libmemcached-1.0/configure.h
support/libmemcached.pc
support/libmemcached.spec
support/libmemcached-fc.spec
=======
-libMemcached is an open source C/C++ client library and tools for the memcached server (http://danga.com/memcached). It has been designed to be light on memory usage, thread safe, and provide full access to server side methods.
+libMemcached is an open source C/C++ client library and tools for the memcached server (http://memcached.org/). It has been designed to be light on memory usage, thread safe, and provide full access to server side methods.
libMemcached was designed to provide the greatest number of options to use Memcached. Some of the features provided:
"Memcached is a high-performance, distributed memory object caching
system, generic in nature, but intended for use in speeding up dynamic web
-applications by alleviating database load." `http://danga.com/memcached/ <http://danga.com/memcached/>`_
+applications by alleviating database load." `http://memcached.org/ <http://memcached.org/>`_
:program:`libmemcached` is a small, thread-safe client library for the
memcached protocol. The code has all been written to allow
.. c:function:: memcached_return_t memcached_server_push (memcached_st *ptr, const memcached_server_st *list)
-.. c:function:: memcached_server_instance_st memcached_server_by_key (const memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error)
+.. c:function:: memcached_server_instance_st memcached_server_by_key (memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error)
.. c:function:: memcached_server_instance_st memcached_server_get_last_disconnect (const memcached_st *ptr)
#include <stdlib.h>
#include <string.h>
-#include <libmemcached/protocol_handler.h>
+#include <libmemcachedprotocol-0.0/handler.h>
#include <example/byteorder.h>
-#include "storage.h"
-#include "memcached_light.h"
+#include "example/storage.h"
+#include "example/memcached_light.h"
static protocol_binary_response_status noop_command_handler(const void *cookie,
protocol_binary_request_header *header,
#include <stdlib.h>
#include <string.h>
-#include <libmemcached/protocol_handler.h>
+#include <libmemcachedprotocol-0.0/handler.h>
#include <example/byteorder.h>
#include "storage.h"
#include <string.h>
#include <event.h>
-#include <libmemcached/protocol_handler.h>
+#include <libmemcachedprotocol-0.0/handler.h>
#include <example/byteorder.h>
#include "storage.h"
#include "memcached_light.h"
--- /dev/null
+/* HashKit
+ * Copyright (C) 2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+/**
+ * @file
+ * @brief HashKit Header
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1_64(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1_32(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_crc32(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_hsieh(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_murmur(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_jenkins(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_md5(const char *key, size_t key_length);
+
+HASHKIT_LOCAL
+uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_crc32(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_murmur(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_jenkins(const char *key, size_t key_length, void *context);
+
+HASHKIT_LOCAL
+uint32_t hashkit_md5(const char *key, size_t key_length, void *context);
+
+HASHKIT_API
+void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* HashKit
+ * Copyright (C) 2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+/**
+ * @file
+ * @brief HashKit Header
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* HashKit
+ * Copyright (C) 2009-2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* HashKit
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length);
+
+/**
+ This is a utilitly function provided so that you can directly access hashes with a hashkit_st.
+*/
+
+HASHKIT_API
+uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* HashKit
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ This sets/gets the default function we will be using.
+*/
+HASHKIT_API
+hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
+
+HASHKIT_API
+hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context);
+
+HASHKIT_API
+hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash);
+
+/**
+ This sets/gets the function we use for distribution.
+*/
+HASHKIT_API
+hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
+
+HASHKIT_API
+hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context);
+
+HASHKIT_API
+hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+bool libhashkit_has_algorithm(const hashkit_hash_algorithm_t);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * HashKit library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include <libhashkit-1.0/visibility.h>
+#include <libhashkit-1.0/configure.h>
+#include <libhashkit-1.0/types.h>
+#include <libhashkit-1.0/has.h>
+#include <libhashkit-1.0/algorithm.h>
+#include <libhashkit-1.0/behavior.h>
+#include <libhashkit-1.0/digest.h>
+#include <libhashkit-1.0/function.h>
+#include <libhashkit-1.0/str_algorithm.h>
+#include <libhashkit-1.0/strerror.h>
+
+struct hashkit_st
+{
+ struct hashkit_function_st {
+ hashkit_hash_fn function;
+ void *context;
+ } base_hash, distribution_hash;
+
+ struct {
+ bool is_base_same_distributed:1;
+ } flags;
+
+ struct {
+ bool is_allocated:1;
+ } options;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+hashkit_st *hashkit_create(hashkit_st *hash);
+
+HASHKIT_API
+hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *ptr);
+
+HASHKIT_API
+bool hashkit_compare(const hashkit_st *first, const hashkit_st *second);
+
+HASHKIT_API
+void hashkit_free(hashkit_st *hash);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libhashkit-1.0/hashkit.h>
+#include <string>
+
+class Hashkit {
+
+public:
+
+ Hashkit()
+ {
+ hashkit_create(&self);
+ }
+
+ Hashkit(const Hashkit& source)
+ {
+ hashkit_clone(&self, &source.self);
+ }
+
+ Hashkit& operator=(const Hashkit& source)
+ {
+ hashkit_free(&self);
+ hashkit_clone(&self, &source.self);
+
+ return *this;
+ }
+
+ friend bool operator==(const Hashkit &left, const Hashkit &right)
+ {
+ return hashkit_compare(&left.self, &right.self);
+ }
+
+ uint32_t digest(std::string& str)
+ {
+ return hashkit_digest(&self, str.c_str(), str.length());
+ }
+
+ uint32_t digest(const char *key, size_t key_length)
+ {
+ return hashkit_digest(&self, key, key_length);
+ }
+
+ hashkit_return_t set_function(hashkit_hash_algorithm_t hash_algorithm)
+ {
+ return hashkit_set_function(&self, hash_algorithm);
+ }
+
+ hashkit_return_t set_distribution_function(hashkit_hash_algorithm_t hash_algorithm)
+ {
+ return hashkit_set_function(&self, hash_algorithm);
+ }
+
+ ~Hashkit()
+ {
+ hashkit_free(&self);
+ }
+private:
+
+ hashkit_st self;
+};
--- /dev/null
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+#
+
+EXTRA_DIST+= \
+ libhashkit-1.0/configure.h.in
+
+nobase_include_HEADERS+= \
+ libhashkit-1.0/algorithm.h \
+ libhashkit-1.0/behavior.h \
+ libhashkit-1.0/configure.h \
+ libhashkit-1.0/digest.h \
+ libhashkit-1.0/function.h \
+ libhashkit-1.0/has.h \
+ libhashkit-1.0/hashkit.h \
+ libhashkit-1.0/hashkit.hpp \
+ libhashkit-1.0/strerror.h \
+ libhashkit-1.0/str_algorithm.h \
+ libhashkit-1.0/types.h \
+ libhashkit-1.0/visibility.h
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * HashKit
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+const char *libhashkit_string_hash(hashkit_hash_algorithm_t type);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* HashKit
+ * Copyright (C) 2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+ const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * HashKit
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+typedef enum {
+ HASHKIT_SUCCESS,
+ HASHKIT_FAILURE,
+ HASHKIT_MEMORY_ALLOCATION_FAILURE,
+ HASHKIT_INVALID_HASH,
+ HASHKIT_INVALID_ARGUMENT,
+ HASHKIT_MAXIMUM_RETURN /* Always add new error code before */
+} hashkit_return_t;
+
+static inline bool hashkit_success(const hashkit_return_t rc)
+{
+ return (rc == HASHKIT_SUCCESS);
+}
+
+static inline bool hashkit_failed(const hashkit_return_t rc)
+{
+ return (rc != HASHKIT_SUCCESS);
+}
+
+typedef enum {
+ HASHKIT_HASH_DEFAULT= 0, // hashkit_one_at_a_time()
+ HASHKIT_HASH_MD5,
+ HASHKIT_HASH_CRC,
+ HASHKIT_HASH_FNV1_64,
+ HASHKIT_HASH_FNV1A_64,
+ HASHKIT_HASH_FNV1_32,
+ HASHKIT_HASH_FNV1A_32,
+ HASHKIT_HASH_HSIEH,
+ HASHKIT_HASH_MURMUR,
+ HASHKIT_HASH_JENKINS,
+ HASHKIT_HASH_CUSTOM,
+ HASHKIT_HASH_MAX
+} hashkit_hash_algorithm_t;
+
+/**
+ * Hash distributions that are available to use.
+ */
+typedef enum
+{
+ HASHKIT_DISTRIBUTION_MODULA,
+ HASHKIT_DISTRIBUTION_RANDOM,
+ HASHKIT_DISTRIBUTION_KETAMA,
+ HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */
+} hashkit_distribution_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct hashkit_st hashkit_st;
+
+typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*
+ * Summary: interface for HashKit functions
+ * Description: visibitliy macros for HashKit library
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in this directory for full text.
+ *
+ * Author: Monty Taylor
+ */
+
+/**
+ * @file
+ * @brief Visibility control macros
+ */
+
+#pragma once
+
+/**
+ *
+ * HASHKIT_API is used for the public API symbols. It either DLL imports or
+ * DLL exports (or does nothing for static build).
+ *
+ * HASHKIT_LOCAL is used for non-api symbols.
+ */
+
+#if defined(BUILDING_HASHKIT)
+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+# define HASHKIT_API __attribute__ ((visibility("default")))
+# define HASHKIT_LOCAL __attribute__ ((visibility("hidden")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define HASHKIT_API __global
+# define HASHKIT_LOCAL __hidden
+# elif defined(_MSC_VER)
+# define HASHKIT_API extern __declspec(dllexport)
+# define HASHKIT_LOCAL
+# else
+# define HASHKIT_API
+# define HASHKIT_LOCAL
+# endif /* defined(HAVE_VISIBILITY) */
+#else /* defined(BUILDING_HASHKIT) */
+# if defined(_MSC_VER)
+# define HASHKIT_API extern __declspec(dllimport)
+# define HASHKIT_LOCAL
+# else
+# define HASHKIT_API
+# define HASHKIT_LOCAL
+# endif /* defined(_MSC_VER) */
+#endif /* defined(BUILDING_HASHKIT) */
+++ /dev/null
-/* HashKit
- * Copyright (C) 2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- */
-
-/**
- * @file
- * @brief HashKit Header
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1_64(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1_32(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_crc32(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_hsieh(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_murmur(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_jenkins(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_md5(const char *key, size_t key_length);
-
-HASHKIT_LOCAL
-uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_crc32(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_murmur(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_jenkins(const char *key, size_t key_length, void *context);
-
-HASHKIT_LOCAL
-uint32_t hashkit_md5(const char *key, size_t key_length, void *context);
-
-HASHKIT_API
-void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* HashKit
- * Copyright (C) 2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- */
-
-/**
- * @file
- * @brief HashKit Header
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
#include <stdlib.h>
#include <math.h>
-#include <libhashkit/hashkit.h>
+#include <libhashkit-1.0/hashkit.h>
+#include <libhashkit/is.h>
#ifdef __cplusplus
extern "C" {
+++ /dev/null
-/* HashKit
- * Copyright (C) 2009-2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* HashKit
- * Copyright (C) 2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length);
-
-/**
- This is a utilitly function provided so that you can directly access hashes with a hashkit_st.
-*/
-
-HASHKIT_API
-uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* HashKit
- * Copyright (C) 2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- */
-
-#ifndef HASHKIT_FUNCTION_H
-#define HASHKIT_FUNCTION_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- This sets/gets the default function we will be using.
-*/
-HASHKIT_API
-hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
-
-HASHKIT_API
-hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context);
-
-HASHKIT_API
-hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash);
-
-/**
- This sets/gets the function we use for distribution.
-*/
-HASHKIT_API
-hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
-
-HASHKIT_API
-hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context);
-
-HASHKIT_API
-hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HASHKIT_FUNCTION_H */
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-bool libhashkit_has_algorithm(const hashkit_hash_algorithm_t);
-
-#ifdef __cplusplus
-}
-#endif
* HashKit library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2009-2010 Brian Aker All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
#pragma once
-
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include <libhashkit/visibility.h>
-#include <libhashkit/configure.h>
-#include <libhashkit/types.h>
-#include <libhashkit/has.h>
-#include <libhashkit/algorithm.h>
-#include <libhashkit/behavior.h>
-#include <libhashkit/digest.h>
-#include <libhashkit/function.h>
-#include <libhashkit/str_algorithm.h>
-#include <libhashkit/strerror.h>
-
-struct hashkit_st
-{
- struct hashkit_function_st {
- hashkit_hash_fn function;
- void *context;
- } base_hash, distribution_hash;
-
- struct {
- bool is_base_same_distributed:1;
- } flags;
-
- struct {
- bool is_allocated:1;
- } options;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-hashkit_st *hashkit_create(hashkit_st *hash);
-
-HASHKIT_API
-hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *ptr);
-
-HASHKIT_API
-bool hashkit_compare(const hashkit_st *first, const hashkit_st *second);
-
-HASHKIT_API
-void hashkit_free(hashkit_st *hash);
-
-#define hashkit_is_allocated(__object) ((__object)->options.is_allocated)
-#define hashkit_is_initialized(__object) ((__object)->options.is_initialized)
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+#include <libhashkit-1.0/hashkit.h>
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libhashkit/hashkit.h>
-#include <string>
-
-class Hashkit {
-
-public:
-
- Hashkit()
- {
- hashkit_create(&self);
- }
-
- Hashkit(const Hashkit& source)
- {
- hashkit_clone(&self, &source.self);
- }
-
- Hashkit& operator=(const Hashkit& source)
- {
- hashkit_free(&self);
- hashkit_clone(&self, &source.self);
-
- return *this;
- }
-
- friend bool operator==(const Hashkit &left, const Hashkit &right)
- {
- return hashkit_compare(&left.self, &right.self);
- }
-
- uint32_t digest(std::string& str)
- {
- return hashkit_digest(&self, str.c_str(), str.length());
- }
-
- uint32_t digest(const char *key, size_t key_length)
- {
- return hashkit_digest(&self, key, key_length);
- }
-
- hashkit_return_t set_function(hashkit_hash_algorithm_t hash_algorithm)
- {
- return hashkit_set_function(&self, hash_algorithm);
- }
-
- hashkit_return_t set_distribution_function(hashkit_hash_algorithm_t hash_algorithm)
- {
- return hashkit_set_function(&self, hash_algorithm);
- }
-
- ~Hashkit()
- {
- hashkit_free(&self);
- }
-private:
-
- hashkit_st self;
-};
lib_LTLIBRARIES+= libhashkit/libhashkit.la
-EXTRA_DIST+= \
- libhashkit/configure.h.in
+noinst_HEADERS+= \
+ libhashkit/common.h \
+ libhashkit/is.h
nobase_include_HEADERS+= \
- libhashkit/algorithm.h \
- libhashkit/behavior.h \
- libhashkit/configure.h \
- libhashkit/digest.h \
- libhashkit/function.h \
- libhashkit/has.h \
- libhashkit/hashkit.h \
- libhashkit/hashkit.hpp \
- libhashkit/strerror.h \
- libhashkit/str_algorithm.h \
- libhashkit/types.h \
- libhashkit/visibility.h
-
-noinst_HEADERS+= \
- libhashkit/common.h
+ libhashkit/hashkit.h
libhashkit_libhashkit_la_SOURCES= \
libhashkit/algorithm.cc \
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * HashKit library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#pragma once
+
+#define hashkit_is_allocated(__object) ((__object)->options.is_allocated)
+#define hashkit_is_initialized(__object) ((__object)->options.is_initialized)
+
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * HashKit
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-const char *libhashkit_string_hash(hashkit_hash_algorithm_t type);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* HashKit
- * Copyright (C) 2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- */
-
-#ifndef HASHKIT_STRERROR_H
-#define HASHKIT_STRERROR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
- const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HASHKIT_STRERROR_H */
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * HashKit
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-typedef enum {
- HASHKIT_SUCCESS,
- HASHKIT_FAILURE,
- HASHKIT_MEMORY_ALLOCATION_FAILURE,
- HASHKIT_INVALID_HASH,
- HASHKIT_INVALID_ARGUMENT,
- HASHKIT_MAXIMUM_RETURN /* Always add new error code before */
-} hashkit_return_t;
-
-static inline bool hashkit_success(const hashkit_return_t rc)
-{
- return (rc == HASHKIT_SUCCESS);
-}
-
-static inline bool hashkit_failed(const hashkit_return_t rc)
-{
- return (rc != HASHKIT_SUCCESS);
-}
-
-typedef enum {
- HASHKIT_HASH_DEFAULT= 0, // hashkit_one_at_a_time()
- HASHKIT_HASH_MD5,
- HASHKIT_HASH_CRC,
- HASHKIT_HASH_FNV1_64,
- HASHKIT_HASH_FNV1A_64,
- HASHKIT_HASH_FNV1_32,
- HASHKIT_HASH_FNV1A_32,
- HASHKIT_HASH_HSIEH,
- HASHKIT_HASH_MURMUR,
- HASHKIT_HASH_JENKINS,
- HASHKIT_HASH_CUSTOM,
- HASHKIT_HASH_MAX
-} hashkit_hash_algorithm_t;
-
-/**
- * Hash distributions that are available to use.
- */
-typedef enum
-{
- HASHKIT_DISTRIBUTION_MODULA,
- HASHKIT_DISTRIBUTION_RANDOM,
- HASHKIT_DISTRIBUTION_KETAMA,
- HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */
-} hashkit_distribution_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct hashkit_st hashkit_st;
-
-typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/*
- * Summary: interface for HashKit functions
- * Description: visibitliy macros for HashKit library
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in this directory for full text.
- *
- * Author: Monty Taylor
- */
-
-/**
- * @file
- * @brief Visibility control macros
- */
-
-#pragma once
-
-/**
- *
- * HASHKIT_API is used for the public API symbols. It either DLL imports or
- * DLL exports (or does nothing for static build).
- *
- * HASHKIT_LOCAL is used for non-api symbols.
- */
-
-#if defined(BUILDING_HASHKIT)
-# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-# define HASHKIT_API __attribute__ ((visibility("default")))
-# define HASHKIT_LOCAL __attribute__ ((visibility("hidden")))
-# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-# define HASHKIT_API __global
-# define HASHKIT_LOCAL __hidden
-# elif defined(_MSC_VER)
-# define HASHKIT_API extern __declspec(dllexport)
-# define HASHKIT_LOCAL
-# else
-# define HASHKIT_API
-# define HASHKIT_LOCAL
-# endif /* defined(HAVE_VISIBILITY) */
-#else /* defined(BUILDING_HASHKIT) */
-# if defined(_MSC_VER)
-# define HASHKIT_API extern __declspec(dllimport)
-# define HASHKIT_LOCAL
-# else
-# define HASHKIT_API
-# define HASHKIT_LOCAL
-# endif /* defined(_MSC_VER) */
-#endif /* defined(BUILDING_HASHKIT) */
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_allocator_t {
+ memcached_calloc_fn calloc;
+ memcached_free_fn free;
+ memcached_malloc_fn malloc;
+ memcached_realloc_fn realloc;
+ void *context;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_memory_allocators(memcached_st *ptr,
+ memcached_malloc_fn mem_malloc,
+ memcached_free_fn mem_free,
+ memcached_realloc_fn mem_realloc,
+ memcached_calloc_fn mem_calloc,
+ void *context);
+
+LIBMEMCACHED_API
+void memcached_get_memory_allocators(const memcached_st *ptr,
+ memcached_malloc_fn *mem_malloc,
+ memcached_free_fn *mem_free,
+ memcached_realloc_fn *mem_realloc,
+ memcached_calloc_fn *mem_calloc);
+
+LIBMEMCACHED_API
+void *memcached_get_memory_allocators_context(const memcached_st *ptr);
+
+LIBMEMCACHED_LOCAL
+void _libmemcached_free(const memcached_st *ptr, void *mem, void *context);
+
+LIBMEMCACHED_LOCAL
+void *_libmemcached_malloc(const memcached_st *ptr, const size_t size, void *context);
+
+LIBMEMCACHED_LOCAL
+void *_libmemcached_realloc(const memcached_st *ptr, void *mem, const size_t size, void *context);
+
+LIBMEMCACHED_LOCAL
+void *_libmemcached_calloc(const memcached_st *ptr, size_t nelem, size_t size, void *context);
+
+LIBMEMCACHED_LOCAL
+struct memcached_allocator_t memcached_allocators_return_default(void);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_analysis_st {
+ memcached_st *root;
+ uint32_t average_item_size;
+ uint32_t longest_uptime;
+ uint32_t least_free_server;
+ uint32_t most_consumed_server;
+ uint32_t oldest_server;
+ double pool_hit_ratio;
+ uint64_t most_used_bytes;
+ uint64_t least_remaining_bytes;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_analysis_st *memcached_analyze(memcached_st *memc,
+ memcached_stat_st *memc_stat,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+void memcached_analyze_free(memcached_analysis_st *);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_increment(memcached_st *ptr,
+ const char *key, size_t key_length,
+ uint32_t offset,
+ uint64_t *value);
+LIBMEMCACHED_API
+ memcached_return_t memcached_decrement(memcached_st *ptr,
+ const char *key, size_t key_length,
+ uint32_t offset,
+ uint64_t *value);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_increment_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ uint64_t offset,
+ uint64_t *value);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ uint64_t offset,
+ uint64_t *value);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
+ const char *group_key,
+ size_t group_key_length,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
+ const char *group_key,
+ size_t group_key_length,
+ const char *key,
+ size_t key_length,
+ uint64_t offset,
+ uint64_t initial,
+ time_t expiration,
+ uint64_t *value);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+// No assumptions of NULL should be made
+
+struct memcached_string_t {
+ const char *c_str;
+ size_t size;
+};
+
+#define memcached_size(X) (X).size;
+#define memcached_c_str(X) (X).c_str;
+#define memcached_string_param(X) (X).c_str, (X).size
+
+#ifdef __cplusplus
+#define memcached_string_printf(X) int((X).size), (X).c_str
+#else
+#define memcached_string_printf(X) (int)((X).size), (X).c_str
+#endif
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data);
+
+LIBMEMCACHED_API
+uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set_distribution(memcached_st *ptr, memcached_server_distribution_t type);
+
+LIBMEMCACHED_API
+memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_hash_t type);
+
+LIBMEMCACHED_API
+memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, memcached_hash_t type);
+
+LIBMEMCACHED_API
+memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr);
+
+LIBMEMCACHED_LOCAL
+bool _is_auto_eject_host(const memcached_st *ptr);
+
+LIBMEMCACHED_API
+ const char *libmemcached_string_behavior(const memcached_behavior_t flag);
+
+LIBMEMCACHED_API
+ const char *libmemcached_string_distribution(const memcached_server_distribution_t flag);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_bucket_set(memcached_st *self,
+ const uint32_t *host_map,
+ const uint32_t *forward_map,
+ const uint32_t buckets,
+ const uint32_t replicas);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_callback_st {
+ memcached_execute_fn *callback;
+ void *context;
+ uint32_t number_of_callback;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_callback_set(memcached_st *ptr,
+ const memcached_callback_t flag,
+ const void *data);
+LIBMEMCACHED_API
+void *memcached_callback_get(memcached_st *ptr,
+ const memcached_callback_t flag,
+ memcached_return_t *error);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker, Trond Norbye All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+@DEPRECATED@
+@LIBMEMCACHED_WITH_SASL_SUPPORT@
+
+#define LIBMEMCACHED_VERSION_STRING "@VERSION@"
+#define LIBMEMCACHED_VERSION_HEX @PANDORA_HEX_VERSION@
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+/* Public defines */
+#define MEMCACHED_DEFAULT_PORT 11211
+#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
+#define MEMCACHED_MAX_BUFFER 8196
+#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
+#define MEMCACHED_POINTS_PER_SERVER 100
+#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
+#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
+#define MEMCACHED_STRIDE 4
+#define MEMCACHED_DEFAULT_TIMEOUT 5000
+#define MEMCACHED_DEFAULT_CONNECT_TIMEOUT 4000
+#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
+#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
+#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
+#define MEMCACHED_VERSION_STRING_LENGTH 24
+#define MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH 20
+#define MEMCACHED_SERVER_FAILURE_LIMIT 5
+#define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
+
+
+enum memcached_server_distribution_t {
+ MEMCACHED_DISTRIBUTION_MODULA,
+ MEMCACHED_DISTRIBUTION_CONSISTENT,
+ MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
+ MEMCACHED_DISTRIBUTION_RANDOM,
+ MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY,
+ MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED,
+ MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET,
+ MEMCACHED_DISTRIBUTION_CONSISTENT_MAX
+};
+
+#ifndef __cplusplus
+typedef enum memcached_server_distribution_t memcached_server_distribution_t;
+#endif
+
+enum memcached_behavior_t {
+ MEMCACHED_BEHAVIOR_NO_BLOCK,
+ MEMCACHED_BEHAVIOR_TCP_NODELAY,
+ MEMCACHED_BEHAVIOR_HASH,
+ MEMCACHED_BEHAVIOR_KETAMA,
+ MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE,
+ MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE,
+ MEMCACHED_BEHAVIOR_CACHE_LOOKUPS,
+ MEMCACHED_BEHAVIOR_SUPPORT_CAS,
+ MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
+ MEMCACHED_BEHAVIOR_DISTRIBUTION,
+ MEMCACHED_BEHAVIOR_BUFFER_REQUESTS,
+ MEMCACHED_BEHAVIOR_USER_DATA,
+ MEMCACHED_BEHAVIOR_SORT_HOSTS,
+ MEMCACHED_BEHAVIOR_VERIFY_KEY,
+ MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,
+ MEMCACHED_BEHAVIOR_RETRY_TIMEOUT,
+ MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED,
+ MEMCACHED_BEHAVIOR_KETAMA_HASH,
+ MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+ MEMCACHED_BEHAVIOR_SND_TIMEOUT,
+ MEMCACHED_BEHAVIOR_RCV_TIMEOUT,
+ MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT,
+ MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK,
+ MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK,
+ MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH,
+ MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY,
+ MEMCACHED_BEHAVIOR_NOREPLY,
+ MEMCACHED_BEHAVIOR_USE_UDP,
+ MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS,
+ MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
+ MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ,
+ MEMCACHED_BEHAVIOR_CORK,
+ MEMCACHED_BEHAVIOR_TCP_KEEPALIVE,
+ MEMCACHED_BEHAVIOR_TCP_KEEPIDLE,
+ MEMCACHED_BEHAVIOR_LOAD_FROM_FILE,
+ MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS,
+ MEMCACHED_BEHAVIOR_MAX
+};
+
+#ifndef __cplusplus
+typedef enum memcached_behavior_t memcached_behavior_t;
+#endif
+
+enum memcached_callback_t {
+ MEMCACHED_CALLBACK_PREFIX_KEY = 0,
+ MEMCACHED_CALLBACK_USER_DATA = 1,
+ MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2,
+ MEMCACHED_CALLBACK_CLONE_FUNCTION = 3,
+ MEMCACHED_CALLBACK_GET_FAILURE = 7,
+ MEMCACHED_CALLBACK_DELETE_TRIGGER = 8,
+ MEMCACHED_CALLBACK_MAX,
+ MEMCACHED_CALLBACK_NAMESPACE= MEMCACHED_CALLBACK_PREFIX_KEY
+};
+
+#ifndef __cplusplus
+typedef enum memcached_callback_t memcached_callback_t;
+#endif
+
+enum memcached_hash_t {
+ MEMCACHED_HASH_DEFAULT= 0,
+ MEMCACHED_HASH_MD5,
+ MEMCACHED_HASH_CRC,
+ MEMCACHED_HASH_FNV1_64,
+ MEMCACHED_HASH_FNV1A_64,
+ MEMCACHED_HASH_FNV1_32,
+ MEMCACHED_HASH_FNV1A_32,
+ MEMCACHED_HASH_HSIEH,
+ MEMCACHED_HASH_MURMUR,
+ MEMCACHED_HASH_JENKINS,
+ MEMCACHED_HASH_CUSTOM,
+ MEMCACHED_HASH_MAX
+};
+
+#ifndef __cplusplus
+typedef enum memcached_hash_t memcached_hash_t;
+#endif
+
+enum memcached_connection_t {
+ MEMCACHED_CONNECTION_TCP,
+ MEMCACHED_CONNECTION_UDP,
+ MEMCACHED_CONNECTION_UNIX_SOCKET
+};
+
+enum {
+ MEMCACHED_CONNECTION_UNKNOWN= 0,
+ MEMCACHED_CONNECTION_MAX= 0
+};
+
+#ifndef __cplusplus
+typedef enum memcached_connection_t memcached_connection_t;
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
+ time_t expiration);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_delete_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *function, void *context, uint32_t number_of_callbacks);
+
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * LibMemcached
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+ const char *memcached_last_error_message(memcached_st *);
+
+LIBMEMCACHED_API
+ void memcached_error_print(const memcached_st *);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_last_error(memcached_st *);
+
+LIBMEMCACHED_API
+ int memcached_last_error_errno(memcached_st *);
+
+LIBMEMCACHED_API
+ const char *memcached_server_error(memcached_server_instance_st ptr);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/*
+ * Summary: Exceptions for the C++ interface
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ */
+
+/**
+ * @file
+ * @brief Exception declarations
+ */
+
+#pragma once
+
+#include <stdexcept>
+#include <string>
+
+namespace memcache
+{
+ class Exception : public std::runtime_error
+ {
+ public:
+ Exception(const std::string& msg, int in_errno)
+ :
+ std::runtime_error(msg),
+ _errno(in_errno)
+ {}
+
+ Exception(const char *msg, int in_errno)
+ :
+ std::runtime_error(std::string(msg)),
+ _errno(in_errno) {}
+
+ virtual ~Exception() throw() {}
+
+ int getErrno() const
+ {
+ return _errno;
+ }
+
+ private:
+ int _errno;
+ };
+
+ class Warning : public Exception
+ {
+ public:
+ Warning(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
+ Warning(const char *msg, int in_errno) : Exception(msg, in_errno) {}
+ };
+
+ class Error : public Exception
+ {
+ public:
+ Error(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
+ Error(const char *msg, int in_errno) : Exception(msg, in_errno) {}
+ virtual ~Error() throw() {}
+ };
+
+} /* namespace libmemcached */
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_return_t memcached_exist(memcached_st *memc, const char *key, size_t key_length);
+
+memcached_return_t memcached_exist_by_key(memcached_st *memc,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length);
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_fetch_execute(memcached_st *ptr,
+ memcached_execute_fn *callback,
+ void *context,
+ uint32_t number_of_callbacks);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_flush_buffers(memcached_st *mem);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public defines */
+LIBMEMCACHED_API
+char *memcached_get(memcached_st *ptr,
+ const char *key, size_t key_length,
+ size_t *value_length,
+ uint32_t *flags,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget(memcached_st *ptr,
+ const char * const *keys,
+ const size_t *key_length,
+ size_t number_of_keys);
+
+LIBMEMCACHED_API
+char *memcached_get_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ size_t *value_length,
+ uint32_t *flags,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_by_key(memcached_st *ptr,
+ const char *group_key,
+ size_t group_key_length,
+ const char * const *keys,
+ const size_t *key_length,
+ const size_t number_of_keys);
+
+LIBMEMCACHED_API
+char *memcached_fetch(memcached_st *ptr,
+ char *key,
+ size_t *key_length,
+ size_t *value_length,
+ uint32_t *flags,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_result_st *memcached_fetch_result(memcached_st *ptr,
+ memcached_result_st *result,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_execute(memcached_st *ptr,
+ const char * const *keys,
+ const size_t *key_length,
+ const size_t number_of_keys,
+ memcached_execute_fn *callback,
+ void *context,
+ const uint32_t number_of_callbacks);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
+ const char *group_key,
+ size_t group_key_length,
+ const char * const *keys,
+ const size_t *key_length,
+ size_t number_of_keys,
+ memcached_execute_fn *callback,
+ void *context,
+ const uint32_t number_of_callbacks);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The two public hash bits */
+LIBMEMCACHED_API
+uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm);
+
+LIBMEMCACHED_API
+const hashkit_st *memcached_get_hashkit(const memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_hashkit(memcached_st *ptr, hashkit_st *hashk);
+
+LIBMEMCACHED_API
+uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length);
+
+LIBMEMCACHED_LOCAL
+uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length);
+
+LIBMEMCACHED_API
+void memcached_autoeject(memcached_st *ptr);
+
+LIBMEMCACHED_API
+ const char * libmemcached_string_hash(memcached_hash_t type);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+
+EXTRA_DIST+= \
+ libmemcached-1.0/configure.h.in
+
+nobase_include_HEADERS+= \
+ libmemcached-1.0/allocators.h \
+ libmemcached-1.0/analyze.h \
+ libmemcached-1.0/auto.h \
+ libmemcached-1.0/basic_string.h \
+ libmemcached-1.0/behavior.h \
+ libmemcached-1.0/callback.h \
+ libmemcached-1.0/configure.h \
+ libmemcached-1.0/constants.h \
+ libmemcached-1.0/delete.h \
+ libmemcached-1.0/dump.h \
+ libmemcached-1.0/error.h \
+ libmemcached-1.0/exist.h \
+ libmemcached-1.0/exception.hpp \
+ libmemcached-1.0/fetch.h \
+ libmemcached-1.0/flush.h \
+ libmemcached-1.0/flush_buffers.h \
+ libmemcached-1.0/get.h \
+ libmemcached-1.0/hash.h \
+ libmemcached-1.0/memcached.h \
+ libmemcached-1.0/memcached.hpp \
+ libmemcached-1.0/options.h \
+ libmemcached-1.0/parse.h \
+ libmemcached-1.0/quit.h \
+ libmemcached-1.0/return.h \
+ libmemcached-1.0/platform.h \
+ libmemcached-1.0/result.h \
+ libmemcached-1.0/sasl.h \
+ libmemcached-1.0/server.h \
+ libmemcached-1.0/server_list.h \
+ libmemcached-1.0/stats.h \
+ libmemcached-1.0/storage.h \
+ libmemcached-1.0/strerror.h \
+ libmemcached-1.0/string.h \
+ libmemcached-1.0/touch.h \
+ libmemcached-1.0/types.h \
+ libmemcached-1.0/verbosity.h \
+ libmemcached-1.0/version.h \
+ libmemcached-1.0/visibility.h
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+
+#include <libmemcached-1.0/visibility.h>
+#include <libmemcached-1.0/configure.h>
+#include <libmemcached-1.0/platform.h>
+#include <libmemcached-1.0/constants.h>
+#include <libmemcached-1.0/return.h>
+#include <libmemcached-1.0/types.h>
+#include <libmemcached-1.0/basic_string.h>
+#include <libmemcached-1.0/string.h>
+#include <libmemcached-1.0/error.h>
+#include <libmemcached-1.0/stats.h>
+#include <libhashkit-1.0/hashkit.h>
+
+// Everything above this line must be in the order specified.
+#include <libmemcached-1.0/allocators.h>
+#include <libmemcached-1.0/analyze.h>
+#include <libmemcached-1.0/auto.h>
+#include <libmemcached-1.0/behavior.h>
+#include <libmemcached-1.0/callback.h>
+#include <libmemcached-1.0/delete.h>
+#include <libmemcached-1.0/dump.h>
+#include <libmemcached-1.0/exist.h>
+#include <libmemcached-1.0/fetch.h>
+#include <libmemcached-1.0/flush.h>
+#include <libmemcached-1.0/flush_buffers.h>
+#include <libmemcached-1.0/get.h>
+#include <libmemcached-1.0/hash.h>
+#include <libmemcached-1.0/options.h>
+#include <libmemcached-1.0/parse.h>
+#include <libmemcached-1.0/quit.h>
+#include <libmemcached-1.0/result.h>
+#include <libmemcached-1.0/server.h>
+#include <libmemcached-1.0/server_list.h>
+#include <libmemcached-1.0/storage.h>
+#include <libmemcached-1.0/strerror.h>
+#include <libmemcached-1.0/touch.h>
+#include <libmemcached-1.0/verbosity.h>
+#include <libmemcached-1.0/version.h>
+#include <libmemcached-1.0/sasl.h>
+
+struct memcached_st {
+ /**
+ @note these are static and should not change without a call to behavior.
+ */
+ struct {
+ bool is_purging:1;
+ bool is_processing_input:1;
+ bool is_time_for_rebuild:1;
+ } state;
+
+ struct {
+ // Everything below here is pretty static.
+ bool auto_eject_hosts:1;
+ bool binary_protocol:1;
+ bool buffer_requests:1;
+ bool hash_with_namespace:1;
+ bool no_block:1; // Don't block
+ bool no_reply:1;
+ bool randomize_replica_read:1;
+ bool support_cas:1;
+ bool tcp_nodelay:1;
+ bool use_sort_hosts:1;
+ bool use_udp:1;
+ bool verify_key:1;
+ bool tcp_keepalive:1;
+ } flags;
+
+ memcached_server_distribution_t distribution;
+ hashkit_st hashkit;
+ struct {
+ unsigned int version;
+ } server_info;
+ uint32_t number_of_hosts;
+ memcached_server_st *servers;
+ memcached_server_st *last_disconnected_server;
+ int32_t snd_timeout;
+ int32_t rcv_timeout;
+ uint32_t server_failure_limit;
+ uint32_t io_msg_watermark;
+ uint32_t io_bytes_watermark;
+ uint32_t io_key_prefetch;
+ uint32_t tcp_keepidle;
+ int32_t poll_timeout;
+ int32_t connect_timeout; // How long we will wait on connect() before we will timeout
+ int32_t retry_timeout;
+ int send_size;
+ int recv_size;
+ void *user_data;
+ uint64_t query_id;
+ uint32_t number_of_replicas;
+ memcached_result_st result;
+
+ struct {
+ bool weighted;
+ uint32_t continuum_count; // Ketama
+ uint32_t continuum_points_counter; // Ketama
+ time_t next_distribution_rebuild; // Ketama
+ memcached_continuum_item_st *continuum; // Ketama
+ } ketama;
+
+ struct memcached_virtual_bucket_t *virtual_bucket;
+
+ struct memcached_allocator_t allocators;
+
+ memcached_clone_fn on_clone;
+ memcached_cleanup_fn on_cleanup;
+ memcached_trigger_key_fn get_key_failure;
+ memcached_trigger_delete_key_fn delete_trigger;
+ memcached_callback_st *callbacks;
+ struct memcached_sasl_st sasl;
+ struct memcached_error_t *error_messages;
+ struct memcached_array_st *_namespace;
+ struct {
+ uint32_t initial_pool_size;
+ uint32_t max_pool_size;
+ int32_t version; // This is used by pool and others to determine if the memcached_st is out of date.
+ struct memcached_array_st *filename;
+ } configure;
+ struct {
+ bool is_allocated:1;
+ } options;
+
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_servers_reset(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_st *memcached_create(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_st *memcached(const char *string, size_t string_length);
+
+LIBMEMCACHED_API
+void memcached_free(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_reset(memcached_st *ptr);
+
+LIBMEMCACHED_API
+void memcached_reset_last_disconnected_server(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_st *memcached_clone(memcached_st *clone, const memcached_st *ptr);
+
+LIBMEMCACHED_API
+void *memcached_get_user_data(const memcached_st *ptr);
+
+LIBMEMCACHED_API
+void *memcached_set_user_data(memcached_st *ptr, void *data);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source);
+
+LIBMEMCACHED_API
+memcached_server_instance_st memcached_server_instance_by_position(const memcached_st *ptr, uint32_t server_key);
+
+LIBMEMCACHED_API
+uint32_t memcached_server_count(const memcached_st *);
+
+LIBMEMCACHED_API
+uint64_t memcached_query_id(const memcached_st *);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/*
+ * Summary: C++ interface for memcached server
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
+ * Patrick Galbraith <patg@patg.net>
+ */
+
+/**
+ * @file memcached.hpp
+ * @brief Libmemcached C++ interface
+ */
+
+#pragma once
+
+#include <libmemcached-1.0/memcached.h>
+#if 0
+#include <libmemcached/exception.hpp>
+#endif
+
+#include <string.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace memcache
+{
+
+/**
+ * This is the core memcached library (if later, other objects
+ * are needed, they will be created from this class).
+ */
+class Memcache
+{
+public:
+
+ Memcache()
+ {
+ memc= memcached("", 0);
+ }
+
+ Memcache(const std::string &config)
+ {
+ memc= memcached(config.c_str(), config.size());
+ }
+
+ Memcache(const std::string &hostname, in_port_t port)
+ {
+ memc= memcached("", 0);
+ if (memc)
+ memcached_server_add(memc, hostname.c_str(), port);
+ }
+
+ Memcache(memcached_st *clone)
+ {
+ memc= memcached_clone(NULL, clone);
+ }
+
+ Memcache(const Memcache &rhs)
+ {
+ memc= memcached_clone(NULL, rhs.getImpl());
+ }
+
+ Memcache &operator=(const Memcache &rhs)
+ {
+ if (this != &rhs)
+ {
+ memcached_free(memc);
+ memc= memcached_clone(NULL, rhs.getImpl());
+ }
+
+ return *this;
+ }
+
+ ~Memcache()
+ {
+ memcached_free(memc);
+ }
+
+ /**
+ * Get the internal memcached_st *
+ */
+ const memcached_st *getImpl() const
+ {
+ return memc;
+ }
+
+ /**
+ * Return an error string for the given return structure.
+ *
+ * @param[in] rc a memcached_return_t structure
+ * @return error string corresponding to given return code in the library.
+ */
+ const std::string getError(memcached_return_t rc) const
+ {
+ /* first parameter to strerror is unused */
+ return memcached_strerror(NULL, rc);
+ }
+
+ bool error(std::string& error_message) const
+ {
+ if (memcached_failed(memcached_last_error(memc)))
+ {
+ error_message+= memcached_last_error_message(memc);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool error() const
+ {
+ if (memcached_failed(memcached_last_error(memc)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ bool error(memcached_return_t& arg) const
+ {
+ arg= memcached_last_error(memc);
+ return memcached_failed(arg);
+ }
+
+ bool setBehavior(memcached_behavior_t flag, uint64_t data)
+ {
+ return (memcached_success(memcached_behavior_set(memc, flag, data)));
+ }
+
+ uint64_t getBehavior(memcached_behavior_t flag)
+ {
+ return memcached_behavior_get(memc, flag);
+ }
+
+ /**
+ * Configure the memcache object
+ *
+ * @param[in] in_config configuration
+ * @return true on success; false otherwise
+ */
+ bool configure(const std::string &configuration)
+ {
+ memcached_st *new_memc= memcached(configuration.c_str(), configuration.size());
+
+ if (new_memc)
+ {
+ memcached_free(memc);
+ memc= new_memc;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Add a server to the list of memcached servers to use.
+ *
+ * @param[in] server_name name of the server to add
+ * @param[in] port port number of server to add
+ * @return true on success; false otherwise
+ */
+ bool addServer(const std::string &server_name, in_port_t port)
+ {
+ return memcached_success(memcached_server_add(memc, server_name.c_str(), port));
+ }
+
+ /**
+ * Remove a server from the list of memcached servers to use.
+ *
+ * @param[in] server_name name of the server to remove
+ * @param[in] port port number of server to remove
+ * @return true on success; false otherwise
+ */
+ bool removeServer(const std::string &server_name, in_port_t port)
+ {
+ std::string tmp_str;
+ std::ostringstream strstm;
+ tmp_str.append(",");
+ tmp_str.append(server_name);
+ tmp_str.append(":");
+ strstm << port;
+ tmp_str.append(strstm.str());
+
+ //memcached_return_t rc= memcached_server_remove(server);
+
+ return false;
+ }
+
+ /**
+ * Fetches an individual value from the server. mget() must always
+ * be called before using this method.
+ *
+ * @param[in] key key of object to fetch
+ * @param[out] ret_val store returned object in this vector
+ * @return a memcached return structure
+ */
+ memcached_return_t fetch(std::string &key,
+ std::vector<char> &ret_val,
+ uint32_t &flags,
+ uint64_t &cas_value)
+ {
+ memcached_return_t rc;
+
+ memcached_result_st *result;
+ if ((result= memcached_fetch_result(memc, NULL, &rc)))
+ {
+ // Key
+ key.assign(memcached_result_key_value(result), memcached_result_key_length(result));
+
+ // Actual value, null terminated
+ ret_val.reserve(memcached_result_length(result) +1);
+ ret_val.assign(memcached_result_value(result),
+ memcached_result_value(result) +memcached_result_length(result));
+
+ // Misc
+ flags= memcached_result_flags(result);
+ cas_value= memcached_result_cas(result);
+ }
+ memcached_result_free(result);
+
+ return rc;
+ }
+
+ memcached_return_t fetch(std::string &key,
+ std::vector<char> &ret_val)
+ {
+ uint32_t flags= 0;
+ uint64_t cas_value= 0;
+
+ return fetch(key, ret_val, flags, cas_value);
+ }
+
+ /**
+ * Fetches an individual value from the server.
+ *
+ * @param[in] key key of object whose value to get
+ * @param[out] ret_val object that is retrieved is stored in
+ * this vector
+ * @return true on success; false otherwise
+ */
+ bool get(const std::string &key, std::vector<char> &ret_val)
+ {
+ uint32_t flags= 0;
+ memcached_return_t rc;
+ size_t value_length= 0;
+
+ char *value= memcached_get(memc, key.c_str(), key.length(),
+ &value_length, &flags, &rc);
+ if (value != NULL && ret_val.empty())
+ {
+ ret_val.reserve(value_length);
+ ret_val.assign(value, value + value_length);
+ free(value);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Fetches an individual from a server which is specified by
+ * the master_key parameter that is used for determining which
+ * server an object was stored in if key partitioning was
+ * used for storage.
+ *
+ * @param[in] master_key key that specifies server object is stored on
+ * @param[in] key key of object whose value to get
+ * @param[out] ret_val object that is retrieved is stored in
+ * this vector
+ * @return true on success; false otherwise
+ */
+ bool getByKey(const std::string &master_key,
+ const std::string &key,
+ std::vector<char> &ret_val)
+ {
+ uint32_t flags= 0;
+ memcached_return_t rc;
+ size_t value_length= 0;
+
+ char *value= memcached_get_by_key(memc,
+ master_key.c_str(), master_key.length(),
+ key.c_str(), key.length(),
+ &value_length, &flags, &rc);
+ if (value)
+ {
+ ret_val.reserve(value_length);
+ ret_val.assign(value, value + value_length);
+ free(value);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Selects multiple keys at once. This method always
+ * works asynchronously.
+ *
+ * @param[in] keys vector of keys to select
+ * @return true if all keys are found
+ */
+ bool mget(std::vector<std::string> &keys)
+ {
+ std::vector<const char *> real_keys;
+ std::vector<size_t> key_len;
+ /*
+ * Construct an array which will contain the length
+ * of each of the strings in the input vector. Also, to
+ * interface with the memcached C API, we need to convert
+ * the vector of std::string's to a vector of char *.
+ */
+ real_keys.reserve(keys.size());
+ key_len.reserve(keys.size());
+
+ std::vector<std::string>::iterator it= keys.begin();
+
+ while (it != keys.end())
+ {
+ real_keys.push_back(const_cast<char *>((*it).c_str()));
+ key_len.push_back((*it).length());
+ ++it;
+ }
+
+ /*
+ * If the std::vector of keys is empty then we cannot
+ * call memcached_mget as we will get undefined behavior.
+ */
+ if (not real_keys.empty())
+ {
+ return memcached_success(memcached_mget(memc, &real_keys[0], &key_len[0], real_keys.size()));
+ }
+
+ return false;
+ }
+
+ /**
+ * Writes an object to the server. If the object already exists, it will
+ * overwrite the existing object. This method always returns true
+ * when using non-blocking mode unless a network error occurs.
+ *
+ * @param[in] key key of object to write to server
+ * @param[in] value value of object to write to server
+ * @param[in] expiration time to keep the object stored in the server for
+ * @param[in] flags flags to store with the object
+ * @return true on succcess; false otherwise
+ */
+ bool set(const std::string &key,
+ const std::vector<char> &value,
+ time_t expiration,
+ uint32_t flags)
+ {
+ memcached_return_t rc= memcached_set(memc,
+ key.c_str(), key.length(),
+ &value[0], value.size(),
+ expiration, flags);
+ return memcached_success(rc);
+ }
+
+ /**
+ * Writes an object to a server specified by the master_key parameter.
+ * If the object already exists, it will overwrite the existing object.
+ *
+ * @param[in] master_key key that specifies server to write to
+ * @param[in] key key of object to write to server
+ * @param[in] value value of object to write to server
+ * @param[in] expiration time to keep the object stored in the server for
+ * @param[in] flags flags to store with the object
+ * @return true on succcess; false otherwise
+ */
+ bool setByKey(const std::string &master_key,
+ const std::string &key,
+ const std::vector<char> &value,
+ time_t expiration,
+ uint32_t flags)
+ {
+ return memcached_success(memcached_set_by_key(memc, master_key.c_str(),
+ master_key.length(),
+ key.c_str(), key.length(),
+ &value[0], value.size(),
+ expiration,
+ flags));
+ }
+
+ /**
+ * Writes a list of objects to the server. Objects are specified by
+ * 2 vectors - 1 vector of keys and 1 vector of values.
+ *
+ * @param[in] keys vector of keys of objects to write to server
+ * @param[in] values vector of values of objects to write to server
+ * @param[in] expiration time to keep the objects stored in server for
+ * @param[in] flags flags to store with the objects
+ * @return true on success; false otherwise
+ */
+ bool setAll(std::vector<std::string> &keys,
+ std::vector< std::vector<char> *> &values,
+ time_t expiration,
+ uint32_t flags)
+ {
+ bool retval= true;
+ std::vector<std::string>::iterator key_it= keys.begin();
+ std::vector< std::vector<char> *>::iterator val_it= values.begin();
+ while (key_it != keys.end())
+ {
+ retval= set((*key_it), *(*val_it), expiration, flags);
+ if (retval == false)
+ {
+ return retval;
+ }
+ ++key_it;
+ ++val_it;
+ }
+ return retval;
+ }
+
+ /**
+ * Writes a list of objects to the server. Objects are specified by
+ * a map of keys to values.
+ *
+ * @param[in] key_value_map map of keys and values to store in server
+ * @param[in] expiration time to keep the objects stored in server for
+ * @param[in] flags flags to store with the objects
+ * @return true on success; false otherwise
+ */
+ bool setAll(std::map<const std::string, std::vector<char> > &key_value_map,
+ time_t expiration,
+ uint32_t flags)
+ {
+ bool retval= true;
+ std::map<const std::string, std::vector<char> >::iterator it= key_value_map.begin();
+
+ while (it != key_value_map.end())
+ {
+ retval= set(it->first, it->second, expiration, flags);
+ if (retval == false)
+ {
+ // We should tell the user what the key that failed was
+ return false;
+ }
+ ++it;
+ }
+ return true;
+ }
+
+ /**
+ * Increment the value of the object associated with the specified
+ * key by the offset given. The resulting value is saved in the value
+ * parameter.
+ *
+ * @param[in] key key of object in server whose value to increment
+ * @param[in] offset amount to increment object's value by
+ * @param[out] value store the result of the increment here
+ * @return true on success; false otherwise
+ */
+ bool increment(const std::string &key, uint32_t offset, uint64_t *value)
+ {
+ return memcached_success(memcached_increment(memc, key.c_str(), key.length(), offset, value));
+ }
+
+ /**
+ * Decrement the value of the object associated with the specified
+ * key by the offset given. The resulting value is saved in the value
+ * parameter.
+ *
+ * @param[in] key key of object in server whose value to decrement
+ * @param[in] offset amount to increment object's value by
+ * @param[out] value store the result of the decrement here
+ * @return true on success; false otherwise
+ */
+ bool decrement(const std::string &key, uint32_t offset, uint64_t *value)
+ {
+ return memcached_success(memcached_decrement(memc, key.c_str(),
+ key.length(),
+ offset, value));
+ }
+
+
+ /**
+ * Add an object with the specified key and value to the server. This
+ * function returns false if the object already exists on the server.
+ *
+ * @param[in] key key of object to add
+ * @param[in] value of object to add
+ * @return true on success; false otherwise
+ */
+ bool add(const std::string &key, const std::vector<char> &value)
+ {
+ return memcached_success(memcached_add(memc, key.c_str(), key.length(),
+ &value[0], value.size(), 0, 0));
+ }
+
+ /**
+ * Add an object with the specified key and value to the server. This
+ * function returns false if the object already exists on the server. The
+ * server to add the object to is specified by the master_key parameter.
+ *
+ * @param[in[ master_key key of server to add object to
+ * @param[in] key key of object to add
+ * @param[in] value of object to add
+ * @return true on success; false otherwise
+ */
+ bool addByKey(const std::string &master_key,
+ const std::string &key,
+ const std::vector<char> &value)
+ {
+ return memcached_success(memcached_add_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ &value[0],
+ value.size(),
+ 0, 0));
+ }
+
+ /**
+ * Replaces an object on the server. This method only succeeds
+ * if the object is already present on the server.
+ *
+ * @param[in] key key of object to replace
+ * @param[in[ value value to replace object with
+ * @return true on success; false otherwise
+ */
+ bool replace(const std::string &key, const std::vector<char> &value)
+ {
+ return memcached_success(memcached_replace(memc, key.c_str(), key.length(),
+ &value[0], value.size(),
+ 0, 0));
+ }
+
+ /**
+ * Replaces an object on the server. This method only succeeds
+ * if the object is already present on the server. The server
+ * to replace the object on is specified by the master_key param.
+ *
+ * @param[in] master_key key of server to replace object on
+ * @param[in] key key of object to replace
+ * @param[in[ value value to replace object with
+ * @return true on success; false otherwise
+ */
+ bool replaceByKey(const std::string &master_key,
+ const std::string &key,
+ const std::vector<char> &value)
+ {
+ return memcached_success(memcached_replace_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ &value[0],
+ value.size(),
+ 0, 0));
+ }
+
+ /**
+ * Places a segment of data before the last piece of data stored.
+ *
+ * @param[in] key key of object whose value we will prepend data to
+ * @param[in] value data to prepend to object's value
+ * @return true on success; false otherwise
+ */
+ bool prepend(const std::string &key, const std::vector<char> &value)
+ {
+ return memcached_success(memcached_prepend(memc, key.c_str(), key.length(),
+ &value[0], value.size(), 0, 0));
+ }
+
+ /**
+ * Places a segment of data before the last piece of data stored. The
+ * server on which the object where we will be prepending data is stored
+ * on is specified by the master_key parameter.
+ *
+ * @param[in] master_key key of server where object is stored
+ * @param[in] key key of object whose value we will prepend data to
+ * @param[in] value data to prepend to object's value
+ * @return true on success; false otherwise
+ */
+ bool prependByKey(const std::string &master_key,
+ const std::string &key,
+ const std::vector<char> &value)
+ {
+ return memcached_success(memcached_prepend_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ &value[0],
+ value.size(),
+ 0,
+ 0));
+ }
+
+ /**
+ * Places a segment of data at the end of the last piece of data stored.
+ *
+ * @param[in] key key of object whose value we will append data to
+ * @param[in] value data to append to object's value
+ * @return true on success; false otherwise
+ */
+ bool append(const std::string &key, const std::vector<char> &value)
+ {
+ return memcached_success(memcached_append(memc,
+ key.c_str(),
+ key.length(),
+ &value[0],
+ value.size(),
+ 0, 0));
+ }
+
+ /**
+ * Places a segment of data at the end of the last piece of data stored. The
+ * server on which the object where we will be appending data is stored
+ * on is specified by the master_key parameter.
+ *
+ * @param[in] master_key key of server where object is stored
+ * @param[in] key key of object whose value we will append data to
+ * @param[in] value data to append to object's value
+ * @return true on success; false otherwise
+ */
+ bool appendByKey(const std::string &master_key,
+ const std::string &key,
+ const std::vector<char> &value)
+ {
+ return memcached_success(memcached_append_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ &value[0],
+ value.size(),
+ 0, 0));
+ }
+
+ /**
+ * Overwrite data in the server as long as the cas_arg value
+ * is still the same in the server.
+ *
+ * @param[in] key key of object in server
+ * @param[in] value value to store for object in server
+ * @param[in] cas_arg "cas" value
+ */
+ bool cas(const std::string &key,
+ const std::vector<char> &value,
+ uint64_t cas_arg)
+ {
+ return memcached_success(memcached_cas(memc, key.c_str(), key.length(),
+ &value[0], value.size(),
+ 0, 0, cas_arg));
+ }
+
+ /**
+ * Overwrite data in the server as long as the cas_arg value
+ * is still the same in the server. The server to use is
+ * specified by the master_key parameter.
+ *
+ * @param[in] master_key specifies server to operate on
+ * @param[in] key key of object in server
+ * @param[in] value value to store for object in server
+ * @param[in] cas_arg "cas" value
+ */
+ bool casByKey(const std::string &master_key,
+ const std::string &key,
+ const std::vector<char> &value,
+ uint64_t cas_arg)
+ {
+ return memcached_success(memcached_cas_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ &value[0],
+ value.size(),
+ 0, 0, cas_arg));
+ }
+
+ /**
+ * Delete an object from the server specified by the key given.
+ *
+ * @param[in] key key of object to delete
+ * @return true on success; false otherwise
+ */
+ bool remove(const std::string &key)
+ {
+ return memcached_success(memcached_delete(memc, key.c_str(), key.length(), 0));
+ }
+
+ /**
+ * Delete an object from the server specified by the key given.
+ *
+ * @param[in] key key of object to delete
+ * @param[in] expiration time to delete the object after
+ * @return true on success; false otherwise
+ */
+ bool remove(const std::string &key, time_t expiration)
+ {
+ return memcached_success(memcached_delete(memc,
+ key.c_str(),
+ key.length(),
+ expiration));
+ }
+
+ /**
+ * Delete an object from the server specified by the key given.
+ *
+ * @param[in] master_key specifies server to remove object from
+ * @param[in] key key of object to delete
+ * @return true on success; false otherwise
+ */
+ bool removeByKey(const std::string &master_key,
+ const std::string &key)
+ {
+ return memcached_success(memcached_delete_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ 0));
+ }
+
+ /**
+ * Delete an object from the server specified by the key given.
+ *
+ * @param[in] master_key specifies server to remove object from
+ * @param[in] key key of object to delete
+ * @param[in] expiration time to delete the object after
+ * @return true on success; false otherwise
+ */
+ bool removeByKey(const std::string &master_key,
+ const std::string &key,
+ time_t expiration)
+ {
+ return memcached_success(memcached_delete_by_key(memc,
+ master_key.c_str(),
+ master_key.length(),
+ key.c_str(),
+ key.length(),
+ expiration));
+ }
+
+ /**
+ * Wipe the contents of memcached servers.
+ *
+ * @param[in] expiration time to wait until wiping contents of
+ * memcached servers
+ * @return true on success; false otherwise
+ */
+ bool flush(time_t expiration= 0)
+ {
+ return memcached_success(memcached_flush(memc, expiration));
+ }
+
+ /**
+ * Get the library version string.
+ * @return std::string containing a copy of the library version string.
+ */
+ const std::string libVersion() const
+ {
+ const char *ver= memcached_lib_version();
+ const std::string version(ver);
+ return version;
+ }
+
+ /**
+ * Retrieve memcached statistics. Populate a std::map with the retrieved
+ * stats. Each server will map to another std::map of the key:value stats.
+ *
+ * @param[out] stats_map a std::map to be populated with the memcached
+ * stats
+ * @return true on success; false otherwise
+ */
+ bool getStats(std::map< std::string, std::map<std::string, std::string> >
+ &stats_map)
+ {
+ memcached_return_t rc;
+ memcached_stat_st *stats= memcached_stat(memc, NULL, &rc);
+
+ if (rc != MEMCACHED_SUCCESS &&
+ rc != MEMCACHED_SOME_ERRORS)
+ {
+ return false;
+ }
+
+ uint32_t server_count= memcached_server_count(memc);
+
+ /*
+ * For each memcached server, construct a std::map for its stats and add
+ * it to the std::map of overall stats.
+ */
+ for (uint32_t x= 0; x < server_count; x++)
+ {
+ memcached_server_instance_st instance=
+ memcached_server_instance_by_position(memc, x);
+ std::ostringstream strstm;
+ std::string server_name(memcached_server_name(instance));
+ server_name.append(":");
+ strstm << memcached_server_port(instance);
+ server_name.append(strstm.str());
+
+ std::map<std::string, std::string> server_stats;
+ char **list= NULL;
+ char **ptr= NULL;
+
+ list= memcached_stat_get_keys(memc, &stats[x], &rc);
+ for (ptr= list; *ptr; ptr++)
+ {
+ char *value= memcached_stat_get_value(memc, &stats[x], *ptr, &rc);
+ server_stats[*ptr]= value;
+ free(value);
+ }
+
+ stats_map[server_name]= server_stats;
+ free(list);
+ }
+
+ memcached_stat_free(memc, stats);
+ return true;
+ }
+
+private:
+ memcached_st *memc;
+};
+
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+ memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* LibMemcached
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Work with fetching results
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_server_list_st memcached_servers_parse(const char *server_strings);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker, Trond Norbye All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef WIN32
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+typedef short in_port_t;
+typedef SOCKET memcached_socket_t;
+#else
+typedef int memcached_socket_t;
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/un.h>
+#include <netinet/tcp.h>
+
+#endif /* WIN32 */
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_quit(memcached_st *ptr);
+
+LIBMEMCACHED_LOCAL
+void memcached_quit_server(memcached_server_st *ptr, bool io_death);
+
+LIBMEMCACHED_LOCAL
+void send_quit(memcached_st *ptr);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_result_st {
+ uint32_t item_flags;
+ time_t item_expiration;
+ size_t key_length;
+ uint64_t item_cas;
+ memcached_st *root;
+ memcached_string_st value;
+ uint64_t count;
+ char item_key[MEMCACHED_MAX_KEY];
+ struct {
+ bool is_allocated:1;
+ bool is_initialized:1;
+ } options;
+ /* Add result callback function */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Result Struct */
+LIBMEMCACHED_API
+void memcached_result_free(memcached_result_st *result);
+
+LIBMEMCACHED_API
+void memcached_result_reset(memcached_result_st *ptr);
+
+LIBMEMCACHED_API
+memcached_result_st *memcached_result_create(const memcached_st *ptr,
+ memcached_result_st *result);
+
+LIBMEMCACHED_API
+const char *memcached_result_key_value(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+size_t memcached_result_key_length(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+const char *memcached_result_value(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+size_t memcached_result_length(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+uint32_t memcached_result_flags(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+uint64_t memcached_result_cas(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
+
+LIBMEMCACHED_API
+void memcached_result_set_flags(memcached_result_st *self, uint32_t flags);
+
+LIBMEMCACHED_API
+void memcached_result_set_expiration(memcached_result_st *self, time_t expiration);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+enum memcached_return_t {
+ MEMCACHED_SUCCESS,
+ MEMCACHED_FAILURE,
+ MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() and getnameinfo() only
+ MEMCACHED_CONNECTION_FAILURE,
+ MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
+ MEMCACHED_WRITE_FAILURE,
+ MEMCACHED_READ_FAILURE,
+ MEMCACHED_UNKNOWN_READ_FAILURE,
+ MEMCACHED_PROTOCOL_ERROR,
+ MEMCACHED_CLIENT_ERROR,
+ MEMCACHED_SERVER_ERROR,
+ MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE, // DEPRECATED
+ MEMCACHED_DATA_EXISTS,
+ MEMCACHED_DATA_DOES_NOT_EXIST,
+ MEMCACHED_NOTSTORED,
+ MEMCACHED_STORED,
+ MEMCACHED_NOTFOUND,
+ MEMCACHED_MEMORY_ALLOCATION_FAILURE,
+ MEMCACHED_PARTIAL_READ,
+ MEMCACHED_SOME_ERRORS,
+ MEMCACHED_NO_SERVERS,
+ MEMCACHED_END,
+ MEMCACHED_DELETED,
+ MEMCACHED_VALUE,
+ MEMCACHED_STAT,
+ MEMCACHED_ITEM,
+ MEMCACHED_ERRNO,
+ MEMCACHED_FAIL_UNIX_SOCKET, // DEPRECATED
+ MEMCACHED_NOT_SUPPORTED,
+ MEMCACHED_NO_KEY_PROVIDED, /* Deprecated. Use MEMCACHED_BAD_KEY_PROVIDED! */
+ MEMCACHED_FETCH_NOTFINISHED,
+ MEMCACHED_TIMEOUT,
+ MEMCACHED_BUFFERED,
+ MEMCACHED_BAD_KEY_PROVIDED,
+ MEMCACHED_INVALID_HOST_PROTOCOL,
+ MEMCACHED_SERVER_MARKED_DEAD,
+ MEMCACHED_UNKNOWN_STAT_KEY,
+ MEMCACHED_E2BIG,
+ MEMCACHED_INVALID_ARGUMENTS,
+ MEMCACHED_KEY_TOO_BIG,
+ MEMCACHED_AUTH_PROBLEM,
+ MEMCACHED_AUTH_FAILURE,
+ MEMCACHED_AUTH_CONTINUE,
+ MEMCACHED_PARSE_ERROR,
+ MEMCACHED_PARSE_USER_ERROR,
+ MEMCACHED_DEPRECATED,
+ MEMCACHED_IN_PROGRESS,
+ MEMCACHED_SERVER_TEMPORARILY_DISABLED,
+ MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
+};
+
+#ifndef __cplusplus
+typedef enum memcached_return_t memcached_return_t;
+#endif
+
+static inline bool memcached_success(memcached_return_t rc)
+{
+ return (rc == MEMCACHED_BUFFERED ||
+ rc == MEMCACHED_DELETED ||
+ rc == MEMCACHED_END ||
+ rc == MEMCACHED_ITEM ||
+ rc == MEMCACHED_STAT ||
+ rc == MEMCACHED_STORED ||
+ rc == MEMCACHED_SUCCESS ||
+ rc == MEMCACHED_VALUE);
+}
+
+static inline bool memcached_failed(memcached_return_t rc)
+{
+ return (rc != MEMCACHED_SUCCESS &&
+ rc != MEMCACHED_END &&
+ rc != MEMCACHED_STORED &&
+ rc != MEMCACHED_STAT &&
+ rc != MEMCACHED_DELETED &&
+ rc != MEMCACHED_BUFFERED &&
+ rc != MEMCACHED_VALUE);
+}
+
+static inline bool memcached_fatal(memcached_return_t rc)
+{
+ return (rc != MEMCACHED_SUCCESS &&
+ rc != MEMCACHED_END &&
+ rc != MEMCACHED_STORED &&
+ rc != MEMCACHED_STAT &&
+ rc != MEMCACHED_DELETED &&
+ rc != MEMCACHED_BUFFERED &&
+ rc != MEMCACHED_VALUE);
+}
+
+#define memcached_continue(__memcached_return_t) ((__memcached_return_t) == MEMCACHED_IN_PROGRESS)
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+#include <sasl/sasl.h>
+#else
+#define sasl_callback_t void
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_set_sasl_callbacks(memcached_st *ptr,
+ const sasl_callback_t *callbacks);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_sasl_auth_data(memcached_st *ptr,
+ const char *username,
+ const char *password);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr);
+
+
+LIBMEMCACHED_API
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr);
+
+LIBMEMCACHED_LOCAL
+memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source);
+
+LIBMEMCACHED_LOCAL
+memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *server);
+
+#ifdef __cplusplus
+}
+#endif
+
+struct memcached_sasl_st {
+ sasl_callback_t *callbacks;
+ /*
+ ** Did we allocate data inside the callbacks, or did the user
+ ** supply that.
+ */
+ bool is_allocated;
+};
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifndef WIN32
+#include <netdb.h>
+#endif
+
+#ifdef NI_MAXHOST
+#define MEMCACHED_NI_MAXHOST NI_MAXHOST
+#else
+#define MEMCACHED_NI_MAXHOST 1025
+#endif
+
+enum memcached_server_state_t {
+ MEMCACHED_SERVER_STATE_NEW, // fd == -1, no address lookup has been done
+ MEMCACHED_SERVER_STATE_ADDRINFO, // ADDRRESS information has been gathered
+ MEMCACHED_SERVER_STATE_IN_PROGRESS,
+ MEMCACHED_SERVER_STATE_CONNECTED,
+ MEMCACHED_SERVER_STATE_IN_TIMEOUT
+};
+
+struct memcached_server_st {
+ struct {
+ bool is_allocated:1;
+ bool is_initialized:1;
+ bool is_shutting_down:1;
+ bool is_dead:1;
+ } options;
+ uint32_t number_of_hosts;
+ uint32_t cursor_active;
+ in_port_t port;
+ memcached_socket_t fd;
+ uint32_t io_bytes_sent; /* # bytes sent since last read */
+ uint32_t server_failure_counter;
+ uint64_t server_failure_counter_query_id;
+ uint32_t weight;
+ uint32_t version;
+ enum memcached_server_state_t state;
+ struct {
+ uint32_t read;
+ uint32_t write;
+ } io_wait_count;
+ uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
+ uint8_t micro_version; // ditto
+ uint8_t minor_version; // ditto
+ memcached_connection_t type;
+ char *read_ptr;
+ size_t read_buffer_length;
+ size_t read_data_length;
+ size_t write_buffer_offset;
+ struct addrinfo *address_info;
+ struct addrinfo *address_info_next;
+ time_t next_retry;
+ memcached_st *root;
+ uint64_t limit_maxbytes;
+ struct memcached_error_t *error_messages;
+ char read_buffer[MEMCACHED_MAX_BUFFER];
+ char write_buffer[MEMCACHED_MAX_BUFFER];
+ char hostname[MEMCACHED_NI_MAXHOST];
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_cursor(const memcached_st *ptr,
+ const memcached_server_fn *callback,
+ void *context,
+ uint32_t number_of_callbacks);
+
+LIBMEMCACHED_API
+ memcached_server_instance_st memcached_server_by_key(memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+void memcached_server_error_reset(memcached_server_st *ptr);
+
+LIBMEMCACHED_API
+void memcached_server_free(memcached_server_st *ptr);
+
+LIBMEMCACHED_LOCAL
+memcached_server_st *memcached_server_clone(memcached_server_st *destination,
+ memcached_server_st *source);
+
+LIBMEMCACHED_API
+memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *ptr);
+
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_udp(memcached_st *ptr,
+ const char *hostname,
+ in_port_t port);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
+ const char *filename);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add(memcached_st *ptr,
+ const char *hostname, in_port_t port);
+
+LIBMEMCACHED_LOCAL
+ memcached_return_t memcached_server_add_parsed(memcached_st *ptr,
+ const char *hostname,
+ size_t hostname_length,
+ in_port_t port,
+ uint32_t weight);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_udp_with_weight(memcached_st *ptr,
+ const char *hostname,
+ in_port_t port,
+ uint32_t weight);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
+ const char *filename,
+ uint32_t weight);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_with_weight(memcached_st *ptr, const char *hostname,
+ in_port_t port,
+ uint32_t weight);
+
+/**
+ Operations on Single Servers.
+*/
+LIBMEMCACHED_API
+uint32_t memcached_server_response_count(const memcached_server_instance_st self);
+
+LIBMEMCACHED_API
+const char *memcached_server_name(const memcached_server_instance_st self);
+
+LIBMEMCACHED_API
+in_port_t memcached_server_port(const memcached_server_instance_st self);
+
+LIBMEMCACHED_API
+const char *memcached_server_type(const memcached_server_instance_st ptr);
+
+
+LIBMEMCACHED_LOCAL
+void __server_free(memcached_server_st *);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Server List Public functions */
+LIBMEMCACHED_API
+ void memcached_server_list_free(memcached_server_list_st ptr);
+
+LIBMEMCACHED_API
+ memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list);
+
+LIBMEMCACHED_API
+ memcached_server_list_st memcached_server_list_append(memcached_server_list_st ptr,
+ const char *hostname,
+ in_port_t port,
+ memcached_return_t *error);
+LIBMEMCACHED_API
+ memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr,
+ const char *hostname,
+ in_port_t port,
+ uint32_t weight,
+ memcached_return_t *error);
+LIBMEMCACHED_API
+ uint32_t memcached_server_list_count(const memcached_server_list_st ptr);
+
+LIBMEMCACHED_LOCAL
+ uint32_t memcached_servers_set_count(memcached_server_list_st servers, uint32_t count);
+
+LIBMEMCACHED_LOCAL
+ memcached_server_st *memcached_server_list(const memcached_st *);
+
+LIBMEMCACHED_LOCAL
+ void memcached_server_list_set(memcached_st *self, memcached_server_list_st list);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_stat_st {
+ unsigned long connection_structures;
+ unsigned long curr_connections;
+ unsigned long curr_items;
+ pid_t pid;
+ unsigned long pointer_size;
+ unsigned long rusage_system_microseconds;
+ unsigned long rusage_system_seconds;
+ unsigned long rusage_user_microseconds;
+ unsigned long rusage_user_seconds;
+ unsigned long threads;
+ unsigned long time;
+ unsigned long total_connections;
+ unsigned long total_items;
+ unsigned long uptime;
+ unsigned long long bytes;
+ unsigned long long bytes_read;
+ unsigned long long bytes_written;
+ unsigned long long cmd_get;
+ unsigned long long cmd_set;
+ unsigned long long evictions;
+ unsigned long long get_hits;
+ unsigned long long get_misses;
+ unsigned long long limit_maxbytes;
+ char version[MEMCACHED_VERSION_STRING_LENGTH];
+ void *__future; // @todo create a new structure to place here for future usage
+ memcached_st *root;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_stat_free(const memcached_st *, memcached_stat_st *);
+
+LIBMEMCACHED_API
+memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
+ const char *hostname, in_port_t port);
+
+LIBMEMCACHED_API
+char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat,
+ const char *key, memcached_return_t *error);
+
+LIBMEMCACHED_API
+char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat,
+ memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args, memcached_stat_fn func, void *context);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* All of the functions for adding data to the server */
+LIBMEMCACHED_API
+memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_append(memcached_st *ptr,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_prepend(memcached_st *ptr,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_cas(memcached_st *ptr,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags,
+ uint64_t cas);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_add_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_replace_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_append_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_cas_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ time_t expiration,
+ uint32_t flags,
+ uint64_t cas);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+const char *memcached_strerror(memcached_st *ptr, memcached_return_t rc);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/**
+ Strings are always under our control so we make some assumptions
+ about them.
+
+ 1) is_initialized is always valid.
+ 2) A string once intialized will always be, until free where we
+ unset this flag.
+ 3) A string always has a root.
+*/
+
+struct memcached_string_st {
+ char *end;
+ char *string;
+ size_t current_size;
+ memcached_st *root;
+ struct {
+ bool is_allocated:1;
+ bool is_initialized:1;
+ } options;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_LOCAL
+memcached_string_st *memcached_string_create(memcached_st *ptr,
+ memcached_string_st *string,
+ size_t initial_size);
+LIBMEMCACHED_LOCAL
+memcached_return_t memcached_string_check(memcached_string_st *string, size_t need);
+
+LIBMEMCACHED_LOCAL
+char *memcached_string_c_copy(memcached_string_st *string);
+
+LIBMEMCACHED_LOCAL
+memcached_return_t memcached_string_append_character(memcached_string_st *string,
+ char character);
+LIBMEMCACHED_LOCAL
+memcached_return_t memcached_string_append(memcached_string_st *string,
+ const char *value, size_t length);
+LIBMEMCACHED_LOCAL
+memcached_return_t memcached_string_reset(memcached_string_st *string);
+
+LIBMEMCACHED_LOCAL
+void memcached_string_free(memcached_string_st *string);
+
+LIBMEMCACHED_LOCAL
+size_t memcached_string_length(const memcached_string_st *self);
+
+LIBMEMCACHED_LOCAL
+size_t memcached_string_size(const memcached_string_st *self);
+
+LIBMEMCACHED_LOCAL
+const char *memcached_string_value(const memcached_string_st *self);
+
+LIBMEMCACHED_LOCAL
+char *memcached_string_take_value(memcached_string_st *self);
+
+LIBMEMCACHED_LOCAL
+char *memcached_string_value_mutable(const memcached_string_st *self);
+
+LIBMEMCACHED_LOCAL
+void memcached_string_set_length(memcached_string_st *self, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+LIBMEMCACHED_API
+memcached_return_t memcached_touch(memcached_st *ptr,
+ const char *key, size_t key_length,
+ time_t expiration);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_touch_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+typedef struct memcached_st memcached_st;
+typedef struct memcached_stat_st memcached_stat_st;
+typedef struct memcached_analysis_st memcached_analysis_st;
+typedef struct memcached_result_st memcached_result_st;
+typedef struct memcached_array_st memcached_array_st;
+typedef struct memcached_error_t memcached_error_t;
+
+// All of the flavors of memcache_server_st
+typedef struct memcached_server_st memcached_server_st;
+typedef const struct memcached_server_st *memcached_server_instance_st;
+typedef struct memcached_server_st *memcached_server_list_st;
+
+typedef struct memcached_callback_st memcached_callback_st;
+
+// The following two structures are internal, and never exposed to users.
+typedef struct memcached_string_st memcached_string_st;
+typedef struct memcached_string_t memcached_string_t;
+typedef struct memcached_continuum_item_st memcached_continuum_item_st;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef memcached_return_t (*memcached_clone_fn)(memcached_st *destination, const memcached_st *source);
+typedef memcached_return_t (*memcached_cleanup_fn)(const memcached_st *ptr);
+
+/**
+ Memory allocation functions.
+*/
+typedef void (*memcached_free_fn)(const memcached_st *ptr, void *mem, void *context);
+typedef void *(*memcached_malloc_fn)(const memcached_st *ptr, const size_t size, void *context);
+typedef void *(*memcached_realloc_fn)(const memcached_st *ptr, void *mem, const size_t size, void *context);
+typedef void *(*memcached_calloc_fn)(const memcached_st *ptr, size_t nelem, const size_t elsize, void *context);
+
+
+typedef memcached_return_t (*memcached_execute_fn)(const memcached_st *ptr, memcached_result_st *result, void *context);
+typedef memcached_return_t (*memcached_server_fn)(const memcached_st *ptr, memcached_server_instance_st server, void *context);
+typedef memcached_return_t (*memcached_stat_fn)(memcached_server_instance_st server,
+ const char *key, size_t key_length,
+ const char *value, size_t value_length,
+ void *context);
+
+/**
+ Trigger functions.
+*/
+typedef memcached_return_t (*memcached_trigger_key_fn)(const memcached_st *ptr,
+ const char *key, size_t key_length,
+ memcached_result_st *result);
+typedef memcached_return_t (*memcached_trigger_delete_key_fn)(const memcached_st *ptr,
+ const char *key, size_t key_length);
+
+typedef memcached_return_t (*memcached_dump_fn)(const memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ void *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ @note The following definitions are just here for backwards compatibility.
+*/
+typedef memcached_return_t memcached_return;
+typedef memcached_server_distribution_t memcached_server_distribution;
+typedef memcached_behavior_t memcached_behavior;
+typedef memcached_callback_t memcached_callback;
+typedef memcached_hash_t memcached_hash;
+typedef memcached_connection_t memcached_connection;
+typedef memcached_clone_fn memcached_clone_func;
+typedef memcached_cleanup_fn memcached_cleanup_func;
+typedef memcached_execute_fn memcached_execute_function;
+typedef memcached_server_fn memcached_server_function;
+typedef memcached_trigger_key_fn memcached_trigger_key;
+typedef memcached_trigger_delete_key_fn memcached_trigger_delete_key;
+typedef memcached_dump_fn memcached_dump_func;
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity);
+
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_version(memcached_st *ptr);
+
+LIBMEMCACHED_API
+const char * memcached_lib_version(void);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Interface for memcached server.
+ *
+ * Author: Trond Norbye
+ *
+ */
+
+/**
+ * @file
+ * @brief Visibility control macros
+ */
+
+#pragma once
+
+/**
+ *
+ * LIBMEMCACHED_API is used for the public API symbols. It either DLL imports or
+ * DLL exports (or does nothing for static build).
+ *
+ * LIBMEMCACHED_LOCAL is used for non-api symbols.
+ */
+
+#if defined(BUILDING_LIBMEMCACHEDINTERNAL)
+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+# define LIBMEMCACHED_API __attribute__ ((visibility("default")))
+# define LIBMEMCACHED_LOCAL __attribute__ ((visibility("default")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define LIBMEMCACHED_API __global
+# define LIBMEMCACHED_LOCAL __global
+# elif defined(_MSC_VER)
+# define LIBMEMCACHED_API extern __declspec(dllexport)
+# define LIBMEMCACHED_LOCAL extern __declspec(dllexport)
+# else
+# define LIBMEMCACHED_API
+# define LIBMEMCACHED_LOCAL
+# endif
+#else
+# if defined(BUILDING_LIBMEMCACHED)
+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+# define LIBMEMCACHED_API __attribute__ ((visibility("default")))
+# define LIBMEMCACHED_LOCAL __attribute__ ((visibility("hidden")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define LIBMEMCACHED_API __global
+# define LIBMEMCACHED_LOCAL __hidden
+# elif defined(_MSC_VER)
+# define LIBMEMCACHED_API extern __declspec(dllexport)
+# define LIBMEMCACHED_LOCAL
+# else
+# define LIBMEMCACHED_API
+# define LIBMEMCACHED_LOCAL
+# endif /* defined(HAVE_VISIBILITY) */
+# else /* defined(BUILDING_LIBMEMCACHED) */
+# if defined(_MSC_VER)
+# define LIBMEMCACHED_API extern __declspec(dllimport)
+# define LIBMEMCACHED_LOCAL
+# else
+# define LIBMEMCACHED_API
+# define LIBMEMCACHED_LOCAL
+# endif /* defined(_MSC_VER) */
+# endif /* defined(BUILDING_LIBMEMCACHED) */
+#endif /* defined(BUILDING_LIBMEMCACHEDINTERNAL) */
}
/* All should be set, or none should be set */
- if (mem_malloc == NULL && mem_free == NULL && mem_realloc == NULL && mem_calloc == NULL)
+ if (mem_malloc == NULL and mem_free == NULL and mem_realloc == NULL and mem_calloc == NULL)
{
self->allocators= memcached_allocators_return_default();
}
- else if (mem_malloc == NULL || mem_free == NULL || mem_realloc == NULL || mem_calloc == NULL)
+ else if (mem_malloc == NULL or mem_free == NULL or mem_realloc == NULL or mem_calloc == NULL)
{
return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("NULL parameter provided for one or more allocators"));
}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_allocator_t {
- memcached_calloc_fn calloc;
- memcached_free_fn free;
- memcached_malloc_fn malloc;
- memcached_realloc_fn realloc;
- void *context;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_memory_allocators(memcached_st *ptr,
- memcached_malloc_fn mem_malloc,
- memcached_free_fn mem_free,
- memcached_realloc_fn mem_realloc,
- memcached_calloc_fn mem_calloc,
- void *context);
-
-LIBMEMCACHED_API
-void memcached_get_memory_allocators(const memcached_st *ptr,
- memcached_malloc_fn *mem_malloc,
- memcached_free_fn *mem_free,
- memcached_realloc_fn *mem_realloc,
- memcached_calloc_fn *mem_calloc);
-
-LIBMEMCACHED_API
-void *memcached_get_memory_allocators_context(const memcached_st *ptr);
-
-LIBMEMCACHED_LOCAL
-void _libmemcached_free(const memcached_st *ptr, void *mem, void *context);
-
-LIBMEMCACHED_LOCAL
-void *_libmemcached_malloc(const memcached_st *ptr, const size_t size, void *context);
-
-LIBMEMCACHED_LOCAL
-void *_libmemcached_realloc(const memcached_st *ptr, void *mem, const size_t size, void *context);
-
-LIBMEMCACHED_LOCAL
-void *_libmemcached_calloc(const memcached_st *ptr, size_t nelem, size_t size, void *context);
-
-LIBMEMCACHED_LOCAL
-struct memcached_allocator_t memcached_allocators_return_default(void);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_analysis_st {
- memcached_st *root;
- uint32_t average_item_size;
- uint32_t longest_uptime;
- uint32_t least_free_server;
- uint32_t most_consumed_server;
- uint32_t oldest_server;
- double pool_hit_ratio;
- uint64_t most_used_bytes;
- uint64_t least_remaining_bytes;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_analysis_st *memcached_analyze(memcached_st *memc,
- memcached_stat_st *memc_stat,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-void memcached_analyze_free(memcached_analysis_st *);
-
-#ifdef __cplusplus
-}
-#endif
{
bool no_reply= ptr->flags.no_reply;
- if (memcached_server_count(ptr) == 0)
- return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
-
uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
struct libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes },
- { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
- { key_length, key }
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { key, key_length }
};
memcached_return_t rc;
}
if (no_reply)
+ {
return MEMCACHED_SUCCESS;
+ }
return memcached_response(instance, (char*)value, sizeof(*value), NULL);
}
{
memcached_return_t rc;
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
if (memcached_failed(rc= initialize_query(ptr)))
{
uint64_t *value)
{
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
memcached_return_t rc;
if (memcached_failed(rc= initialize_query(ptr)))
uint64_t *value)
{
uint64_t local_value;
- if (! value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
return memcached_increment_with_initial_by_key(ptr, key, key_length,
key, key_length,
uint64_t *value)
{
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
memcached_return_t rc;
if (memcached_failed(rc= initialize_query(ptr)))
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
if (ptr->flags.binary_protocol)
+ {
rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
group_key, group_key_length, key, key_length,
offset, initial, (uint32_t)expiration,
value);
+ }
else
+ {
rc= MEMCACHED_PROTOCOL_ERROR;
+ }
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
uint64_t *value)
{
uint64_t local_value;
- if (! value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
return memcached_decrement_with_initial_by_key(ptr, key, key_length,
key, key_length,
uint64_t *value)
{
uint64_t local_value;
- if (not value)
+ if (value == NULL)
+ {
value= &local_value;
+ }
memcached_return_t rc;
if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
- memcached_return_t memcached_increment(memcached_st *ptr,
- const char *key, size_t key_length,
- uint32_t offset,
- uint64_t *value);
-LIBMEMCACHED_API
- memcached_return_t memcached_decrement(memcached_st *ptr,
- const char *key, size_t key_length,
- uint32_t offset,
- uint64_t *value);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_increment_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- uint64_t offset,
- uint64_t *value);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- uint64_t offset,
- uint64_t *value);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
- const char *key,
- size_t key_length,
- uint64_t offset,
- uint64_t initial,
- time_t expiration,
- uint64_t *value);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
- const char *key,
- size_t key_length,
- uint64_t offset,
- uint64_t initial,
- time_t expiration,
- uint64_t *value);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
- const char *group_key,
- size_t group_key_length,
- const char *key,
- size_t key_length,
- uint64_t offset,
- uint64_t initial,
- time_t expiration,
- uint64_t *value);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
- const char *group_key,
- size_t group_key_length,
- const char *key,
- size_t key_length,
- uint64_t offset,
- uint64_t initial,
- time_t expiration,
- uint64_t *value);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-// No assumptions of NULL should be made
-
-struct memcached_string_t {
- const char *c_str;
- size_t size;
-};
-
-#define memcached_size(X) (X).size;
-#define memcached_c_str(X) (X).c_str;
-#define memcached_string_param(X) (X).c_str, (X).size
-
-#ifdef __cplusplus
-#define memcached_string_printf(X) int((X).size), (X).c_str
-#else
-#define memcached_string_printf(X) (int)((X).size), (X).c_str
-#endif
-
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data);
-
-LIBMEMCACHED_API
-uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set_distribution(memcached_st *ptr, memcached_server_distribution_t type);
-
-LIBMEMCACHED_API
-memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_hash_t type);
-
-LIBMEMCACHED_API
-memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, memcached_hash_t type);
-
-LIBMEMCACHED_API
-memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr);
-
-LIBMEMCACHED_LOCAL
-bool _is_auto_eject_host(const memcached_st *ptr);
-
-LIBMEMCACHED_API
- const char *libmemcached_string_behavior(const memcached_behavior_t flag);
-
-LIBMEMCACHED_API
- const char *libmemcached_string_distribution(const memcached_server_distribution_t flag);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_bucket_set(memcached_st *self,
- const uint32_t *host_map,
- const uint32_t *forward_map,
- const uint32_t buckets,
- const uint32_t replicas);
-
-#ifdef __cplusplus
-}
-#endif
{
return memcached_set_namespace(ptr, (char*)data, data ? strlen((char*)data) : 0);
}
+
case MEMCACHED_CALLBACK_USER_DATA:
{
ptr->user_data= const_cast<void *>(data);
break;
}
+
case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
{
memcached_cleanup_fn func= *(memcached_cleanup_fn *)&data;
ptr->on_cleanup= func;
break;
}
+
case MEMCACHED_CALLBACK_CLONE_FUNCTION:
{
memcached_clone_fn func= *(memcached_clone_fn *)&data;
ptr->on_clone= func;
break;
}
-#ifdef MEMCACHED_ENABLE_DEPRECATED
- case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
- {
- memcached_malloc_function func= *(memcached_malloc_fn *)&data;
- ptr->call_malloc= func;
- break;
- }
- case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
- {
- memcached_realloc_function func= *(memcached_realloc_fn *)&data;
- ptr->call_realloc= func;
- break;
- }
- case MEMCACHED_CALLBACK_FREE_FUNCTION:
- {
- memcached_free_function func= *(memcached_free_fn *)&data;
- ptr->call_free= func;
- break;
- }
-#endif
+
case MEMCACHED_CALLBACK_GET_FAILURE:
{
memcached_trigger_key_fn func= *(memcached_trigger_key_fn *)&data;
ptr->get_key_failure= func;
break;
}
+
case MEMCACHED_CALLBACK_DELETE_TRIGGER:
{
+ if (data) // NULL would mean we are disabling.
+ {
+ if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS))
+ {
+ return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
+ }
+
+ if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_NOREPLY))
+ {
+ return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
+ }
+ }
+
memcached_trigger_delete_key_fn func= *(memcached_trigger_delete_key_fn *)&data;
ptr->delete_trigger= func;
break;
}
+
case MEMCACHED_CALLBACK_MAX:
- return MEMCACHED_FAILURE;
+ return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid callback supplied"));
}
return MEMCACHED_SUCCESS;
error = &local_error;
}
+ if (ptr == NULL)
+ {
+ *error= MEMCACHED_INVALID_ARGUMENTS;
+ return NULL;
+ }
+
switch (flag)
{
case MEMCACHED_CALLBACK_PREFIX_KEY:
{
+ *error= MEMCACHED_SUCCESS;
if (ptr->_namespace)
{
- *error= MEMCACHED_SUCCESS;
return (void *)memcached_array_string(ptr->_namespace);
}
- else
- {
- *error= MEMCACHED_FAILURE;
- return NULL;
- }
+ return NULL;
}
+
case MEMCACHED_CALLBACK_USER_DATA:
{
*error= ptr->user_data ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
return (void *)ptr->user_data;
}
+
case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
{
*error= ptr->on_cleanup ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
return *(void **)&ptr->on_cleanup;
}
+
case MEMCACHED_CALLBACK_CLONE_FUNCTION:
{
*error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
return *(void **)&ptr->on_clone;
}
-#ifdef MEMCACHED_ENABLE_DEPRECATED
- case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
- {
- *error= ptr->call_malloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
- return *(void **)&ptr->call_malloc;
- }
- case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
- {
- *error= ptr->call_realloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
- return *(void **)&ptr->call_realloc;
- }
- case MEMCACHED_CALLBACK_FREE_FUNCTION:
- {
- *error= ptr->call_free ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
- return *(void **)&ptr->call_free;
- }
-#endif
+
case MEMCACHED_CALLBACK_GET_FAILURE:
{
*error= ptr->get_key_failure ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
return *(void **)&ptr->get_key_failure;
}
+
case MEMCACHED_CALLBACK_DELETE_TRIGGER:
{
*error= ptr->delete_trigger ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
return *(void **)&ptr->delete_trigger;
}
+
case MEMCACHED_CALLBACK_MAX:
- default:
- assert_msg(0, "Invalid behavior passed to memcached_behavior_set()");
- *error= MEMCACHED_FAILURE;
- return NULL;
+ break;
}
+
+ assert_msg(0, "Invalid behavior passed to memcached_behavior_set()");
+ *error= MEMCACHED_FAILURE;
+ return NULL;
}
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Libmemcached library
+ * Libmemcached Client and Server
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
#pragma once
-struct memcached_callback_st {
- memcached_execute_fn *callback;
- void *context;
- uint32_t number_of_callback;
-};
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER(memcached_st *);
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_callback_set(memcached_st *ptr,
- const memcached_callback_t flag,
- const void *data);
-LIBMEMCACHED_API
-void *memcached_callback_get(memcached_st *ptr,
- const memcached_callback_t flag,
- memcached_return_t *error);
-
-#ifdef __cplusplus
-}
-#endif
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY(memcached_st *);
#include <strings.h>
#endif
-#include <libmemcached/memcached.h>
+#include <libmemcached-1.0/memcached.h>
#include <libmemcached/watchpoint.h>
#include <libmemcached/is.h>
-#include <libmemcached/namespace.h>
#include <libmemcached/server_instance.h>
#include <libmemcached/initialize_query.h>
#include <libmemcached/response.h>
#include <libmemcached/namespace.h>
+#include <libmemcached/virtual_bucket.h>
#ifdef __cplusplus
#include <libmemcached/backtrace.hpp>
#include <libmemcached/assert.hpp>
#include <libmemcached/server.hpp>
+#include <libmemcached/key.hpp>
#endif
#include <libmemcached/continuum.hpp>
#define memcached_server_response_decrement(A) (A)->cursor_active--
#define memcached_server_response_reset(A) (A)->cursor_active=0
-#ifdef __cplusplus
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_key_test(const memcached_st& memc,
- const char * const *keys,
- const size_t *key_length,
- size_t number_of_keys);
-#endif
-
LIBMEMCACHED_LOCAL
memcached_return_t memcached_purge(memcached_server_write_instance_st ptr);
-
-static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary)
-{
- if (key_length == 0)
- {
- return MEMCACHED_BAD_KEY_PROVIDED;
- }
-
- if (binary)
- {
- if (key_length > 0xffff)
- {
- return MEMCACHED_BAD_KEY_PROVIDED;
- }
- }
- else
- {
- if (key_length >= MEMCACHED_MAX_KEY)
- {
- return MEMCACHED_BAD_KEY_PROVIDED;
- }
- }
-
- return MEMCACHED_SUCCESS;
-}
-
#ifdef __cplusplus
}
#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker, Trond Norbye All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-@DEPRECATED@
-@LIBMEMCACHED_WITH_SASL_SUPPORT@
-
-#define LIBMEMCACHED_VERSION_STRING "@VERSION@"
-#define LIBMEMCACHED_VERSION_HEX @PANDORA_HEX_VERSION@
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-/* Public defines */
-#define MEMCACHED_DEFAULT_PORT 11211
-#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
-#define MEMCACHED_MAX_BUFFER 8196
-#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
-#define MEMCACHED_POINTS_PER_SERVER 100
-#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
-#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
-#define MEMCACHED_STRIDE 4
-#define MEMCACHED_DEFAULT_TIMEOUT 5000
-#define MEMCACHED_DEFAULT_CONNECT_TIMEOUT 4000
-#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
-#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
-#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
-#define MEMCACHED_VERSION_STRING_LENGTH 24
-#define MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH 20
-#define MEMCACHED_SERVER_FAILURE_LIMIT 5
-#define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
-
-
-enum memcached_server_distribution_t {
- MEMCACHED_DISTRIBUTION_MODULA,
- MEMCACHED_DISTRIBUTION_CONSISTENT,
- MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
- MEMCACHED_DISTRIBUTION_RANDOM,
- MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY,
- MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED,
- MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET,
- MEMCACHED_DISTRIBUTION_CONSISTENT_MAX
-};
-
-#ifndef __cplusplus
-typedef enum memcached_server_distribution_t memcached_server_distribution_t;
-#endif
-
-enum memcached_behavior_t {
- MEMCACHED_BEHAVIOR_NO_BLOCK,
- MEMCACHED_BEHAVIOR_TCP_NODELAY,
- MEMCACHED_BEHAVIOR_HASH,
- MEMCACHED_BEHAVIOR_KETAMA,
- MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE,
- MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE,
- MEMCACHED_BEHAVIOR_CACHE_LOOKUPS,
- MEMCACHED_BEHAVIOR_SUPPORT_CAS,
- MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
- MEMCACHED_BEHAVIOR_DISTRIBUTION,
- MEMCACHED_BEHAVIOR_BUFFER_REQUESTS,
- MEMCACHED_BEHAVIOR_USER_DATA,
- MEMCACHED_BEHAVIOR_SORT_HOSTS,
- MEMCACHED_BEHAVIOR_VERIFY_KEY,
- MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,
- MEMCACHED_BEHAVIOR_RETRY_TIMEOUT,
- MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED,
- MEMCACHED_BEHAVIOR_KETAMA_HASH,
- MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
- MEMCACHED_BEHAVIOR_SND_TIMEOUT,
- MEMCACHED_BEHAVIOR_RCV_TIMEOUT,
- MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT,
- MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK,
- MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK,
- MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH,
- MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY,
- MEMCACHED_BEHAVIOR_NOREPLY,
- MEMCACHED_BEHAVIOR_USE_UDP,
- MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS,
- MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
- MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ,
- MEMCACHED_BEHAVIOR_CORK,
- MEMCACHED_BEHAVIOR_TCP_KEEPALIVE,
- MEMCACHED_BEHAVIOR_TCP_KEEPIDLE,
- MEMCACHED_BEHAVIOR_LOAD_FROM_FILE,
- MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS,
- MEMCACHED_BEHAVIOR_MAX
-};
-
-#ifndef __cplusplus
-typedef enum memcached_behavior_t memcached_behavior_t;
-#endif
-
-enum memcached_callback_t {
- MEMCACHED_CALLBACK_PREFIX_KEY = 0,
- MEMCACHED_CALLBACK_USER_DATA = 1,
- MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2,
- MEMCACHED_CALLBACK_CLONE_FUNCTION = 3,
-#ifdef MEMCACHED_ENABLE_DEPRECATED
- MEMCACHED_CALLBACK_MALLOC_FUNCTION = 4,
- MEMCACHED_CALLBACK_REALLOC_FUNCTION = 5,
- MEMCACHED_CALLBACK_FREE_FUNCTION = 6,
-#endif
- MEMCACHED_CALLBACK_GET_FAILURE = 7,
- MEMCACHED_CALLBACK_DELETE_TRIGGER = 8,
- MEMCACHED_CALLBACK_MAX,
- MEMCACHED_CALLBACK_NAMESPACE= MEMCACHED_CALLBACK_PREFIX_KEY
-};
-
-#ifndef __cplusplus
-typedef enum memcached_callback_t memcached_callback_t;
-#endif
-
-enum memcached_hash_t {
- MEMCACHED_HASH_DEFAULT= 0,
- MEMCACHED_HASH_MD5,
- MEMCACHED_HASH_CRC,
- MEMCACHED_HASH_FNV1_64,
- MEMCACHED_HASH_FNV1A_64,
- MEMCACHED_HASH_FNV1_32,
- MEMCACHED_HASH_FNV1A_32,
- MEMCACHED_HASH_HSIEH,
- MEMCACHED_HASH_MURMUR,
- MEMCACHED_HASH_JENKINS,
- MEMCACHED_HASH_CUSTOM,
- MEMCACHED_HASH_MAX
-};
-
-#ifndef __cplusplus
-typedef enum memcached_hash_t memcached_hash_t;
-#endif
-
-enum memcached_connection_t {
- MEMCACHED_CONNECTION_TCP,
- MEMCACHED_CONNECTION_UDP,
- MEMCACHED_CONNECTION_UNIX_SOCKET
-};
-
-enum {
- MEMCACHED_CONNECTION_UNKNOWN= 0,
- MEMCACHED_CONNECTION_MAX= 0
-};
-
-#ifndef __cplusplus
-typedef enum memcached_connection_t memcached_connection_t;
-#endif
#pragma once
#include <libmemcached/common.h>
+#include <libmemcached/csl/server.h>
#pragma once
-#include <libmemcached/basic_string.h>
-#include <libmemcached/constants.h>
-#include <libmemcached/csl/server.h>
+#include <libmemcached/csl/common.h>
union YYSTYPE
{
key, key_length, expiration);
}
-static inline memcached_return_t binary_delete(memcached_st *ptr,
- uint32_t server_key,
- const char *key,
- size_t key_length,
- bool flush);
-
-memcached_return_t memcached_delete_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- time_t expiration)
+static inline memcached_return_t ascii_delete(memcached_st *ptr,
+ memcached_server_write_instance_st instance,
+ uint32_t ,
+ const char *key,
+ size_t key_length,
+ uint64_t expiration,
+ bool& reply,
+ bool& flush)
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- memcached_server_write_instance_st instance;
+ int send_length;
- LIBMEMCACHED_MEMCACHED_DELETE_START();
-
- memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (expiration)
{
- return rc;
- }
-
- rc= memcached_validate_key_length(key_length,
- ptr->flags.binary_protocol);
-
- if (memcached_failed(rc))
- {
- return rc;
- }
-
- uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
- instance= memcached_server_instance_fetch(ptr, server_key);
-
- bool to_write= (ptr->flags.buffer_requests) ? false : true;
-
- bool no_reply= (ptr->flags.no_reply);
-
- if (ptr->flags.binary_protocol)
- {
- likely (! expiration)
+ if ((instance->major_version == 1 and
+ instance->minor_version > 2) or
+ instance->major_version > 1)
{
- rc= binary_delete(ptr, server_key, key, key_length, to_write);
+ return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("Memcached server version does not allow expiration of deleted items"));
}
else
{
- rc= MEMCACHED_INVALID_ARGUMENTS;
- }
- }
- else
- {
- int send_length;
+ /* ensure that we are connected, otherwise we might bump the
+ * command counter before connection */
+ memcached_return_t rc;
+ if ((rc= memcached_connect(instance)) != MEMCACHED_SUCCESS)
+ {
+ WATCHPOINT_ERROR(rc);
+ return rc;
+ }
- unlikely (expiration)
- {
- if ((instance->major_version == 1 &&
- instance->minor_version > 2) ||
- instance->major_version > 1)
- {
- rc= MEMCACHED_INVALID_ARGUMENTS;
- goto error;
- }
- else
- {
- /* ensure that we are connected, otherwise we might bump the
- * command counter before connection */
- if ((rc= memcached_connect(instance)) != MEMCACHED_SUCCESS)
+ if (instance->minor_version == 0)
+ {
+ if (reply == false or flush == false)
+ {
+ /* We might get out of sync with the server if we send this command
+ * to a server newer than 1.2.x.. enable reply and buffered mode.
+ */
+ flush= true;
+ if (reply == false)
{
- WATCHPOINT_ERROR(rc);
- return rc;
+ memcached_server_response_increment(instance);
}
+ reply= true;
+ }
+ }
- if (instance->minor_version == 0)
- {
- if (no_reply or to_write == false)
- {
- /* We might get out of sync with the server if we
- * send this command to a server newer than 1.2.x..
- * disable no_reply and buffered mode.
- */
- to_write= true;
- if (no_reply)
- memcached_server_response_increment(instance);
- no_reply= false;
- }
- }
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "delete %.*s%.*s %u%s\r\n",
- memcached_print_array(ptr->_namespace),
- (int) key_length, key,
- (uint32_t)expiration,
- no_reply ? " noreply" :"" );
- }
- }
- else
- {
send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "delete %.*s%.*s%s\r\n",
+ "delete %.*s%.*s %u%s\r\n",
memcached_print_array(ptr->_namespace),
- (int)key_length, key, no_reply ? " noreply" :"");
- }
-
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
- {
- rc= memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
- goto error;
- }
-
- if (ptr->flags.use_udp and to_write == false)
- {
- if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
- return MEMCACHED_WRITE_FAILURE;
-
- if (send_length + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
- {
- memcached_io_write(instance, NULL, 0, true);
- }
+ (int) key_length, key,
+ (uint32_t)expiration,
+ reply ? "" : " noreply");
}
-
- rc= memcached_do(instance, buffer, (size_t)send_length, to_write);
}
-
- if (rc != MEMCACHED_SUCCESS)
+ else
{
- goto error;
+ send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
+ "delete %.*s%.*s%s\r\n",
+ memcached_print_array(ptr->_namespace),
+ (int)key_length, key,
+ reply ? "" : " noreply");
}
- if (to_write == false)
+ if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
{
- rc= MEMCACHED_BUFFERED;
+ return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
}
- else if (no_reply == false)
+
+ if (ptr->flags.use_udp and flush == false)
{
- rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
- if (rc == MEMCACHED_DELETED)
+ if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
{
- rc= MEMCACHED_SUCCESS;
+ return MEMCACHED_WRITE_FAILURE;
}
- }
- if (rc == MEMCACHED_SUCCESS and ptr->delete_trigger)
- {
- ptr->delete_trigger(ptr, key, key_length);
+ if (send_length +instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+ {
+ memcached_io_write(instance, NULL, 0, true);
+ }
}
-error:
- LIBMEMCACHED_MEMCACHED_DELETE_END();
- return rc;
+ return memcached_do(instance, buffer, (size_t)send_length, flush);
}
static inline memcached_return_t binary_delete(memcached_st *ptr,
+ memcached_server_write_instance_st instance,
uint32_t server_key,
const char *key,
size_t key_length,
- bool flush)
+ time_t expiration,
+ bool& reply,
+ bool& flush)
{
- memcached_server_write_instance_st instance;
protocol_binary_request_delete request= {};
- instance= memcached_server_instance_fetch(ptr, server_key);
+ // No expiration is supported in the binary protocol
+ if (expiration)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
- if (ptr->flags.no_reply)
+ if (reply)
{
- request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
}
else
{
- request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
}
request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace)));
- if (ptr->flags.use_udp && ! flush)
+ if (ptr->flags.use_udp and flush == false)
{
size_t cmd_size= sizeof(request.bytes) + key_length;
if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
+ {
return MEMCACHED_WRITE_FAILURE;
+ }
- if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+ if (cmd_size +instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+ {
memcached_io_write(instance, NULL, 0, true);
+ }
}
struct libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes},
- { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
- { key_length, key },
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { key, key_length }
};
memcached_return_t rc= MEMCACHED_SUCCESS;
memcached_io_reset(instance);
}
- unlikely (ptr->number_of_replicas > 0)
+ if (ptr->number_of_replicas > 0)
{
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
return rc;
}
+
+memcached_return_t memcached_delete_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ LIBMEMCACHED_MEMCACHED_DELETE_START();
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr)))
+ {
+ return rc;
+ }
+
+ rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
+ if (memcached_failed(rc))
+ {
+ return rc;
+ }
+
+ // If a delete trigger exists, we need a response, so no buffering/noreply
+ if (ptr->delete_trigger)
+ {
+ if (ptr->flags.buffer_requests)
+ {
+ return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
+ }
+
+ if (ptr->flags.no_reply)
+ {
+ return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
+ }
+ }
+
+
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ bool to_write= (ptr->flags.buffer_requests) ? false : true;
+
+ // Invert the logic to make it simpler to read the code
+ bool reply= (ptr->flags.no_reply) ? false : true;
+
+ if (ptr->flags.binary_protocol)
+ {
+ rc= binary_delete(ptr, instance, server_key, key, key_length, expiration, reply, to_write);
+ }
+ else
+ {
+ rc= ascii_delete(ptr, instance, server_key, key, key_length, expiration, reply, to_write);
+ }
+
+ if (rc == MEMCACHED_SUCCESS)
+ {
+ if (to_write == false)
+ {
+ rc= MEMCACHED_BUFFERED;
+ }
+ else if (reply)
+ {
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ if (rc == MEMCACHED_DELETED)
+ {
+ rc= MEMCACHED_SUCCESS;
+ }
+ }
+
+ if (rc == MEMCACHED_SUCCESS and ptr->delete_trigger)
+ {
+ ptr->delete_trigger(ptr, key, key_length);
+ }
+ }
+
+ LIBMEMCACHED_MEMCACHED_DELETE_END();
+ return rc;
+}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
- time_t expiration);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_delete_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- time_t expiration);
-
-#ifdef __cplusplus
-}
-#endif
memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const void *command,
size_t command_length, bool with_flush)
{
- memcached_return_t rc;
- ssize_t sent_length;
-
- WATCHPOINT_ASSERT(command_length);
- WATCHPOINT_ASSERT(command);
+ assert_msg(command_length, "Programming error, somehow a command had a length of zero");
+ assert_msg(command, "Programming error, somehow a command was NULL");
+ memcached_return_t rc;
if (memcached_failed(rc= memcached_connect(ptr)))
{
WATCHPOINT_ASSERT(rc == memcached_last_error(ptr->root));
memcached_io_write(ptr, NULL, 0, true);
}
- sent_length= memcached_io_write(ptr, command, command_length, with_flush);
+ ssize_t sent_length= memcached_io_write(ptr, command, command_length, with_flush);
- if (sent_length == -1 || (size_t)sent_length != command_length)
+ if (sent_length == -1 or size_t(sent_length) != command_length)
{
rc= MEMCACHED_WRITE_FAILURE;
}
bool with_flush)
{
memcached_return_t rc;
- ssize_t sent_length;
WATCHPOINT_ASSERT(count);
WATCHPOINT_ASSERT(vector);
memcached_io_write(ptr, NULL, 0, true);
}
- sent_length= memcached_io_writev(ptr, vector, count, with_flush);
+ ssize_t sent_length= memcached_io_writev(ptr, vector, count, with_flush);
size_t command_length= 0;
for (uint32_t x= 0; x < count; ++x, vector++)
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *function, void *context, uint32_t number_of_callbacks);
-
-
-#ifdef __cplusplus
-}
-#endif
}
if (memc.error_messages == NULL)
+ {
return;
+ }
memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
- if (not error) // Bad business if this happens
+ if (error == NULL) // Bad business if this happens
+ {
return;
+ }
memcpy(error, memc.error_messages, sizeof(memcached_error_t));
error->next= server.error_messages;
static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
{
- (void)at;
if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
{
memcached_error_free(memc);
}
memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
- if (not error) // Bad business if this happens
+ if (error == NULL) // Bad business if this happens
+ {
return;
+ }
error->root= &memc;
error->query_id= memc.query_id;
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
_set(memc, &str, rc, at);
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
char hostname_port_message[MAX_ERROR_LENGTH];
int size;
memcached_string_t error_host= { hostname_port_message, size };
- if (not self.root)
+ assert(self.root);
+ if (self.root == NULL)
+ {
return rc;
+ }
_set(*self.root, &error_host, rc, at);
_set(self, (*self.root));
+ assert(self.root->error_messages);
+ assert(self.error_messages);
return rc;
}
memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at)
{
- assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port));
memcached_string_t error_host= { hostname_port, size};
- if (not self.root)
+ if (self.root == NULL)
+ {
return rc;
+ }
_set(*self.root, &error_host, rc, at);
_set(self, *self.root);
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
_set(self, NULL, rc, at);
memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
memcached_return_t rc= MEMCACHED_ERRNO;
_set(self, NULL, rc, at, local_errno);
memcached_return_t memcached_set_errno(memcached_st& memc, int local_errno, const char *at, memcached_string_t& str)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
memcached_return_t rc= MEMCACHED_ERRNO;
_set(memc, &str, rc, at, local_errno);
memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, memcached_string_t& str)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
char hostname_port_message[MAX_ERROR_LENGTH];
int size;
memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
char hostname_port_message[MAX_ERROR_LENGTH];
int size = snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
static void _error_free(memcached_error_t *error)
{
if (not error)
+ {
return;
+ }
_error_free(error->next);
return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
}
- if (not memc->error_messages)
+ if (memc->error_messages == NULL)
+ {
return memcached_strerror(memc, MEMCACHED_SUCCESS);
+ }
- if (not memc->error_messages->size)
+ if (memc->error_messages->size == 0)
+ {
return memcached_strerror(memc, memc->error_messages->rc);
+ }
return memc->error_messages->message;
}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * LibMemcached
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
- const char *memcached_last_error_message(memcached_st *);
-
-LIBMEMCACHED_API
- void memcached_error_print(const memcached_st *);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_last_error(memcached_st *);
-
-LIBMEMCACHED_API
- int memcached_last_error_errno(memcached_st *);
-
-LIBMEMCACHED_API
- const char *memcached_server_error(memcached_server_instance_st ptr);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
*
*/
-#include <libmemcached/error.h>
+#include <libmemcached/common.h>
#pragma once
+++ /dev/null
-/*
- * Summary: Exceptions for the C++ interface
- *
- * Copy: See Copyright for the status of this software.
- *
- */
-
-/**
- * @file
- * @brief Exception declarations
- */
-
-#pragma once
-
-#include <stdexcept>
-#include <string>
-
-namespace memcache
-{
- class Exception : public std::runtime_error
- {
- public:
- Exception(const std::string& msg, int in_errno)
- :
- std::runtime_error(msg),
- _errno(in_errno)
- {}
-
- Exception(const char *msg, int in_errno)
- :
- std::runtime_error(std::string(msg)),
- _errno(in_errno) {}
-
- virtual ~Exception() throw() {}
-
- int getErrno() const
- {
- return _errno;
- }
-
- private:
- int _errno;
- };
-
- class Warning : public Exception
- {
- public:
- Warning(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
- Warning(const char *msg, int in_errno) : Exception(msg, in_errno) {}
- };
-
- class Error : public Exception
- {
- public:
- Error(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
- Error(const char *msg, int in_errno) : Exception(msg, in_errno) {}
- virtual ~Error() throw() {}
- };
-
-} /* namespace libmemcached */
{
struct libmemcached_io_vector_st vector[]=
{
- { sizeof("add ") -1, "add " },
- { memcached_array_size(memc->_namespace), memcached_array_string(memc->_namespace) },
- { key_length, key },
- { sizeof(" 0") -1, " 0" },
- { sizeof(" 2678400") -1, " 2678400" },
- { sizeof(" 0") -1, " 0" },
- { 2, "\r\n" },
- { 2, "\r\n" }
+ { memcached_literal_param("add ") },
+ { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
+ { key, key_length },
+ { memcached_literal_param(" 0") },
+ { memcached_literal_param(" 2678400") },
+ { memcached_literal_param(" 0") },
+ { memcached_literal_param("\r\n") },
+ { memcached_literal_param("\r\n") }
};
/* Send command header */
struct libmemcached_io_vector_st vector[]=
{
- { send_length, request.bytes },
- { memcached_array_size(memc->_namespace), memcached_array_string(memc->_namespace) },
- { key_length, key }
+ { request.bytes, send_length },
+ { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
+ { key, key_length }
};
/* write the header */
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-memcached_return_t memcached_exist(memcached_st *memc, const char *key, size_t key_length);
-
-memcached_return_t memcached_exist_by_key(memcached_st *memc,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length);
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_fetch_execute(memcached_st *ptr,
- memcached_execute_fn *callback,
- void *context,
- uint32_t number_of_callbacks);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_flush_buffers(memcached_st *mem);
-
-#ifdef __cplusplus
-}
-#endif
struct libmemcached_io_vector_st vector[]=
{
- { get_command_length, get_command },
- { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
- { key_length[x], keys[x] },
- { 1, " " }
+ { get_command, get_command_length },
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { keys[x], key_length[x] },
+ { memcached_literal_param(" ") }
};
struct libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes },
- { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
- { key_length[x], keys[x] }
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { keys[x], key_length[x] }
};
if (memcached_io_writev(instance, vector, 3, flush) == -1)
*/
struct libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes },
- { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
- { key_length[x], keys[x] }
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { keys[x], key_length[x] }
};
if (memcached_io_writev(instance, vector, 3, true) == -1)
}
if (success)
+ {
break;
+ }
}
return rc;
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Public defines */
-LIBMEMCACHED_API
-char *memcached_get(memcached_st *ptr,
- const char *key, size_t key_length,
- size_t *value_length,
- uint32_t *flags,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget(memcached_st *ptr,
- const char * const *keys,
- const size_t *key_length,
- size_t number_of_keys);
-
-LIBMEMCACHED_API
-char *memcached_get_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- size_t *value_length,
- uint32_t *flags,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_by_key(memcached_st *ptr,
- const char *group_key,
- size_t group_key_length,
- const char * const *keys,
- const size_t *key_length,
- const size_t number_of_keys);
-
-LIBMEMCACHED_API
-char *memcached_fetch(memcached_st *ptr,
- char *key,
- size_t *key_length,
- size_t *value_length,
- uint32_t *flags,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_result_st *memcached_fetch_result(memcached_st *ptr,
- memcached_result_st *result,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_execute(memcached_st *ptr,
- const char * const *keys,
- const size_t *key_length,
- const size_t number_of_keys,
- memcached_execute_fn *callback,
- void *context,
- const uint32_t number_of_callbacks);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
- const char *group_key,
- size_t group_key_length,
- const char * const *keys,
- const size_t *key_length,
- size_t number_of_keys,
- memcached_execute_fn *callback,
- void *context,
- const uint32_t number_of_callbacks);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The two public hash bits */
-LIBMEMCACHED_API
-uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm);
-
-LIBMEMCACHED_API
-const hashkit_st *memcached_get_hashkit(const memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_hashkit(memcached_st *ptr, hashkit_st *hashk);
-
-LIBMEMCACHED_API
-uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length);
-
-LIBMEMCACHED_LOCAL
-uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length);
-
-LIBMEMCACHED_API
-void memcached_autoeject(memcached_st *ptr);
-
-LIBMEMCACHED_API
- const char * libmemcached_string_hash(memcached_hash_t type);
-
-#ifdef __cplusplus
-}
-#endif
memcached_server_st *new_host_list= static_cast<memcached_server_st*>(libmemcached_realloc(ptr, memcached_server_list(ptr),
sizeof(memcached_server_st) * (ptr->number_of_hosts + 1)));
- if (not new_host_list)
+ if (new_host_list == NULL)
{
- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
}
memcached_server_list_set(ptr, new_host_list);
/* TODO: Check return type */
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
- if (not __server_create_with(ptr, instance, hostname, port, weight, type))
+ if (__server_create_with(ptr, instance, hostname, port, weight, type) == NULL)
{
return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
}
include libmemcached/csl/include.am
EXTRA_DIST+= \
- libmemcached/configure.h.in \
libmemcached/libmemcached_probes.d \
libmemcached/memcached/README.txt
+nobase_include_HEADERS+= \
+ libmemcached/memcached.h \
+ libmemcached/memcached.hpp \
+ libmemcached/util.h
+
noinst_HEADERS+= \
+ libmemcached/array.h \
libmemcached/assert.hpp \
libmemcached/backtrace.hpp \
libmemcached/byteorder.h \
libmemcached/io.h \
libmemcached/io.hpp \
libmemcached/is.h \
+ libmemcached/key.hpp \
libmemcached/libmemcached_probes.h \
+ libmemcached/memcached/protocol_binary.h \
+ libmemcached/memcached/vbucket.h \
libmemcached/memory.h \
+ libmemcached/namespace.h \
libmemcached/options.hpp \
- libmemcached/protocol/ascii_handler.h \
- libmemcached/protocol/binary_handler.h \
- libmemcached/protocol/common.h \
libmemcached/response.h \
libmemcached/server.hpp \
libmemcached/server_instance.h \
libmemcached/string.hpp \
- libmemcached/virtual_bucket.h
-
-nobase_include_HEADERS+= \
- libmemcached/allocators.h \
- libmemcached/analyze.h \
- libmemcached/array.h \
- libmemcached/auto.h \
- libmemcached/basic_string.h \
- libmemcached/behavior.h \
- libmemcached/callback.h \
- libmemcached/configure.h \
- libmemcached/constants.h \
- libmemcached/delete.h \
- libmemcached/dump.h \
- libmemcached/error.h \
- libmemcached/exist.h \
- libmemcached/exception.hpp \
- libmemcached/fetch.h \
- libmemcached/flush.h \
- libmemcached/flush_buffers.h \
- libmemcached/get.h \
- libmemcached/hash.h \
- libmemcached/memcached.h \
- libmemcached/memcached.hpp \
- libmemcached/memcached/protocol_binary.h \
- libmemcached/memcached/vbucket.h \
- libmemcached/options.h \
- libmemcached/parse.h \
- libmemcached/namespace.h \
- libmemcached/protocol/cache.h \
- libmemcached/protocol/callback.h \
- libmemcached/protocol_handler.h \
- libmemcached/quit.h \
- libmemcached/return.h \
- libmemcached/platform.h \
- libmemcached/result.h \
- libmemcached/sasl.h \
- libmemcached/server.h \
- libmemcached/server_list.h \
- libmemcached/stats.h \
- libmemcached/storage.h \
- libmemcached/strerror.h \
- libmemcached/string.h \
- libmemcached/types.h \
- libmemcached/verbosity.h \
- libmemcached/version.h \
- libmemcached/visibility.h \
- libmemcached/watchpoint.h
+ libmemcached/virtual_bucket.h \
+ libmemcached/watchpoint.h
lib_LTLIBRARIES+= libmemcached/libmemcached.la
libmemcached_libmemcached_la_CFLAGS= -DBUILDING_LIBMEMCACHED
libmemcached/flush.cc \
libmemcached/flush_buffers.cc \
libmemcached/get.cc \
+ libmemcached/touch.cc \
libmemcached/hash.cc \
libmemcached/hosts.cc \
libmemcached/initialize_query.cc \
memcached_return_t initialize_query(memcached_st *self)
{
- if (not self)
+ if (self == NULL)
{
return MEMCACHED_INVALID_ARGUMENTS;
}
static ssize_t _io_write(memcached_server_write_instance_st ptr,
const void *buffer, size_t length, bool with_flush)
{
- size_t original_length;
- const char* buffer_ptr;
-
WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
- original_length= length;
- buffer_ptr= static_cast<const char *>(buffer);
+ size_t original_length= length;
+ const char *buffer_ptr= static_cast<const char *>(buffer);
while (length)
{
struct libmemcached_io_vector_st
{
- size_t length;
const void *buffer;
+ size_t length;
};
#ifdef __cplusplus
#include <libmemcached/common.h>
-memcached_return_t memcached_key_test(const memcached_st &memc,
+memcached_return_t memcached_key_test(memcached_st &memc,
const char * const *keys,
const size_t *key_length,
size_t number_of_keys)
{
+ if (keys == NULL or key_length == NULL)
+ {
+ return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+ }
+
if (not memc.flags.verify_key)
+ {
+ for (uint32_t x= 0; x < number_of_keys; x++)
+ {
+ memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false);
+ if (memcached_failed(rc))
+ {
+ return rc;
+ }
+ }
+
return MEMCACHED_SUCCESS;
+ }
if (memc.flags.binary_protocol)
+ {
+ for (uint32_t x= 0; x < number_of_keys; x++)
+ {
+ memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false);
+ if (memcached_failed(rc))
+ {
+ return rc;
+ }
+ }
+
return MEMCACHED_SUCCESS;
+ }
for (uint32_t x= 0; x < number_of_keys; x++)
{
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_return_t memcached_key_test(memcached_st& memc,
+ const char * const *keys,
+ const size_t *key_length,
+ size_t number_of_keys);
+
+static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary)
+{
+ if (key_length == 0)
+ {
+ return MEMCACHED_BAD_KEY_PROVIDED;
+ }
+
+ if (binary)
+ {
+ if (key_length > 0xffff)
+ {
+ return MEMCACHED_BAD_KEY_PROVIDED;
+ }
+ }
+ else
+ {
+ if (key_length >= MEMCACHED_MAX_KEY)
+ {
+ return MEMCACHED_BAD_KEY_PROVIDED;
+ }
+ }
+
+ return MEMCACHED_SUCCESS;
+}
probe memcached_replace_end();
probe memcached_get_start();
probe memcached_get_end();
+ probe memcached_touch_start();
+ probe memcached_touch_end();
probe memcached_mget_start();
probe memcached_mget_end();
probe memcached_connect_start();
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
+ *
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
#define LIBMEMCACHED_MEMCACHED_GET_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_GET_START()
#define LIBMEMCACHED_MEMCACHED_GET_START_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_TOUCH_END()
+#define LIBMEMCACHED_MEMCACHED_TOUCH_END_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_TOUCH_START()
+#define LIBMEMCACHED_MEMCACHED_TOUCH_START_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_INCREMENT_END()
#define LIBMEMCACHED_MEMCACHED_INCREMENT_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_INCREMENT_START()
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
+ *
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
#pragma once
-#include <inttypes.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-
-#include <libmemcached/visibility.h>
-#include <libmemcached/configure.h>
-#include <libmemcached/platform.h>
-#include <libmemcached/constants.h>
-#include <libmemcached/return.h>
-#include <libmemcached/types.h>
-#include <libmemcached/string.h>
-#include <libmemcached/array.h>
-#include <libmemcached/error.h>
-#include <libmemcached/stats.h>
-#include <libhashkit/hashkit.h>
-
-// Everything above this line must be in the order specified.
-#include <libmemcached/allocators.h>
-#include <libmemcached/analyze.h>
-#include <libmemcached/auto.h>
-#include <libmemcached/behavior.h>
-#include <libmemcached/callback.h>
-#include <libmemcached/delete.h>
-#include <libmemcached/dump.h>
-#include <libmemcached/exist.h>
-#include <libmemcached/fetch.h>
-#include <libmemcached/flush.h>
-#include <libmemcached/flush_buffers.h>
-#include <libmemcached/get.h>
-#include <libmemcached/hash.h>
-#include <libmemcached/namespace.h>
-#include <libmemcached/options.h>
-#include <libmemcached/parse.h>
-#include <libmemcached/quit.h>
-#include <libmemcached/result.h>
-#include <libmemcached/server.h>
-#include <libmemcached/server_list.h>
-#include <libmemcached/storage.h>
-#include <libmemcached/strerror.h>
-#include <libmemcached/verbosity.h>
-#include <libmemcached/version.h>
-#include <libmemcached/sasl.h>
-
-struct memcached_st {
- /**
- @note these are static and should not change without a call to behavior.
- */
- struct {
- bool is_purging:1;
- bool is_processing_input:1;
- bool is_time_for_rebuild:1;
- } state;
-
- struct {
- // Everything below here is pretty static.
- bool auto_eject_hosts:1;
- bool binary_protocol:1;
- bool buffer_requests:1;
- bool hash_with_namespace:1;
- bool no_block:1; // Don't block
- bool no_reply:1;
- bool randomize_replica_read:1;
- bool support_cas:1;
- bool tcp_nodelay:1;
- bool use_sort_hosts:1;
- bool use_udp:1;
- bool verify_key:1;
- bool tcp_keepalive:1;
- } flags;
-
- memcached_server_distribution_t distribution;
- hashkit_st hashkit;
- struct {
- unsigned int version;
- } server_info;
- uint32_t number_of_hosts;
- memcached_server_st *servers;
- memcached_server_st *last_disconnected_server;
- int32_t snd_timeout;
- int32_t rcv_timeout;
- uint32_t server_failure_limit;
- uint32_t io_msg_watermark;
- uint32_t io_bytes_watermark;
- uint32_t io_key_prefetch;
- uint32_t tcp_keepidle;
- int32_t poll_timeout;
- int32_t connect_timeout; // How long we will wait on connect() before we will timeout
- int32_t retry_timeout;
- int send_size;
- int recv_size;
- void *user_data;
- uint64_t query_id;
- uint32_t number_of_replicas;
- memcached_result_st result;
-
- struct {
- bool weighted;
- uint32_t continuum_count; // Ketama
- uint32_t continuum_points_counter; // Ketama
- time_t next_distribution_rebuild; // Ketama
- memcached_continuum_item_st *continuum; // Ketama
- } ketama;
-
- struct memcached_virtual_bucket_t *virtual_bucket;
-
- struct memcached_allocator_t allocators;
-
- memcached_clone_fn on_clone;
- memcached_cleanup_fn on_cleanup;
- memcached_trigger_key_fn get_key_failure;
- memcached_trigger_delete_key_fn delete_trigger;
- memcached_callback_st *callbacks;
- struct memcached_sasl_st sasl;
- struct memcached_error_t *error_messages;
- struct memcached_array_st *_namespace;
- struct {
- uint32_t initial_pool_size;
- uint32_t max_pool_size;
- int32_t version; // This is used by pool and others to determine if the memcached_st is out of date.
- struct memcached_array_st *filename;
- } configure;
- struct {
- bool is_allocated:1;
- } options;
-
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_servers_reset(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_st *memcached_create(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_st *memcached(const char *string, size_t string_length);
-
-LIBMEMCACHED_API
-void memcached_free(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_reset(memcached_st *ptr);
-
-LIBMEMCACHED_API
-void memcached_reset_last_disconnected_server(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_st *memcached_clone(memcached_st *clone, const memcached_st *ptr);
-
-LIBMEMCACHED_API
-void *memcached_get_user_data(const memcached_st *ptr);
-
-LIBMEMCACHED_API
-void *memcached_set_user_data(memcached_st *ptr, void *data);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source);
-
-LIBMEMCACHED_API
-memcached_server_instance_st memcached_server_instance_by_position(const memcached_st *ptr, uint32_t server_key);
-
-LIBMEMCACHED_API
-uint32_t memcached_server_count(const memcached_st *);
-
-LIBMEMCACHED_API
-uint64_t memcached_query_id(const memcached_st *);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+#include <libmemcached-1.0/memcached.h>
-/*
- * Summary: C++ interface for memcached server
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
*
- * Copy: See Copyright for the status of this software.
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
- * Patrick Galbraith <patg@patg.net>
- */
-
-/**
- * @file memcached.hpp
- * @brief Libmemcached C++ interface
*/
#pragma once
-#include <libmemcached/memcached.h>
-#include <libmemcached/exception.hpp>
-
-#include <string.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-#include <map>
-
-namespace memcache
-{
-
-/**
- * This is the core memcached library (if later, other objects
- * are needed, they will be created from this class).
- */
-class Memcache
-{
-public:
-
- Memcache()
- {
- memc= memcached("", 0);
- }
-
- Memcache(const std::string &config)
- {
- memc= memcached(config.c_str(), config.size());
- }
-
- Memcache(const std::string &hostname, in_port_t port)
- {
- memc= memcached("", 0);
- if (memc)
- memcached_server_add(memc, hostname.c_str(), port);
- }
-
- Memcache(memcached_st *clone)
- {
- memc= memcached_clone(NULL, clone);
- }
-
- Memcache(const Memcache &rhs)
- {
- memc= memcached_clone(NULL, rhs.getImpl());
- }
-
- Memcache &operator=(const Memcache &rhs)
- {
- if (this != &rhs)
- {
- memcached_free(memc);
- memc= memcached_clone(NULL, rhs.getImpl());
- }
-
- return *this;
- }
-
- ~Memcache()
- {
- memcached_free(memc);
- }
-
- /**
- * Get the internal memcached_st *
- */
- const memcached_st *getImpl() const
- {
- return memc;
- }
-
- /**
- * Return an error string for the given return structure.
- *
- * @param[in] rc a memcached_return_t structure
- * @return error string corresponding to given return code in the library.
- */
- const std::string getError(memcached_return_t rc) const
- {
- /* first parameter to strerror is unused */
- return memcached_strerror(NULL, rc);
- }
-
- bool error(std::string& error_message) const
- {
- if (memcached_failed(memcached_last_error(memc)))
- {
- error_message+= memcached_last_error_message(memc);
- return true;
- }
-
- return false;
- }
-
- bool error() const
- {
- if (memcached_failed(memcached_last_error(memc)))
- {
- return true;
- }
-
- return false;
- }
-
- bool error(memcached_return_t& arg) const
- {
- arg= memcached_last_error(memc);
- return memcached_failed(arg);
- }
-
- bool setBehavior(memcached_behavior_t flag, uint64_t data)
- {
- return (memcached_success(memcached_behavior_set(memc, flag, data)));
- }
-
- uint64_t getBehavior(memcached_behavior_t flag)
- {
- return memcached_behavior_get(memc, flag);
- }
-
- /**
- * Configure the memcache object
- *
- * @param[in] in_config configuration
- * @return true on success; false otherwise
- */
- bool configure(const std::string &configuration)
- {
- memcached_st *new_memc= memcached(configuration.c_str(), configuration.size());
-
- if (new_memc)
- {
- memcached_free(memc);
- memc= new_memc;
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Add a server to the list of memcached servers to use.
- *
- * @param[in] server_name name of the server to add
- * @param[in] port port number of server to add
- * @return true on success; false otherwise
- */
- bool addServer(const std::string &server_name, in_port_t port)
- {
- return memcached_success(memcached_server_add(memc, server_name.c_str(), port));
- }
-
- /**
- * Remove a server from the list of memcached servers to use.
- *
- * @param[in] server_name name of the server to remove
- * @param[in] port port number of server to remove
- * @return true on success; false otherwise
- */
- bool removeServer(const std::string &server_name, in_port_t port)
- {
- std::string tmp_str;
- std::ostringstream strstm;
- tmp_str.append(",");
- tmp_str.append(server_name);
- tmp_str.append(":");
- strstm << port;
- tmp_str.append(strstm.str());
-
- //memcached_return_t rc= memcached_server_remove(server);
-
- return false;
- }
-
- /**
- * Fetches an individual value from the server. mget() must always
- * be called before using this method.
- *
- * @param[in] key key of object to fetch
- * @param[out] ret_val store returned object in this vector
- * @return a memcached return structure
- */
- memcached_return_t fetch(std::string &key,
- std::vector<char> &ret_val,
- uint32_t &flags,
- uint64_t &cas_value)
- {
- memcached_return_t rc;
-
- memcached_result_st *result;
- if ((result= memcached_fetch_result(memc, NULL, &rc)))
- {
- // Key
- key.assign(memcached_result_key_value(result), memcached_result_key_length(result));
-
- // Actual value, null terminated
- ret_val.reserve(memcached_result_length(result) +1);
- ret_val.assign(memcached_result_value(result),
- memcached_result_value(result) +memcached_result_length(result));
-
- // Misc
- flags= memcached_result_flags(result);
- cas_value= memcached_result_cas(result);
- }
- memcached_result_free(result);
-
- return rc;
- }
-
- memcached_return_t fetch(std::string &key,
- std::vector<char> &ret_val)
- {
- uint32_t flags= 0;
- uint64_t cas_value= 0;
-
- return fetch(key, ret_val, flags, cas_value);
- }
-
- /**
- * Fetches an individual value from the server.
- *
- * @param[in] key key of object whose value to get
- * @param[out] ret_val object that is retrieved is stored in
- * this vector
- * @return true on success; false otherwise
- */
- bool get(const std::string &key, std::vector<char> &ret_val)
- {
- uint32_t flags= 0;
- memcached_return_t rc;
- size_t value_length= 0;
-
- char *value= memcached_get(memc, key.c_str(), key.length(),
- &value_length, &flags, &rc);
- if (value != NULL && ret_val.empty())
- {
- ret_val.reserve(value_length);
- ret_val.assign(value, value + value_length);
- free(value);
- return true;
- }
-
- return false;
- }
-
- /**
- * Fetches an individual from a server which is specified by
- * the master_key parameter that is used for determining which
- * server an object was stored in if key partitioning was
- * used for storage.
- *
- * @param[in] master_key key that specifies server object is stored on
- * @param[in] key key of object whose value to get
- * @param[out] ret_val object that is retrieved is stored in
- * this vector
- * @return true on success; false otherwise
- */
- bool getByKey(const std::string &master_key,
- const std::string &key,
- std::vector<char> &ret_val)
- {
- uint32_t flags= 0;
- memcached_return_t rc;
- size_t value_length= 0;
-
- char *value= memcached_get_by_key(memc,
- master_key.c_str(), master_key.length(),
- key.c_str(), key.length(),
- &value_length, &flags, &rc);
- if (value)
- {
- ret_val.reserve(value_length);
- ret_val.assign(value, value + value_length);
- free(value);
- return true;
- }
- return false;
- }
-
- /**
- * Selects multiple keys at once. This method always
- * works asynchronously.
- *
- * @param[in] keys vector of keys to select
- * @return true if all keys are found
- */
- bool mget(std::vector<std::string> &keys)
- {
- std::vector<const char *> real_keys;
- std::vector<size_t> key_len;
- /*
- * Construct an array which will contain the length
- * of each of the strings in the input vector. Also, to
- * interface with the memcached C API, we need to convert
- * the vector of std::string's to a vector of char *.
- */
- real_keys.reserve(keys.size());
- key_len.reserve(keys.size());
-
- std::vector<std::string>::iterator it= keys.begin();
-
- while (it != keys.end())
- {
- real_keys.push_back(const_cast<char *>((*it).c_str()));
- key_len.push_back((*it).length());
- ++it;
- }
-
- /*
- * If the std::vector of keys is empty then we cannot
- * call memcached_mget as we will get undefined behavior.
- */
- if (not real_keys.empty())
- {
- return memcached_success(memcached_mget(memc, &real_keys[0], &key_len[0], real_keys.size()));
- }
-
- return false;
- }
-
- /**
- * Writes an object to the server. If the object already exists, it will
- * overwrite the existing object. This method always returns true
- * when using non-blocking mode unless a network error occurs.
- *
- * @param[in] key key of object to write to server
- * @param[in] value value of object to write to server
- * @param[in] expiration time to keep the object stored in the server for
- * @param[in] flags flags to store with the object
- * @return true on succcess; false otherwise
- */
- bool set(const std::string &key,
- const std::vector<char> &value,
- time_t expiration,
- uint32_t flags)
- {
- memcached_return_t rc= memcached_set(memc,
- key.c_str(), key.length(),
- &value[0], value.size(),
- expiration, flags);
- return memcached_success(rc);
- }
-
- /**
- * Writes an object to a server specified by the master_key parameter.
- * If the object already exists, it will overwrite the existing object.
- *
- * @param[in] master_key key that specifies server to write to
- * @param[in] key key of object to write to server
- * @param[in] value value of object to write to server
- * @param[in] expiration time to keep the object stored in the server for
- * @param[in] flags flags to store with the object
- * @return true on succcess; false otherwise
- */
- bool setByKey(const std::string &master_key,
- const std::string &key,
- const std::vector<char> &value,
- time_t expiration,
- uint32_t flags)
- {
- return memcached_success(memcached_set_by_key(memc, master_key.c_str(),
- master_key.length(),
- key.c_str(), key.length(),
- &value[0], value.size(),
- expiration,
- flags));
- }
-
- /**
- * Writes a list of objects to the server. Objects are specified by
- * 2 vectors - 1 vector of keys and 1 vector of values.
- *
- * @param[in] keys vector of keys of objects to write to server
- * @param[in] values vector of values of objects to write to server
- * @param[in] expiration time to keep the objects stored in server for
- * @param[in] flags flags to store with the objects
- * @return true on success; false otherwise
- */
- bool setAll(std::vector<std::string> &keys,
- std::vector< std::vector<char> *> &values,
- time_t expiration,
- uint32_t flags)
- {
- bool retval= true;
- std::vector<std::string>::iterator key_it= keys.begin();
- std::vector< std::vector<char> *>::iterator val_it= values.begin();
- while (key_it != keys.end())
- {
- retval= set((*key_it), *(*val_it), expiration, flags);
- if (retval == false)
- {
- return retval;
- }
- ++key_it;
- ++val_it;
- }
- return retval;
- }
-
- /**
- * Writes a list of objects to the server. Objects are specified by
- * a map of keys to values.
- *
- * @param[in] key_value_map map of keys and values to store in server
- * @param[in] expiration time to keep the objects stored in server for
- * @param[in] flags flags to store with the objects
- * @return true on success; false otherwise
- */
- bool setAll(std::map<const std::string, std::vector<char> > &key_value_map,
- time_t expiration,
- uint32_t flags)
- {
- bool retval= true;
- std::map<const std::string, std::vector<char> >::iterator it= key_value_map.begin();
-
- while (it != key_value_map.end())
- {
- retval= set(it->first, it->second, expiration, flags);
- if (retval == false)
- {
- // We should tell the user what the key that failed was
- return false;
- }
- ++it;
- }
- return true;
- }
-
- /**
- * Increment the value of the object associated with the specified
- * key by the offset given. The resulting value is saved in the value
- * parameter.
- *
- * @param[in] key key of object in server whose value to increment
- * @param[in] offset amount to increment object's value by
- * @param[out] value store the result of the increment here
- * @return true on success; false otherwise
- */
- bool increment(const std::string &key, uint32_t offset, uint64_t *value)
- {
- return memcached_success(memcached_increment(memc, key.c_str(), key.length(), offset, value));
- }
-
- /**
- * Decrement the value of the object associated with the specified
- * key by the offset given. The resulting value is saved in the value
- * parameter.
- *
- * @param[in] key key of object in server whose value to decrement
- * @param[in] offset amount to increment object's value by
- * @param[out] value store the result of the decrement here
- * @return true on success; false otherwise
- */
- bool decrement(const std::string &key, uint32_t offset, uint64_t *value)
- {
- return memcached_success(memcached_decrement(memc, key.c_str(),
- key.length(),
- offset, value));
- }
-
-
- /**
- * Add an object with the specified key and value to the server. This
- * function returns false if the object already exists on the server.
- *
- * @param[in] key key of object to add
- * @param[in] value of object to add
- * @return true on success; false otherwise
- */
- bool add(const std::string &key, const std::vector<char> &value)
- {
- return memcached_success(memcached_add(memc, key.c_str(), key.length(),
- &value[0], value.size(), 0, 0));
- }
-
- /**
- * Add an object with the specified key and value to the server. This
- * function returns false if the object already exists on the server. The
- * server to add the object to is specified by the master_key parameter.
- *
- * @param[in[ master_key key of server to add object to
- * @param[in] key key of object to add
- * @param[in] value of object to add
- * @return true on success; false otherwise
- */
- bool addByKey(const std::string &master_key,
- const std::string &key,
- const std::vector<char> &value)
- {
- return memcached_success(memcached_add_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- &value[0],
- value.size(),
- 0, 0));
- }
-
- /**
- * Replaces an object on the server. This method only succeeds
- * if the object is already present on the server.
- *
- * @param[in] key key of object to replace
- * @param[in[ value value to replace object with
- * @return true on success; false otherwise
- */
- bool replace(const std::string &key, const std::vector<char> &value)
- {
- return memcached_success(memcached_replace(memc, key.c_str(), key.length(),
- &value[0], value.size(),
- 0, 0));
- }
-
- /**
- * Replaces an object on the server. This method only succeeds
- * if the object is already present on the server. The server
- * to replace the object on is specified by the master_key param.
- *
- * @param[in] master_key key of server to replace object on
- * @param[in] key key of object to replace
- * @param[in[ value value to replace object with
- * @return true on success; false otherwise
- */
- bool replaceByKey(const std::string &master_key,
- const std::string &key,
- const std::vector<char> &value)
- {
- return memcached_success(memcached_replace_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- &value[0],
- value.size(),
- 0, 0));
- }
-
- /**
- * Places a segment of data before the last piece of data stored.
- *
- * @param[in] key key of object whose value we will prepend data to
- * @param[in] value data to prepend to object's value
- * @return true on success; false otherwise
- */
- bool prepend(const std::string &key, const std::vector<char> &value)
- {
- return memcached_success(memcached_prepend(memc, key.c_str(), key.length(),
- &value[0], value.size(), 0, 0));
- }
-
- /**
- * Places a segment of data before the last piece of data stored. The
- * server on which the object where we will be prepending data is stored
- * on is specified by the master_key parameter.
- *
- * @param[in] master_key key of server where object is stored
- * @param[in] key key of object whose value we will prepend data to
- * @param[in] value data to prepend to object's value
- * @return true on success; false otherwise
- */
- bool prependByKey(const std::string &master_key,
- const std::string &key,
- const std::vector<char> &value)
- {
- return memcached_success(memcached_prepend_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- &value[0],
- value.size(),
- 0,
- 0));
- }
-
- /**
- * Places a segment of data at the end of the last piece of data stored.
- *
- * @param[in] key key of object whose value we will append data to
- * @param[in] value data to append to object's value
- * @return true on success; false otherwise
- */
- bool append(const std::string &key, const std::vector<char> &value)
- {
- return memcached_success(memcached_append(memc,
- key.c_str(),
- key.length(),
- &value[0],
- value.size(),
- 0, 0));
- }
-
- /**
- * Places a segment of data at the end of the last piece of data stored. The
- * server on which the object where we will be appending data is stored
- * on is specified by the master_key parameter.
- *
- * @param[in] master_key key of server where object is stored
- * @param[in] key key of object whose value we will append data to
- * @param[in] value data to append to object's value
- * @return true on success; false otherwise
- */
- bool appendByKey(const std::string &master_key,
- const std::string &key,
- const std::vector<char> &value)
- {
- return memcached_success(memcached_append_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- &value[0],
- value.size(),
- 0, 0));
- }
-
- /**
- * Overwrite data in the server as long as the cas_arg value
- * is still the same in the server.
- *
- * @param[in] key key of object in server
- * @param[in] value value to store for object in server
- * @param[in] cas_arg "cas" value
- */
- bool cas(const std::string &key,
- const std::vector<char> &value,
- uint64_t cas_arg)
- {
- return memcached_success(memcached_cas(memc, key.c_str(), key.length(),
- &value[0], value.size(),
- 0, 0, cas_arg));
- }
-
- /**
- * Overwrite data in the server as long as the cas_arg value
- * is still the same in the server. The server to use is
- * specified by the master_key parameter.
- *
- * @param[in] master_key specifies server to operate on
- * @param[in] key key of object in server
- * @param[in] value value to store for object in server
- * @param[in] cas_arg "cas" value
- */
- bool casByKey(const std::string &master_key,
- const std::string &key,
- const std::vector<char> &value,
- uint64_t cas_arg)
- {
- return memcached_success(memcached_cas_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- &value[0],
- value.size(),
- 0, 0, cas_arg));
- }
-
- /**
- * Delete an object from the server specified by the key given.
- *
- * @param[in] key key of object to delete
- * @return true on success; false otherwise
- */
- bool remove(const std::string &key)
- {
- return memcached_success(memcached_delete(memc, key.c_str(), key.length(), 0));
- }
-
- /**
- * Delete an object from the server specified by the key given.
- *
- * @param[in] key key of object to delete
- * @param[in] expiration time to delete the object after
- * @return true on success; false otherwise
- */
- bool remove(const std::string &key, time_t expiration)
- {
- return memcached_success(memcached_delete(memc,
- key.c_str(),
- key.length(),
- expiration));
- }
-
- /**
- * Delete an object from the server specified by the key given.
- *
- * @param[in] master_key specifies server to remove object from
- * @param[in] key key of object to delete
- * @return true on success; false otherwise
- */
- bool removeByKey(const std::string &master_key,
- const std::string &key)
- {
- return memcached_success(memcached_delete_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- 0));
- }
-
- /**
- * Delete an object from the server specified by the key given.
- *
- * @param[in] master_key specifies server to remove object from
- * @param[in] key key of object to delete
- * @param[in] expiration time to delete the object after
- * @return true on success; false otherwise
- */
- bool removeByKey(const std::string &master_key,
- const std::string &key,
- time_t expiration)
- {
- return memcached_success(memcached_delete_by_key(memc,
- master_key.c_str(),
- master_key.length(),
- key.c_str(),
- key.length(),
- expiration));
- }
-
- /**
- * Wipe the contents of memcached servers.
- *
- * @param[in] expiration time to wait until wiping contents of
- * memcached servers
- * @return true on success; false otherwise
- */
- bool flush(time_t expiration= 0)
- {
- return memcached_success(memcached_flush(memc, expiration));
- }
-
- /**
- * Get the library version string.
- * @return std::string containing a copy of the library version string.
- */
- const std::string libVersion() const
- {
- const char *ver= memcached_lib_version();
- const std::string version(ver);
- return version;
- }
-
- /**
- * Retrieve memcached statistics. Populate a std::map with the retrieved
- * stats. Each server will map to another std::map of the key:value stats.
- *
- * @param[out] stats_map a std::map to be populated with the memcached
- * stats
- * @return true on success; false otherwise
- */
- bool getStats(std::map< std::string, std::map<std::string, std::string> >
- &stats_map)
- {
- memcached_return_t rc;
- memcached_stat_st *stats= memcached_stat(memc, NULL, &rc);
-
- if (rc != MEMCACHED_SUCCESS &&
- rc != MEMCACHED_SOME_ERRORS)
- {
- return false;
- }
-
- uint32_t server_count= memcached_server_count(memc);
-
- /*
- * For each memcached server, construct a std::map for its stats and add
- * it to the std::map of overall stats.
- */
- for (uint32_t x= 0; x < server_count; x++)
- {
- memcached_server_instance_st instance=
- memcached_server_instance_by_position(memc, x);
- std::ostringstream strstm;
- std::string server_name(memcached_server_name(instance));
- server_name.append(":");
- strstm << memcached_server_port(instance);
- server_name.append(strstm.str());
-
- std::map<std::string, std::string> server_stats;
- char **list= NULL;
- char **ptr= NULL;
-
- list= memcached_stat_get_keys(memc, &stats[x], &rc);
- for (ptr= list; *ptr; ptr++)
- {
- char *value= memcached_stat_get_value(memc, &stats[x], *ptr, &rc);
- server_stats[*ptr]= value;
- free(value);
- }
-
- stats_map[server_name]= server_stats;
- free(list);
- }
-
- memcached_stat_free(memc, stats);
- return true;
- }
-
-private:
- memcached_st *memc;
-};
+#include <libmemcached-1.0/memcached.hpp>
-}
PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
PROTOCOL_BINARY_CMD_GAT = 0x1d,
PROTOCOL_BINARY_CMD_GATQ = 0x1e,
+ PROTOCOL_BINARY_CMD_GATK = 0x23,
+ PROTOCOL_BINARY_CMD_GATKQ = 0x24,
PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#include <libmemcached/util/pid.h>
-#include <libmemcached/util/flush.h>
-#include <libmemcached/util/ping.h>
-#include <libmemcached/util/pool.h>
-#include <libmemcached/util/version.h>
LIBMEMCACHED_LOCAL
memcached_return_t memcached_set_namespace(memcached_st *self, const char *str, size_t length);
-LIBMEMCACHED_API
+LIBMEMCACHED_LOCAL
const char * memcached_get_namespace(memcached_st *self);
#ifdef __cplusplus
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
- memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* LibMemcached
- * Copyright (C) 2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Work with fetching results
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_server_list_st memcached_servers_parse(const char *server_strings);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker, Trond Norbye All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef WIN32
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-typedef short in_port_t;
-typedef SOCKET memcached_socket_t;
-#else
-typedef int memcached_socket_t;
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/un.h>
-#include <netinet/tcp.h>
-
-#endif /* WIN32 */
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/protocol/common.h>
-#include <libmemcached/byteorder.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/**
- * Try to parse a key from the string.
- * @pointer start pointer to a pointer to the string (IN and OUT)
- * @return length of the string of -1 if this was an illegal key (invalid
- * characters or invalid length)
- * @todo add length!
- */
-static uint16_t parse_ascii_key(char **start)
-{
- uint16_t len= 0;
- char *c= *start;
- /* Strip leading whitespaces */
- while (isspace(*c))
- {
- ++c;
- }
-
- *start= c;
-
- while (*c != '\0' && !isspace(*c) && !iscntrl(*c))
- {
- ++c;
- ++len;
- }
-
-
- if (len == 0 || len > 240 || (*c != '\0' && *c != '\r' && iscntrl(*c)))
- {
- return 0;
- }
-
- return len;
-}
-
-/**
- * Spool a zero-terminated string
- * @param client destination
- * @param text the text to spool
- * @return status of the spool operation
- */
-static protocol_binary_response_status
-spool_string(memcached_protocol_client_st *client, const char *text)
-{
- return client->root->spool(client, text, strlen(text));
-}
-
-/**
- * Send a "CLIENT_ERROR" message back to the client with the correct
- * format of the command being sent
- * @param client the client to send the message to
- */
-static void send_command_usage(memcached_protocol_client_st *client)
-{
- const char *errmsg[]= {
- [GET_CMD]= "CLIENT_ERROR: Syntax error: get <key>*\r\n",
- [GETS_CMD]= "CLIENT_ERROR: Syntax error: gets <key>*\r\n",
- [SET_CMD]= "CLIENT_ERROR: Syntax error: set <key> <flags> <exptime> <bytes> [noreply]\r\n",
- [ADD_CMD]= "CLIENT_ERROR: Syntax error: add <key> <flags> <exptime> <bytes> [noreply]\r\n",
- [REPLACE_CMD]= "CLIENT_ERROR: Syntax error: replace <key> <flags> <exptime> <bytes> [noreply]\r\n",
- [CAS_CMD]= "CLIENT_ERROR: Syntax error: cas <key> <flags> <exptime> <bytes> <casid> [noreply]\r\n",
- [APPEND_CMD]= "CLIENT_ERROR: Syntax error: append <key> <flags> <exptime> <bytes> [noreply]\r\n",
- [PREPEND_CMD]= "CLIENT_ERROR: Syntax error: prepend <key> <flags> <exptime> <bytes> [noreply]\r\n",
- [DELETE_CMD]= "CLIENT_ERROR: Syntax error: delete <key> [noreply]\r\n",
- [INCR_CMD]= "CLIENT_ERROR: Syntax error: incr <key> <value> [noreply]\r\n",
- [DECR_CMD]= "CLIENT_ERROR: Syntax error: decr <key> <value> [noreply]\r\n",
- [STATS_CMD]= "CLIENT_ERROR: Syntax error: stats [key]\r\n",
- [FLUSH_ALL_CMD]= "CLIENT_ERROR: Syntax error: flush_all [timeout] [noreply]\r\n",
- [VERSION_CMD]= "CLIENT_ERROR: Syntax error: version\r\n",
- [QUIT_CMD]="CLIENT_ERROR: Syntax error: quit\r\n",
-
- [VERBOSITY_CMD]= "CLIENT_ERROR: Syntax error: verbosity <num>\r\n",
- [UNKNOWN_CMD]= "CLIENT_ERROR: Unknown command\r\n",
- };
-
- client->mute = false;
- spool_string(client, errmsg[client->ascii_command]);
-}
-
-/**
- * Callback for the VERSION responses
- * @param cookie client identifier
- * @param text the length of the body
- * @param textlen the length of the body
- */
-static protocol_binary_response_status
-ascii_version_response_handler(const void *cookie,
- const void *text,
- uint32_t textlen)
-{
- memcached_protocol_client_st *client= (memcached_protocol_client_st*)cookie;
- spool_string(client, "VERSION ");
- client->root->spool(client, text, textlen);
- spool_string(client, "\r\n");
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the GET/GETQ/GETK and GETKQ responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- * @param flags the flags for the item
- * @param cas the CAS id for the item
- */
-static protocol_binary_response_status
-ascii_get_response_handler(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void *body,
- uint32_t bodylen,
- uint32_t flags,
- uint64_t cas)
-{
- memcached_protocol_client_st *client= (void*)cookie;
- char buffer[300];
- strcpy(buffer, "VALUE ");
- const char *source= key;
- char *dest= buffer + 6;
-
- for (int x= 0; x < keylen; ++x)
- {
- if (*source != '\0' && !isspace(*source) && !iscntrl(*source))
- {
- *dest= *source;
- }
- else
- {
- return PROTOCOL_BINARY_RESPONSE_EINVAL; /* key constraints in ascii */
- }
-
- ++dest;
- ++source;
- }
-
- size_t used= (size_t)(dest - buffer);
-
- if (client->ascii_command == GETS_CMD)
- {
- snprintf(dest, sizeof(buffer) - used, " %u %u %" PRIu64 "\r\n", flags,
- bodylen, cas);
- }
- else
- {
- snprintf(dest, sizeof(buffer) - used, " %u %u\r\n", flags, bodylen);
- }
-
- client->root->spool(client, buffer, strlen(buffer));
- client->root->spool(client, body, bodylen);
- client->root->spool(client, "\r\n", 2);
-
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the STAT responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- */
-static protocol_binary_response_status
-ascii_stat_response_handler(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void *body,
- uint32_t bodylen)
-{
-
- memcached_protocol_client_st *client= (void*)cookie;
-
- if (key != NULL)
- {
- spool_string(client, "STAT ");
- client->root->spool(client, key, keylen);
- spool_string(client, " ");
- client->root->spool(client, body, bodylen);
- spool_string(client, "\r\n");
- }
- else
- {
- spool_string(client, "END\r\n");
- }
-
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Process a get or a gets request.
- * @param client the client handle
- * @param buffer the complete get(s) command
- * @param end the last character in the command
- */
-static void ascii_process_gets(memcached_protocol_client_st *client,
- char *buffer, char *end)
-{
- char *key= buffer;
-
- /* Skip command */
- key += (client->ascii_command == GETS_CMD) ? 5 : 4;
-
- int num_keys= 0;
- while (key < end)
- {
- uint16_t nkey= parse_ascii_key(&key);
- if (nkey == 0) /* Invalid key... stop processing this line */
- {
- break;
- }
-
- (void)client->root->callback->interface.v1.get(client, key, nkey,
- ascii_get_response_handler);
- key += nkey;
- ++num_keys;
- }
-
- if (num_keys == 0)
- {
- send_command_usage(client);
- }
- else
- client->root->spool(client, "END\r\n", 5);
-}
-
-/**
- * Try to split up the command line "asdf asdf asdf asdf\n" into an
- * argument vector for easier parsing.
- * @param start the first character in the command line
- * @param end the last character in the command line ("\n")
- * @param vec the vector to insert the pointers into
- * @size the number of elements in the vector
- * @return the number of tokens in the vector
- */
-static int ascii_tokenize_command(char *str, char *end, char **vec, int size)
-{
- int elem= 0;
-
- while (str < end)
- {
- /* Skip leading blanks */
- while (str < end && isspace(*str))
- {
- ++str;
- }
-
- if (str == end)
- {
- return elem;
- }
-
- vec[elem++]= str;
- /* find the next non-blank field */
- while (str < end && !isspace(*str))
- {
- ++str;
- }
-
- /* zero-terminate it for easier parsing later on */
- *str= '\0';
- ++str;
-
- /* Is the vector full? */
- if (elem == size)
- {
- break;
- }
- }
-
- return elem;
-}
-
-/**
- * If we for some reasons needs to push the line back to read more
- * data we have to reverse the tokenization. Just do the brain-dead replace
- * of all '\0' to ' ' and set the last character to '\n'. We could have used
- * the vector we created, but then we would have to search for all of the
- * spaces we ignored...
- * @param start pointer to the first character in the buffer to recover
- * @param end pointer to the last character in the buffer to recover
- */
-static void recover_tokenize_command(char *start, char *end)
-{
- while (start < end)
- {
- if (*start == '\0')
- *start= ' ';
- ++start;
- }
-
- *end= '\n';
-}
-
-/**
- * Convert the textual command into a comcode
- */
-static enum ascii_cmd ascii_to_cmd(char *start, size_t length)
-{
- struct {
- const char *cmd;
- size_t len;
- enum ascii_cmd cc;
- } commands[]= {
- { .cmd= "get", .len= 3, .cc= GET_CMD },
- { .cmd= "gets", .len= 4, .cc= GETS_CMD },
- { .cmd= "set", .len= 3, .cc= SET_CMD },
- { .cmd= "add", .len= 3, .cc= ADD_CMD },
- { .cmd= "replace", .len= 7, .cc= REPLACE_CMD },
- { .cmd= "cas", .len= 3, .cc= CAS_CMD },
- { .cmd= "append", .len= 6, .cc= APPEND_CMD },
- { .cmd= "prepend", .len= 7, .cc= PREPEND_CMD },
- { .cmd= "delete", .len= 6, .cc= DELETE_CMD },
- { .cmd= "incr", .len= 4, .cc= INCR_CMD },
- { .cmd= "decr", .len= 4, .cc= DECR_CMD },
- { .cmd= "stats", .len= 5, .cc= STATS_CMD },
- { .cmd= "flush_all", .len= 9, .cc= FLUSH_ALL_CMD },
- { .cmd= "version", .len= 7, .cc= VERSION_CMD },
- { .cmd= "quit", .len= 4, .cc= QUIT_CMD },
- { .cmd= "verbosity", .len= 9, .cc= VERBOSITY_CMD },
- { .cmd= NULL, .len= 0, .cc= UNKNOWN_CMD }};
-
- int x= 0;
- while (commands[x].len > 0) {
- if (length >= commands[x].len)
- {
- if (strncmp(start, commands[x].cmd, commands[x].len) == 0)
- {
- /* Potential hit */
- if (length == commands[x].len || isspace(*(start + commands[x].len)))
- {
- return commands[x].cc;
- }
- }
- }
- ++x;
- }
-
- return UNKNOWN_CMD;
-}
-
-/**
- * Perform a delete operation.
- *
- * @param client client requesting the deletion
- * @param tokens the command as a vector
- * @param ntokens the number of items in the vector
- */
-static void process_delete(memcached_protocol_client_st *client,
- char **tokens, int ntokens)
-{
- char *key= tokens[1];
- uint16_t nkey;
-
- if (ntokens != 2 || (nkey= parse_ascii_key(&key)) == 0)
- {
- send_command_usage(client);
- return;
- }
-
- if (client->root->callback->interface.v1.delete == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return;
- }
-
- protocol_binary_response_status rval;
- rval= client->root->callback->interface.v1.delete(client, key, nkey, 0);
-
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
- {
- spool_string(client, "DELETED\r\n");
- }
- else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
- {
- spool_string(client, "NOT_FOUND\r\n");
- }
- else
- {
- char msg[80];
- snprintf(msg, sizeof(msg), "SERVER_ERROR: delete failed %u\r\n",(uint32_t)rval);
- spool_string(client, msg);
- }
-}
-
-static void process_arithmetic(memcached_protocol_client_st *client,
- char **tokens, int ntokens)
-{
- char *key= tokens[1];
- uint16_t nkey;
-
- if (ntokens != 3 || (nkey= parse_ascii_key(&key)) == 0)
- {
- send_command_usage(client);
- return;
- }
-
- uint64_t cas;
- uint64_t result;
- uint64_t delta= strtoull(tokens[2], NULL, 10);
-
- protocol_binary_response_status rval;
- if (client->ascii_command == INCR_CMD)
- {
- if (client->root->callback->interface.v1.increment == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return;
- }
- rval= client->root->callback->interface.v1.increment(client,
- key, nkey,
- delta, 0,
- 0,
- &result,
- &cas);
- }
- else
- {
- if (client->root->callback->interface.v1.decrement == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return;
- }
- rval= client->root->callback->interface.v1.decrement(client,
- key, nkey,
- delta, 0,
- 0,
- &result,
- &cas);
- }
-
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
- {
- char buffer[80];
- snprintf(buffer, sizeof(buffer), "%"PRIu64"\r\n", result);
- spool_string(client, buffer);
- }
- else
- {
- spool_string(client, "NOT_FOUND\r\n");
- }
-}
-
-/**
- * Process the stats command (with or without a key specified)
- * @param key pointer to the first character after "stats"
- * @param end pointer to the "\n"
- */
-static void process_stats(memcached_protocol_client_st *client,
- char *key, char *end)
-{
- if (client->root->callback->interface.v1.stat == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return;
- }
-
- while (isspace(*key))
- key++;
-
- uint16_t nkey= (uint16_t)(end - key);
- (void)client->root->callback->interface.v1.stat(client, key, nkey,
- ascii_stat_response_handler);
-}
-
-static void process_version(memcached_protocol_client_st *client,
- char **tokens, int ntokens)
-{
- (void)tokens;
- if (ntokens != 1)
- {
- send_command_usage(client);
- return;
- }
-
- if (client->root->callback->interface.v1.version == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return;
- }
-
- client->root->callback->interface.v1.version(client,
- ascii_version_response_handler);
-}
-
-static void process_flush(memcached_protocol_client_st *client,
- char **tokens, int ntokens)
-{
- if (ntokens > 2)
- {
- send_command_usage(client);
- return;
- }
-
- if (client->root->callback->interface.v1.flush == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return;
- }
-
- uint32_t timeout= 0;
- if (ntokens == 2)
- {
- timeout= (uint32_t)strtoul(tokens[1], NULL, 10);
- }
-
- protocol_binary_response_status rval;
- rval= client->root->callback->interface.v1.flush(client, timeout);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
- spool_string(client, "OK\r\n");
- else
- spool_string(client, "SERVER_ERROR: internal error\r\n");
-}
-
-/**
- * Process one of the storage commands
- * @param client the client performing the operation
- * @param tokens the command tokens
- * @param ntokens the number of tokens
- * @param start pointer to the first character in the line
- * @param end pointer to the pointer where the last character of this
- * command is (IN and OUT)
- * @param length the number of bytes available
- * @return -1 if an error occurs (and we should just terminate the connection
- * because we are out of sync)
- * 0 storage command completed, continue processing
- * 1 We need more data, so just go ahead and wait for more!
- */
-static inline int process_storage_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- (void)ntokens; /* already checked */
- char *key= tokens[1];
- uint16_t nkey= parse_ascii_key(&key);
- if (nkey == 0)
- {
- /* return error */
- spool_string(client, "CLIENT_ERROR: bad key\r\n");
- return -1;
- }
-
- uint32_t flags= (uint32_t)strtoul(tokens[2], NULL, 10);
- uint32_t timeout= (uint32_t)strtoul(tokens[3], NULL, 10);
- unsigned long nbytes= strtoul(tokens[4], NULL, 10);
-
- /* Do we have all data? */
- unsigned long need= nbytes + (unsigned long)((*end - start) + 1) + 2; /* \n\r\n */
- if ((ssize_t)need > length)
- {
- /* Keep on reading */
- recover_tokenize_command(start, *end);
- return 1;
- }
-
- void *data= (*end) + 1;
- uint64_t cas= 0;
- uint64_t result_cas;
- protocol_binary_response_status rval;
- switch (client->ascii_command)
- {
- case SET_CMD:
- rval= client->root->callback->interface.v1.set(client, key,
- (uint16_t)nkey,
- data,
- (uint32_t)nbytes,
- flags,
- timeout, cas,
- &result_cas);
- break;
- case ADD_CMD:
- rval= client->root->callback->interface.v1.add(client, key,
- (uint16_t)nkey,
- data,
- (uint32_t)nbytes,
- flags,
- timeout, &result_cas);
- break;
- case CAS_CMD:
- cas= strtoull(tokens[5], NULL, 10);
- /* FALLTHROUGH */
- case REPLACE_CMD:
- rval= client->root->callback->interface.v1.replace(client, key,
- (uint16_t)nkey,
- data,
- (uint32_t)nbytes,
- flags,
- timeout, cas,
- &result_cas);
- break;
- case APPEND_CMD:
- rval= client->root->callback->interface.v1.append(client, key,
- (uint16_t)nkey,
- data,
- (uint32_t)nbytes,
- cas,
- &result_cas);
- break;
- case PREPEND_CMD:
- rval= client->root->callback->interface.v1.prepend(client, key,
- (uint16_t)nkey,
- data,
- (uint32_t)nbytes,
- cas,
- &result_cas);
- break;
-
- /* gcc complains if I don't put all of the enums in here.. */
- case GET_CMD:
- case GETS_CMD:
- case DELETE_CMD:
- case DECR_CMD:
- case INCR_CMD:
- case STATS_CMD:
- case FLUSH_ALL_CMD:
- case VERSION_CMD:
- case QUIT_CMD:
- case VERBOSITY_CMD:
- case UNKNOWN_CMD:
- default:
- abort(); /* impossible */
- }
-
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
- {
- spool_string(client, "STORED\r\n");
- }
- else
- {
- if (client->ascii_command == CAS_CMD)
- {
- if (rval == PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS)
- {
- spool_string(client, "EXISTS\r\n");
- }
- else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
- {
- spool_string(client, "NOT_FOUND\r\n");
- }
- else
- {
- spool_string(client, "NOT_STORED\r\n");
- }
- }
- else
- {
- spool_string(client, "NOT_STORED\r\n");
- }
- }
-
- *end += nbytes + 2;
-
- return 0;
-}
-
-static int process_cas_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- if (ntokens != 6)
- {
- send_command_usage(client);
- return false;
- }
-
- if (client->root->callback->interface.v1.replace == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return false;
- }
-
- return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_set_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- if (ntokens != 5)
- {
- send_command_usage(client);
- return false;
- }
-
- if (client->root->callback->interface.v1.set == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return false;
- }
-
- return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_add_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- if (ntokens != 5)
- {
- send_command_usage(client);
- return false;
- }
-
- if (client->root->callback->interface.v1.add == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return false;
- }
-
- return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_replace_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- if (ntokens != 5)
- {
- send_command_usage(client);
- return false;
- }
-
- if (client->root->callback->interface.v1.replace == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return false;
- }
-
- return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_append_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- if (ntokens != 5)
- {
- send_command_usage(client);
- return false;
- }
-
- if (client->root->callback->interface.v1.append == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return false;
- }
-
- return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_prepend_command(memcached_protocol_client_st *client,
- char **tokens, int ntokens, char *start,
- char **end, ssize_t length)
-{
- if (ntokens != 5)
- {
- send_command_usage(client);
- return false;
- }
-
- if (client->root->callback->interface.v1.prepend == NULL)
- {
- spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
- return false;
- }
-
- return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-/**
- * The ASCII protocol support is just one giant big hack. Instead of adding
- * a optimal ascii support, I just convert the ASCII commands to the binary
- * protocol and calls back into the command handlers for the binary protocol ;)
- */
-memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
-{
- char *ptr= (char*)client->root->input_buffer;
- *endptr= ptr;
-
- do {
- /* Do we have \n (indicating the command preamble)*/
- char *end= memchr(ptr, '\n', (size_t)*length);
- if (end == NULL)
- {
- *endptr= ptr;
- return MEMCACHED_PROTOCOL_READ_EVENT;
- }
-
- client->ascii_command= ascii_to_cmd(ptr, (size_t)(*length));
-
- /* A multiget lists all of the keys, and I don't want to have an
- * avector of let's say 512 pointers to tokenize all of them, so let's
- * just handle them immediately
- */
- if (client->ascii_command == GET_CMD ||
- client->ascii_command == GETS_CMD) {
- if (client->root->callback->interface.v1.get != NULL)
- ascii_process_gets(client, ptr, end);
- else
- spool_string(client, "SERVER_ERROR: Command not implemented\n");
- } else {
- /* None of the defined commands takes 10 parameters, so lets just use
- * that as a maximum limit.
- */
- char *tokens[10];
- int ntokens= ascii_tokenize_command(ptr, end, tokens, 10);
-
- if (ntokens < 10)
- {
- client->mute= strcmp(tokens[ntokens - 1], "noreply") == 0;
- if (client->mute)
- --ntokens; /* processed noreply token*/
- }
-
- int error= 0;
-
- switch (client->ascii_command) {
- case SET_CMD:
- error= process_set_command(client, tokens, ntokens, ptr, &end, *length);
- break;
- case ADD_CMD:
- error= process_add_command(client, tokens, ntokens, ptr, &end, *length);
- break;
- case REPLACE_CMD:
- error= process_replace_command(client, tokens, ntokens,
- ptr, &end, *length);
- break;
- case CAS_CMD:
- error= process_cas_command(client, tokens, ntokens, ptr, &end, *length);
- break;
- case APPEND_CMD:
- error= process_append_command(client, tokens, ntokens,
- ptr, &end, *length);
- break;
- case PREPEND_CMD:
- error= process_prepend_command(client, tokens, ntokens,
- ptr, &end, *length);
- break;
- case DELETE_CMD:
- process_delete(client, tokens, ntokens);
- break;
-
- case INCR_CMD: /* FALLTHROUGH */
- case DECR_CMD:
- process_arithmetic(client, tokens, ntokens);
- break;
- case STATS_CMD:
- if (client->mute)
- {
- send_command_usage(client);
- }
- else
- {
- recover_tokenize_command(ptr, end);
- process_stats(client, ptr + 6, end);
- }
- break;
- case FLUSH_ALL_CMD:
- process_flush(client, tokens, ntokens);
- break;
- case VERSION_CMD:
- if (client->mute)
- {
- send_command_usage(client);
- }
- else
- {
- process_version(client, tokens, ntokens);
- }
- break;
- case QUIT_CMD:
- if (ntokens != 1 || client->mute)
- {
- send_command_usage(client);
- }
- else
- {
- if (client->root->callback->interface.v1.quit != NULL)
- client->root->callback->interface.v1.quit(client);
-
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
- break;
-
- case VERBOSITY_CMD:
- if (ntokens != 2)
- send_command_usage(client);
- else
- spool_string(client, "OK\r\n");
- break;
-
- case UNKNOWN_CMD:
- send_command_usage(client);
- break;
-
- case GET_CMD:
- case GETS_CMD:
- default:
- /* Should already be handled */
- abort();
- }
-
- if (error == -1)
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- else if (error == 1)
- return MEMCACHED_PROTOCOL_READ_EVENT;
- }
-
- /* Move past \n */
- ++end;
- *length -= end - ptr;
- ptr= end;
- } while (*length > 0);
-
- *endptr= ptr;
- return MEMCACHED_PROTOCOL_READ_EVENT;
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-LIBMEMCACHED_LOCAL
-memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/protocol/common.h>
-#include <libmemcached/byteorder.h>
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-
-/*
-** **********************************************************************
-** INTERNAL INTERFACE
-** **********************************************************************
-*/
-
-/**
- * Send a preformatted packet back to the client. If the connection is in
- * pedantic mode, it will validate the packet and refuse to send it if it
- * breaks the specification.
- *
- * @param cookie client identification
- * @param request the original request packet
- * @param response the packet to send
- * @return The status of the operation
- */
-static protocol_binary_response_status
-raw_response_handler(const void *cookie,
- protocol_binary_request_header *request,
- protocol_binary_response_header *response)
-{
- memcached_protocol_client_st *client= (void*)cookie;
-
- if (client->root->pedantic &&
- !memcached_binary_protocol_pedantic_check_response(request, response))
- {
- return PROTOCOL_BINARY_RESPONSE_EINVAL;
- }
-
- if (!client->root->drain(client))
- {
- return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
- }
-
- size_t len= sizeof(*response) + htonl(response->response.bodylen);
- size_t offset= 0;
- char *ptr= (void*)response;
-
- if (client->output == NULL)
- {
- /* I can write directly to the socket.... */
- do
- {
- size_t num_bytes= len - offset;
- ssize_t nw= client->root->send(client,
- client->sock,
- ptr + offset,
- num_bytes);
- if (nw == -1)
- {
- if (get_socket_errno() == EWOULDBLOCK)
- {
- break;
- }
- else if (get_socket_errno() != EINTR)
- {
- client->error= errno;
- return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
- }
- }
- else
- {
- offset += (size_t)nw;
- }
- } while (offset < len);
- }
-
- return client->root->spool(client, ptr, len - offset);
-}
-
-/*
- * Version 0 of the interface is really low level and protocol specific,
- * while the version 1 of the interface is more API focused. We need a
- * way to translate between the command codes on the wire and the
- * application level interface in V1, so let's just use the V0 of the
- * interface as a map instead of creating a huuuge switch :-)
- */
-
-/**
- * Callback for the GET/GETQ/GETK and GETKQ responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- * @param flags the flags for the item
- * @param cas the CAS id for the item
- */
-static protocol_binary_response_status
-get_response_handler(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void *body,
- uint32_t bodylen,
- uint32_t flags,
- uint64_t cas) {
-
- memcached_protocol_client_st *client= (void*)cookie;
- uint8_t opcode= client->current_command->request.opcode;
-
- if (opcode == PROTOCOL_BINARY_CMD_GET || opcode == PROTOCOL_BINARY_CMD_GETQ)
- {
- keylen= 0;
- }
-
- protocol_binary_response_get response= {
- .message.header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= opcode,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= client->current_command->request.opaque,
- .cas= memcached_htonll(cas),
- .keylen= htons(keylen),
- .extlen= 4,
- .bodylen= htonl(bodylen + keylen + 4),
- },
- };
-
- response.message.body.flags= htonl(flags);
-
- protocol_binary_response_status rval;
- const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
- if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
- (rval= client->root->spool(client, key, keylen)) != success ||
- (rval= client->root->spool(client, body, bodylen)) != success)
- {
- return rval;
- }
-
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the STAT responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- */
-static protocol_binary_response_status stat_response_handler(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void *body,
- uint32_t bodylen)
-{
-
- memcached_protocol_client_st *client= (void*)cookie;
-
- protocol_binary_response_no_extras response= {
- .message.header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= client->current_command->request.opcode,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= client->current_command->request.opaque,
- .keylen= htons(keylen),
- .bodylen= htonl(bodylen + keylen),
- .cas= 0
- },
- };
-
- protocol_binary_response_status rval;
- const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
- if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
- (rval= client->root->spool(client, key, keylen)) != success ||
- (rval= client->root->spool(client, body, bodylen)) != success)
- {
- return rval;
- }
-
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the VERSION responses
- * @param cookie client identifier
- * @param text the length of the body
- * @param textlen the length of the body
- */
-static protocol_binary_response_status
-version_response_handler(const void *cookie,
- const void *text,
- uint32_t textlen) {
-
- memcached_protocol_client_st *client= (void*)cookie;
-
- protocol_binary_response_no_extras response= {
- .message.header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= client->current_command->request.opcode,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= client->current_command->request.opaque,
- .bodylen= htonl(textlen),
- .cas= 0
- },
- };
-
- protocol_binary_response_status rval;
- const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
- if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
- (rval= client->root->spool(client, text, textlen)) != success)
- {
- return rval;
- }
-
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for ADD and ADDQ
- * @param cookie the calling client
- * @param header the add/addq command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-add_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.add != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
- protocol_binary_request_add *request= (void*)header;
- uint32_t flags= ntohl(request->message.body.flags);
- uint32_t timeout= ntohl(request->message.body.expiration);
- char *key= ((char*)header) + sizeof(*header) + 8;
- char *data= key + keylen;
- uint64_t cas;
-
- rval= client->root->callback->interface.v1.add(cookie, key, keylen,
- data, datalen, flags,
- timeout, &cas);
-
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_ADD)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_ADD,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(cas)
- }
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for DECREMENT and DECREMENTQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-decrement_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.decrement != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- protocol_binary_request_decr *request= (void*)header;
- uint64_t init= memcached_ntohll(request->message.body.initial);
- uint64_t delta= memcached_ntohll(request->message.body.delta);
- uint32_t timeout= ntohl(request->message.body.expiration);
- void *key= request->bytes + sizeof(request->bytes);
- uint64_t result;
- uint64_t cas;
-
- rval= client->root->callback->interface.v1.decrement(cookie, key, keylen,
- delta, init, timeout,
- &result, &cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_DECREMENT)
- {
- /* Send a positive request */
- protocol_binary_response_decr response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_DECREMENT,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(cas),
- .bodylen= htonl(8)
- },
- .body.value= memcached_htonll(result)
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for DELETE and DELETEQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-delete_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.delete != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- void *key= (header +1);
- uint64_t cas= memcached_ntohll(header->request.cas);
- rval= client->root->callback->interface.v1.delete(cookie, key, keylen, cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_DELETE)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_DELETE,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- }
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for FLUSH and FLUSHQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-flush_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.flush != NULL)
- {
- protocol_binary_request_flush *flush= (void*)header;
- uint32_t timeout= 0;
- if (htonl(header->request.bodylen) == 4)
- {
- timeout= ntohl(flush->message.body.expiration);
- }
-
- rval= client->root->callback->interface.v1.flush(cookie, timeout);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_FLUSH)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_FLUSH,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- }
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for GET, GETK, GETQ, GETKQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-get_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.get != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- void *key= (header + 1);
- rval= client->root->callback->interface.v1.get(cookie, key, keylen,
- get_response_handler);
-
- if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT &&
- (header->request.opcode == PROTOCOL_BINARY_CMD_GETQ ||
- header->request.opcode == PROTOCOL_BINARY_CMD_GETKQ))
- {
- /* Quiet commands shouldn't respond on cache misses */
- rval= PROTOCOL_BINARY_RESPONSE_SUCCESS;
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for INCREMENT and INCREMENTQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-increment_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.increment != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- protocol_binary_request_incr *request= (void*)header;
- uint64_t init= memcached_ntohll(request->message.body.initial);
- uint64_t delta= memcached_ntohll(request->message.body.delta);
- uint32_t timeout= ntohl(request->message.body.expiration);
- void *key= request->bytes + sizeof(request->bytes);
- uint64_t cas;
- uint64_t result;
-
- rval= client->root->callback->interface.v1.increment(cookie, key, keylen,
- delta, init, timeout,
- &result, &cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_INCREMENT)
- {
- /* Send a positive request */
- protocol_binary_response_incr response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_INCREMENT,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(cas),
- .bodylen= htonl(8)
- },
- .body.value= memcached_htonll(result)
- }
- };
-
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for noop. Inform the v1 interface about the noop packet, and
- * create and send a packet back to the client
- *
- * @param cookie the calling client
- * @param header the command
- * @param response_handler the response handler
- * @return the result of the operation
- */
-static protocol_binary_response_status
-noop_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.noop != NULL)
- {
- client->root->callback->interface.v1.noop(cookie);
- }
-
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_NOOP,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- }
- }
- };
-
- return response_handler(cookie, header, (void*)&response);
-}
-
-/**
- * Callback for APPEND and APPENDQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-append_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.append != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- uint32_t datalen= ntohl(header->request.bodylen) - keylen;
- char *key= (void*)(header +1);
- char *data= key +keylen;
- uint64_t cas= memcached_ntohll(header->request.cas);
- uint64_t result_cas;
-
- rval= client->root->callback->interface.v1.append(cookie, key, keylen,
- data, datalen, cas,
- &result_cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_APPEND)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_APPEND,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(result_cas),
- },
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for PREPEND and PREPENDQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-prepend_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.prepend != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- uint32_t datalen= ntohl(header->request.bodylen) - keylen;
- char *key= (char*)(header + 1);
- char *data= key + keylen;
- uint64_t cas= memcached_ntohll(header->request.cas);
- uint64_t result_cas;
- rval= client->root->callback->interface.v1.prepend(cookie, key, keylen,
- data, datalen, cas,
- &result_cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_PREPEND)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_PREPEND,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(result_cas),
- },
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for QUIT and QUITQ. Notify the client and shut down the connection
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-quit_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.quit != NULL)
- {
- client->root->callback->interface.v1.quit(cookie);
- }
-
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_QUIT,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque
- }
- }
- };
-
- if (header->request.opcode == PROTOCOL_BINARY_CMD_QUIT)
- {
- response_handler(cookie, header, (void*)&response);
- }
-
- /* I need a better way to signal to close the connection */
- return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
-}
-
-/**
- * Callback for REPLACE and REPLACEQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-replace_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.replace != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
- protocol_binary_request_replace *request= (void*)header;
- uint32_t flags= ntohl(request->message.body.flags);
- uint32_t timeout= ntohl(request->message.body.expiration);
- char *key= ((char*)header) + sizeof(*header) + 8;
- char *data= key + keylen;
- uint64_t cas= memcached_ntohll(header->request.cas);
- uint64_t result_cas;
-
- rval= client->root->callback->interface.v1.replace(cookie, key, keylen,
- data, datalen, flags,
- timeout, cas,
- &result_cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_REPLACE)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_REPLACE,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(result_cas),
- },
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for SET and SETQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-set_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.set != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
- uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
- protocol_binary_request_replace *request= (void*)header;
- uint32_t flags= ntohl(request->message.body.flags);
- uint32_t timeout= ntohl(request->message.body.expiration);
- char *key= ((char*)header) + sizeof(*header) + 8;
- char *data= key + keylen;
- uint64_t cas= memcached_ntohll(header->request.cas);
- uint64_t result_cas;
-
-
- rval= client->root->callback->interface.v1.set(cookie, key, keylen,
- data, datalen, flags,
- timeout, cas, &result_cas);
- if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- header->request.opcode == PROTOCOL_BINARY_CMD_SET)
- {
- /* Send a positive request */
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= PROTOCOL_BINARY_CMD_SET,
- .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
- .opaque= header->request.opaque,
- .cas= memcached_ntohll(result_cas),
- },
- }
- };
- rval= response_handler(cookie, header, (void*)&response);
- }
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for STAT
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-stat_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.stat != NULL)
- {
- uint16_t keylen= ntohs(header->request.keylen);
-
- rval= client->root->callback->interface.v1.stat(cookie,
- (void*)(header + 1),
- keylen,
- stat_response_handler);
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * Callback for VERSION
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-version_command_handler(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler)
-{
- (void)response_handler;
- (void)header;
- protocol_binary_response_status rval;
-
- memcached_protocol_client_st *client= (void*)cookie;
- if (client->root->callback->interface.v1.version != NULL)
- {
- rval= client->root->callback->interface.v1.version(cookie,
- version_response_handler);
- }
- else
- {
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- }
-
- return rval;
-}
-
-/**
- * The map to remap between the com codes and the v1 logical setting
- */
-static memcached_binary_protocol_command_handler comcode_v0_v1_remap[256]= {
- [PROTOCOL_BINARY_CMD_ADDQ]= add_command_handler,
- [PROTOCOL_BINARY_CMD_ADD]= add_command_handler,
- [PROTOCOL_BINARY_CMD_APPENDQ]= append_command_handler,
- [PROTOCOL_BINARY_CMD_APPEND]= append_command_handler,
- [PROTOCOL_BINARY_CMD_DECREMENTQ]= decrement_command_handler,
- [PROTOCOL_BINARY_CMD_DECREMENT]= decrement_command_handler,
- [PROTOCOL_BINARY_CMD_DELETEQ]= delete_command_handler,
- [PROTOCOL_BINARY_CMD_DELETE]= delete_command_handler,
- [PROTOCOL_BINARY_CMD_FLUSHQ]= flush_command_handler,
- [PROTOCOL_BINARY_CMD_FLUSH]= flush_command_handler,
- [PROTOCOL_BINARY_CMD_GETKQ]= get_command_handler,
- [PROTOCOL_BINARY_CMD_GETK]= get_command_handler,
- [PROTOCOL_BINARY_CMD_GETQ]= get_command_handler,
- [PROTOCOL_BINARY_CMD_GET]= get_command_handler,
- [PROTOCOL_BINARY_CMD_INCREMENTQ]= increment_command_handler,
- [PROTOCOL_BINARY_CMD_INCREMENT]= increment_command_handler,
- [PROTOCOL_BINARY_CMD_NOOP]= noop_command_handler,
- [PROTOCOL_BINARY_CMD_PREPENDQ]= prepend_command_handler,
- [PROTOCOL_BINARY_CMD_PREPEND]= prepend_command_handler,
- [PROTOCOL_BINARY_CMD_QUITQ]= quit_command_handler,
- [PROTOCOL_BINARY_CMD_QUIT]= quit_command_handler,
- [PROTOCOL_BINARY_CMD_REPLACEQ]= replace_command_handler,
- [PROTOCOL_BINARY_CMD_REPLACE]= replace_command_handler,
- [PROTOCOL_BINARY_CMD_SETQ]= set_command_handler,
- [PROTOCOL_BINARY_CMD_SET]= set_command_handler,
- [PROTOCOL_BINARY_CMD_STAT]= stat_command_handler,
- [PROTOCOL_BINARY_CMD_VERSION]= version_command_handler,
-};
-
-/**
- * Try to execute a command. Fire the pre/post functions and the specialized
- * handler function if it's set. If not, the unknown probe should be fired
- * if it's present.
- * @param client the client connection to operate on
- * @param header the command to execute
- * @return true if success or false if a fatal error occured so that the
- * connection should be shut down.
- */
-static protocol_binary_response_status execute_command(memcached_protocol_client_st *client, protocol_binary_request_header *header)
-{
- if (client->root->pedantic &&
- memcached_binary_protocol_pedantic_check_request(header))
- {
- /* @todo return invalid command packet */
- }
-
- /* we got all data available, execute the callback! */
- if (client->root->callback->pre_execute != NULL)
- {
- client->root->callback->pre_execute(client, header);
- }
-
- protocol_binary_response_status rval;
- rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
- uint8_t cc= header->request.opcode;
-
- switch (client->root->callback->interface_version)
- {
- case 0:
- if (client->root->callback->interface.v0.comcode[cc] != NULL) {
- rval= client->root->callback->interface.v0.comcode[cc](client, header, raw_response_handler);
- }
- break;
- case 1:
- if (comcode_v0_v1_remap[cc] != NULL) {
- rval= comcode_v0_v1_remap[cc](client, header, raw_response_handler);
- }
- break;
- default:
- /* Unknown interface.
- * It should be impossible to get here so I'll just call abort
- * to avoid getting a compiler warning :-)
- */
- abort();
- }
-
-
- if (rval == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND &&
- client->root->callback->unknown != NULL)
- {
- rval= client->root->callback->unknown(client, header, raw_response_handler);
- }
-
- if (rval != PROTOCOL_BINARY_RESPONSE_SUCCESS &&
- rval != PROTOCOL_BINARY_RESPONSE_EINTERNAL &&
- rval != PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
- {
- protocol_binary_response_no_extras response= {
- .message= {
- .header.response= {
- .magic= PROTOCOL_BINARY_RES,
- .opcode= cc,
- .status= htons(rval),
- .opaque= header->request.opaque,
- },
- }
- };
- rval= raw_response_handler(client, header, (void*)&response);
- }
-
- if (client->root->callback->post_execute != NULL)
- {
- client->root->callback->post_execute(client, header);
- }
-
- return rval;
-}
-
-/*
-** **********************************************************************
-** "PROTOECTED" INTERFACE
-** **********************************************************************
-*/
-memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
-{
- /* try to parse all of the received packets */
- protocol_binary_request_header *header;
- header= (void*)client->root->input_buffer;
- if (header->request.magic != (uint8_t)PROTOCOL_BINARY_REQ)
- {
- client->error= EINVAL;
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
- ssize_t len= *length;
-
- while (len >= (ssize_t)sizeof(*header) &&
- (len >= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen))))
- {
- /* I have the complete package */
- client->current_command= header;
- protocol_binary_response_status rv= execute_command(client, header);
-
- if (rv == PROTOCOL_BINARY_RESPONSE_EINTERNAL)
- {
- *length= len;
- *endptr= (void*)header;
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- } else if (rv == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
- return MEMCACHED_PROTOCOL_PAUSE_EVENT;
-
- ssize_t total= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen));
- len -= total;
- if (len > 0)
- {
- intptr_t ptr= (intptr_t)header;
- ptr += total;
- if ((ptr % 8) == 0)
- {
- header= (void*)ptr;
- }
- else
- {
- /* Fix alignment */
- memmove(client->root->input_buffer, (void*)ptr, (size_t)len);
- header= (void*)client->root->input_buffer;
- }
- }
- *length= len;
- *endptr= (void*)header;
- }
-
- return MEMCACHED_PROTOCOL_READ_EVENT;
-}
-
-/*
-** **********************************************************************
-** PUBLIC INTERFACE
-** **********************************************************************
-*/
-memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance)
-{
- return instance->callback;
-}
-
-void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback)
-{
- instance->callback= callback;
-}
-
-memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie)
-{
- (void)cookie;
- return raw_response_handler;
-}
-
-void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable)
-{
- instance->pedantic= enable;
-}
-
-bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance)
-{
- return instance->pedantic;
-}
-
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-LIBMEMCACHED_LOCAL
-bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request);
-
-LIBMEMCACHED_LOCAL
-bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
- const protocol_binary_response_header *response);
-
-LIBMEMCACHED_LOCAL
-memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-#ifndef NDEBUG
-#include <signal.h>
-#endif
-
-#include "cache.h"
-
-#ifndef NDEBUG
-const uint64_t redzone_pattern = 0xdeadbeefcafebabe;
-int cache_error = 0;
-#endif
-
-const size_t initial_pool_size = 64;
-
-cache_t* cache_create(const char *name, size_t bufsize, size_t align,
- cache_constructor_t* constructor,
- cache_destructor_t* destructor) {
- cache_t* ret = calloc(1, sizeof(cache_t));
- size_t name_length= strlen(name);
- char* nm= calloc(1, (sizeof(char) * name_length) +1);
- memcpy(nm, name, name_length);
- void** ptr = calloc(initial_pool_size, bufsize);
- if (ret == NULL || nm == NULL || ptr == NULL ||
- pthread_mutex_init(&ret->mutex, NULL) == -1) {
- free(ret);
- free(nm);
- free(ptr);
- return NULL;
- }
-
- ret->name = nm;
- ret->ptr = ptr;
- ret->freetotal = initial_pool_size;
- ret->constructor = constructor;
- ret->destructor = destructor;
-
-#ifndef NDEBUG
- ret->bufsize = bufsize + 2 * sizeof(redzone_pattern);
-#else
- ret->bufsize = bufsize;
-#endif
-
- (void)align;
-
- return ret;
-}
-
-static inline void* get_object(void *ptr) {
-#ifndef NDEBUG
- uint64_t *pre = ptr;
- return pre + 1;
-#else
- return ptr;
-#endif
-}
-
-void cache_destroy(cache_t *cache) {
- while (cache->freecurr > 0) {
- void *ptr = cache->ptr[--cache->freecurr];
- if (cache->destructor) {
- cache->destructor(get_object(ptr), NULL);
- }
- free(ptr);
- }
- free(cache->name);
- free(cache->ptr);
- pthread_mutex_destroy(&cache->mutex);
-}
-
-void* cache_alloc(cache_t *cache) {
- void *ret;
- void *object;
- pthread_mutex_lock(&cache->mutex);
- if (cache->freecurr > 0) {
- ret = cache->ptr[--cache->freecurr];
- object = get_object(ret);
- } else {
- object = ret = malloc(cache->bufsize);
- if (ret != NULL) {
- object = get_object(ret);
-
- if (cache->constructor != NULL &&
- cache->constructor(object, NULL, 0) != 0) {
- free(ret);
- object = NULL;
- }
- }
- }
- pthread_mutex_unlock(&cache->mutex);
-
-#ifndef NDEBUG
- if (object != NULL) {
- /* add a simple form of buffer-check */
- uint64_t *pre = ret;
- *pre = redzone_pattern;
- ret = pre+1;
- memcpy(((char*)ret) + cache->bufsize - (2 * sizeof(redzone_pattern)),
- &redzone_pattern, sizeof(redzone_pattern));
- }
-#endif
-
- return object;
-}
-
-void cache_free(cache_t *cache, void *ptr) {
- pthread_mutex_lock(&cache->mutex);
-
-#ifndef NDEBUG
- /* validate redzone... */
- if (memcmp(((char*)ptr) + cache->bufsize - (2 * sizeof(redzone_pattern)),
- &redzone_pattern, sizeof(redzone_pattern)) != 0) {
- raise(SIGABRT);
- cache_error = 1;
- pthread_mutex_unlock(&cache->mutex);
- return;
- }
- uint64_t *pre = ptr;
- --pre;
- if (*pre != redzone_pattern) {
- raise(SIGABRT);
- cache_error = -1;
- pthread_mutex_unlock(&cache->mutex);
- return;
- }
- ptr = pre;
-#endif
- if (cache->freecurr < cache->freetotal) {
- cache->ptr[cache->freecurr++] = ptr;
- } else {
- /* try to enlarge free connections array */
- size_t newtotal = cache->freetotal * 2;
- void **new_free = realloc(cache->ptr, sizeof(char *) * newtotal);
- if (new_free) {
- cache->freetotal = newtotal;
- cache->ptr = new_free;
- cache->ptr[cache->freecurr++] = ptr;
- } else {
- if (cache->destructor) {
- cache->destructor(ptr, NULL);
- }
- free(ptr);
-
- }
- }
- pthread_mutex_unlock(&cache->mutex);
-}
-
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-#pragma once
-
-#include <pthread.h>
-
-#ifdef HAVE_UMEM_H
-# include <umem.h>
-# define cache_t umem_cache_t
-# define cache_alloc(a) umem_cache_alloc(a, UMEM_DEFAULT)
-# define cache_free(a, b) umem_cache_free(a, b)
-# define cache_create(a,b,c,d,e) umem_cache_create((char*)a, b, c, d, e, NULL, NULL, NULL, 0)
-# define cache_destroy(a) umem_cache_destroy(a);
-#else
-# ifndef NDEBUG
-/* may be used for debug purposes */
-extern int cache_error;
-# endif
-
-/**
- * Constructor used to initialize allocated objects
- *
- * @param obj pointer to the object to initialized.
- * @param notused1 This parameter is currently not used.
- * @param notused2 This parameter is currently not used.
- * @return you should return 0, but currently this is not checked
- */
-typedef int cache_constructor_t(void* obj, void* notused1, int notused2);
-/**
- * Destructor used to clean up allocated objects before they are
- * returned to the operating system.
- *
- * @param obj pointer to the object to initialized.
- * @param notused1 This parameter is currently not used.
- * @param notused2 This parameter is currently not used.
- * @return you should return 0, but currently this is not checked
- */
-typedef void cache_destructor_t(void* obj, void* notused);
-
-/**
- * Definition of the structure to keep track of the internal details of
- * the cache allocator. Touching any of these variables results in
- * undefined behavior.
- */
-typedef struct {
- /** Mutex to protect access to the structure */
- pthread_mutex_t mutex;
- /** Name of the cache objects in this cache (provided by the caller) */
- char *name;
- /** List of pointers to available buffers in this cache */
- void **ptr;
- /** The size of each element in this cache */
- size_t bufsize;
- /** The capacity of the list of elements */
- size_t freetotal;
- /** The current number of free elements */
- size_t freecurr;
- /** The constructor to be called each time we allocate more memory */
- cache_constructor_t* constructor;
- /** The destructor to be called each time before we release memory */
- cache_destructor_t* destructor;
-} cache_t;
-
-/**
- * Create an object cache.
- *
- * The object cache will let you allocate objects of the same size. It is fully
- * MT safe, so you may allocate objects from multiple threads without having to
- * do any syncrhonization in the application code.
- *
- * @param name the name of the object cache. This name may be used for debug purposes
- * and may help you track down what kind of object you have problems with
- * (buffer overruns, leakage etc)
- * @param bufsize the size of each object in the cache
- * @param align the alignment requirements of the objects in the cache.
- * @param constructor the function to be called to initialize memory when we need
- * to allocate more memory from the os.
- * @param destructor the function to be called before we release the memory back
- * to the os.
- * @return a handle to an object cache if successful, NULL otherwise.
- */
-cache_t* cache_create(const char* name, size_t bufsize, size_t align,
- cache_constructor_t* constructor,
- cache_destructor_t* destructor);
-/**
- * Destroy an object cache.
- *
- * Destroy and invalidate an object cache. You should return all buffers allocated
- * with cache_alloc by using cache_free before calling this function. Not doing
- * so results in undefined behavior (the buffers may or may not be invalidated)
- *
- * @param handle the handle to the object cache to destroy.
- */
-void cache_destroy(cache_t* handle);
-/**
- * Allocate an object from the cache.
- *
- * @param handle the handle to the object cache to allocate from
- * @return a pointer to an initialized object from the cache, or NULL if
- * the allocation cannot be satisfied.
- */
-void* cache_alloc(cache_t* handle);
-/**
- * Return an object back to the cache.
- *
- * The caller should return the object in an initialized state so that
- * the object may be returned in an expected state from cache_alloc.
- *
- * @param handle handle to the object cache to return the object to
- * @param ptr pointer to the object to return.
- */
-void cache_free(cache_t* handle, void* ptr);
-#endif // HAVE_UMEM_H
+++ /dev/null
-/*
- * Summary: Definition of the callback interface
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Trond Norbye
- */
-#ifndef LIBMEMCACHEDPROTOCOL_CALLBACK_H
-#define LIBMEMCACHEDPROTOCOL_CALLBACK_H
-
-/**
- * Callback to send data back from a successful GET/GETQ/GETK/GETKQ command
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param key What to insert as key in the reply
- * @param keylen The length of the key
- * @param body What to store in the body of the package
- * @param bodylen The number of bytes of the body
- * @param flags The flags stored with the item
- * @param cas The CAS value to insert into the response (should be 0
- * if you don't care)
- */
-typedef protocol_binary_response_status
-(*memcached_binary_protocol_get_response_handler)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void *body,
- uint32_t bodylen,
- uint32_t flags,
- uint64_t cas);
-/**
- * Callback to send data back from a STAT command
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param key What to insert as key in the reply
- * @param keylen The length of the key
- * @param body What to store in the body of the package
- * @param bodylen The number of bytes of the body
- */
-typedef protocol_binary_response_status
-(*memcached_binary_protocol_stat_response_handler)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void *body,
- uint32_t bodylen);
-/**
- * Callback to send data back from a VERSION command
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param text The version string
- * @param length The number of bytes in the version string
- */
-typedef protocol_binary_response_status
-(*memcached_binary_protocol_version_response_handler)(const void *cookie,
- const void *text,
- uint32_t length);
-
-
-/**
- * In the low level interface you need to format the response
- * packet yourself (giving you complete freedom :-)
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param request Pointer to the request packet you are sending a reply to
- * @param response Pointer to the response packet to send
- *
- */
-typedef protocol_binary_response_status (*memcached_binary_protocol_raw_response_handler)(const void *cookie,
- protocol_binary_request_header *request,
- protocol_binary_response_header *response);
-
-/**
- * In the low lever interface you have to do most of the work by
- * yourself, but it also gives you a lot of freedom :-)
- * @param cookie identification for this connection, just pass it along to
- * the response handler
- * @param header the command received over the wire. Never try to access
- * <u>anything</u> outside the command.
- * @param resonse_handler call this function to send data back to the client
- */
-typedef protocol_binary_response_status (*memcached_binary_protocol_command_handler)(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler);
-
-/**
- * The raw interface to the packets is implemented in version 0. It contains
- * just an array with command handlers. The inxed in the array is the
- * com code.
- */
-typedef struct {
- memcached_binary_protocol_command_handler comcode[256];
-} memcached_binary_protocol_callback_v0_st;
-
-
-/**
- * The first version of the callback struct containing all of the
- * documented commands in the initial release of the binary protocol
- * (aka. memcached 1.4.0).
- *
- * You might miss the Q commands (addq etc) but the response function
- * knows how to deal with them so you don't need to worry about that :-)
- */
-typedef struct {
- /**
- * Add an item to the cache
- * @param cookie id of the client receiving the command
- * @param key the key to add
- * @param len the length of the key
- * @param val the value to store for the key (may be NIL)
- * @param vallen the length of the data
- * @param flags the flags to store with the key
- * @param exptime the expiry time for the key-value pair
- * @param cas the resulting cas for the add operation (if success)
- */
- protocol_binary_response_status (*add)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void* val,
- uint32_t vallen,
- uint32_t flags,
- uint32_t exptime,
- uint64_t *cas);
-
- /**
- * Append data to an <b>existing</b> key-value pair.
- *
- * @param cookie id of the client receiving the command
- * @param key the key to add data to
- * @param len the length of the key
- * @param val the value to append to the value
- * @param vallen the length of the data
- * @param cas the CAS in the request
- * @param result_cas the resulting cas for the append operation
- *
- */
- protocol_binary_response_status (*append)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void* val,
- uint32_t vallen,
- uint64_t cas,
- uint64_t *result_cas);
-
- /**
- * Decrement the value for a key
- *
- * @param cookie id of the client receiving the command
- * @param key the key to decrement the value for
- * @param len the length of the key
- * @param delta the amount to decrement
- * @param initial initial value to store (if the key doesn't exist)
- * @param expiration expiration time for the object (if the key doesn't exist)
- * @param cas the CAS in the request
- * @param result the result from the decrement
- * @param result_cas the cas of the item
- *
- */
- protocol_binary_response_status (*decrement)(const void *cookie,
- const void *key,
- uint16_t keylen,
- uint64_t delta,
- uint64_t initial,
- uint32_t expiration,
- uint64_t *result,
- uint64_t *result_cas);
-
- /**
- * Delete an existing key
- *
- * @param cookie id of the client receiving the command
- * @param key the key to delete
- * @param len the length of the key
- * @param cas the CAS in the request
- */
- protocol_binary_response_status (*delete)(const void *cookie,
- const void *key,
- uint16_t keylen,
- uint64_t cas);
-
-
- /**
- * Flush the cache
- *
- * @param cookie id of the client receiving the command
- * @param when when the cache should be flushed (0 == immediately)
- */
- protocol_binary_response_status (*flush)(const void *cookie,
- uint32_t when);
-
-
-
- /**
- * Get a key-value pair
- *
- * @param cookie id of the client receiving the command
- * @param key the key to get
- * @param len the length of the key
- * @param response_handler to send the result back to the client
- */
- protocol_binary_response_status (*get)(const void *cookie,
- const void *key,
- uint16_t keylen,
- memcached_binary_protocol_get_response_handler response_handler);
-
- /**
- * Increment the value for a key
- *
- * @param cookie id of the client receiving the command
- * @param key the key to increment the value on
- * @param len the length of the key
- * @param delta the amount to increment
- * @param initial initial value to store (if the key doesn't exist)
- * @param expiration expiration time for the object (if the key doesn't exist)
- * @param cas the CAS in the request
- * @param result the result from the decrement
- * @param result_cas the cas of the item
- *
- */
- protocol_binary_response_status (*increment)(const void *cookie,
- const void *key,
- uint16_t keylen,
- uint64_t delta,
- uint64_t initial,
- uint32_t expiration,
- uint64_t *result,
- uint64_t *result_cas);
-
- /**
- * The noop command was received. This is just a notification callback (the
- * response is automatically created).
- *
- * @param cookie id of the client receiving the command
- */
- protocol_binary_response_status (*noop)(const void *cookie);
-
- /**
- * Prepend data to an <b>existing</b> key-value pair.
- *
- * @param cookie id of the client receiving the command
- * @param key the key to prepend data to
- * @param len the length of the key
- * @param val the value to prepend to the value
- * @param vallen the length of the data
- * @param cas the CAS in the request
- * @param result-cas the cas id of the item
- *
- */
- protocol_binary_response_status (*prepend)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void* val,
- uint32_t vallen,
- uint64_t cas,
- uint64_t *result_cas);
-
- /**
- * The quit command was received. This is just a notification callback (the
- * response is automatically created).
- *
- * @param cookie id of the client receiving the command
- */
- protocol_binary_response_status (*quit)(const void *cookie);
-
-
- /**
- * Replace an <b>existing</b> item to the cache
- *
- * @param cookie id of the client receiving the command
- * @param key the key to replace the content for
- * @param len the length of the key
- * @param val the value to store for the key (may be NIL)
- * @param vallen the length of the data
- * @param flags the flags to store with the key
- * @param exptime the expiry time for the key-value pair
- * @param cas the cas id in the request
- * @param result_cas the cas id of the item
- */
- protocol_binary_response_status (*replace)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void* val,
- uint32_t vallen,
- uint32_t flags,
- uint32_t exptime,
- uint64_t cas,
- uint64_t *result_cas);
-
-
- /**
- * Set a key-value pair in the cache
- *
- * @param cookie id of the client receiving the command
- * @param key the key to insert
- * @param len the length of the key
- * @param val the value to store for the key (may be NIL)
- * @param vallen the length of the data
- * @param flags the flags to store with the key
- * @param exptime the expiry time for the key-value pair
- * @param cas the cas id in the request
- * @param result_cas the cas id of the new item
- */
- protocol_binary_response_status (*set)(const void *cookie,
- const void *key,
- uint16_t keylen,
- const void* val,
- uint32_t vallen,
- uint32_t flags,
- uint32_t exptime,
- uint64_t cas,
- uint64_t *result_cas);
-
- /**
- * Get status information
- *
- * @param cookie id of the client receiving the command
- * @param key the key to get status for (or NIL to request all status).
- * Remember to insert the terminating packet if multiple
- * packets should be returned.
- * @param keylen the length of the key
- * @param response_handler to send the result back to the client, but
- * don't send reply on success!
- *
- */
- protocol_binary_response_status (*stat)(const void *cookie,
- const void *key,
- uint16_t keylen,
- memcached_binary_protocol_stat_response_handler response_handler);
-
- /**
- * Get the version information
- *
- * @param cookie id of the client receiving the command
- * @param response_handler to send the result back to the client, but
- * don't send reply on success!
- *
- */
- protocol_binary_response_status (*version)(const void *cookie,
- memcached_binary_protocol_version_response_handler response_handler);
-} memcached_binary_protocol_callback_v1_st;
-
-
-/**
- * The version numbers for the different callback structures.
- */
-typedef enum {
- /** Version 0 is a lowlevel interface that tries to maximize your freedom */
- MEMCACHED_PROTOCOL_HANDLER_V0= 0,
- /**
- * Version 1 abstracts more of the protocol details, and let you work at
- * a logical level
- */
- MEMCACHED_PROTOCOL_HANDLER_V1= 1,
-} memcached_protocol_interface_version_t;
-
-/**
- * Definition of the protocol callback structure.
- */
-typedef struct {
- /**
- * The interface version you provide callbacks for.
- */
- memcached_protocol_interface_version_t interface_version;
-
- /**
- * Callback fired just before the command will be executed.
- *
- * @param cookie id of the client receiving the command
- * @param header the command header as received on the wire. If you look
- * at the content you <b>must</b> ensure that you don't
- * try to access beyond the end of the message.
- */
- void (*pre_execute)(const void *cookie,
- protocol_binary_request_header *header);
- /**
- * Callback fired just after the command was exected (please note
- * that the data transfer back to the client is not finished at this
- * time).
- *
- * @param cookie id of the client receiving the command
- * @param header the command header as received on the wire. If you look
- * at the content you <b>must</b> ensure that you don't
- * try to access beyond the end of the message.
- */
- void (*post_execute)(const void *cookie,
- protocol_binary_request_header *header);
-
- /**
- * Callback fired if no specialized callback is registered for this
- * specific command code.
- *
- * @param cookie id of the client receiving the command
- * @param header the command header as received on the wire. You <b>must</b>
- * ensure that you don't try to access beyond the end of the
- * message.
- * @param response_handler The response handler to send data back.
- */
- protocol_binary_response_status (*unknown)(const void *cookie,
- protocol_binary_request_header *header,
- memcached_binary_protocol_raw_response_handler response_handler);
-
- /**
- * The different interface levels we support. A pointer is used so the
- * size of the structure is fixed. You must ensure that the memory area
- * passed as the pointer is valid as long as you use the protocol handler.
- */
- union {
- memcached_binary_protocol_callback_v0_st v0;
-
- /**
- * The first version of the callback struct containing all of the
- * documented commands in the initial release of the binary protocol
- * (aka. memcached 1.4.0).
- */
- memcached_binary_protocol_callback_v1_st v1;
- } interface;
-} memcached_binary_protocol_callback_st;
-
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "config.h"
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-#include <assert.h>
-
-#include <libmemcached/visibility.h>
-#include <libmemcached/protocol_handler.h>
-#include <libmemcached/protocol/cache.h>
-
-/*
- * I don't really need the following two functions as function pointers
- * in the instance handle, but I don't want to put them in the global
- * namespace for those linking statically (personally I don't like that,
- * but some people still do). If it ever shows up as a performance thing
- * I'll look into optimizing this ;-)
- */
-typedef bool (*drain_func)(memcached_protocol_client_st *client);
-typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
- const void *data,
- size_t length);
-
-/**
- * Definition of the per instance structure.
- */
-struct memcached_protocol_st {
- memcached_binary_protocol_callback_st *callback;
- memcached_protocol_recv_func recv;
- memcached_protocol_send_func send;
-
- /*
- * I really don't need these as funciton pointers, but I don't want
- * to clutter the namespace if someone links statically.
- */
- drain_func drain;
- spool_func spool;
-
- /*
- * To avoid keeping a buffer in each client all the time I have a
- * bigger buffer in the instance that I read to initially, and then
- * I try to parse and execute as much from the buffer. If I wasn't able
- * to process all data I'll keep that in a per-connection buffer until
- * the next time I can read from the socket.
- */
- uint8_t *input_buffer;
- size_t input_buffer_size;
-
- bool pedantic;
- /* @todo use multiple sized buffers */
- cache_t *buffer_cache;
-};
-
-struct chunk_st {
- /* Pointer to the data */
- char *data;
- /* The offset to the first byte into the buffer that is used */
- size_t offset;
- /* The offset into the buffer for the first free byte */
- size_t nbytes;
- /* The number of bytes in the buffer */
- size_t size;
- /* Pointer to the next buffer in the chain */
- struct chunk_st *next;
-};
-
-#define CHUNK_BUFFERSIZE 2048
-
-typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
-
-enum ascii_cmd {
- GET_CMD,
- GETS_CMD,
- SET_CMD,
- ADD_CMD,
- REPLACE_CMD,
- CAS_CMD,
- APPEND_CMD,
- PREPEND_CMD,
- DELETE_CMD,
- INCR_CMD,
- DECR_CMD,
- STATS_CMD,
- FLUSH_ALL_CMD,
- VERSION_CMD,
- QUIT_CMD,
- VERBOSITY_CMD,
- UNKNOWN_CMD
-};
-
-struct memcached_protocol_client_st {
- memcached_protocol_st *root;
- memcached_socket_t sock;
- int error;
-
- /* Linked list of data to send */
- struct chunk_st *output;
- struct chunk_st *output_tail;
-
- /*
- * While we process input data, this is where we spool incomplete commands
- * if we need to receive more data....
- * @todo use the buffercace
- */
- uint8_t *input_buffer;
- size_t input_buffer_size;
- size_t input_buffer_offset;
-
- /* The callback to the protocol handler to use (ascii or binary) */
- process_data work;
-
- /*
- * Should the spool data discard the data to send or not? (aka noreply in
- * the ascii protocol..
- */
- bool mute;
-
- /* Members used by the binary protocol */
- protocol_binary_request_header *current_command;
-
- /* Members used by the ascii protocol */
- enum ascii_cmd ascii_command;
-};
-
-#include "ascii_handler.h"
-#include "binary_handler.h"
+++ /dev/null
-# vim:ft=automake
-# included from Top Level Makefile.am
-# All paths should be given relative to the root
-
-
-lib_LTLIBRARIES+= libmemcached/libmemcachedprotocol.la
-libmemcached_libmemcachedprotocol_la_SOURCES= \
- libmemcached/byteorder.cc \
- libmemcached/protocol/ascii_handler.c \
- libmemcached/protocol/binary_handler.c \
- libmemcached/protocol/cache.c \
- libmemcached/protocol/pedantic.c \
- libmemcached/protocol/protocol_handler.c
-
-libmemcached_libmemcachedprotocol_la_CFLAGS= \
- ${AM_CFLAGS} \
- ${NO_CONVERSION} \
- -DBUILDING_LIBMEMCACHED
-libmemcached_libmemcachedprotocol_la_CFLAGS+= ${PTHREAD_CFLAGS}
-
-libmemcached_libmemcachedprotocol_la_CXXFLAGS= \
- ${AM_CXXFLAGS} \
- -DBUILDING_LIBMEMCACHED
-libmemcached_libmemcachedprotocol_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
-
-libmemcached_libmemcachedprotocol_la_LIBADD= ${PTHREAD_LIBS}
-libmemcached_libmemcachedprotocol_la_LDFLAGS= ${AM_LDFLAGS}
-libmemcached_libmemcachedprotocol_la_LDFLAGS+= -version-info ${MEMCACHED_PROTOCAL_LIBRARY_VERSION}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#include <libmemcached/protocol/common.h>
-
-#include <sys/types.h>
-#include <inttypes.h>
-
-#define ensure(a) if (!(a)) { return false; }
-
-bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request)
-{
- ensure(request->request.magic == PROTOCOL_BINARY_REQ);
- ensure(request->request.datatype == PROTOCOL_BINARY_RAW_BYTES);
-
- ensure(request->bytes[6] == 0);
- ensure(request->bytes[7] == 0);
-
- uint8_t opcode= request->request.opcode;
- uint16_t keylen= ntohs(request->request.keylen);
- uint8_t extlen= request->request.extlen;
- uint32_t bodylen= ntohl(request->request.bodylen);
-
- ensure(bodylen >= (keylen + extlen));
-
- switch (opcode) {
- case PROTOCOL_BINARY_CMD_GET:
- case PROTOCOL_BINARY_CMD_GETK:
- case PROTOCOL_BINARY_CMD_GETKQ:
- case PROTOCOL_BINARY_CMD_GETQ:
- ensure(extlen == 0);
- ensure(keylen > 0);
- ensure(keylen == bodylen);
- ensure(request->request.cas == 0);
- break;
-
- case PROTOCOL_BINARY_CMD_ADD:
- case PROTOCOL_BINARY_CMD_ADDQ:
- /* it makes no sense to run add with a cas value */
- ensure(request->request.cas == 0);
- /* FALLTHROUGH */
- case PROTOCOL_BINARY_CMD_SET:
- case PROTOCOL_BINARY_CMD_SETQ:
- case PROTOCOL_BINARY_CMD_REPLACE:
- case PROTOCOL_BINARY_CMD_REPLACEQ:
- ensure(keylen > 0);
- ensure(extlen == 8);
- break;
-
- case PROTOCOL_BINARY_CMD_DELETE:
- case PROTOCOL_BINARY_CMD_DELETEQ:
- ensure(extlen == 0);
- ensure(keylen > 0);
- ensure(keylen == bodylen);
- break;
-
- case PROTOCOL_BINARY_CMD_INCREMENT:
- case PROTOCOL_BINARY_CMD_INCREMENTQ:
- case PROTOCOL_BINARY_CMD_DECREMENT:
- case PROTOCOL_BINARY_CMD_DECREMENTQ:
- ensure(extlen == 20);
- ensure(keylen > 0);
- ensure(keylen + extlen == bodylen);
- break;
-
- case PROTOCOL_BINARY_CMD_QUIT:
- case PROTOCOL_BINARY_CMD_QUITQ:
- case PROTOCOL_BINARY_CMD_NOOP:
- case PROTOCOL_BINARY_CMD_VERSION:
- ensure(extlen == 0);
- ensure(keylen == 0);
- ensure(bodylen == 0);
- break;
-
- case PROTOCOL_BINARY_CMD_FLUSH:
- case PROTOCOL_BINARY_CMD_FLUSHQ:
- ensure(extlen == 0 || extlen == 4);
- ensure(keylen == 0);
- ensure(bodylen == extlen);
- break;
-
- case PROTOCOL_BINARY_CMD_STAT:
- ensure(extlen == 0);
- /* May have key, but not value */
- ensure(keylen == bodylen);
- break;
-
- case PROTOCOL_BINARY_CMD_APPEND:
- case PROTOCOL_BINARY_CMD_APPENDQ:
- case PROTOCOL_BINARY_CMD_PREPEND:
- case PROTOCOL_BINARY_CMD_PREPENDQ:
- ensure(extlen == 0);
- ensure(keylen > 0);
- break;
- default:
- /* Unknown command */
- ;
- }
-
- return true;
-}
-
-bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
- const protocol_binary_response_header *response)
-{
- ensure(response->response.magic == PROTOCOL_BINARY_RES);
- ensure(response->response.datatype == PROTOCOL_BINARY_RAW_BYTES);
- ensure(response->response.opaque == request->request.opaque);
-
- uint16_t status= ntohs(response->response.status);
- uint8_t opcode= response->response.opcode;
-
- if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
- {
- switch (opcode) {
- case PROTOCOL_BINARY_CMD_ADDQ:
- case PROTOCOL_BINARY_CMD_APPENDQ:
- case PROTOCOL_BINARY_CMD_DECREMENTQ:
- case PROTOCOL_BINARY_CMD_DELETEQ:
- case PROTOCOL_BINARY_CMD_FLUSHQ:
- case PROTOCOL_BINARY_CMD_INCREMENTQ:
- case PROTOCOL_BINARY_CMD_PREPENDQ:
- case PROTOCOL_BINARY_CMD_QUITQ:
- case PROTOCOL_BINARY_CMD_REPLACEQ:
- case PROTOCOL_BINARY_CMD_SETQ:
- /* Quiet command shouldn't return on success */
- return false;
- default:
- break;
- }
-
- switch (opcode) {
- case PROTOCOL_BINARY_CMD_ADD:
- case PROTOCOL_BINARY_CMD_REPLACE:
- case PROTOCOL_BINARY_CMD_SET:
- case PROTOCOL_BINARY_CMD_APPEND:
- case PROTOCOL_BINARY_CMD_PREPEND:
- ensure(response->response.keylen == 0);
- ensure(response->response.extlen == 0);
- ensure(response->response.bodylen == 0);
- ensure(response->response.cas != 0);
- break;
- case PROTOCOL_BINARY_CMD_FLUSH:
- case PROTOCOL_BINARY_CMD_NOOP:
- case PROTOCOL_BINARY_CMD_QUIT:
- case PROTOCOL_BINARY_CMD_DELETE:
- ensure(response->response.keylen == 0);
- ensure(response->response.extlen == 0);
- ensure(response->response.bodylen == 0);
- ensure(response->response.cas == 0);
- break;
-
- case PROTOCOL_BINARY_CMD_DECREMENT:
- case PROTOCOL_BINARY_CMD_INCREMENT:
- ensure(response->response.keylen == 0);
- ensure(response->response.extlen == 0);
- ensure(ntohl(response->response.bodylen) == 8);
- ensure(response->response.cas != 0);
- break;
-
- case PROTOCOL_BINARY_CMD_STAT:
- ensure(response->response.extlen == 0);
- /* key and value exists in all packets except in the terminating */
- ensure(response->response.cas == 0);
- break;
-
- case PROTOCOL_BINARY_CMD_VERSION:
- ensure(response->response.keylen == 0);
- ensure(response->response.extlen == 0);
- ensure(response->response.bodylen != 0);
- ensure(response->response.cas == 0);
- break;
-
- case PROTOCOL_BINARY_CMD_GET:
- case PROTOCOL_BINARY_CMD_GETQ:
- ensure(response->response.keylen == 0);
- ensure(response->response.extlen == 4);
- ensure(response->response.cas != 0);
- break;
-
- case PROTOCOL_BINARY_CMD_GETK:
- case PROTOCOL_BINARY_CMD_GETKQ:
- ensure(response->response.keylen != 0);
- ensure(response->response.extlen == 4);
- ensure(response->response.cas != 0);
- break;
-
- default:
- /* Undefined command code */
- break;
- }
- }
- else
- {
- ensure(response->response.cas == 0);
- ensure(response->response.extlen == 0);
- if (opcode != PROTOCOL_BINARY_CMD_GETK)
- {
- ensure(response->response.keylen == 0);
- }
- }
-
- return true;
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#include <libmemcached/protocol/common.h>
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-#include <stdio.h>
-
-/*
-** **********************************************************************
-** INTERNAL INTERFACE
-** **********************************************************************
-*/
-
-/**
- * The default function to receive data from the client. This function
- * just wraps the recv function to receive from a socket.
- * See man -s3socket recv for more information.
- *
- * @param cookie cookie indentifying a client, not used
- * @param sock socket to read from
- * @param buf the destination buffer
- * @param nbytes the number of bytes to read
- * @return the number of bytes transferred of -1 upon error
- */
-static ssize_t default_recv(const void *cookie,
- memcached_socket_t sock,
- void *buf,
- size_t nbytes)
-{
- (void)cookie;
- return recv(sock, buf, nbytes, 0);
-}
-
-/**
- * The default function to send data to the server. This function
- * just wraps the send function to send through a socket.
- * See man -s3socket send for more information.
- *
- * @param cookie cookie indentifying a client, not used
- * @param sock socket to send to
- * @param buf the source buffer
- * @param nbytes the number of bytes to send
- * @return the number of bytes transferred of -1 upon error
- */
-static ssize_t default_send(const void *cookie,
- memcached_socket_t fd,
- const void *buf,
- size_t nbytes)
-{
- (void)cookie;
- return send(fd, buf, nbytes, 0);
-}
-
-/**
- * Try to drain the output buffers without blocking
- *
- * @param client the client to drain
- * @return false if an error occured (connection should be shut down)
- * true otherwise (please note that there may be more data to
- * left in the buffer to send)
- */
-static bool drain_output(struct memcached_protocol_client_st *client)
-{
- ssize_t len;
-
- /* Do we have pending data to send? */
- while (client->output != NULL)
- {
- len= client->root->send(client,
- client->sock,
- client->output->data + client->output->offset,
- client->output->nbytes - client->output->offset);
-
- if (len == -1)
- {
- if (get_socket_errno() == EWOULDBLOCK)
- {
- return true;
- }
- else if (get_socket_errno() != EINTR)
- {
- client->error= get_socket_errno();
- return false;
- }
- }
- else
- {
- client->output->offset += (size_t)len;
- if (client->output->offset == client->output->nbytes)
- {
- /* This was the complete buffer */
- struct chunk_st *old= client->output;
- client->output= client->output->next;
- if (client->output == NULL)
- {
- client->output_tail= NULL;
- }
- cache_free(client->root->buffer_cache, old);
- }
- }
- }
-
- return true;
-}
-
-/**
- * Allocate an output buffer and chain it into the output list
- *
- * @param client the client that needs the buffer
- * @return pointer to the new chunk if the allocation succeeds, NULL otherwise
- */
-static struct chunk_st *allocate_output_chunk(struct memcached_protocol_client_st *client)
-{
- struct chunk_st *ret= cache_alloc(client->root->buffer_cache);
-
- if (ret == NULL)
- {
- return NULL;
- }
-
- ret->offset= ret->nbytes= 0;
- ret->next= NULL;
- ret->size= CHUNK_BUFFERSIZE;
- ret->data= (void*)(ret + 1);
- if (client->output == NULL)
- {
- client->output= client->output_tail= ret;
- }
- else
- {
- client->output_tail->next= ret;
- client->output_tail= ret;
- }
-
- return ret;
-}
-
-/**
- * Spool data into the send-buffer for a client.
- *
- * @param client the client to spool the data for
- * @param data the data to spool
- * @param length the number of bytes of data to spool
- * @return PROTOCOL_BINARY_RESPONSE_SUCCESS if success,
- * PROTOCOL_BINARY_RESPONSE_ENOMEM if we failed to allocate memory
- */
-static protocol_binary_response_status spool_output(struct memcached_protocol_client_st *client,
- const void *data,
- size_t length)
-{
- if (client->mute)
- {
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
- }
-
- size_t offset= 0;
-
- struct chunk_st *chunk= client->output;
- while (offset < length)
- {
- if (chunk == NULL || (chunk->size - chunk->nbytes) == 0)
- {
- if ((chunk= allocate_output_chunk(client)) == NULL)
- {
- return PROTOCOL_BINARY_RESPONSE_ENOMEM;
- }
- }
-
- size_t bulk= length - offset;
- if (bulk > chunk->size - chunk->nbytes)
- {
- bulk= chunk->size - chunk->nbytes;
- }
-
- memcpy(chunk->data + chunk->nbytes, data, bulk);
- chunk->nbytes += bulk;
- offset += bulk;
- }
-
- return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Try to determine the protocol used on this connection.
- * If the first byte contains the magic byte PROTOCOL_BINARY_REQ we should
- * be using the binary protocol on the connection. I implemented the support
- * for the ASCII protocol by wrapping into the simple interface (aka v1),
- * so the implementors needs to provide an implementation of that interface
- *
- */
-static memcached_protocol_event_t determine_protocol(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr)
-{
- if (*client->root->input_buffer == (uint8_t)PROTOCOL_BINARY_REQ)
- {
- client->work= memcached_binary_protocol_process_data;
- }
- else if (client->root->callback->interface_version == 1)
- {
- /*
- * The ASCII protocol can only be used if the implementors provide
- * an implementation for the version 1 of the interface..
- *
- * @todo I should allow the implementors to provide an implementation
- * for version 0 and 1 at the same time and set the preferred
- * interface to use...
- */
- client->work= memcached_ascii_protocol_process_data;
- }
- else
- {
- /* Let's just output a warning the way it is supposed to look like
- * in the ASCII protocol...
- */
- const char *err= "CLIENT_ERROR: Unsupported protocol\r\n";
- client->root->spool(client, err, strlen(err));
- client->root->drain(client);
- return MEMCACHED_PROTOCOL_ERROR_EVENT; /* Unsupported protocol */
- }
-
- return client->work(client, length, endptr);
-}
-
-/*
-** **********************************************************************
-** * PUBLIC INTERFACE
-** * See protocol_handler.h for function description
-** **********************************************************************
-*/
-struct memcached_protocol_st *memcached_protocol_create_instance(void)
-{
- struct memcached_protocol_st *ret= calloc(1, sizeof(*ret));
- if (ret != NULL)
- {
- ret->recv= default_recv;
- ret->send= default_send;
- ret->drain= drain_output;
- ret->spool= spool_output;
- ret->input_buffer_size= 1 * 1024 * 1024;
- ret->input_buffer= malloc(ret->input_buffer_size);
- if (ret->input_buffer == NULL)
- {
- free(ret);
- ret= NULL;
- return NULL;
- }
-
- ret->buffer_cache= cache_create("protocol_handler",
- CHUNK_BUFFERSIZE + sizeof(struct chunk_st),
- 0, NULL, NULL);
- if (ret->buffer_cache == NULL)
- {
- free(ret->input_buffer);
- free(ret);
- }
- }
-
- return ret;
-}
-
-void memcached_protocol_destroy_instance(struct memcached_protocol_st *instance)
-{
- cache_destroy(instance->buffer_cache);
- free(instance->input_buffer);
- free(instance);
-}
-
-struct memcached_protocol_client_st *memcached_protocol_create_client(struct memcached_protocol_st *instance, memcached_socket_t sock)
-{
- struct memcached_protocol_client_st *ret= calloc(1, sizeof(*ret));
- if (ret != NULL)
- {
- ret->root= instance;
- ret->sock= sock;
- ret->work= determine_protocol;
- }
-
- return ret;
-}
-
-void memcached_protocol_client_destroy(struct memcached_protocol_client_st *client)
-{
- free(client);
-}
-
-memcached_protocol_event_t memcached_protocol_client_work(struct memcached_protocol_client_st *client)
-{
- /* Try to send data and read from the socket */
- bool more_data= true;
- do
- {
- ssize_t len= client->root->recv(client,
- client->sock,
- client->root->input_buffer + client->input_buffer_offset,
- client->root->input_buffer_size - client->input_buffer_offset);
-
- if (len > 0)
- {
- /* Do we have the complete packet? */
- if (client->input_buffer_offset > 0)
- {
- memcpy(client->root->input_buffer, client->input_buffer,
- client->input_buffer_offset);
- len += (ssize_t)client->input_buffer_offset;
-
- /* @todo use buffer-cache! */
- free(client->input_buffer);
- client->input_buffer_offset= 0;
- }
-
- void *endptr;
- memcached_protocol_event_t events= client->work(client, &len, &endptr);
- if (events == MEMCACHED_PROTOCOL_ERROR_EVENT)
- {
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
-
- if (len > 0)
- {
- /* save the data for later on */
- /* @todo use buffer-cache */
- client->input_buffer= malloc((size_t)len);
- if (client->input_buffer == NULL)
- {
- client->error= ENOMEM;
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
- memcpy(client->input_buffer, endptr, (size_t)len);
- client->input_buffer_offset= (size_t)len;
- more_data= false;
- }
- }
- else if (len == 0)
- {
- /* Connection closed */
- drain_output(client);
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
- else
- {
- if (get_socket_errno() != EWOULDBLOCK)
- {
- client->error= get_socket_errno();
- /* mark this client as terminated! */
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
- more_data= false;
- }
- } while (more_data);
-
- if (!drain_output(client))
- {
- return MEMCACHED_PROTOCOL_ERROR_EVENT;
- }
-
- memcached_protocol_event_t ret= MEMCACHED_PROTOCOL_READ_EVENT;
- if (client->output)
- ret|= MEMCACHED_PROTOCOL_READ_EVENT;
-
- return ret;
-}
+++ /dev/null
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Definition of the callback interface to the protocol handler
- *
- * Author: Trond Norbye
- *
- */
-
-#pragma once
-
-#include <sys/types.h>
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-
-#include <libmemcached/platform.h>
-#include <libmemcached/memcached/protocol_binary.h>
-#include <libmemcached/visibility.h>
-#include <libmemcached/protocol/callback.h>
-
-/* Forward declarations */
-/*
- * You should only access memcached_protocol_st from one thread!,
- * and never assume anything about the internal layout / sizes of the
- * structures.
- */
-typedef struct memcached_protocol_st memcached_protocol_st;
-typedef struct memcached_protocol_client_st memcached_protocol_client_st;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Function the protocol handler should call to receive data.
- * This function should behave exactly like read(2)
- *
- * @param cookie a cookie used to represent a given client
- * @param fd the filedescriptor associated with the client
- * @param buf destination buffer
- * @param nbuf number of bytes to receive
- * @return the number of bytes copied into buf
- * or -1 upon error (errno should contain more information)
- */
-typedef ssize_t (*memcached_protocol_recv_func)(const void *cookie,
- memcached_socket_t fd,
- void *buf,
- size_t nbuf);
-
-/**
- * Function the protocol handler should call to send data.
- * This function should behave exactly like write(2)
- *
- * @param cookie a cookie used to represent a given client
- * @param fd the filedescriptor associated with the client
- * @param buf the source buffer
- * @param nbuf number of bytes to send
- * @return the number of bytes sent
- * or -1 upon error (errno should contain more information)
- */
-typedef ssize_t (*memcached_protocol_send_func)(const void *cookie,
- memcached_socket_t fd,
- const void *buf,
- size_t nbuf);
-
-/**
- * Create an instance of the protocol handler
- *
- * @return NULL if allocation of an instance fails
- */
-LIBMEMCACHED_API
-memcached_protocol_st *memcached_protocol_create_instance(void);
-
-/**
- * Get the callbacks associated with a protocol handler instance
- * @return the callbacks currently used
- */
-LIBMEMCACHED_API
-memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance);
-
-/**
- * Set the callbacks to be used by the given protocol handler instance
- * @param instance the instance to update
- * @param callback the callbacks to use
- */
-LIBMEMCACHED_API
-void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback);
-
-/**
- * Should the library inspect the packages being sent and received and verify
- * that they are according to the specification? If it encounters an invalid
- * packet, it will return an EINVAL packet.
- *
- * @param instance the instance to update
- * @param enable true if you want the library to check packages, false otherwise
- */
-LIBMEMCACHED_API
-void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable);
-
-/**
- * Is the library inpecting each package?
- * @param instance the instance to check
- * @return true it the library is inspecting each package, false otherwise
- */
-LIBMEMCACHED_API
-bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance);
-
-/**
- * Destroy an instance of the protocol handler
- *
- * @param instance The instance to destroy
- */
-LIBMEMCACHED_API
-void memcached_protocol_destroy_instance(memcached_protocol_st *instance);
-
-/**
- * Set the IO functions used by the instance to send and receive data. The
- * functions should behave like recv(3socket) and send(3socket).
- *
- * @param instance the instance to specify the IO functions for
- * @param recv the function to call for reciving data
- * @param send the function to call for sending data
- */
-LIBMEMCACHED_API
-void memached_protocol_set_io_functions(memcached_protocol_st *instance,
- memcached_protocol_recv_func recv,
- memcached_protocol_send_func send);
-
-
-/**
- * Create a new client instance and associate it with a socket
- * @param instance the protocol instance to bind the client to
- * @param sock the client socket
- * @return NULL if allocation fails, otherwise an instance
- */
-LIBMEMCACHED_API
-memcached_protocol_client_st *memcached_protocol_create_client(memcached_protocol_st *instance, memcached_socket_t sock);
-
-/**
- * Destroy a client handle.
- * The caller needs to close the socket accociated with the client
- * <b>before</b> calling this function. This function invalidates the
- * client memory area.
- *
- * @param client the client to destroy
- */
-LIBMEMCACHED_API
-void memcached_protocol_client_destroy(memcached_protocol_client_st *client);
-
-/**
- * Error event means that the client encountered an error with the
- * connection so you should shut it down
- */
-#define MEMCACHED_PROTOCOL_ERROR_EVENT 1
-/**
- * Please notify when there is more data available to read
- */
-#define MEMCACHED_PROTOCOL_READ_EVENT 2
-/**
- * Please notify when it is possible to send more data
- */
-#define MEMCACHED_PROTOCOL_WRITE_EVENT 4
-/**
- * Backed paused the execution for this client
- */
-#define MEMCACHED_PROTOCOL_PAUSE_EVENT 8
-
-/**
- * The different events the client is interested in. This is a bitmask of
- * the constants defined above.
- */
-typedef uint32_t memcached_protocol_event_t;
-
-/**
- * Let the client do some work. This might involve reading / sending data
- * to/from the client, or perform callbacks to execute a command.
- * @param client the client structure to work on
- * @return The next event the protocol handler will be notified for
- */
-LIBMEMCACHED_API
-memcached_protocol_event_t memcached_protocol_client_work(memcached_protocol_client_st *client);
-
-/**
- * Get the socket attached to a client handle
- * @param client the client to query
- * @return the socket handle
- */
-LIBMEMCACHED_API
-memcached_socket_t memcached_protocol_client_get_socket(memcached_protocol_client_st *client);
-
-/**
- * Get the error id socket attached to a client handle
- * @param client the client to query for an error code
- * @return the OS error code from the client
- */
-LIBMEMCACHED_API
-int memcached_protocol_client_get_errno(memcached_protocol_client_st *client);
-
-/**
- * Get a raw response handler for the given cookie
- * @param cookie the cookie passed along into the callback
- * @return the raw reponse handler you may use if you find
- * the generic callback too limiting
- */
-LIBMEMCACHED_API
-memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_quit(memcached_st *ptr);
-
-LIBMEMCACHED_LOCAL
-void memcached_quit_server(memcached_server_st *ptr, bool io_death);
-
-LIBMEMCACHED_LOCAL
-void send_quit(memcached_st *ptr);
-
-#ifdef __cplusplus
-}
-#endif
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
+ *
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
rc == MEMCACHED_PROTOCOL_ERROR or
rc == MEMCACHED_CLIENT_ERROR or
rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
+ {
memcached_io_reset(ptr);
+ }
return rc;
}
ssize_t read_length= 0;
if (ptr->root->flags.use_udp)
+ {
return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ }
WATCHPOINT_ASSERT(ptr->root);
end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
}
case 'O': /* OK */
return MEMCACHED_SUCCESS;
+
case 'S': /* STORED STATS SERVER_ERROR */
{
if (buffer[2] == 'A') /* STORED STATS */
case 'N': /* NOT_FOUND */
{
if (buffer[4] == 'F')
+ {
return MEMCACHED_NOTFOUND;
+ }
else if (buffer[4] == 'S')
+ {
return MEMCACHED_NOTSTORED;
+ }
else
{
WATCHPOINT_STRING(buffer);
case 'E': /* PROTOCOL ERROR or END */
{
if (buffer[1] == 'N')
+ {
return MEMCACHED_END;
+ }
else if (buffer[1] == 'R')
+ {
return MEMCACHED_PROTOCOL_ERROR;
+ }
else if (buffer[1] == 'X')
+ {
return MEMCACHED_DATA_EXISTS;
+ }
else
{
WATCHPOINT_STRING(buffer);
}
}
+ case 'T': /* TOUCHED */
+ {
+ if (buffer[1] == 'O' and buffer[2] == 'U'
+ and buffer[3] == 'C' and buffer[4] == 'H'
+ and buffer[5] == 'E' and buffer[6] == 'D')
+ {
+ return MEMCACHED_SUCCESS;
+ }
+ }
+ return MEMCACHED_UNKNOWN_READ_FAILURE;
+
case 'I': /* CLIENT ERROR */
/* We add back in one because we will need to search for END */
memcached_server_response_increment(ptr);
return MEMCACHED_ITEM;
+
case 'C': /* CLIENT ERROR */
return MEMCACHED_CLIENT_ERROR;
+
default:
{
unsigned long long auto_return_value;
case PROTOCOL_BINARY_CMD_APPEND:
case PROTOCOL_BINARY_CMD_PREPEND:
case PROTOCOL_BINARY_CMD_DELETE:
+ case PROTOCOL_BINARY_CMD_TOUCH:
{
WATCHPOINT_ASSERT(bodylen == 0);
return MEMCACHED_SUCCESS;
}
+
case PROTOCOL_BINARY_CMD_NOOP:
{
WATCHPOINT_ASSERT(bodylen == 0);
return MEMCACHED_END;
}
+
case PROTOCOL_BINARY_CMD_STAT:
{
if (bodylen == 0)
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_result_st {
- uint32_t item_flags;
- time_t item_expiration;
- size_t key_length;
- uint64_t item_cas;
- memcached_st *root;
- memcached_string_st value;
- uint64_t count;
- char item_key[MEMCACHED_MAX_KEY];
- struct {
- bool is_allocated:1;
- bool is_initialized:1;
- } options;
- /* Add result callback function */
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Result Struct */
-LIBMEMCACHED_API
-void memcached_result_free(memcached_result_st *result);
-
-LIBMEMCACHED_API
-void memcached_result_reset(memcached_result_st *ptr);
-
-LIBMEMCACHED_API
-memcached_result_st *memcached_result_create(const memcached_st *ptr,
- memcached_result_st *result);
-
-LIBMEMCACHED_API
-const char *memcached_result_key_value(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-size_t memcached_result_key_length(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-const char *memcached_result_value(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-size_t memcached_result_length(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-uint32_t memcached_result_flags(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-uint64_t memcached_result_cas(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
-
-LIBMEMCACHED_API
-void memcached_result_set_flags(memcached_result_st *self, uint32_t flags);
-
-LIBMEMCACHED_API
-void memcached_result_set_expiration(memcached_result_st *self, time_t expiration);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-enum memcached_return_t {
- MEMCACHED_SUCCESS,
- MEMCACHED_FAILURE,
- MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() and getnameinfo() only
- MEMCACHED_CONNECTION_FAILURE,
- MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
- MEMCACHED_WRITE_FAILURE,
- MEMCACHED_READ_FAILURE,
- MEMCACHED_UNKNOWN_READ_FAILURE,
- MEMCACHED_PROTOCOL_ERROR,
- MEMCACHED_CLIENT_ERROR,
- MEMCACHED_SERVER_ERROR,
- MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE, // DEPRECATED
- MEMCACHED_DATA_EXISTS,
- MEMCACHED_DATA_DOES_NOT_EXIST,
- MEMCACHED_NOTSTORED,
- MEMCACHED_STORED,
- MEMCACHED_NOTFOUND,
- MEMCACHED_MEMORY_ALLOCATION_FAILURE,
- MEMCACHED_PARTIAL_READ,
- MEMCACHED_SOME_ERRORS,
- MEMCACHED_NO_SERVERS,
- MEMCACHED_END,
- MEMCACHED_DELETED,
- MEMCACHED_VALUE,
- MEMCACHED_STAT,
- MEMCACHED_ITEM,
- MEMCACHED_ERRNO,
- MEMCACHED_FAIL_UNIX_SOCKET, // DEPRECATED
- MEMCACHED_NOT_SUPPORTED,
- MEMCACHED_NO_KEY_PROVIDED, /* Deprecated. Use MEMCACHED_BAD_KEY_PROVIDED! */
- MEMCACHED_FETCH_NOTFINISHED,
- MEMCACHED_TIMEOUT,
- MEMCACHED_BUFFERED,
- MEMCACHED_BAD_KEY_PROVIDED,
- MEMCACHED_INVALID_HOST_PROTOCOL,
- MEMCACHED_SERVER_MARKED_DEAD,
- MEMCACHED_UNKNOWN_STAT_KEY,
- MEMCACHED_E2BIG,
- MEMCACHED_INVALID_ARGUMENTS,
- MEMCACHED_KEY_TOO_BIG,
- MEMCACHED_AUTH_PROBLEM,
- MEMCACHED_AUTH_FAILURE,
- MEMCACHED_AUTH_CONTINUE,
- MEMCACHED_PARSE_ERROR,
- MEMCACHED_PARSE_USER_ERROR,
- MEMCACHED_DEPRECATED,
- MEMCACHED_IN_PROGRESS,
- MEMCACHED_SERVER_TEMPORARILY_DISABLED,
- MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
-};
-
-#ifndef __cplusplus
-typedef enum memcached_return_t memcached_return_t;
-#endif
-
-static inline bool memcached_success(memcached_return_t rc)
-{
- return (rc == MEMCACHED_BUFFERED ||
- rc == MEMCACHED_DELETED ||
- rc == MEMCACHED_END ||
- rc == MEMCACHED_ITEM ||
- rc == MEMCACHED_STAT ||
- rc == MEMCACHED_STORED ||
- rc == MEMCACHED_SUCCESS ||
- rc == MEMCACHED_VALUE);
-}
-
-static inline bool memcached_failed(memcached_return_t rc)
-{
- return (rc != MEMCACHED_SUCCESS &&
- rc != MEMCACHED_END &&
- rc != MEMCACHED_STORED &&
- rc != MEMCACHED_STAT &&
- rc != MEMCACHED_DELETED &&
- rc != MEMCACHED_BUFFERED &&
- rc != MEMCACHED_VALUE);
-}
-
-static inline bool memcached_fatal(memcached_return_t rc)
-{
- return (rc != MEMCACHED_SUCCESS &&
- rc != MEMCACHED_END &&
- rc != MEMCACHED_STORED &&
- rc != MEMCACHED_STAT &&
- rc != MEMCACHED_DELETED &&
- rc != MEMCACHED_BUFFERED &&
- rc != MEMCACHED_VALUE);
-}
-
-#define memcached_continue(__memcached_return_t) ((__memcached_return_t) == MEMCACHED_IN_PROGRESS)
struct libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes },
- { keylen, chosenmech },
- { len, data }
+ { request.bytes, sizeof(request.bytes) },
+ { chosenmech, keylen },
+ { data, len }
};
if (memcached_io_writev(server, vector, 3, true) == -1)
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
-#include <sasl/sasl.h>
-#else
-#define sasl_callback_t void
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_set_sasl_callbacks(memcached_st *ptr,
- const sasl_callback_t *callbacks);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_sasl_auth_data(memcached_st *ptr,
- const char *username,
- const char *password);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr);
-
-
-LIBMEMCACHED_API
-sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr);
-
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source);
-
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *server);
-
-#ifdef __cplusplus
-}
-#endif
-
-struct memcached_sasl_st {
- sasl_callback_t *callbacks;
- /*
- ** Did we allocate data inside the callbacks, or did the user
- ** supply that.
- */
- bool is_allocated;
-};
self= _server_create(self, memc);
- if (not self)
+ if (self == NULL)
{
return NULL;
}
void memcached_server_free(memcached_server_st *self)
{
- if (not self)
+ if (self == NULL)
+ {
return;
+ }
if (memcached_server_list_count(self))
{
memcached_server_st *source)
{
/* We just do a normal create if source is missing */
- if (not source)
+ if (source == NULL)
{
return NULL;
}
return MEMCACHED_SUCCESS;
}
-memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr,
+memcached_server_instance_st memcached_server_by_key(memcached_st *ptr,
const char *key,
size_t key_length,
memcached_return_t *error)
{
- memcached_return_t rc;
memcached_return_t unused;
-
if (not error)
+ {
error= &unused;
+ }
+
+ memcached_return_t rc;
if (memcached_failed(rc= initialize_const_query(ptr)))
{
*error= rc;
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifndef WIN32
-#include <netdb.h>
-#endif
-
-#ifdef NI_MAXHOST
-#define MEMCACHED_NI_MAXHOST NI_MAXHOST
-#else
-#define MEMCACHED_NI_MAXHOST 1025
-#endif
-
-enum memcached_server_state_t {
- MEMCACHED_SERVER_STATE_NEW, // fd == -1, no address lookup has been done
- MEMCACHED_SERVER_STATE_ADDRINFO, // ADDRRESS information has been gathered
- MEMCACHED_SERVER_STATE_IN_PROGRESS,
- MEMCACHED_SERVER_STATE_CONNECTED,
- MEMCACHED_SERVER_STATE_IN_TIMEOUT
-};
-
-struct memcached_server_st {
- struct {
- bool is_allocated:1;
- bool is_initialized:1;
- bool is_shutting_down:1;
- bool is_dead:1;
- } options;
- uint32_t number_of_hosts;
- uint32_t cursor_active;
- in_port_t port;
- memcached_socket_t fd;
- uint32_t io_bytes_sent; /* # bytes sent since last read */
- uint32_t server_failure_counter;
- uint64_t server_failure_counter_query_id;
- uint32_t weight;
- uint32_t version;
- enum memcached_server_state_t state;
- struct {
- uint32_t read;
- uint32_t write;
- } io_wait_count;
- uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
- uint8_t micro_version; // ditto
- uint8_t minor_version; // ditto
- memcached_connection_t type;
- char *read_ptr;
- size_t read_buffer_length;
- size_t read_data_length;
- size_t write_buffer_offset;
- struct addrinfo *address_info;
- struct addrinfo *address_info_next;
- time_t next_retry;
- memcached_st *root;
- uint64_t limit_maxbytes;
- struct memcached_error_t *error_messages;
- char read_buffer[MEMCACHED_MAX_BUFFER];
- char write_buffer[MEMCACHED_MAX_BUFFER];
- char hostname[MEMCACHED_NI_MAXHOST];
-};
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_cursor(const memcached_st *ptr,
- const memcached_server_fn *callback,
- void *context,
- uint32_t number_of_callbacks);
-
-LIBMEMCACHED_API
- memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr,
- const char *key,
- size_t key_length,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-void memcached_server_error_reset(memcached_server_st *ptr);
-
-LIBMEMCACHED_API
-void memcached_server_free(memcached_server_st *ptr);
-
-LIBMEMCACHED_LOCAL
-memcached_server_st *memcached_server_clone(memcached_server_st *destination,
- memcached_server_st *source);
-
-LIBMEMCACHED_API
-memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *ptr);
-
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_udp(memcached_st *ptr,
- const char *hostname,
- in_port_t port);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
- const char *filename);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add(memcached_st *ptr,
- const char *hostname, in_port_t port);
-
-LIBMEMCACHED_LOCAL
- memcached_return_t memcached_server_add_parsed(memcached_st *ptr,
- const char *hostname,
- size_t hostname_length,
- in_port_t port,
- uint32_t weight);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_udp_with_weight(memcached_st *ptr,
- const char *hostname,
- in_port_t port,
- uint32_t weight);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
- const char *filename,
- uint32_t weight);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_with_weight(memcached_st *ptr, const char *hostname,
- in_port_t port,
- uint32_t weight);
-
-/**
- Operations on Single Servers.
-*/
-LIBMEMCACHED_API
-uint32_t memcached_server_response_count(const memcached_server_instance_st self);
-
-LIBMEMCACHED_API
-const char *memcached_server_name(const memcached_server_instance_st self);
-
-LIBMEMCACHED_API
-in_port_t memcached_server_port(const memcached_server_instance_st self);
-
-LIBMEMCACHED_API
-const char *memcached_server_type(const memcached_server_instance_st ptr);
-
-
-LIBMEMCACHED_LOCAL
-void __server_free(memcached_server_st *);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
#pragma once
-#include <libmemcached/basic_string.h>
-
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Server List Public functions */
-LIBMEMCACHED_API
- void memcached_server_list_free(memcached_server_list_st ptr);
-
-LIBMEMCACHED_API
- memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list);
-
-LIBMEMCACHED_API
- memcached_server_list_st memcached_server_list_append(memcached_server_list_st ptr,
- const char *hostname,
- in_port_t port,
- memcached_return_t *error);
-LIBMEMCACHED_API
- memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr,
- const char *hostname,
- in_port_t port,
- uint32_t weight,
- memcached_return_t *error);
-LIBMEMCACHED_API
- uint32_t memcached_server_list_count(const memcached_server_list_st ptr);
-
-LIBMEMCACHED_LOCAL
- uint32_t memcached_servers_set_count(memcached_server_list_st servers, uint32_t count);
-
-LIBMEMCACHED_LOCAL
- memcached_server_st *memcached_server_list(const memcached_st *);
-
-LIBMEMCACHED_LOCAL
- void memcached_server_list_set(memcached_st *self, memcached_server_list_st list);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
size_t len= strlen(args);
memcached_return_t rc= memcached_validate_key_length(len, true);
- unlikely (rc != MEMCACHED_SUCCESS)
+ if (rc != MEMCACHED_SUCCESS)
+ {
return rc;
+ }
request.message.header.request.keylen= htons((uint16_t)len);
request.message.header.request.bodylen= htonl((uint32_t) len);
struct libmemcached_io_vector_st vector[]=
{
- { sizeof(request.bytes), request.bytes },
- { len, args }
+ { request.bytes, sizeof(request.bytes) },
+ { args, len }
};
if (memcached_vdo(instance, vector, 2, true) != MEMCACHED_SUCCESS)
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_stat_st {
- unsigned long connection_structures;
- unsigned long curr_connections;
- unsigned long curr_items;
- pid_t pid;
- unsigned long pointer_size;
- unsigned long rusage_system_microseconds;
- unsigned long rusage_system_seconds;
- unsigned long rusage_user_microseconds;
- unsigned long rusage_user_seconds;
- unsigned long threads;
- unsigned long time;
- unsigned long total_connections;
- unsigned long total_items;
- unsigned long uptime;
- unsigned long long bytes;
- unsigned long long bytes_read;
- unsigned long long bytes_written;
- unsigned long long cmd_get;
- unsigned long long cmd_set;
- unsigned long long evictions;
- unsigned long long get_hits;
- unsigned long long get_misses;
- unsigned long long limit_maxbytes;
- char version[MEMCACHED_VERSION_STRING_LENGTH];
- void *__future; // @todo create a new structure to place here for future usage
- memcached_st *root;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_stat_free(const memcached_st *, memcached_stat_st *);
-
-LIBMEMCACHED_API
-memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
- const char *hostname, in_port_t port);
-
-LIBMEMCACHED_API
-char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat,
- const char *key, memcached_return_t *error);
-
-LIBMEMCACHED_API
-char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat,
- memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args, memcached_stat_fn func, void *context);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
struct libmemcached_io_vector_st vector[]=
{
- { send_length, request.bytes },
- { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
- { key_length, key },
- { value_length, value }
+ { request.bytes, send_length },
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { key, key_length },
+ { value, value_length }
};
/* write the header */
{
struct libmemcached_io_vector_st vector[]=
{
- { write_length, buffer },
- { value_length, value },
- { 2, "\r\n" }
+ { buffer, write_length },
+ { value, value_length },
+ { memcached_literal_param("\r\n") }
};
if (ptr->flags.buffer_requests && verb == SET_OP)
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "libmemcached/memcached.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* All of the functions for adding data to the server */
-LIBMEMCACHED_API
-memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_append(memcached_st *ptr,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_prepend(memcached_st *ptr,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_cas(memcached_st *ptr,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags,
- uint64_t cas);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_add_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_replace_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_append_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_cas_by_key(memcached_st *ptr,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- time_t expiration,
- uint32_t flags,
- uint64_t cas);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-const char *memcached_strerror(memcached_st *ptr, memcached_return_t rc);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libmemcached/basic_string.h>
-
-/**
- Strings are always under our control so we make some assumptions
- about them.
-
- 1) is_initialized is always valid.
- 2) A string once intialized will always be, until free where we
- unset this flag.
- 3) A string always has a root.
-*/
-
-struct memcached_string_st {
- char *end;
- char *string;
- size_t current_size;
- memcached_st *root;
- struct {
- bool is_allocated:1;
- bool is_initialized:1;
- } options;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_LOCAL
-memcached_string_st *memcached_string_create(memcached_st *ptr,
- memcached_string_st *string,
- size_t initial_size);
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_string_check(memcached_string_st *string, size_t need);
-
-LIBMEMCACHED_LOCAL
-char *memcached_string_c_copy(memcached_string_st *string);
-
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_string_append_character(memcached_string_st *string,
- char character);
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_string_append(memcached_string_st *string,
- const char *value, size_t length);
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_string_reset(memcached_string_st *string);
-
-LIBMEMCACHED_LOCAL
-void memcached_string_free(memcached_string_st *string);
-
-LIBMEMCACHED_LOCAL
-size_t memcached_string_length(const memcached_string_st *self);
-
-LIBMEMCACHED_LOCAL
-size_t memcached_string_size(const memcached_string_st *self);
-
-LIBMEMCACHED_LOCAL
-const char *memcached_string_value(const memcached_string_st *self);
-
-LIBMEMCACHED_LOCAL
-char *memcached_string_take_value(memcached_string_st *self);
-
-LIBMEMCACHED_LOCAL
-char *memcached_string_value_mutable(const memcached_string_st *self);
-
-LIBMEMCACHED_LOCAL
-void memcached_string_set_length(memcached_string_st *self, size_t length);
-
-#ifdef __cplusplus
-}
-#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/memcached/protocol_binary.h>
+
+static memcached_return_t ascii_touch(memcached_server_write_instance_st instance,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ char buffer[21];
+
+ int buffer_length= snprintf(buffer, sizeof(buffer), " %u", uint32_t(expiration));
+ struct libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("touch ") },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length },
+ { buffer, buffer_length },
+ { memcached_literal_param("\r\n") }
+ };
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 5, true)))
+ {
+ memcached_io_reset(instance);
+ return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ }
+
+ return rc;
+}
+
+static memcached_return_t binary_touch(memcached_server_write_instance_st instance,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ protocol_binary_request_touch request= {}; //{.bytes= {0}};
+ request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_TOUCH;
+ request.message.header.request.extlen= 4;
+ request.message.header.request.keylen= htons((uint16_t)(key_length +memcached_array_size(instance->root->_namespace)));
+ request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+ request.message.header.request.bodylen= htonl((uint32_t)(key_length +memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
+ request.message.body.expiration= htonl((uint32_t) expiration);
+
+ struct libmemcached_io_vector_st vector[]=
+ {
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length }
+ };
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
+ {
+ memcached_io_reset(instance);
+ return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ }
+
+ return rc;
+}
+
+memcached_return_t memcached_touch(memcached_st *ptr,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ return memcached_touch_by_key(ptr, key, key_length, key, key_length, expiration);
+}
+
+memcached_return_t memcached_touch_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ LIBMEMCACHED_MEMCACHED_TOUCH_START();
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr)))
+ {
+ return rc;
+ }
+
+ if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ {
+ return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ }
+
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ if (ptr->flags.binary_protocol)
+ {
+ rc= binary_touch(instance, key, key_length, expiration);
+ }
+ else
+ {
+ rc= ascii_touch(instance, key, key_length, expiration);
+ }
+
+ if (memcached_failed(rc))
+ {
+ return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while writing touch command to server"));
+ }
+
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ rc= memcached_read_one_response(instance, buffer, sizeof(buffer), NULL);
+
+ if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_NOTFOUND)
+ {
+ return rc;
+ }
+
+ return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while reading response"));
+}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-typedef struct memcached_st memcached_st;
-typedef struct memcached_stat_st memcached_stat_st;
-typedef struct memcached_analysis_st memcached_analysis_st;
-typedef struct memcached_result_st memcached_result_st;
-typedef struct memcached_array_st memcached_array_st;
-typedef struct memcached_error_t memcached_error_t;
-
-// All of the flavors of memcache_server_st
-typedef struct memcached_server_st memcached_server_st;
-typedef const struct memcached_server_st *memcached_server_instance_st;
-typedef struct memcached_server_st *memcached_server_list_st;
-
-typedef struct memcached_callback_st memcached_callback_st;
-
-// The following two structures are internal, and never exposed to users.
-typedef struct memcached_string_st memcached_string_st;
-typedef struct memcached_string_t memcached_string_t;
-typedef struct memcached_continuum_item_st memcached_continuum_item_st;
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef memcached_return_t (*memcached_clone_fn)(memcached_st *destination, const memcached_st *source);
-typedef memcached_return_t (*memcached_cleanup_fn)(const memcached_st *ptr);
-
-/**
- Memory allocation functions.
-*/
-typedef void (*memcached_free_fn)(const memcached_st *ptr, void *mem, void *context);
-typedef void *(*memcached_malloc_fn)(const memcached_st *ptr, const size_t size, void *context);
-typedef void *(*memcached_realloc_fn)(const memcached_st *ptr, void *mem, const size_t size, void *context);
-typedef void *(*memcached_calloc_fn)(const memcached_st *ptr, size_t nelem, const size_t elsize, void *context);
-
-
-typedef memcached_return_t (*memcached_execute_fn)(const memcached_st *ptr, memcached_result_st *result, void *context);
-typedef memcached_return_t (*memcached_server_fn)(const memcached_st *ptr, memcached_server_instance_st server, void *context);
-typedef memcached_return_t (*memcached_stat_fn)(memcached_server_instance_st server,
- const char *key, size_t key_length,
- const char *value, size_t value_length,
- void *context);
-
-/**
- Trigger functions.
-*/
-typedef memcached_return_t (*memcached_trigger_key_fn)(const memcached_st *ptr,
- const char *key, size_t key_length,
- memcached_result_st *result);
-typedef memcached_return_t (*memcached_trigger_delete_key_fn)(const memcached_st *ptr,
- const char *key, size_t key_length);
-
-typedef memcached_return_t (*memcached_dump_fn)(const memcached_st *ptr,
- const char *key,
- size_t key_length,
- void *context);
-
-#ifdef __cplusplus
-}
-#endif
-
-/**
- @note The following definitions are just here for backwards compatibility.
-*/
-typedef memcached_return_t memcached_return;
-typedef memcached_server_distribution_t memcached_server_distribution;
-typedef memcached_behavior_t memcached_behavior;
-typedef memcached_callback_t memcached_callback;
-typedef memcached_hash_t memcached_hash;
-typedef memcached_connection_t memcached_connection;
-typedef memcached_clone_fn memcached_clone_func;
-typedef memcached_cleanup_fn memcached_cleanup_func;
-typedef memcached_execute_fn memcached_execute_function;
-typedef memcached_server_fn memcached_server_function;
-typedef memcached_trigger_key_fn memcached_trigger_key;
-typedef memcached_trigger_delete_key_fn memcached_trigger_delete_key;
-typedef memcached_dump_fn memcached_dump_func;
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
#pragma once
-#include <libmemcached/memcached_util.h>
+#include <libmemcachedutil-1.0/util.h>
+
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and then flushes it (memcached_flush(3)).
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/memcached_util.h>
-
-
-bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
- memcached_st *memc_ptr= memcached_create(NULL);
-
- memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
- if (memcached_success(rc))
- {
- rc= memcached_flush(memc_ptr, 0);
- }
-
- memcached_free(memc_ptr);
-
- if (ret)
- {
- *ret= rc;
- }
-
- return memcached_success(rc);
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret);
-
-#ifdef __cplusplus
-}
-#endif
-
+++ /dev/null
-# vim:ft=automake
-# included from Top Level Makefile.am
-# All paths should be given relative to the root
-
-nobase_include_HEADERS+= \
- libmemcached/memcached_util.h \
- libmemcached/util.h \
- libmemcached/util/flush.h \
- libmemcached/util/pid.h \
- libmemcached/util/ping.h \
- libmemcached/util/pool.h \
- libmemcached/util/version.h
-lib_LTLIBRARIES+= libmemcached/libmemcachedutil.la
-
-libmemcached_libmemcachedutil_la_SOURCES= \
- libmemcached/backtrace.cc \
- libmemcached/util/flush.cc \
- libmemcached/util/pid.cc \
- libmemcached/util/ping.cc \
- libmemcached/util/pool.cc \
- libmemcached/util/version.cc
-libmemcached_libmemcachedutil_la_CXXFLAGS= \
- ${AM_CXXFLAGS} \
- ${NO_CONVERSION} \
- -DBUILDING_LIBMEMCACHED
-libmemcached_libmemcachedutil_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
-libmemcached_libmemcachedutil_la_LIBADD= libmemcached/libmemcached.la
-libmemcached_libmemcachedutil_la_LIBADD+= ${PTHREAD_LIBS}
-libmemcached_libmemcachedutil_la_LDFLAGS= ${AM_LDFLAGS} -version-info ${MEMCACHED_UTIL_LIBRARY_VERSION}
-libmemcached_libmemcachedutil_la_DEPENDENCIES= libmemcached/libmemcached.la
-
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and determines what its pid is
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/memcached_util.h>
-
-
-// Never look at the stat object directly.
-
-
-pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
- pid_t pid= -1;
-
- memcached_return_t unused;
- if (not ret)
- ret= &unused;
-
- memcached_st *memc_ptr= memcached_create(NULL);
- if (not memc_ptr)
- {
- *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
- return -1;
- }
-
- memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
- if (memcached_success(rc))
- {
- memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
- if (memcached_success(rc) and stat and stat->pid != -1)
- {
- pid= stat->pid;
- }
- else if (memcached_success(rc))
- {
- rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
- }
- else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
- {
- memcached_server_instance_st instance=
- memcached_server_instance_by_position(memc_ptr, 0);
-
- assert_msg(instance and instance->error_messages, " ");
- if (instance and instance->error_messages)
- {
- rc= memcached_server_error_return(instance);
- }
- }
-
- memcached_stat_free(memc_ptr, stat);
- }
- memcached_free(memc_ptr);
-
- *ret= rc;
-
- return pid;
-}
-
-pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret)
-{
- if (username == NULL)
- {
- return libmemcached_util_getpid(hostname, port, ret);
- }
-
- pid_t pid= -1;
-
- memcached_return_t unused;
- if (not ret)
- ret= &unused;
-
- if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
- {
- *ret= MEMCACHED_NOT_SUPPORTED;
- return pid;
- }
-
- memcached_st *memc_ptr= memcached_create(NULL);
- if (not memc_ptr)
- {
- *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
- return -1;
- }
-
- if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
- {
- memcached_free(memc_ptr);
- return false;
- }
-
-
- memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
- if (memcached_success(rc))
- {
- memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
- if (memcached_success(rc) and stat and stat->pid != -1)
- {
- pid= stat->pid;
- }
- else if (memcached_success(rc))
- {
- rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
- }
- else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
- {
- memcached_server_instance_st instance=
- memcached_server_instance_by_position(memc_ptr, 0);
-
-#if 0
- assert_msg(instance and instance->error_messages, " ");
-#endif
- if (instance and instance->error_messages)
- {
- rc= memcached_server_error_return(instance);
- }
- }
-
- memcached_stat_free(memc_ptr, stat);
- }
- memcached_free(memc_ptr);
-
- *ret= rc;
-
- return pid;
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
-
-LIBMEMCACHED_API
-pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret);
-
-#ifdef __cplusplus
-}
-#endif
-
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and makes sure it is alive.
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/memcached_util.h>
-
-bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
- memcached_return_t unused;
- if (not ret)
- ret= &unused;
-
- memcached_st *memc_ptr= memcached_create(NULL);
- if (not memc_ptr)
- {
- *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
- return false;
- }
-
- memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
- if (memcached_success(rc))
- {
- rc= memcached_version(memc_ptr);
- }
-
- if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
- {
- memcached_server_instance_st instance=
- memcached_server_instance_by_position(memc_ptr, 0);
-
- assert_msg(instance and instance->error_messages, " ");
- if (instance and instance->error_messages)
- {
- rc= memcached_server_error_return(instance);
- }
- }
- memcached_free(memc_ptr);
-
- *ret= rc;
-
- return memcached_success(rc);
-}
-
-bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret)
-{
- if (username == NULL)
- {
- return libmemcached_util_ping(hostname, port, ret);
- }
-
- memcached_return_t unused;
- if (not ret)
- ret= &unused;
-
- if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
- {
- *ret= MEMCACHED_NOT_SUPPORTED;
- return false;
- }
-
- memcached_st *memc_ptr= memcached_create(NULL);
- if (not memc_ptr)
- {
- *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
- return false;
- }
-
- if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
- {
- memcached_free(memc_ptr);
- return false;
- }
-
- memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
- if (memcached_success(rc))
- {
- rc= memcached_version(memc_ptr);
- }
-
- if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
- {
- memcached_server_instance_st instance=
- memcached_server_instance_by_position(memc_ptr, 0);
-
- assert_msg(instance and instance->error_messages, " ");
- if (instance and instance->error_messages)
- {
- rc= memcached_server_error_return(instance);
- }
- }
- memcached_free(memc_ptr);
-
- *ret= rc;
-
- return memcached_success(rc);
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret);
-
-LIBMEMCACHED_API
-bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret);
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-#include <libmemcached/memcached_util.h>
-
-#include <libmemcached/error.hpp>
-
-#include <cassert>
-#include <cerrno>
-#include <pthread.h>
-#include <memory>
-
-struct memcached_pool_st
-{
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- memcached_st *master;
- memcached_st **server_pool;
- int firstfree;
- const uint32_t size;
- uint32_t current_size;
- bool _owns_master;
- struct timespec _timeout;
-
- memcached_pool_st(memcached_st *master_arg, size_t max_arg) :
- master(master_arg),
- server_pool(NULL),
- firstfree(-1),
- size(max_arg),
- current_size(0),
- _owns_master(false)
- {
- pthread_mutex_init(&mutex, NULL);
- pthread_cond_init(&cond, NULL);
- _timeout.tv_sec= 5;
- _timeout.tv_nsec= 0;
- }
-
- const struct timespec& timeout() const
- {
- return _timeout;
- }
-
- bool release(memcached_st*, memcached_return_t& rc);
-
- memcached_st *fetch(memcached_return_t& rc);
- memcached_st *fetch(const struct timespec&, memcached_return_t& rc);
-
- bool init(uint32_t initial);
-
- ~memcached_pool_st()
- {
- for (int x= 0; x <= firstfree; ++x)
- {
- memcached_free(server_pool[x]);
- server_pool[x] = NULL;
- }
-
- pthread_mutex_destroy(&mutex);
- pthread_cond_destroy(&cond);
- delete [] server_pool;
- if (_owns_master)
- {
- memcached_free(master);
- }
- }
-
- void increment_version()
- {
- ++master->configure.version;
- }
-
- bool compare_version(const memcached_st *arg) const
- {
- return (arg->configure.version == version());
- }
-
- int32_t version() const
- {
- return master->configure.version;
- }
-};
-
-
-/**
- * Grow the connection pool by creating a connection structure and clone the
- * original memcached handle.
- */
-static bool grow_pool(memcached_pool_st* pool)
-{
- assert(pool);
-
- memcached_st *obj;
- if (not (obj= memcached_clone(NULL, pool->master)))
- {
- return false;
- }
-
- pool->server_pool[++pool->firstfree]= obj;
- pool->current_size++;
- obj->configure.version= pool->version();
-
- return true;
-}
-
-bool memcached_pool_st::init(uint32_t initial)
-{
- server_pool= new (std::nothrow) memcached_st *[size];
- if (not server_pool)
- return false;
-
- /*
- Try to create the initial size of the pool. An allocation failure at
- this time is not fatal..
- */
- for (unsigned int x= 0; x < initial; ++x)
- {
- if (grow_pool(this) == false)
- {
- break;
- }
- }
-
- return true;
-}
-
-
-static inline memcached_pool_st *_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
-{
- if (initial == 0 or max == 0 or (initial > max))
- {
- return NULL;
- }
-
- memcached_pool_st *object= new (std::nothrow) memcached_pool_st(master, max);
- if (object == NULL)
- {
- return NULL;
- }
-
- /*
- Try to create the initial size of the pool. An allocation failure at
- this time is not fatal..
- */
- if (not object->init(initial))
- {
- delete object;
- return NULL;
- }
-
- return object;
-}
-
-memcached_pool_st *memcached_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
-{
- return _pool_create(master, initial, max);
-}
-
-memcached_pool_st * memcached_pool(const char *option_string, size_t option_string_length)
-{
- memcached_st *memc= memcached(option_string, option_string_length);
-
- if (memc == NULL)
- {
- return NULL;
- }
-
- memcached_pool_st *self= memcached_pool_create(memc, memc->configure.initial_pool_size, memc->configure.max_pool_size);
- if (self == NULL)
- {
- memcached_free(memc);
- return NULL;
- }
-
- self->_owns_master= true;
-
- return self;
-}
-
-memcached_st* memcached_pool_destroy(memcached_pool_st* pool)
-{
- if (pool == NULL)
- {
- return NULL;
- }
-
- // Legacy that we return the original structure
- memcached_st *ret= NULL;
- if (pool->_owns_master)
- { }
- else
- {
- ret= pool->master;
- }
-
- delete pool;
-
- return ret;
-}
-
-memcached_st* memcached_pool_st::fetch(memcached_return_t& rc)
-{
- static struct timespec relative_time= { 0, 0 };
- return fetch(relative_time, rc);
-}
-
-memcached_st* memcached_pool_st::fetch(const struct timespec& relative_time, memcached_return_t& rc)
-{
- rc= MEMCACHED_SUCCESS;
-
- if (pthread_mutex_lock(&mutex))
- {
- rc= MEMCACHED_IN_PROGRESS;
- return NULL;
- }
-
- memcached_st *ret= NULL;
- do
- {
- if (firstfree > -1)
- {
- ret= server_pool[firstfree--];
- }
- else if (current_size == size)
- {
- if (relative_time.tv_sec == 0 and relative_time.tv_nsec == 0)
- {
- pthread_mutex_unlock(&mutex);
- rc= MEMCACHED_NOTFOUND;
-
- return NULL;
- }
-
- struct timespec time_to_wait= {0, 0};
- time_to_wait.tv_sec= time(NULL) +relative_time.tv_sec;
- time_to_wait.tv_nsec= relative_time.tv_nsec;
-
- int thread_ret;
- if ((thread_ret= pthread_cond_timedwait(&cond, &mutex, &time_to_wait)) != 0)
- {
- pthread_mutex_unlock(&mutex);
-
- if (thread_ret == ETIMEDOUT)
- {
- rc= MEMCACHED_TIMEOUT;
- }
- else
- {
- errno= thread_ret;
- rc= MEMCACHED_ERRNO;
- }
-
- return NULL;
- }
- }
- else if (grow_pool(this) == false)
- {
- (void)pthread_mutex_unlock(&mutex);
- return NULL;
- }
- } while (ret == NULL);
-
- pthread_mutex_unlock(&mutex);
-
- return ret;
-}
-
-bool memcached_pool_st::release(memcached_st *released, memcached_return_t& rc)
-{
- rc= MEMCACHED_SUCCESS;
- if (released == NULL)
- {
- rc= MEMCACHED_INVALID_ARGUMENTS;
- return false;
- }
-
- if (pthread_mutex_lock(&mutex))
- {
- rc= MEMCACHED_IN_PROGRESS;
- return false;
- }
-
- /*
- Someone updated the behavior on the object, so we clone a new memcached_st with the new settings. If we fail to clone, we keep the old one around.
- */
- if (compare_version(released) == false)
- {
- memcached_st *memc;
- if ((memc= memcached_clone(NULL, master)))
- {
- memcached_free(released);
- released= memc;
- }
- }
-
- server_pool[++firstfree]= released;
-
- if (firstfree == 0 and current_size == size)
- {
- /* we might have people waiting for a connection.. wake them up :-) */
- pthread_cond_broadcast(&cond);
- }
-
- (void)pthread_mutex_unlock(&mutex);
-
- return true;
-}
-
-memcached_st* memcached_pool_fetch(memcached_pool_st* pool, struct timespec* relative_time, memcached_return_t* rc)
-{
- if (pool == NULL)
- {
- return NULL;
- }
-
- memcached_return_t unused;
- if (rc == NULL)
- {
- rc= &unused;
- }
-
- if (relative_time == NULL)
- {
- return pool->fetch(*rc);
- }
-
- return pool->fetch(*relative_time, *rc);
-}
-
-memcached_st* memcached_pool_pop(memcached_pool_st* pool,
- bool block,
- memcached_return_t *rc)
-{
- if (pool == NULL)
- {
- return NULL;
- }
-
- memcached_return_t unused;
- if (rc == NULL)
- {
- rc= &unused;
- }
-
- memcached_st *memc;
- if (block)
- {
- memc= pool->fetch(pool->timeout(), *rc);
- }
- else
- {
- memc= pool->fetch(*rc);
- }
-
- return memc;
-}
-
-memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st *released)
-{
- if (pool == NULL)
- {
- return MEMCACHED_INVALID_ARGUMENTS;
- }
-
- memcached_return_t rc;
-
- (void) pool->release(released, rc);
-
- return rc;
-}
-
-memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *released)
-{
- return memcached_pool_release(pool, released);
-}
-
-
-memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
- memcached_behavior_t flag,
- uint64_t data)
-{
- if (pool == NULL)
- {
- return MEMCACHED_INVALID_ARGUMENTS;
- }
-
- if (pthread_mutex_lock(&pool->mutex))
- {
- return MEMCACHED_IN_PROGRESS;
- }
-
- /* update the master */
- memcached_return_t rc= memcached_behavior_set(pool->master, flag, data);
- if (memcached_failed(rc))
- {
- (void)pthread_mutex_unlock(&pool->mutex);
- return rc;
- }
-
- pool->increment_version();
- /* update the clones */
- for (int xx= 0; xx <= pool->firstfree; ++xx)
- {
- if (memcached_success(memcached_behavior_set(pool->server_pool[xx], flag, data)))
- {
- pool->server_pool[xx]->configure.version= pool->version();
- }
- else
- {
- memcached_st *memc;
- if ((memc= memcached_clone(NULL, pool->master)))
- {
- memcached_free(pool->server_pool[xx]);
- pool->server_pool[xx]= memc;
- /* I'm not sure what to do in this case.. this would happen
- if we fail to push the server list inside the client..
- I should add a testcase for this, but I believe the following
- would work, except that you would add a hole in the pool list..
- in theory you could end up with an empty pool....
- */
- }
- }
- }
-
- (void)pthread_mutex_unlock(&pool->mutex);
-
- return rc;
-}
-
-memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
- memcached_behavior_t flag,
- uint64_t *value)
-{
- if (pool == NULL)
- {
- return MEMCACHED_INVALID_ARGUMENTS;
- }
-
- if (pthread_mutex_lock(&pool->mutex))
- {
- return MEMCACHED_IN_PROGRESS;
- }
-
- *value= memcached_behavior_get(pool->master, flag);
-
- (void)pthread_mutex_unlock(&pool->mutex);
-
- return MEMCACHED_SUCCESS;
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#include <libmemcached/memcached.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct memcached_pool_st;
-typedef struct memcached_pool_st memcached_pool_st;
-
-LIBMEMCACHED_API
-memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max);
-
-LIBMEMCACHED_API
-memcached_pool_st *memcached_pool(const char *option_string, size_t option_string_length);
-
-LIBMEMCACHED_API
-memcached_st* memcached_pool_destroy(memcached_pool_st* pool);
-
-LIBMEMCACHED_API
-memcached_st* memcached_pool_pop(memcached_pool_st* pool,
- bool block,
- memcached_return_t* rc);
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_push(memcached_pool_st* pool,
- memcached_st* mmc);
-LIBMEMCACHED_API
- memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st* mmc);
-
-LIBMEMCACHED_API
-memcached_st* memcached_pool_fetch(memcached_pool_st*, struct timespec* relative_time, memcached_return_t* rc);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_behavior_set(memcached_pool_st *ptr,
- memcached_behavior_t flag,
- uint64_t data);
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_behavior_get(memcached_pool_st *ptr,
- memcached_behavior_t flag,
- uint64_t *value);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-#include <libmemcached/memcached_util.h>
-
-struct local_context
-{
- uint8_t major_version;
- uint8_t minor_version;
- uint8_t micro_version;
-
- bool truth;
-};
-
-static memcached_return_t check_server_version(const memcached_st *ptr,
- const memcached_server_st *instance,
- void *context)
-{
- /* Do Nothing */
- struct local_context *check= (struct local_context *)context;
- (void)ptr;
-
- if (instance->major_version != UINT8_MAX &&
- instance->major_version >= check->major_version &&
- instance->minor_version >= check->minor_version &&
- instance->micro_version >= check->micro_version )
- {
- return MEMCACHED_SUCCESS;
- }
-
- check->truth= false;
-
- return MEMCACHED_FAILURE;
-}
-
-bool libmemcached_util_version_check(memcached_st *memc,
- uint8_t major_version,
- uint8_t minor_version,
- uint8_t micro_version)
-{
- if (memcached_version(memc) != MEMCACHED_SUCCESS)
- return false;
-
- struct local_context check= { major_version, minor_version, micro_version, true };
-
- memcached_server_fn callbacks[1];
- callbacks[0]= check_server_version;
- memcached_server_cursor(memc, callbacks, (void *)&check, 1);
-
- return check.truth;
-}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
- bool libmemcached_util_version_check(memcached_st *memc,
- uint8_t major_version,
- uint8_t minor_version,
- uint8_t micro_version);
-
-#ifdef __cplusplus
-}
-#endif
const char *buffer;
};
-static memcached_return_t _set_verbosity(const memcached_st *ptr,
+static memcached_return_t _set_verbosity(const memcached_st *,
const memcached_server_st *server,
void *context)
{
- memcached_return_t rc;
- memcached_st local_memc;
- memcached_st *memc_ptr;
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
struct context_st *execute= (struct context_st *)context;
- (void)ptr;
- memc_ptr= memcached_create(&local_memc);
+ memcached_st local_memc;
+ memcached_st *memc_ptr= memcached_create(&local_memc);
- rc= memcached_server_add(memc_ptr, memcached_server_name(server), memcached_server_port(server));
+ memcached_return_t rc= memcached_server_add(memc_ptr, memcached_server_name(server), memcached_server_port(server));
if (rc == MEMCACHED_SUCCESS)
{
- memcached_server_write_instance_st instance=
- memcached_server_instance_fetch(memc_ptr, 0);
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc_ptr, 0);
+
rc= memcached_do(instance, execute->buffer, execute->length, true);
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity);
-
-
-#ifdef __cplusplus
-}
-#endif
memcached_return_t memcached_version(memcached_st *ptr)
{
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr)))
+ {
+ return rc;
+ }
+
if (ptr->flags.use_udp)
+ {
return MEMCACHED_NOT_SUPPORTED;
-
- memcached_return_t rc;
+ }
if (ptr->flags.binary_protocol)
+ {
rc= memcached_version_binary(ptr);
+ }
else
+ {
rc= memcached_version_textual(ptr);
+ }
return rc;
}
static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
{
- size_t send_length;
- memcached_return_t rc;
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- char *response_ptr;
- const char *command= "version\r\n";
-
- send_length= sizeof("version\r\n") -1;
-
- rc= MEMCACHED_SUCCESS;
+ memcached_return_t rc= MEMCACHED_SUCCESS;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- memcached_return_t rrc;
- memcached_server_write_instance_st instance=
- memcached_server_instance_fetch(ptr, x);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
// Optimization, we only fetch version once.
if (instance->major_version != UINT8_MAX)
+ {
continue;
+ }
- rrc= memcached_do(instance, command, send_length, true);
- if (rrc != MEMCACHED_SUCCESS)
+ memcached_return_t rrc= memcached_do(instance, memcached_literal_param("version\r\n"), true);
+ if (memcached_failed(rrc))
{
+ (void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
- if (rrc != MEMCACHED_SUCCESS)
+ if (memcached_failed(rrc))
{
+ memcached_set_error(*instance, rrc, MEMCACHED_AT);
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
/* Find the space, and then move one past it to copy version */
- response_ptr= index(buffer, ' ');
+ char *response_ptr= index(buffer, ' ');
response_ptr++;
- instance->major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
- if (errno == ERANGE)
+ long int version= strtol(response_ptr, (char **)NULL, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->major_version= uint8_t(version);
response_ptr= index(response_ptr, '.');
response_ptr++;
- instance->minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
- if (errno == ERANGE)
+ version= strtol(response_ptr, (char **)NULL, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->minor_version= uint8_t(version);
response_ptr= index(response_ptr, '.');
response_ptr++;
- instance->micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
- if (errno == ERANGE)
+
+ version= strtol(response_ptr, (char **)NULL, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->micro_version= uint8_t(version);
}
return rc;
static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
{
- memcached_return_t rc;
protocol_binary_request_version request= {};
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
- rc= MEMCACHED_SUCCESS;
+ memcached_return_t rc= MEMCACHED_SUCCESS;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- memcached_return_t rrc;
-
- memcached_server_write_instance_st instance=
- memcached_server_instance_fetch(ptr, x);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
if (instance->major_version != UINT8_MAX)
+ {
continue;
+ }
- rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
- if (rrc != MEMCACHED_SUCCESS)
+ memcached_return_t rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
+ if (memcached_failed(rrc))
{
memcached_io_reset(instance);
rc= MEMCACHED_SOME_ERRORS;
memcached_server_instance_fetch(ptr, x);
if (instance->major_version != UINT8_MAX)
+ {
continue;
+ }
if (memcached_server_response_count(instance) > 0)
{
- memcached_return_t rrc;
char buffer[32];
char *p;
- rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
- if (rrc != MEMCACHED_SUCCESS)
+ memcached_return_t rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+ if (memcached_failed(rrc))
{
memcached_io_reset(instance);
rc= MEMCACHED_SOME_ERRORS;
continue;
}
- instance->major_version= (uint8_t)strtol(buffer, &p, 10);
- if (errno == ERANGE)
+ long int version= strtol(buffer, &p, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->major_version= uint8_t(version);
- instance->minor_version= (uint8_t)strtol(p + 1, &p, 10);
- if (errno == ERANGE)
+ version= strtol(p +1, &p, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->minor_version= uint8_t(version);
- instance->micro_version= (uint8_t)strtol(p + 1, NULL, 10);
+ version= strtol(p + 1, NULL, 10);
if (errno == ERANGE)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
-
+ instance->micro_version= uint8_t(version);
}
}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Libmemcached library
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_version(memcached_st *ptr);
-
-LIBMEMCACHED_API
-const char * memcached_lib_version(void);
-
-#ifdef __cplusplus
-}
-#endif
*/
#include <config.h>
-#include <libmemcached/memcached.h>
-#include <libmemcached/virtual_bucket.h>
+#include <libmemcached/common.h>
struct bucket_t {
uint32_t master;
const uint32_t replicas)
{
if (! self || ! host_map || ! buckets)
+ {
return MEMCACHED_INVALID_ARGUMENTS;
+ }
memcached_virtual_bucket_free(self);
+++ /dev/null
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Interface for memcached server.
- *
- * Author: Trond Norbye
- *
- */
-
-/**
- * @file
- * @brief Visibility control macros
- */
-
-#pragma once
-
-/**
- *
- * LIBMEMCACHED_API is used for the public API symbols. It either DLL imports or
- * DLL exports (or does nothing for static build).
- *
- * LIBMEMCACHED_LOCAL is used for non-api symbols.
- */
-
-#if defined(BUILDING_LIBMEMCACHEDINTERNAL)
-# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-# define LIBMEMCACHED_API __attribute__ ((visibility("default")))
-# define LIBMEMCACHED_LOCAL __attribute__ ((visibility("default")))
-# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-# define LIBMEMCACHED_API __global
-# define LIBMEMCACHED_LOCAL __global
-# elif defined(_MSC_VER)
-# define LIBMEMCACHED_API extern __declspec(dllexport)
-# define LIBMEMCACHED_LOCAL extern __declspec(dllexport)
-# else
-# define LIBMEMCACHED_API
-# define LIBMEMCACHED_LOCAL
-# endif
-#else
-# if defined(BUILDING_LIBMEMCACHED)
-# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-# define LIBMEMCACHED_API __attribute__ ((visibility("default")))
-# define LIBMEMCACHED_LOCAL __attribute__ ((visibility("hidden")))
-# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-# define LIBMEMCACHED_API __global
-# define LIBMEMCACHED_LOCAL __hidden
-# elif defined(_MSC_VER)
-# define LIBMEMCACHED_API extern __declspec(dllexport)
-# define LIBMEMCACHED_LOCAL
-# else
-# define LIBMEMCACHED_API
-# define LIBMEMCACHED_LOCAL
-# endif /* defined(HAVE_VISIBILITY) */
-# else /* defined(BUILDING_LIBMEMCACHED) */
-# if defined(_MSC_VER)
-# define LIBMEMCACHED_API extern __declspec(dllimport)
-# define LIBMEMCACHED_LOCAL
-# else
-# define LIBMEMCACHED_API
-# define LIBMEMCACHED_LOCAL
-# endif /* defined(_MSC_VER) */
-# endif /* defined(BUILDING_LIBMEMCACHED) */
-#endif /* defined(BUILDING_LIBMEMCACHEDINTERNAL) */
--- /dev/null
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (c) <2008>, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Summary: Constants used by to implement the binary protocol.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Trond Norbye <trond.norbye@sun.com>
+ */
+
+#ifndef PROTOCOL_BINARY_H
+#define PROTOCOL_BINARY_H
+
+#include <libmemcachedprotocol-0.0/vbucket.h>
+
+/**
+ * \addtogroup Protocol
+ * @{
+ */
+
+/**
+ * This file contains definitions of the constants and packet formats
+ * defined in the binary specification. Please note that you _MUST_ remember
+ * to convert each multibyte field to / from network byte order to / from
+ * host order.
+ */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * Definition of the legal "magic" values used in a packet.
+ * See section 3.1 Magic byte
+ */
+ typedef enum {
+ PROTOCOL_BINARY_REQ = 0x80,
+ PROTOCOL_BINARY_RES = 0x81
+ } protocol_binary_magic;
+
+ /**
+ * Definition of the valid response status numbers.
+ * See section 3.2 Response Status
+ */
+ typedef enum {
+ PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00,
+ PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01,
+ PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02,
+ PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03,
+ PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04,
+ PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05,
+ PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL = 0x06,
+ PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET = 0x07,
+ PROTOCOL_BINARY_RESPONSE_AUTH_ERROR = 0x20,
+ PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE = 0x21,
+ PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81,
+ PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82,
+ PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED = 0x83,
+ PROTOCOL_BINARY_RESPONSE_EINTERNAL = 0x84,
+ PROTOCOL_BINARY_RESPONSE_EBUSY = 0x85,
+ PROTOCOL_BINARY_RESPONSE_ETMPFAIL = 0x86
+ } protocol_binary_response_status;
+
+ /**
+ * Defintion of the different command opcodes.
+ * See section 3.3 Command Opcodes
+ */
+ typedef enum {
+ PROTOCOL_BINARY_CMD_GET = 0x00,
+ PROTOCOL_BINARY_CMD_SET = 0x01,
+ PROTOCOL_BINARY_CMD_ADD = 0x02,
+ PROTOCOL_BINARY_CMD_REPLACE = 0x03,
+ PROTOCOL_BINARY_CMD_DELETE = 0x04,
+ PROTOCOL_BINARY_CMD_INCREMENT = 0x05,
+ PROTOCOL_BINARY_CMD_DECREMENT = 0x06,
+ PROTOCOL_BINARY_CMD_QUIT = 0x07,
+ PROTOCOL_BINARY_CMD_FLUSH = 0x08,
+ PROTOCOL_BINARY_CMD_GETQ = 0x09,
+ PROTOCOL_BINARY_CMD_NOOP = 0x0a,
+ PROTOCOL_BINARY_CMD_VERSION = 0x0b,
+ PROTOCOL_BINARY_CMD_GETK = 0x0c,
+ PROTOCOL_BINARY_CMD_GETKQ = 0x0d,
+ PROTOCOL_BINARY_CMD_APPEND = 0x0e,
+ PROTOCOL_BINARY_CMD_PREPEND = 0x0f,
+ PROTOCOL_BINARY_CMD_STAT = 0x10,
+ PROTOCOL_BINARY_CMD_SETQ = 0x11,
+ PROTOCOL_BINARY_CMD_ADDQ = 0x12,
+ PROTOCOL_BINARY_CMD_REPLACEQ = 0x13,
+ PROTOCOL_BINARY_CMD_DELETEQ = 0x14,
+ PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15,
+ PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16,
+ PROTOCOL_BINARY_CMD_QUITQ = 0x17,
+ PROTOCOL_BINARY_CMD_FLUSHQ = 0x18,
+ PROTOCOL_BINARY_CMD_APPENDQ = 0x19,
+ PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a,
+ PROTOCOL_BINARY_CMD_VERBOSITY = 0x1b,
+ PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
+ PROTOCOL_BINARY_CMD_GAT = 0x1d,
+ PROTOCOL_BINARY_CMD_GATQ = 0x1e,
+
+ PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
+ PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
+ PROTOCOL_BINARY_CMD_SASL_STEP = 0x22,
+
+ /* These commands are used for range operations and exist within
+ * this header for use in other projects. Range operations are
+ * not expected to be implemented in the memcached server itself.
+ */
+ PROTOCOL_BINARY_CMD_RGET = 0x30,
+ PROTOCOL_BINARY_CMD_RSET = 0x31,
+ PROTOCOL_BINARY_CMD_RSETQ = 0x32,
+ PROTOCOL_BINARY_CMD_RAPPEND = 0x33,
+ PROTOCOL_BINARY_CMD_RAPPENDQ = 0x34,
+ PROTOCOL_BINARY_CMD_RPREPEND = 0x35,
+ PROTOCOL_BINARY_CMD_RPREPENDQ = 0x36,
+ PROTOCOL_BINARY_CMD_RDELETE = 0x37,
+ PROTOCOL_BINARY_CMD_RDELETEQ = 0x38,
+ PROTOCOL_BINARY_CMD_RINCR = 0x39,
+ PROTOCOL_BINARY_CMD_RINCRQ = 0x3a,
+ PROTOCOL_BINARY_CMD_RDECR = 0x3b,
+ PROTOCOL_BINARY_CMD_RDECRQ = 0x3c,
+ /* End Range operations */
+
+ /* VBucket commands */
+ PROTOCOL_BINARY_CMD_SET_VBUCKET = 0x3d,
+ PROTOCOL_BINARY_CMD_GET_VBUCKET = 0x3e,
+ PROTOCOL_BINARY_CMD_DEL_VBUCKET = 0x3f,
+ /* End VBucket commands */
+
+ /* TAP commands */
+ PROTOCOL_BINARY_CMD_TAP_CONNECT = 0x40,
+ PROTOCOL_BINARY_CMD_TAP_MUTATION = 0x41,
+ PROTOCOL_BINARY_CMD_TAP_DELETE = 0x42,
+ PROTOCOL_BINARY_CMD_TAP_FLUSH = 0x43,
+ PROTOCOL_BINARY_CMD_TAP_OPAQUE = 0x44,
+ PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET = 0x45,
+ PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START = 0x46,
+ PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END = 0x47,
+ /* End TAP */
+
+ PROTOCOL_BINARY_CMD_LAST_RESERVED = 0xef,
+
+ /* Scrub the data */
+ PROTOCOL_BINARY_CMD_SCRUB = 0xf0
+ } protocol_binary_command;
+
+ /**
+ * Definition of the data types in the packet
+ * See section 3.4 Data Types
+ */
+ typedef enum {
+ PROTOCOL_BINARY_RAW_BYTES = 0x00
+ } protocol_binary_datatypes;
+
+ /**
+ * Definition of the header structure for a request packet.
+ * See section 2
+ */
+ typedef union {
+ struct {
+ uint8_t magic;
+ uint8_t opcode;
+ uint16_t keylen;
+ uint8_t extlen;
+ uint8_t datatype;
+ uint16_t vbucket;
+ uint32_t bodylen;
+ uint32_t opaque;
+ uint64_t cas;
+ } request;
+ uint8_t bytes[24];
+ } protocol_binary_request_header;
+
+ /**
+ * Definition of the header structure for a response packet.
+ * See section 2
+ */
+ typedef union {
+ struct {
+ uint8_t magic;
+ uint8_t opcode;
+ uint16_t keylen;
+ uint8_t extlen;
+ uint8_t datatype;
+ uint16_t status;
+ uint32_t bodylen;
+ uint32_t opaque;
+ uint64_t cas;
+ } response;
+ uint8_t bytes[24];
+ } protocol_binary_response_header;
+
+ /**
+ * Definition of a request-packet containing no extras
+ */
+ union protocol_binary_request_no_extras {
+ struct {
+ protocol_binary_request_header header;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header)];
+ };
+ typedef union protocol_binary_request_no_extras protocol_binary_request_no_extras;
+
+ /**
+ * Definition of a response-packet containing no extras
+ */
+ typedef union {
+ struct {
+ protocol_binary_response_header header;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_response_header)];
+ } protocol_binary_response_no_extras;
+
+ /**
+ * Definition of the packet used by the get, getq, getk and getkq command.
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_get;
+ typedef protocol_binary_request_no_extras protocol_binary_request_getq;
+ typedef protocol_binary_request_no_extras protocol_binary_request_getk;
+ typedef protocol_binary_request_no_extras protocol_binary_request_getkq;
+
+ /**
+ * Definition of the packet returned from a successful get, getq, getk and
+ * getkq.
+ * See section 4
+ */
+ typedef union {
+ struct {
+ protocol_binary_response_header header;
+ struct {
+ uint32_t flags;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
+ } protocol_binary_response_get;
+
+ typedef protocol_binary_response_get protocol_binary_response_getq;
+ typedef protocol_binary_response_get protocol_binary_response_getk;
+ typedef protocol_binary_response_get protocol_binary_response_getkq;
+
+ /**
+ * Definition of the packet used by the delete command
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_delete;
+
+ /**
+ * Definition of the packet returned by the delete command
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_delete;
+
+ /**
+ * Definition of the packet used by the flush command
+ * See section 4
+ * Please note that the expiration field is optional, so remember to see
+ * check the header.bodysize to see if it is present.
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ uint32_t expiration;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+ } protocol_binary_request_flush;
+
+ /**
+ * Definition of the packet returned by the flush command
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_flush;
+
+ /**
+ * Definition of the packet used by set, add and replace
+ * See section 4
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ uint32_t flags;
+ uint32_t expiration;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
+ } protocol_binary_request_set;
+ typedef protocol_binary_request_set protocol_binary_request_add;
+ typedef protocol_binary_request_set protocol_binary_request_replace;
+
+ /**
+ * Definition of the packet returned by set, add and replace
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_set;
+ typedef protocol_binary_response_no_extras protocol_binary_response_add;
+ typedef protocol_binary_response_no_extras protocol_binary_response_replace;
+
+ /**
+ * Definition of the noop packet
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_noop;
+
+ /**
+ * Definition of the packet returned by the noop command
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_noop;
+
+ /**
+ * Definition of the structure used by the increment and decrement
+ * command.
+ * See section 4
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ uint64_t delta;
+ uint64_t initial;
+ uint32_t expiration;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
+ } protocol_binary_request_incr;
+ typedef protocol_binary_request_incr protocol_binary_request_decr;
+
+ /**
+ * Definition of the response from an incr or decr command
+ * command.
+ * See section 4
+ */
+ typedef union {
+ struct {
+ protocol_binary_response_header header;
+ struct {
+ uint64_t value;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_response_header) + 8];
+ } protocol_binary_response_incr;
+ typedef protocol_binary_response_incr protocol_binary_response_decr;
+
+ /**
+ * Definition of the quit
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_quit;
+
+ /**
+ * Definition of the packet returned by the quit command
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_quit;
+
+ /**
+ * Definition of the packet used by append and prepend command
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_append;
+ typedef protocol_binary_request_no_extras protocol_binary_request_prepend;
+
+ /**
+ * Definition of the packet returned from a successful append or prepend
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_append;
+ typedef protocol_binary_response_no_extras protocol_binary_response_prepend;
+
+ /**
+ * Definition of the packet used by the version command
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_version;
+
+ /**
+ * Definition of the packet returned from a successful version command
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_version;
+
+
+ /**
+ * Definition of the packet used by the stats command.
+ * See section 4
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_stats;
+
+ /**
+ * Definition of the packet returned from a successful stats command
+ * See section 4
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_stats;
+
+ /**
+ * Definition of the packet used by the verbosity command
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ uint32_t level;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+ } protocol_binary_request_verbosity;
+
+ /**
+ * Definition of the packet returned from the verbosity command
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_verbosity;
+
+ /**
+ * Definition of the packet used by the touch command.
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ uint32_t expiration;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+ } protocol_binary_request_touch;
+
+ /**
+ * Definition of the packet returned from the touch command
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_touch;
+
+ /**
+ * Definition of the packet used by the GAT(Q) command.
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ uint32_t expiration;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+ } protocol_binary_request_gat;
+
+ typedef protocol_binary_request_gat protocol_binary_request_gatq;
+
+ /**
+ * Definition of the packet returned from the GAT(Q)
+ */
+ typedef protocol_binary_response_get protocol_binary_response_gat;
+ typedef protocol_binary_response_get protocol_binary_response_gatq;
+
+
+ /**
+ * Definition of a request for a range operation.
+ * See http://code.google.com/p/memcached/wiki/RangeOps
+ *
+ * These types are used for range operations and exist within
+ * this header for use in other projects. Range operations are
+ * not expected to be implemented in the memcached server itself.
+ */
+ typedef union {
+ struct {
+ protocol_binary_response_header header;
+ struct {
+ uint16_t size;
+ uint8_t reserved;
+ uint8_t flags;
+ uint32_t max_results;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+ } protocol_binary_request_rangeop;
+
+ typedef protocol_binary_request_rangeop protocol_binary_request_rget;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rset;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rsetq;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rappend;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rappendq;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rprepend;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rprependq;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rdelete;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rincr;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rincrq;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rdecr;
+ typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq;
+
+
+ /**
+ * Definition of tap commands
+ * See To be written
+ *
+ */
+
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ /**
+ * flags is a bitmask used to set properties for the
+ * the connection. Please In order to be forward compatible
+ * you should set all undefined bits to 0.
+ *
+ * If the bit require extra userdata, it will be stored
+ * in the user-data field of the body (passed to the engine
+ * as enginespeciffic). That means that when you parse the
+ * flags and the engine-specific data, you have to work your
+ * way from bit 0 and upwards to find the correct offset for
+ * the data.
+ *
+ */
+ uint32_t flags;
+
+ /**
+ * Backfill age
+ *
+ * By using this flag you can limit the amount of data being
+ * transmitted. If you don't specify a backfill age, the
+ * server will transmit everything it contains.
+ *
+ * The first 8 bytes in the engine specific data contains
+ * the oldest entry (from epoc) you're interested in.
+ * Specifying a time in the future (for the server you are
+ * connecting to), will cause it to start streaming current
+ * changes.
+ */
+#define TAP_CONNECT_FLAG_BACKFILL 0x01
+ /**
+ * Dump will cause the server to send the data stored on the
+ * server, but disconnect when the keys stored in the server
+ * are transmitted.
+ */
+#define TAP_CONNECT_FLAG_DUMP 0x02
+ /**
+ * The body contains a list of 16 bits words in network byte
+ * order specifying the vbucket ids to monitor. The first 16
+ * bit word contains the number of buckets. The number of 0
+ * means "all buckets"
+ */
+#define TAP_CONNECT_FLAG_LIST_VBUCKETS 0x04
+ /**
+ * The responsibility of the vbuckets is to be transferred
+ * over to the caller when all items are transferred.
+ */
+#define TAP_CONNECT_FLAG_TAKEOVER_VBUCKETS 0x08
+ /**
+ * The tap consumer supports ack'ing of tap messages
+ */
+#define TAP_CONNECT_SUPPORT_ACK 0x10
+ /**
+ * The tap consumer would prefer to just get the keys
+ * back. If the engine supports this it will set
+ * the TAP_FLAG_NO_VALUE flag in each of the
+ * tap packets returned.
+ */
+#define TAP_CONNECT_REQUEST_KEYS_ONLY 0x20
+ /**
+ * The body contains a list of (vbucket_id, last_checkpoint_id)
+ * pairs. This provides the checkpoint support in TAP streams.
+ * The last checkpoint id represents the last checkpoint that
+ * was successfully persisted.
+ */
+#define TAP_CONNECT_CHECKPOINT 0x40
+ /**
+ * The tap consumer is a registered tap client, which means that
+ * the tap server will maintain its checkpoint cursor permanently.
+ */
+#define TAP_CONNECT_REGISTERED_CLIENT 0x80
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+ } protocol_binary_request_tap_connect;
+
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ struct {
+ uint16_t enginespecific_length;
+ /*
+ * The flag section support the following flags
+ */
+ /**
+ * Request that the consumer send a response packet
+ * for this packet. The opaque field must be preserved
+ * in the response.
+ */
+#define TAP_FLAG_ACK 0x01
+ /**
+ * The value for the key is not included in the packet
+ */
+#define TAP_FLAG_NO_VALUE 0x02
+ uint16_t flags;
+ uint8_t ttl;
+ uint8_t res1;
+ uint8_t res2;
+ uint8_t res3;
+ } tap;
+ struct {
+ uint32_t flags;
+ uint32_t expiration;
+ } item;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 16];
+ } protocol_binary_request_tap_mutation;
+
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ struct {
+ uint16_t enginespecific_length;
+ /**
+ * See the definition of the flags for
+ * protocol_binary_request_tap_mutation for a description
+ * of the available flags.
+ */
+ uint16_t flags;
+ uint8_t ttl;
+ uint8_t res1;
+ uint8_t res2;
+ uint8_t res3;
+ } tap;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
+ } protocol_binary_request_tap_no_extras;
+
+ typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_delete;
+ typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_flush;
+ typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_opaque;
+ typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_vbucket_set;
+
+
+ /**
+ * Definition of the packet used by the scrub.
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_scrub;
+
+ /**
+ * Definition of the packet returned from scrub.
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_scrub;
+
+
+ /**
+ * Definition of the packet used by set vbucket
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ struct {
+ vbucket_state_t state;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(vbucket_state_t)];
+ } protocol_binary_request_set_vbucket;
+ /**
+ * Definition of the packet returned from set vbucket
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_set_vbucket;
+ /**
+ * Definition of the packet used by del vbucket
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_del_vbucket;
+ /**
+ * Definition of the packet returned from del vbucket
+ */
+ typedef protocol_binary_response_no_extras protocol_binary_response_del_vbucket;
+
+ /**
+ * Definition of the packet used by get vbucket
+ */
+ typedef protocol_binary_request_no_extras protocol_binary_request_get_vbucket;
+
+ /**
+ * Definition of the packet returned from get vbucket
+ */
+ typedef union {
+ struct {
+ protocol_binary_response_header header;
+ struct {
+ vbucket_state_t state;
+ } body;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_response_header) + sizeof(vbucket_state_t)];
+ } protocol_binary_response_get_vbucket;
+
+
+ /**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* PROTOCOL_BINARY_H */
--- /dev/null
+/*
+ * Summary: Definition of the callback interface
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Trond Norbye
+ */
+
+#pragma once
+
+/**
+ * Callback to send data back from a successful GET/GETQ/GETK/GETKQ command
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param key What to insert as key in the reply
+ * @param keylen The length of the key
+ * @param body What to store in the body of the package
+ * @param bodylen The number of bytes of the body
+ * @param flags The flags stored with the item
+ * @param cas The CAS value to insert into the response (should be 0
+ * if you don't care)
+ */
+typedef protocol_binary_response_status
+(*memcached_binary_protocol_get_response_handler)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void *body,
+ uint32_t bodylen,
+ uint32_t flags,
+ uint64_t cas);
+/**
+ * Callback to send data back from a STAT command
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param key What to insert as key in the reply
+ * @param keylen The length of the key
+ * @param body What to store in the body of the package
+ * @param bodylen The number of bytes of the body
+ */
+typedef protocol_binary_response_status
+(*memcached_binary_protocol_stat_response_handler)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void *body,
+ uint32_t bodylen);
+/**
+ * Callback to send data back from a VERSION command
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param text The version string
+ * @param length The number of bytes in the version string
+ */
+typedef protocol_binary_response_status
+(*memcached_binary_protocol_version_response_handler)(const void *cookie,
+ const void *text,
+ uint32_t length);
+
+
+/**
+ * In the low level interface you need to format the response
+ * packet yourself (giving you complete freedom :-)
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param request Pointer to the request packet you are sending a reply to
+ * @param response Pointer to the response packet to send
+ *
+ */
+typedef protocol_binary_response_status (*memcached_binary_protocol_raw_response_handler)(const void *cookie,
+ protocol_binary_request_header *request,
+ protocol_binary_response_header *response);
+
+/**
+ * In the low lever interface you have to do most of the work by
+ * yourself, but it also gives you a lot of freedom :-)
+ * @param cookie identification for this connection, just pass it along to
+ * the response handler
+ * @param header the command received over the wire. Never try to access
+ * <u>anything</u> outside the command.
+ * @param resonse_handler call this function to send data back to the client
+ */
+typedef protocol_binary_response_status (*memcached_binary_protocol_command_handler)(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler);
+
+/**
+ * The raw interface to the packets is implemented in version 0. It contains
+ * just an array with command handlers. The inxed in the array is the
+ * com code.
+ */
+typedef struct {
+ memcached_binary_protocol_command_handler comcode[256];
+} memcached_binary_protocol_callback_v0_st;
+
+
+/**
+ * The first version of the callback struct containing all of the
+ * documented commands in the initial release of the binary protocol
+ * (aka. memcached 1.4.0).
+ *
+ * You might miss the Q commands (addq etc) but the response function
+ * knows how to deal with them so you don't need to worry about that :-)
+ */
+typedef struct {
+ /**
+ * Add an item to the cache
+ * @param cookie id of the client receiving the command
+ * @param key the key to add
+ * @param len the length of the key
+ * @param val the value to store for the key (may be NIL)
+ * @param vallen the length of the data
+ * @param flags the flags to store with the key
+ * @param exptime the expiry time for the key-value pair
+ * @param cas the resulting cas for the add operation (if success)
+ */
+ protocol_binary_response_status (*add)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void* val,
+ uint32_t vallen,
+ uint32_t flags,
+ uint32_t exptime,
+ uint64_t *cas);
+
+ /**
+ * Append data to an <b>existing</b> key-value pair.
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to add data to
+ * @param len the length of the key
+ * @param val the value to append to the value
+ * @param vallen the length of the data
+ * @param cas the CAS in the request
+ * @param result_cas the resulting cas for the append operation
+ *
+ */
+ protocol_binary_response_status (*append)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void* val,
+ uint32_t vallen,
+ uint64_t cas,
+ uint64_t *result_cas);
+
+ /**
+ * Decrement the value for a key
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to decrement the value for
+ * @param len the length of the key
+ * @param delta the amount to decrement
+ * @param initial initial value to store (if the key doesn't exist)
+ * @param expiration expiration time for the object (if the key doesn't exist)
+ * @param cas the CAS in the request
+ * @param result the result from the decrement
+ * @param result_cas the cas of the item
+ *
+ */
+ protocol_binary_response_status (*decrement)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ uint64_t delta,
+ uint64_t initial,
+ uint32_t expiration,
+ uint64_t *result,
+ uint64_t *result_cas);
+
+ /**
+ * Delete an existing key
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to delete
+ * @param len the length of the key
+ * @param cas the CAS in the request
+ */
+ protocol_binary_response_status (*delete)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ uint64_t cas);
+
+
+ /**
+ * Flush the cache
+ *
+ * @param cookie id of the client receiving the command
+ * @param when when the cache should be flushed (0 == immediately)
+ */
+ protocol_binary_response_status (*flush)(const void *cookie,
+ uint32_t when);
+
+
+
+ /**
+ * Get a key-value pair
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to get
+ * @param len the length of the key
+ * @param response_handler to send the result back to the client
+ */
+ protocol_binary_response_status (*get)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ memcached_binary_protocol_get_response_handler response_handler);
+
+ /**
+ * Increment the value for a key
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to increment the value on
+ * @param len the length of the key
+ * @param delta the amount to increment
+ * @param initial initial value to store (if the key doesn't exist)
+ * @param expiration expiration time for the object (if the key doesn't exist)
+ * @param cas the CAS in the request
+ * @param result the result from the decrement
+ * @param result_cas the cas of the item
+ *
+ */
+ protocol_binary_response_status (*increment)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ uint64_t delta,
+ uint64_t initial,
+ uint32_t expiration,
+ uint64_t *result,
+ uint64_t *result_cas);
+
+ /**
+ * The noop command was received. This is just a notification callback (the
+ * response is automatically created).
+ *
+ * @param cookie id of the client receiving the command
+ */
+ protocol_binary_response_status (*noop)(const void *cookie);
+
+ /**
+ * Prepend data to an <b>existing</b> key-value pair.
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to prepend data to
+ * @param len the length of the key
+ * @param val the value to prepend to the value
+ * @param vallen the length of the data
+ * @param cas the CAS in the request
+ * @param result-cas the cas id of the item
+ *
+ */
+ protocol_binary_response_status (*prepend)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void* val,
+ uint32_t vallen,
+ uint64_t cas,
+ uint64_t *result_cas);
+
+ /**
+ * The quit command was received. This is just a notification callback (the
+ * response is automatically created).
+ *
+ * @param cookie id of the client receiving the command
+ */
+ protocol_binary_response_status (*quit)(const void *cookie);
+
+
+ /**
+ * Replace an <b>existing</b> item to the cache
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to replace the content for
+ * @param len the length of the key
+ * @param val the value to store for the key (may be NIL)
+ * @param vallen the length of the data
+ * @param flags the flags to store with the key
+ * @param exptime the expiry time for the key-value pair
+ * @param cas the cas id in the request
+ * @param result_cas the cas id of the item
+ */
+ protocol_binary_response_status (*replace)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void* val,
+ uint32_t vallen,
+ uint32_t flags,
+ uint32_t exptime,
+ uint64_t cas,
+ uint64_t *result_cas);
+
+
+ /**
+ * Set a key-value pair in the cache
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to insert
+ * @param len the length of the key
+ * @param val the value to store for the key (may be NIL)
+ * @param vallen the length of the data
+ * @param flags the flags to store with the key
+ * @param exptime the expiry time for the key-value pair
+ * @param cas the cas id in the request
+ * @param result_cas the cas id of the new item
+ */
+ protocol_binary_response_status (*set)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void* val,
+ uint32_t vallen,
+ uint32_t flags,
+ uint32_t exptime,
+ uint64_t cas,
+ uint64_t *result_cas);
+
+ /**
+ * Get status information
+ *
+ * @param cookie id of the client receiving the command
+ * @param key the key to get status for (or NIL to request all status).
+ * Remember to insert the terminating packet if multiple
+ * packets should be returned.
+ * @param keylen the length of the key
+ * @param response_handler to send the result back to the client, but
+ * don't send reply on success!
+ *
+ */
+ protocol_binary_response_status (*stat)(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ memcached_binary_protocol_stat_response_handler response_handler);
+
+ /**
+ * Get the version information
+ *
+ * @param cookie id of the client receiving the command
+ * @param response_handler to send the result back to the client, but
+ * don't send reply on success!
+ *
+ */
+ protocol_binary_response_status (*version)(const void *cookie,
+ memcached_binary_protocol_version_response_handler response_handler);
+} memcached_binary_protocol_callback_v1_st;
+
+
+/**
+ * The version numbers for the different callback structures.
+ */
+typedef enum {
+ /** Version 0 is a lowlevel interface that tries to maximize your freedom */
+ MEMCACHED_PROTOCOL_HANDLER_V0= 0,
+ /**
+ * Version 1 abstracts more of the protocol details, and let you work at
+ * a logical level
+ */
+ MEMCACHED_PROTOCOL_HANDLER_V1= 1,
+} memcached_protocol_interface_version_t;
+
+/**
+ * Definition of the protocol callback structure.
+ */
+typedef struct {
+ /**
+ * The interface version you provide callbacks for.
+ */
+ memcached_protocol_interface_version_t interface_version;
+
+ /**
+ * Callback fired just before the command will be executed.
+ *
+ * @param cookie id of the client receiving the command
+ * @param header the command header as received on the wire. If you look
+ * at the content you <b>must</b> ensure that you don't
+ * try to access beyond the end of the message.
+ */
+ void (*pre_execute)(const void *cookie,
+ protocol_binary_request_header *header);
+ /**
+ * Callback fired just after the command was exected (please note
+ * that the data transfer back to the client is not finished at this
+ * time).
+ *
+ * @param cookie id of the client receiving the command
+ * @param header the command header as received on the wire. If you look
+ * at the content you <b>must</b> ensure that you don't
+ * try to access beyond the end of the message.
+ */
+ void (*post_execute)(const void *cookie,
+ protocol_binary_request_header *header);
+
+ /**
+ * Callback fired if no specialized callback is registered for this
+ * specific command code.
+ *
+ * @param cookie id of the client receiving the command
+ * @param header the command header as received on the wire. You <b>must</b>
+ * ensure that you don't try to access beyond the end of the
+ * message.
+ * @param response_handler The response handler to send data back.
+ */
+ protocol_binary_response_status (*unknown)(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler);
+
+ /**
+ * The different interface levels we support. A pointer is used so the
+ * size of the structure is fixed. You must ensure that the memory area
+ * passed as the pointer is valid as long as you use the protocol handler.
+ */
+ union {
+ memcached_binary_protocol_callback_v0_st v0;
+
+ /**
+ * The first version of the callback struct containing all of the
+ * documented commands in the initial release of the binary protocol
+ * (aka. memcached 1.4.0).
+ */
+ memcached_binary_protocol_callback_v1_st v1;
+ } interface;
+} memcached_binary_protocol_callback_st;
--- /dev/null
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Definition of the callback interface to the protocol handler
+ *
+ * Author: Trond Norbye
+ *
+ */
+
+#pragma once
+
+#include <sys/types.h>
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+
+#include <libmemcached-1.0/visibility.h>
+#include <libmemcached-1.0/platform.h>
+#include <libmemcachedprotocol-0.0/binary.h>
+#include <libmemcachedprotocol-0.0/callback.h>
+
+/* Forward declarations */
+/*
+ * You should only access memcached_protocol_st from one thread!,
+ * and never assume anything about the internal layout / sizes of the
+ * structures.
+ */
+typedef struct memcached_protocol_st memcached_protocol_st;
+typedef struct memcached_protocol_client_st memcached_protocol_client_st;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Function the protocol handler should call to receive data.
+ * This function should behave exactly like read(2)
+ *
+ * @param cookie a cookie used to represent a given client
+ * @param fd the filedescriptor associated with the client
+ * @param buf destination buffer
+ * @param nbuf number of bytes to receive
+ * @return the number of bytes copied into buf
+ * or -1 upon error (errno should contain more information)
+ */
+typedef ssize_t (*memcached_protocol_recv_func)(const void *cookie,
+ memcached_socket_t fd,
+ void *buf,
+ size_t nbuf);
+
+/**
+ * Function the protocol handler should call to send data.
+ * This function should behave exactly like write(2)
+ *
+ * @param cookie a cookie used to represent a given client
+ * @param fd the filedescriptor associated with the client
+ * @param buf the source buffer
+ * @param nbuf number of bytes to send
+ * @return the number of bytes sent
+ * or -1 upon error (errno should contain more information)
+ */
+typedef ssize_t (*memcached_protocol_send_func)(const void *cookie,
+ memcached_socket_t fd,
+ const void *buf,
+ size_t nbuf);
+
+/**
+ * Create an instance of the protocol handler
+ *
+ * @return NULL if allocation of an instance fails
+ */
+LIBMEMCACHED_API
+memcached_protocol_st *memcached_protocol_create_instance(void);
+
+/**
+ * Get the callbacks associated with a protocol handler instance
+ * @return the callbacks currently used
+ */
+LIBMEMCACHED_API
+memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance);
+
+/**
+ * Set the callbacks to be used by the given protocol handler instance
+ * @param instance the instance to update
+ * @param callback the callbacks to use
+ */
+LIBMEMCACHED_API
+void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback);
+
+/**
+ * Should the library inspect the packages being sent and received and verify
+ * that they are according to the specification? If it encounters an invalid
+ * packet, it will return an EINVAL packet.
+ *
+ * @param instance the instance to update
+ * @param enable true if you want the library to check packages, false otherwise
+ */
+LIBMEMCACHED_API
+void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable);
+
+/**
+ * Is the library inpecting each package?
+ * @param instance the instance to check
+ * @return true it the library is inspecting each package, false otherwise
+ */
+LIBMEMCACHED_API
+bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance);
+
+/**
+ * Destroy an instance of the protocol handler
+ *
+ * @param instance The instance to destroy
+ */
+LIBMEMCACHED_API
+void memcached_protocol_destroy_instance(memcached_protocol_st *instance);
+
+/**
+ * Set the IO functions used by the instance to send and receive data. The
+ * functions should behave like recv(3socket) and send(3socket).
+ *
+ * @param instance the instance to specify the IO functions for
+ * @param recv the function to call for reciving data
+ * @param send the function to call for sending data
+ */
+LIBMEMCACHED_API
+void memached_protocol_set_io_functions(memcached_protocol_st *instance,
+ memcached_protocol_recv_func recv,
+ memcached_protocol_send_func send);
+
+
+/**
+ * Create a new client instance and associate it with a socket
+ * @param instance the protocol instance to bind the client to
+ * @param sock the client socket
+ * @return NULL if allocation fails, otherwise an instance
+ */
+LIBMEMCACHED_API
+memcached_protocol_client_st *memcached_protocol_create_client(memcached_protocol_st *instance, memcached_socket_t sock);
+
+/**
+ * Destroy a client handle.
+ * The caller needs to close the socket accociated with the client
+ * <b>before</b> calling this function. This function invalidates the
+ * client memory area.
+ *
+ * @param client the client to destroy
+ */
+LIBMEMCACHED_API
+void memcached_protocol_client_destroy(memcached_protocol_client_st *client);
+
+/**
+ * Error event means that the client encountered an error with the
+ * connection so you should shut it down
+ */
+#define MEMCACHED_PROTOCOL_ERROR_EVENT 1
+/**
+ * Please notify when there is more data available to read
+ */
+#define MEMCACHED_PROTOCOL_READ_EVENT 2
+/**
+ * Please notify when it is possible to send more data
+ */
+#define MEMCACHED_PROTOCOL_WRITE_EVENT 4
+/**
+ * Backed paused the execution for this client
+ */
+#define MEMCACHED_PROTOCOL_PAUSE_EVENT 8
+
+/**
+ * The different events the client is interested in. This is a bitmask of
+ * the constants defined above.
+ */
+typedef uint32_t memcached_protocol_event_t;
+
+/**
+ * Let the client do some work. This might involve reading / sending data
+ * to/from the client, or perform callbacks to execute a command.
+ * @param client the client structure to work on
+ * @return The next event the protocol handler will be notified for
+ */
+LIBMEMCACHED_API
+memcached_protocol_event_t memcached_protocol_client_work(memcached_protocol_client_st *client);
+
+/**
+ * Get the socket attached to a client handle
+ * @param client the client to query
+ * @return the socket handle
+ */
+LIBMEMCACHED_API
+memcached_socket_t memcached_protocol_client_get_socket(memcached_protocol_client_st *client);
+
+/**
+ * Get the error id socket attached to a client handle
+ * @param client the client to query for an error code
+ * @return the OS error code from the client
+ */
+LIBMEMCACHED_API
+int memcached_protocol_client_get_errno(memcached_protocol_client_st *client);
+
+/**
+ * Get a raw response handler for the given cookie
+ * @param cookie the cookie passed along into the callback
+ * @return the raw reponse handler you may use if you find
+ * the generic callback too limiting
+ */
+LIBMEMCACHED_API
+memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+
+nobase_include_HEADERS+= \
+ libmemcachedprotocol-0.0/binary.h \
+ libmemcachedprotocol-0.0/callback.h \
+ libmemcachedprotocol-0.0/handler.h \
+ libmemcachedprotocol-0.0/vbucket.h
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef enum {
+ vbucket_state_active = 1, /**< Actively servicing a vbucket. */
+ vbucket_state_replica, /**< Servicing a vbucket as a replica only. */
+ vbucket_state_pending, /**< Pending active. */
+ vbucket_state_dead /**< Not in use, pending deletion. */
+} vbucket_state_t;
+
+#define is_valid_vbucket_state_t(state) \
+ (state == vbucket_state_active || \
+ state == vbucket_state_replica || \
+ state == vbucket_state_pending || \
+ state == vbucket_state_dead)
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcachedprotocol/common.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Try to parse a key from the string.
+ * @pointer start pointer to a pointer to the string (IN and OUT)
+ * @return length of the string of -1 if this was an illegal key (invalid
+ * characters or invalid length)
+ * @todo add length!
+ */
+static uint16_t parse_ascii_key(char **start)
+{
+ uint16_t len= 0;
+ char *c= *start;
+ /* Strip leading whitespaces */
+ while (isspace(*c))
+ {
+ ++c;
+ }
+
+ *start= c;
+
+ while (*c != '\0' && !isspace(*c) && !iscntrl(*c))
+ {
+ ++c;
+ ++len;
+ }
+
+
+ if (len == 0 || len > 240 || (*c != '\0' && *c != '\r' && iscntrl(*c)))
+ {
+ return 0;
+ }
+
+ return len;
+}
+
+/**
+ * Spool a zero-terminated string
+ * @param client destination
+ * @param text the text to spool
+ * @return status of the spool operation
+ */
+static protocol_binary_response_status
+spool_string(memcached_protocol_client_st *client, const char *text)
+{
+ return client->root->spool(client, text, strlen(text));
+}
+
+/**
+ * Send a "CLIENT_ERROR" message back to the client with the correct
+ * format of the command being sent
+ * @param client the client to send the message to
+ */
+static void send_command_usage(memcached_protocol_client_st *client)
+{
+ const char *errmsg[]= {
+ [GET_CMD]= "CLIENT_ERROR: Syntax error: get <key>*\r\n",
+ [GETS_CMD]= "CLIENT_ERROR: Syntax error: gets <key>*\r\n",
+ [SET_CMD]= "CLIENT_ERROR: Syntax error: set <key> <flags> <exptime> <bytes> [noreply]\r\n",
+ [ADD_CMD]= "CLIENT_ERROR: Syntax error: add <key> <flags> <exptime> <bytes> [noreply]\r\n",
+ [REPLACE_CMD]= "CLIENT_ERROR: Syntax error: replace <key> <flags> <exptime> <bytes> [noreply]\r\n",
+ [CAS_CMD]= "CLIENT_ERROR: Syntax error: cas <key> <flags> <exptime> <bytes> <casid> [noreply]\r\n",
+ [APPEND_CMD]= "CLIENT_ERROR: Syntax error: append <key> <flags> <exptime> <bytes> [noreply]\r\n",
+ [PREPEND_CMD]= "CLIENT_ERROR: Syntax error: prepend <key> <flags> <exptime> <bytes> [noreply]\r\n",
+ [DELETE_CMD]= "CLIENT_ERROR: Syntax error: delete <key> [noreply]\r\n",
+ [INCR_CMD]= "CLIENT_ERROR: Syntax error: incr <key> <value> [noreply]\r\n",
+ [DECR_CMD]= "CLIENT_ERROR: Syntax error: decr <key> <value> [noreply]\r\n",
+ [STATS_CMD]= "CLIENT_ERROR: Syntax error: stats [key]\r\n",
+ [FLUSH_ALL_CMD]= "CLIENT_ERROR: Syntax error: flush_all [timeout] [noreply]\r\n",
+ [VERSION_CMD]= "CLIENT_ERROR: Syntax error: version\r\n",
+ [QUIT_CMD]="CLIENT_ERROR: Syntax error: quit\r\n",
+
+ [VERBOSITY_CMD]= "CLIENT_ERROR: Syntax error: verbosity <num>\r\n",
+ [UNKNOWN_CMD]= "CLIENT_ERROR: Unknown command\r\n",
+ };
+
+ client->mute = false;
+ spool_string(client, errmsg[client->ascii_command]);
+}
+
+/**
+ * Callback for the VERSION responses
+ * @param cookie client identifier
+ * @param text the length of the body
+ * @param textlen the length of the body
+ */
+static protocol_binary_response_status
+ascii_version_response_handler(const void *cookie,
+ const void *text,
+ uint32_t textlen)
+{
+ memcached_protocol_client_st *client= (memcached_protocol_client_st*)cookie;
+ spool_string(client, "VERSION ");
+ client->root->spool(client, text, textlen);
+ spool_string(client, "\r\n");
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the GET/GETQ/GETK and GETKQ responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ * @param flags the flags for the item
+ * @param cas the CAS id for the item
+ */
+static protocol_binary_response_status
+ascii_get_response_handler(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void *body,
+ uint32_t bodylen,
+ uint32_t flags,
+ uint64_t cas)
+{
+ memcached_protocol_client_st *client= (void*)cookie;
+ char buffer[300];
+ strcpy(buffer, "VALUE ");
+ const char *source= key;
+ char *dest= buffer + 6;
+
+ for (int x= 0; x < keylen; ++x)
+ {
+ if (*source != '\0' && !isspace(*source) && !iscntrl(*source))
+ {
+ *dest= *source;
+ }
+ else
+ {
+ return PROTOCOL_BINARY_RESPONSE_EINVAL; /* key constraints in ascii */
+ }
+
+ ++dest;
+ ++source;
+ }
+
+ size_t used= (size_t)(dest - buffer);
+
+ if (client->ascii_command == GETS_CMD)
+ {
+ snprintf(dest, sizeof(buffer) - used, " %u %u %" PRIu64 "\r\n", flags,
+ bodylen, cas);
+ }
+ else
+ {
+ snprintf(dest, sizeof(buffer) - used, " %u %u\r\n", flags, bodylen);
+ }
+
+ client->root->spool(client, buffer, strlen(buffer));
+ client->root->spool(client, body, bodylen);
+ client->root->spool(client, "\r\n", 2);
+
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the STAT responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ */
+static protocol_binary_response_status
+ascii_stat_response_handler(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void *body,
+ uint32_t bodylen)
+{
+
+ memcached_protocol_client_st *client= (void*)cookie;
+
+ if (key != NULL)
+ {
+ spool_string(client, "STAT ");
+ client->root->spool(client, key, keylen);
+ spool_string(client, " ");
+ client->root->spool(client, body, bodylen);
+ spool_string(client, "\r\n");
+ }
+ else
+ {
+ spool_string(client, "END\r\n");
+ }
+
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Process a get or a gets request.
+ * @param client the client handle
+ * @param buffer the complete get(s) command
+ * @param end the last character in the command
+ */
+static void ascii_process_gets(memcached_protocol_client_st *client,
+ char *buffer, char *end)
+{
+ char *key= buffer;
+
+ /* Skip command */
+ key += (client->ascii_command == GETS_CMD) ? 5 : 4;
+
+ int num_keys= 0;
+ while (key < end)
+ {
+ uint16_t nkey= parse_ascii_key(&key);
+ if (nkey == 0) /* Invalid key... stop processing this line */
+ {
+ break;
+ }
+
+ (void)client->root->callback->interface.v1.get(client, key, nkey,
+ ascii_get_response_handler);
+ key += nkey;
+ ++num_keys;
+ }
+
+ if (num_keys == 0)
+ {
+ send_command_usage(client);
+ }
+ else
+ client->root->spool(client, "END\r\n", 5);
+}
+
+/**
+ * Try to split up the command line "asdf asdf asdf asdf\n" into an
+ * argument vector for easier parsing.
+ * @param start the first character in the command line
+ * @param end the last character in the command line ("\n")
+ * @param vec the vector to insert the pointers into
+ * @size the number of elements in the vector
+ * @return the number of tokens in the vector
+ */
+static int ascii_tokenize_command(char *str, char *end, char **vec, int size)
+{
+ int elem= 0;
+
+ while (str < end)
+ {
+ /* Skip leading blanks */
+ while (str < end && isspace(*str))
+ {
+ ++str;
+ }
+
+ if (str == end)
+ {
+ return elem;
+ }
+
+ vec[elem++]= str;
+ /* find the next non-blank field */
+ while (str < end && !isspace(*str))
+ {
+ ++str;
+ }
+
+ /* zero-terminate it for easier parsing later on */
+ *str= '\0';
+ ++str;
+
+ /* Is the vector full? */
+ if (elem == size)
+ {
+ break;
+ }
+ }
+
+ return elem;
+}
+
+/**
+ * If we for some reasons needs to push the line back to read more
+ * data we have to reverse the tokenization. Just do the brain-dead replace
+ * of all '\0' to ' ' and set the last character to '\n'. We could have used
+ * the vector we created, but then we would have to search for all of the
+ * spaces we ignored...
+ * @param start pointer to the first character in the buffer to recover
+ * @param end pointer to the last character in the buffer to recover
+ */
+static void recover_tokenize_command(char *start, char *end)
+{
+ while (start < end)
+ {
+ if (*start == '\0')
+ *start= ' ';
+ ++start;
+ }
+
+ *end= '\n';
+}
+
+/**
+ * Convert the textual command into a comcode
+ */
+static enum ascii_cmd ascii_to_cmd(char *start, size_t length)
+{
+ struct {
+ const char *cmd;
+ size_t len;
+ enum ascii_cmd cc;
+ } commands[]= {
+ { .cmd= "get", .len= 3, .cc= GET_CMD },
+ { .cmd= "gets", .len= 4, .cc= GETS_CMD },
+ { .cmd= "set", .len= 3, .cc= SET_CMD },
+ { .cmd= "add", .len= 3, .cc= ADD_CMD },
+ { .cmd= "replace", .len= 7, .cc= REPLACE_CMD },
+ { .cmd= "cas", .len= 3, .cc= CAS_CMD },
+ { .cmd= "append", .len= 6, .cc= APPEND_CMD },
+ { .cmd= "prepend", .len= 7, .cc= PREPEND_CMD },
+ { .cmd= "delete", .len= 6, .cc= DELETE_CMD },
+ { .cmd= "incr", .len= 4, .cc= INCR_CMD },
+ { .cmd= "decr", .len= 4, .cc= DECR_CMD },
+ { .cmd= "stats", .len= 5, .cc= STATS_CMD },
+ { .cmd= "flush_all", .len= 9, .cc= FLUSH_ALL_CMD },
+ { .cmd= "version", .len= 7, .cc= VERSION_CMD },
+ { .cmd= "quit", .len= 4, .cc= QUIT_CMD },
+ { .cmd= "verbosity", .len= 9, .cc= VERBOSITY_CMD },
+ { .cmd= NULL, .len= 0, .cc= UNKNOWN_CMD }};
+
+ int x= 0;
+ while (commands[x].len > 0) {
+ if (length >= commands[x].len)
+ {
+ if (strncmp(start, commands[x].cmd, commands[x].len) == 0)
+ {
+ /* Potential hit */
+ if (length == commands[x].len || isspace(*(start + commands[x].len)))
+ {
+ return commands[x].cc;
+ }
+ }
+ }
+ ++x;
+ }
+
+ return UNKNOWN_CMD;
+}
+
+/**
+ * Perform a delete operation.
+ *
+ * @param client client requesting the deletion
+ * @param tokens the command as a vector
+ * @param ntokens the number of items in the vector
+ */
+static void process_delete(memcached_protocol_client_st *client,
+ char **tokens, int ntokens)
+{
+ char *key= tokens[1];
+ uint16_t nkey;
+
+ if (ntokens != 2 || (nkey= parse_ascii_key(&key)) == 0)
+ {
+ send_command_usage(client);
+ return;
+ }
+
+ if (client->root->callback->interface.v1.delete == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return;
+ }
+
+ protocol_binary_response_status rval;
+ rval= client->root->callback->interface.v1.delete(client, key, nkey, 0);
+
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+ {
+ spool_string(client, "DELETED\r\n");
+ }
+ else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
+ {
+ spool_string(client, "NOT_FOUND\r\n");
+ }
+ else
+ {
+ char msg[80];
+ snprintf(msg, sizeof(msg), "SERVER_ERROR: delete failed %u\r\n",(uint32_t)rval);
+ spool_string(client, msg);
+ }
+}
+
+static void process_arithmetic(memcached_protocol_client_st *client,
+ char **tokens, int ntokens)
+{
+ char *key= tokens[1];
+ uint16_t nkey;
+
+ if (ntokens != 3 || (nkey= parse_ascii_key(&key)) == 0)
+ {
+ send_command_usage(client);
+ return;
+ }
+
+ uint64_t cas;
+ uint64_t result;
+ uint64_t delta= strtoull(tokens[2], NULL, 10);
+
+ protocol_binary_response_status rval;
+ if (client->ascii_command == INCR_CMD)
+ {
+ if (client->root->callback->interface.v1.increment == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return;
+ }
+ rval= client->root->callback->interface.v1.increment(client,
+ key, nkey,
+ delta, 0,
+ 0,
+ &result,
+ &cas);
+ }
+ else
+ {
+ if (client->root->callback->interface.v1.decrement == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return;
+ }
+ rval= client->root->callback->interface.v1.decrement(client,
+ key, nkey,
+ delta, 0,
+ 0,
+ &result,
+ &cas);
+ }
+
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+ {
+ char buffer[80];
+ snprintf(buffer, sizeof(buffer), "%"PRIu64"\r\n", result);
+ spool_string(client, buffer);
+ }
+ else
+ {
+ spool_string(client, "NOT_FOUND\r\n");
+ }
+}
+
+/**
+ * Process the stats command (with or without a key specified)
+ * @param key pointer to the first character after "stats"
+ * @param end pointer to the "\n"
+ */
+static void process_stats(memcached_protocol_client_st *client,
+ char *key, char *end)
+{
+ if (client->root->callback->interface.v1.stat == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return;
+ }
+
+ while (isspace(*key))
+ key++;
+
+ uint16_t nkey= (uint16_t)(end - key);
+ (void)client->root->callback->interface.v1.stat(client, key, nkey,
+ ascii_stat_response_handler);
+}
+
+static void process_version(memcached_protocol_client_st *client,
+ char **tokens, int ntokens)
+{
+ (void)tokens;
+ if (ntokens != 1)
+ {
+ send_command_usage(client);
+ return;
+ }
+
+ if (client->root->callback->interface.v1.version == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return;
+ }
+
+ client->root->callback->interface.v1.version(client,
+ ascii_version_response_handler);
+}
+
+static void process_flush(memcached_protocol_client_st *client,
+ char **tokens, int ntokens)
+{
+ if (ntokens > 2)
+ {
+ send_command_usage(client);
+ return;
+ }
+
+ if (client->root->callback->interface.v1.flush == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return;
+ }
+
+ uint32_t timeout= 0;
+ if (ntokens == 2)
+ {
+ timeout= (uint32_t)strtoul(tokens[1], NULL, 10);
+ }
+
+ protocol_binary_response_status rval;
+ rval= client->root->callback->interface.v1.flush(client, timeout);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+ spool_string(client, "OK\r\n");
+ else
+ spool_string(client, "SERVER_ERROR: internal error\r\n");
+}
+
+/**
+ * Process one of the storage commands
+ * @param client the client performing the operation
+ * @param tokens the command tokens
+ * @param ntokens the number of tokens
+ * @param start pointer to the first character in the line
+ * @param end pointer to the pointer where the last character of this
+ * command is (IN and OUT)
+ * @param length the number of bytes available
+ * @return -1 if an error occurs (and we should just terminate the connection
+ * because we are out of sync)
+ * 0 storage command completed, continue processing
+ * 1 We need more data, so just go ahead and wait for more!
+ */
+static inline int process_storage_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ (void)ntokens; /* already checked */
+ char *key= tokens[1];
+ uint16_t nkey= parse_ascii_key(&key);
+ if (nkey == 0)
+ {
+ /* return error */
+ spool_string(client, "CLIENT_ERROR: bad key\r\n");
+ return -1;
+ }
+
+ uint32_t flags= (uint32_t)strtoul(tokens[2], NULL, 10);
+ uint32_t timeout= (uint32_t)strtoul(tokens[3], NULL, 10);
+ unsigned long nbytes= strtoul(tokens[4], NULL, 10);
+
+ /* Do we have all data? */
+ unsigned long need= nbytes + (unsigned long)((*end - start) + 1) + 2; /* \n\r\n */
+ if ((ssize_t)need > length)
+ {
+ /* Keep on reading */
+ recover_tokenize_command(start, *end);
+ return 1;
+ }
+
+ void *data= (*end) + 1;
+ uint64_t cas= 0;
+ uint64_t result_cas;
+ protocol_binary_response_status rval;
+ switch (client->ascii_command)
+ {
+ case SET_CMD:
+ rval= client->root->callback->interface.v1.set(client, key,
+ (uint16_t)nkey,
+ data,
+ (uint32_t)nbytes,
+ flags,
+ timeout, cas,
+ &result_cas);
+ break;
+ case ADD_CMD:
+ rval= client->root->callback->interface.v1.add(client, key,
+ (uint16_t)nkey,
+ data,
+ (uint32_t)nbytes,
+ flags,
+ timeout, &result_cas);
+ break;
+ case CAS_CMD:
+ cas= strtoull(tokens[5], NULL, 10);
+ /* FALLTHROUGH */
+ case REPLACE_CMD:
+ rval= client->root->callback->interface.v1.replace(client, key,
+ (uint16_t)nkey,
+ data,
+ (uint32_t)nbytes,
+ flags,
+ timeout, cas,
+ &result_cas);
+ break;
+ case APPEND_CMD:
+ rval= client->root->callback->interface.v1.append(client, key,
+ (uint16_t)nkey,
+ data,
+ (uint32_t)nbytes,
+ cas,
+ &result_cas);
+ break;
+ case PREPEND_CMD:
+ rval= client->root->callback->interface.v1.prepend(client, key,
+ (uint16_t)nkey,
+ data,
+ (uint32_t)nbytes,
+ cas,
+ &result_cas);
+ break;
+
+ /* gcc complains if I don't put all of the enums in here.. */
+ case GET_CMD:
+ case GETS_CMD:
+ case DELETE_CMD:
+ case DECR_CMD:
+ case INCR_CMD:
+ case STATS_CMD:
+ case FLUSH_ALL_CMD:
+ case VERSION_CMD:
+ case QUIT_CMD:
+ case VERBOSITY_CMD:
+ case UNKNOWN_CMD:
+ default:
+ abort(); /* impossible */
+ }
+
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+ {
+ spool_string(client, "STORED\r\n");
+ }
+ else
+ {
+ if (client->ascii_command == CAS_CMD)
+ {
+ if (rval == PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS)
+ {
+ spool_string(client, "EXISTS\r\n");
+ }
+ else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
+ {
+ spool_string(client, "NOT_FOUND\r\n");
+ }
+ else
+ {
+ spool_string(client, "NOT_STORED\r\n");
+ }
+ }
+ else
+ {
+ spool_string(client, "NOT_STORED\r\n");
+ }
+ }
+
+ *end += nbytes + 2;
+
+ return 0;
+}
+
+static int process_cas_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ if (ntokens != 6)
+ {
+ send_command_usage(client);
+ return false;
+ }
+
+ if (client->root->callback->interface.v1.replace == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return false;
+ }
+
+ return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_set_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ if (ntokens != 5)
+ {
+ send_command_usage(client);
+ return false;
+ }
+
+ if (client->root->callback->interface.v1.set == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return false;
+ }
+
+ return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_add_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ if (ntokens != 5)
+ {
+ send_command_usage(client);
+ return false;
+ }
+
+ if (client->root->callback->interface.v1.add == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return false;
+ }
+
+ return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_replace_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ if (ntokens != 5)
+ {
+ send_command_usage(client);
+ return false;
+ }
+
+ if (client->root->callback->interface.v1.replace == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return false;
+ }
+
+ return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_append_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ if (ntokens != 5)
+ {
+ send_command_usage(client);
+ return false;
+ }
+
+ if (client->root->callback->interface.v1.append == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return false;
+ }
+
+ return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_prepend_command(memcached_protocol_client_st *client,
+ char **tokens, int ntokens, char *start,
+ char **end, ssize_t length)
+{
+ if (ntokens != 5)
+ {
+ send_command_usage(client);
+ return false;
+ }
+
+ if (client->root->callback->interface.v1.prepend == NULL)
+ {
+ spool_string(client, "SERVER_ERROR: callback not implemented\r\n");
+ return false;
+ }
+
+ return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+/**
+ * The ASCII protocol support is just one giant big hack. Instead of adding
+ * a optimal ascii support, I just convert the ASCII commands to the binary
+ * protocol and calls back into the command handlers for the binary protocol ;)
+ */
+memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
+{
+ char *ptr= (char*)client->root->input_buffer;
+ *endptr= ptr;
+
+ do {
+ /* Do we have \n (indicating the command preamble)*/
+ char *end= memchr(ptr, '\n', (size_t)*length);
+ if (end == NULL)
+ {
+ *endptr= ptr;
+ return MEMCACHED_PROTOCOL_READ_EVENT;
+ }
+
+ client->ascii_command= ascii_to_cmd(ptr, (size_t)(*length));
+
+ /* A multiget lists all of the keys, and I don't want to have an
+ * avector of let's say 512 pointers to tokenize all of them, so let's
+ * just handle them immediately
+ */
+ if (client->ascii_command == GET_CMD ||
+ client->ascii_command == GETS_CMD) {
+ if (client->root->callback->interface.v1.get != NULL)
+ ascii_process_gets(client, ptr, end);
+ else
+ spool_string(client, "SERVER_ERROR: Command not implemented\n");
+ } else {
+ /* None of the defined commands takes 10 parameters, so lets just use
+ * that as a maximum limit.
+ */
+ char *tokens[10];
+ int ntokens= ascii_tokenize_command(ptr, end, tokens, 10);
+
+ if (ntokens < 10)
+ {
+ client->mute= strcmp(tokens[ntokens - 1], "noreply") == 0;
+ if (client->mute)
+ --ntokens; /* processed noreply token*/
+ }
+
+ int error= 0;
+
+ switch (client->ascii_command) {
+ case SET_CMD:
+ error= process_set_command(client, tokens, ntokens, ptr, &end, *length);
+ break;
+ case ADD_CMD:
+ error= process_add_command(client, tokens, ntokens, ptr, &end, *length);
+ break;
+ case REPLACE_CMD:
+ error= process_replace_command(client, tokens, ntokens,
+ ptr, &end, *length);
+ break;
+ case CAS_CMD:
+ error= process_cas_command(client, tokens, ntokens, ptr, &end, *length);
+ break;
+ case APPEND_CMD:
+ error= process_append_command(client, tokens, ntokens,
+ ptr, &end, *length);
+ break;
+ case PREPEND_CMD:
+ error= process_prepend_command(client, tokens, ntokens,
+ ptr, &end, *length);
+ break;
+ case DELETE_CMD:
+ process_delete(client, tokens, ntokens);
+ break;
+
+ case INCR_CMD: /* FALLTHROUGH */
+ case DECR_CMD:
+ process_arithmetic(client, tokens, ntokens);
+ break;
+ case STATS_CMD:
+ if (client->mute)
+ {
+ send_command_usage(client);
+ }
+ else
+ {
+ recover_tokenize_command(ptr, end);
+ process_stats(client, ptr + 6, end);
+ }
+ break;
+ case FLUSH_ALL_CMD:
+ process_flush(client, tokens, ntokens);
+ break;
+ case VERSION_CMD:
+ if (client->mute)
+ {
+ send_command_usage(client);
+ }
+ else
+ {
+ process_version(client, tokens, ntokens);
+ }
+ break;
+ case QUIT_CMD:
+ if (ntokens != 1 || client->mute)
+ {
+ send_command_usage(client);
+ }
+ else
+ {
+ if (client->root->callback->interface.v1.quit != NULL)
+ client->root->callback->interface.v1.quit(client);
+
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+ break;
+
+ case VERBOSITY_CMD:
+ if (ntokens != 2)
+ send_command_usage(client);
+ else
+ spool_string(client, "OK\r\n");
+ break;
+
+ case UNKNOWN_CMD:
+ send_command_usage(client);
+ break;
+
+ case GET_CMD:
+ case GETS_CMD:
+ default:
+ /* Should already be handled */
+ abort();
+ }
+
+ if (error == -1)
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ else if (error == 1)
+ return MEMCACHED_PROTOCOL_READ_EVENT;
+ }
+
+ /* Move past \n */
+ ++end;
+ *length -= end - ptr;
+ ptr= end;
+ } while (*length > 0);
+
+ *endptr= ptr;
+ return MEMCACHED_PROTOCOL_READ_EVENT;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+LIBMEMCACHED_LOCAL
+memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcachedprotocol/common.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+
+/*
+** **********************************************************************
+** INTERNAL INTERFACE
+** **********************************************************************
+*/
+
+/**
+ * Send a preformatted packet back to the client. If the connection is in
+ * pedantic mode, it will validate the packet and refuse to send it if it
+ * breaks the specification.
+ *
+ * @param cookie client identification
+ * @param request the original request packet
+ * @param response the packet to send
+ * @return The status of the operation
+ */
+static protocol_binary_response_status
+raw_response_handler(const void *cookie,
+ protocol_binary_request_header *request,
+ protocol_binary_response_header *response)
+{
+ memcached_protocol_client_st *client= (void*)cookie;
+
+ if (client->root->pedantic &&
+ !memcached_binary_protocol_pedantic_check_response(request, response))
+ {
+ return PROTOCOL_BINARY_RESPONSE_EINVAL;
+ }
+
+ if (!client->root->drain(client))
+ {
+ return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+ }
+
+ size_t len= sizeof(*response) + htonl(response->response.bodylen);
+ size_t offset= 0;
+ char *ptr= (void*)response;
+
+ if (client->output == NULL)
+ {
+ /* I can write directly to the socket.... */
+ do
+ {
+ size_t num_bytes= len - offset;
+ ssize_t nw= client->root->send(client,
+ client->sock,
+ ptr + offset,
+ num_bytes);
+ if (nw == -1)
+ {
+ if (get_socket_errno() == EWOULDBLOCK)
+ {
+ break;
+ }
+ else if (get_socket_errno() != EINTR)
+ {
+ client->error= errno;
+ return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+ }
+ }
+ else
+ {
+ offset += (size_t)nw;
+ }
+ } while (offset < len);
+ }
+
+ return client->root->spool(client, ptr, len - offset);
+}
+
+/*
+ * Version 0 of the interface is really low level and protocol specific,
+ * while the version 1 of the interface is more API focused. We need a
+ * way to translate between the command codes on the wire and the
+ * application level interface in V1, so let's just use the V0 of the
+ * interface as a map instead of creating a huuuge switch :-)
+ */
+
+/**
+ * Callback for the GET/GETQ/GETK and GETKQ responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ * @param flags the flags for the item
+ * @param cas the CAS id for the item
+ */
+static protocol_binary_response_status
+get_response_handler(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void *body,
+ uint32_t bodylen,
+ uint32_t flags,
+ uint64_t cas) {
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ uint8_t opcode= client->current_command->request.opcode;
+
+ if (opcode == PROTOCOL_BINARY_CMD_GET || opcode == PROTOCOL_BINARY_CMD_GETQ)
+ {
+ keylen= 0;
+ }
+
+ protocol_binary_response_get response= {
+ .message.header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= opcode,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= client->current_command->request.opaque,
+ .cas= memcached_htonll(cas),
+ .keylen= htons(keylen),
+ .extlen= 4,
+ .bodylen= htonl(bodylen + keylen + 4),
+ },
+ };
+
+ response.message.body.flags= htonl(flags);
+
+ protocol_binary_response_status rval;
+ const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+ if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
+ (rval= client->root->spool(client, key, keylen)) != success ||
+ (rval= client->root->spool(client, body, bodylen)) != success)
+ {
+ return rval;
+ }
+
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the STAT responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ */
+static protocol_binary_response_status stat_response_handler(const void *cookie,
+ const void *key,
+ uint16_t keylen,
+ const void *body,
+ uint32_t bodylen)
+{
+
+ memcached_protocol_client_st *client= (void*)cookie;
+
+ protocol_binary_response_no_extras response= {
+ .message.header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= client->current_command->request.opcode,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= client->current_command->request.opaque,
+ .keylen= htons(keylen),
+ .bodylen= htonl(bodylen + keylen),
+ .cas= 0
+ },
+ };
+
+ protocol_binary_response_status rval;
+ const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+ if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
+ (rval= client->root->spool(client, key, keylen)) != success ||
+ (rval= client->root->spool(client, body, bodylen)) != success)
+ {
+ return rval;
+ }
+
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the VERSION responses
+ * @param cookie client identifier
+ * @param text the length of the body
+ * @param textlen the length of the body
+ */
+static protocol_binary_response_status
+version_response_handler(const void *cookie,
+ const void *text,
+ uint32_t textlen) {
+
+ memcached_protocol_client_st *client= (void*)cookie;
+
+ protocol_binary_response_no_extras response= {
+ .message.header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= client->current_command->request.opcode,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= client->current_command->request.opaque,
+ .bodylen= htonl(textlen),
+ .cas= 0
+ },
+ };
+
+ protocol_binary_response_status rval;
+ const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+ if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
+ (rval= client->root->spool(client, text, textlen)) != success)
+ {
+ return rval;
+ }
+
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for ADD and ADDQ
+ * @param cookie the calling client
+ * @param header the add/addq command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+add_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.add != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
+ protocol_binary_request_add *request= (void*)header;
+ uint32_t flags= ntohl(request->message.body.flags);
+ uint32_t timeout= ntohl(request->message.body.expiration);
+ char *key= ((char*)header) + sizeof(*header) + 8;
+ char *data= key + keylen;
+ uint64_t cas;
+
+ rval= client->root->callback->interface.v1.add(cookie, key, keylen,
+ data, datalen, flags,
+ timeout, &cas);
+
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_ADD)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_ADD,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(cas)
+ }
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for DECREMENT and DECREMENTQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+decrement_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.decrement != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ protocol_binary_request_decr *request= (void*)header;
+ uint64_t init= memcached_ntohll(request->message.body.initial);
+ uint64_t delta= memcached_ntohll(request->message.body.delta);
+ uint32_t timeout= ntohl(request->message.body.expiration);
+ void *key= request->bytes + sizeof(request->bytes);
+ uint64_t result;
+ uint64_t cas;
+
+ rval= client->root->callback->interface.v1.decrement(cookie, key, keylen,
+ delta, init, timeout,
+ &result, &cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_DECREMENT)
+ {
+ /* Send a positive request */
+ protocol_binary_response_decr response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_DECREMENT,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(cas),
+ .bodylen= htonl(8)
+ },
+ .body.value= memcached_htonll(result)
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for DELETE and DELETEQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+delete_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.delete != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ void *key= (header +1);
+ uint64_t cas= memcached_ntohll(header->request.cas);
+ rval= client->root->callback->interface.v1.delete(cookie, key, keylen, cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_DELETE)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_DELETE,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ }
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for FLUSH and FLUSHQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+flush_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.flush != NULL)
+ {
+ protocol_binary_request_flush *flush= (void*)header;
+ uint32_t timeout= 0;
+ if (htonl(header->request.bodylen) == 4)
+ {
+ timeout= ntohl(flush->message.body.expiration);
+ }
+
+ rval= client->root->callback->interface.v1.flush(cookie, timeout);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_FLUSH)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_FLUSH,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ }
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for GET, GETK, GETQ, GETKQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+get_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.get != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ void *key= (header + 1);
+ rval= client->root->callback->interface.v1.get(cookie, key, keylen,
+ get_response_handler);
+
+ if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT &&
+ (header->request.opcode == PROTOCOL_BINARY_CMD_GETQ ||
+ header->request.opcode == PROTOCOL_BINARY_CMD_GETKQ))
+ {
+ /* Quiet commands shouldn't respond on cache misses */
+ rval= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for INCREMENT and INCREMENTQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+increment_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.increment != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ protocol_binary_request_incr *request= (void*)header;
+ uint64_t init= memcached_ntohll(request->message.body.initial);
+ uint64_t delta= memcached_ntohll(request->message.body.delta);
+ uint32_t timeout= ntohl(request->message.body.expiration);
+ void *key= request->bytes + sizeof(request->bytes);
+ uint64_t cas;
+ uint64_t result;
+
+ rval= client->root->callback->interface.v1.increment(cookie, key, keylen,
+ delta, init, timeout,
+ &result, &cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_INCREMENT)
+ {
+ /* Send a positive request */
+ protocol_binary_response_incr response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_INCREMENT,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(cas),
+ .bodylen= htonl(8)
+ },
+ .body.value= memcached_htonll(result)
+ }
+ };
+
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for noop. Inform the v1 interface about the noop packet, and
+ * create and send a packet back to the client
+ *
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler the response handler
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+noop_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.noop != NULL)
+ {
+ client->root->callback->interface.v1.noop(cookie);
+ }
+
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_NOOP,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ }
+ }
+ };
+
+ return response_handler(cookie, header, (void*)&response);
+}
+
+/**
+ * Callback for APPEND and APPENDQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+append_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.append != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ uint32_t datalen= ntohl(header->request.bodylen) - keylen;
+ char *key= (void*)(header +1);
+ char *data= key +keylen;
+ uint64_t cas= memcached_ntohll(header->request.cas);
+ uint64_t result_cas;
+
+ rval= client->root->callback->interface.v1.append(cookie, key, keylen,
+ data, datalen, cas,
+ &result_cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_APPEND)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_APPEND,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(result_cas),
+ },
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for PREPEND and PREPENDQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+prepend_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.prepend != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ uint32_t datalen= ntohl(header->request.bodylen) - keylen;
+ char *key= (char*)(header + 1);
+ char *data= key + keylen;
+ uint64_t cas= memcached_ntohll(header->request.cas);
+ uint64_t result_cas;
+ rval= client->root->callback->interface.v1.prepend(cookie, key, keylen,
+ data, datalen, cas,
+ &result_cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_PREPEND)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_PREPEND,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(result_cas),
+ },
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for QUIT and QUITQ. Notify the client and shut down the connection
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+quit_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.quit != NULL)
+ {
+ client->root->callback->interface.v1.quit(cookie);
+ }
+
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_QUIT,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque
+ }
+ }
+ };
+
+ if (header->request.opcode == PROTOCOL_BINARY_CMD_QUIT)
+ {
+ response_handler(cookie, header, (void*)&response);
+ }
+
+ /* I need a better way to signal to close the connection */
+ return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+}
+
+/**
+ * Callback for REPLACE and REPLACEQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+replace_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.replace != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
+ protocol_binary_request_replace *request= (void*)header;
+ uint32_t flags= ntohl(request->message.body.flags);
+ uint32_t timeout= ntohl(request->message.body.expiration);
+ char *key= ((char*)header) + sizeof(*header) + 8;
+ char *data= key + keylen;
+ uint64_t cas= memcached_ntohll(header->request.cas);
+ uint64_t result_cas;
+
+ rval= client->root->callback->interface.v1.replace(cookie, key, keylen,
+ data, datalen, flags,
+ timeout, cas,
+ &result_cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_REPLACE)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_REPLACE,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(result_cas),
+ },
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for SET and SETQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+set_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.set != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+ uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
+ protocol_binary_request_replace *request= (void*)header;
+ uint32_t flags= ntohl(request->message.body.flags);
+ uint32_t timeout= ntohl(request->message.body.expiration);
+ char *key= ((char*)header) + sizeof(*header) + 8;
+ char *data= key + keylen;
+ uint64_t cas= memcached_ntohll(header->request.cas);
+ uint64_t result_cas;
+
+
+ rval= client->root->callback->interface.v1.set(cookie, key, keylen,
+ data, datalen, flags,
+ timeout, cas, &result_cas);
+ if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ header->request.opcode == PROTOCOL_BINARY_CMD_SET)
+ {
+ /* Send a positive request */
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= PROTOCOL_BINARY_CMD_SET,
+ .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+ .opaque= header->request.opaque,
+ .cas= memcached_ntohll(result_cas),
+ },
+ }
+ };
+ rval= response_handler(cookie, header, (void*)&response);
+ }
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for STAT
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+stat_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.stat != NULL)
+ {
+ uint16_t keylen= ntohs(header->request.keylen);
+
+ rval= client->root->callback->interface.v1.stat(cookie,
+ (void*)(header + 1),
+ keylen,
+ stat_response_handler);
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * Callback for VERSION
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+version_command_handler(const void *cookie,
+ protocol_binary_request_header *header,
+ memcached_binary_protocol_raw_response_handler response_handler)
+{
+ (void)response_handler;
+ (void)header;
+ protocol_binary_response_status rval;
+
+ memcached_protocol_client_st *client= (void*)cookie;
+ if (client->root->callback->interface.v1.version != NULL)
+ {
+ rval= client->root->callback->interface.v1.version(cookie,
+ version_response_handler);
+ }
+ else
+ {
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ }
+
+ return rval;
+}
+
+/**
+ * The map to remap between the com codes and the v1 logical setting
+ */
+static memcached_binary_protocol_command_handler comcode_v0_v1_remap[256]= {
+ [PROTOCOL_BINARY_CMD_ADDQ]= add_command_handler,
+ [PROTOCOL_BINARY_CMD_ADD]= add_command_handler,
+ [PROTOCOL_BINARY_CMD_APPENDQ]= append_command_handler,
+ [PROTOCOL_BINARY_CMD_APPEND]= append_command_handler,
+ [PROTOCOL_BINARY_CMD_DECREMENTQ]= decrement_command_handler,
+ [PROTOCOL_BINARY_CMD_DECREMENT]= decrement_command_handler,
+ [PROTOCOL_BINARY_CMD_DELETEQ]= delete_command_handler,
+ [PROTOCOL_BINARY_CMD_DELETE]= delete_command_handler,
+ [PROTOCOL_BINARY_CMD_FLUSHQ]= flush_command_handler,
+ [PROTOCOL_BINARY_CMD_FLUSH]= flush_command_handler,
+ [PROTOCOL_BINARY_CMD_GETKQ]= get_command_handler,
+ [PROTOCOL_BINARY_CMD_GETK]= get_command_handler,
+ [PROTOCOL_BINARY_CMD_GETQ]= get_command_handler,
+ [PROTOCOL_BINARY_CMD_GET]= get_command_handler,
+ [PROTOCOL_BINARY_CMD_INCREMENTQ]= increment_command_handler,
+ [PROTOCOL_BINARY_CMD_INCREMENT]= increment_command_handler,
+ [PROTOCOL_BINARY_CMD_NOOP]= noop_command_handler,
+ [PROTOCOL_BINARY_CMD_PREPENDQ]= prepend_command_handler,
+ [PROTOCOL_BINARY_CMD_PREPEND]= prepend_command_handler,
+ [PROTOCOL_BINARY_CMD_QUITQ]= quit_command_handler,
+ [PROTOCOL_BINARY_CMD_QUIT]= quit_command_handler,
+ [PROTOCOL_BINARY_CMD_REPLACEQ]= replace_command_handler,
+ [PROTOCOL_BINARY_CMD_REPLACE]= replace_command_handler,
+ [PROTOCOL_BINARY_CMD_SETQ]= set_command_handler,
+ [PROTOCOL_BINARY_CMD_SET]= set_command_handler,
+ [PROTOCOL_BINARY_CMD_STAT]= stat_command_handler,
+ [PROTOCOL_BINARY_CMD_VERSION]= version_command_handler,
+};
+
+/**
+ * Try to execute a command. Fire the pre/post functions and the specialized
+ * handler function if it's set. If not, the unknown probe should be fired
+ * if it's present.
+ * @param client the client connection to operate on
+ * @param header the command to execute
+ * @return true if success or false if a fatal error occured so that the
+ * connection should be shut down.
+ */
+static protocol_binary_response_status execute_command(memcached_protocol_client_st *client, protocol_binary_request_header *header)
+{
+ if (client->root->pedantic &&
+ memcached_binary_protocol_pedantic_check_request(header))
+ {
+ /* @todo return invalid command packet */
+ }
+
+ /* we got all data available, execute the callback! */
+ if (client->root->callback->pre_execute != NULL)
+ {
+ client->root->callback->pre_execute(client, header);
+ }
+
+ protocol_binary_response_status rval;
+ rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+ uint8_t cc= header->request.opcode;
+
+ switch (client->root->callback->interface_version)
+ {
+ case 0:
+ if (client->root->callback->interface.v0.comcode[cc] != NULL) {
+ rval= client->root->callback->interface.v0.comcode[cc](client, header, raw_response_handler);
+ }
+ break;
+ case 1:
+ if (comcode_v0_v1_remap[cc] != NULL) {
+ rval= comcode_v0_v1_remap[cc](client, header, raw_response_handler);
+ }
+ break;
+ default:
+ /* Unknown interface.
+ * It should be impossible to get here so I'll just call abort
+ * to avoid getting a compiler warning :-)
+ */
+ abort();
+ }
+
+
+ if (rval == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND &&
+ client->root->callback->unknown != NULL)
+ {
+ rval= client->root->callback->unknown(client, header, raw_response_handler);
+ }
+
+ if (rval != PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+ rval != PROTOCOL_BINARY_RESPONSE_EINTERNAL &&
+ rval != PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
+ {
+ protocol_binary_response_no_extras response= {
+ .message= {
+ .header.response= {
+ .magic= PROTOCOL_BINARY_RES,
+ .opcode= cc,
+ .status= htons(rval),
+ .opaque= header->request.opaque,
+ },
+ }
+ };
+ rval= raw_response_handler(client, header, (void*)&response);
+ }
+
+ if (client->root->callback->post_execute != NULL)
+ {
+ client->root->callback->post_execute(client, header);
+ }
+
+ return rval;
+}
+
+/*
+** **********************************************************************
+** "PROTOECTED" INTERFACE
+** **********************************************************************
+*/
+memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
+{
+ /* try to parse all of the received packets */
+ protocol_binary_request_header *header;
+ header= (void*)client->root->input_buffer;
+ if (header->request.magic != (uint8_t)PROTOCOL_BINARY_REQ)
+ {
+ client->error= EINVAL;
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+ ssize_t len= *length;
+
+ while (len >= (ssize_t)sizeof(*header) &&
+ (len >= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen))))
+ {
+ /* I have the complete package */
+ client->current_command= header;
+ protocol_binary_response_status rv= execute_command(client, header);
+
+ if (rv == PROTOCOL_BINARY_RESPONSE_EINTERNAL)
+ {
+ *length= len;
+ *endptr= (void*)header;
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ } else if (rv == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
+ return MEMCACHED_PROTOCOL_PAUSE_EVENT;
+
+ ssize_t total= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen));
+ len -= total;
+ if (len > 0)
+ {
+ intptr_t ptr= (intptr_t)header;
+ ptr += total;
+ if ((ptr % 8) == 0)
+ {
+ header= (void*)ptr;
+ }
+ else
+ {
+ /* Fix alignment */
+ memmove(client->root->input_buffer, (void*)ptr, (size_t)len);
+ header= (void*)client->root->input_buffer;
+ }
+ }
+ *length= len;
+ *endptr= (void*)header;
+ }
+
+ return MEMCACHED_PROTOCOL_READ_EVENT;
+}
+
+/*
+** **********************************************************************
+** PUBLIC INTERFACE
+** **********************************************************************
+*/
+memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance)
+{
+ return instance->callback;
+}
+
+void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback)
+{
+ instance->callback= callback;
+}
+
+memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie)
+{
+ (void)cookie;
+ return raw_response_handler;
+}
+
+void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable)
+{
+ instance->pedantic= enable;
+}
+
+bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance)
+{
+ return instance->pedantic;
+}
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+LIBMEMCACHED_LOCAL
+bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request);
+
+LIBMEMCACHED_LOCAL
+bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
+ const protocol_binary_response_header *response);
+
+LIBMEMCACHED_LOCAL
+memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#ifndef NDEBUG
+#include <signal.h>
+#endif
+
+#include <libmemcachedprotocol/common.h>
+
+#ifndef NDEBUG
+const uint64_t redzone_pattern = 0xdeadbeefcafebabe;
+int cache_error = 0;
+#endif
+
+const size_t initial_pool_size = 64;
+
+cache_t* cache_create(const char *name, size_t bufsize, size_t align,
+ cache_constructor_t* constructor,
+ cache_destructor_t* destructor) {
+ cache_t* ret = calloc(1, sizeof(cache_t));
+ size_t name_length= strlen(name);
+ char* nm= calloc(1, (sizeof(char) * name_length) +1);
+ memcpy(nm, name, name_length);
+ void** ptr = calloc(initial_pool_size, bufsize);
+ if (ret == NULL || nm == NULL || ptr == NULL ||
+ pthread_mutex_init(&ret->mutex, NULL) == -1) {
+ free(ret);
+ free(nm);
+ free(ptr);
+ return NULL;
+ }
+
+ ret->name = nm;
+ ret->ptr = ptr;
+ ret->freetotal = initial_pool_size;
+ ret->constructor = constructor;
+ ret->destructor = destructor;
+
+#ifndef NDEBUG
+ ret->bufsize = bufsize + 2 * sizeof(redzone_pattern);
+#else
+ ret->bufsize = bufsize;
+#endif
+
+ (void)align;
+
+ return ret;
+}
+
+static inline void* get_object(void *ptr) {
+#ifndef NDEBUG
+ uint64_t *pre = ptr;
+ return pre + 1;
+#else
+ return ptr;
+#endif
+}
+
+void cache_destroy(cache_t *cache) {
+ while (cache->freecurr > 0) {
+ void *ptr = cache->ptr[--cache->freecurr];
+ if (cache->destructor) {
+ cache->destructor(get_object(ptr), NULL);
+ }
+ free(ptr);
+ }
+ free(cache->name);
+ free(cache->ptr);
+ pthread_mutex_destroy(&cache->mutex);
+}
+
+void* cache_alloc(cache_t *cache) {
+ void *ret;
+ void *object;
+ pthread_mutex_lock(&cache->mutex);
+ if (cache->freecurr > 0) {
+ ret = cache->ptr[--cache->freecurr];
+ object = get_object(ret);
+ } else {
+ object = ret = malloc(cache->bufsize);
+ if (ret != NULL) {
+ object = get_object(ret);
+
+ if (cache->constructor != NULL &&
+ cache->constructor(object, NULL, 0) != 0) {
+ free(ret);
+ object = NULL;
+ }
+ }
+ }
+ pthread_mutex_unlock(&cache->mutex);
+
+#ifndef NDEBUG
+ if (object != NULL) {
+ /* add a simple form of buffer-check */
+ uint64_t *pre = ret;
+ *pre = redzone_pattern;
+ ret = pre+1;
+ memcpy(((char*)ret) + cache->bufsize - (2 * sizeof(redzone_pattern)),
+ &redzone_pattern, sizeof(redzone_pattern));
+ }
+#endif
+
+ return object;
+}
+
+void cache_free(cache_t *cache, void *ptr) {
+ pthread_mutex_lock(&cache->mutex);
+
+#ifndef NDEBUG
+ /* validate redzone... */
+ if (memcmp(((char*)ptr) + cache->bufsize - (2 * sizeof(redzone_pattern)),
+ &redzone_pattern, sizeof(redzone_pattern)) != 0) {
+ raise(SIGABRT);
+ cache_error = 1;
+ pthread_mutex_unlock(&cache->mutex);
+ return;
+ }
+ uint64_t *pre = ptr;
+ --pre;
+ if (*pre != redzone_pattern) {
+ raise(SIGABRT);
+ cache_error = -1;
+ pthread_mutex_unlock(&cache->mutex);
+ return;
+ }
+ ptr = pre;
+#endif
+ if (cache->freecurr < cache->freetotal) {
+ cache->ptr[cache->freecurr++] = ptr;
+ } else {
+ /* try to enlarge free connections array */
+ size_t newtotal = cache->freetotal * 2;
+ void **new_free = realloc(cache->ptr, sizeof(char *) * newtotal);
+ if (new_free) {
+ cache->freetotal = newtotal;
+ cache->ptr = new_free;
+ cache->ptr[cache->freecurr++] = ptr;
+ } else {
+ if (cache->destructor) {
+ cache->destructor(ptr, NULL);
+ }
+ free(ptr);
+
+ }
+ }
+ pthread_mutex_unlock(&cache->mutex);
+}
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#pragma once
+
+#include <pthread.h>
+
+#ifdef HAVE_UMEM_H
+# include <umem.h>
+# define cache_t umem_cache_t
+# define cache_alloc(a) umem_cache_alloc(a, UMEM_DEFAULT)
+# define cache_free(a, b) umem_cache_free(a, b)
+# define cache_create(a,b,c,d,e) umem_cache_create((char*)a, b, c, d, e, NULL, NULL, NULL, 0)
+# define cache_destroy(a) umem_cache_destroy(a);
+#else
+# ifndef NDEBUG
+/* may be used for debug purposes */
+extern int cache_error;
+# endif
+
+/**
+ * Constructor used to initialize allocated objects
+ *
+ * @param obj pointer to the object to initialized.
+ * @param notused1 This parameter is currently not used.
+ * @param notused2 This parameter is currently not used.
+ * @return you should return 0, but currently this is not checked
+ */
+typedef int cache_constructor_t(void* obj, void* notused1, int notused2);
+/**
+ * Destructor used to clean up allocated objects before they are
+ * returned to the operating system.
+ *
+ * @param obj pointer to the object to initialized.
+ * @param notused1 This parameter is currently not used.
+ * @param notused2 This parameter is currently not used.
+ * @return you should return 0, but currently this is not checked
+ */
+typedef void cache_destructor_t(void* obj, void* notused);
+
+/**
+ * Definition of the structure to keep track of the internal details of
+ * the cache allocator. Touching any of these variables results in
+ * undefined behavior.
+ */
+typedef struct {
+ /** Mutex to protect access to the structure */
+ pthread_mutex_t mutex;
+ /** Name of the cache objects in this cache (provided by the caller) */
+ char *name;
+ /** List of pointers to available buffers in this cache */
+ void **ptr;
+ /** The size of each element in this cache */
+ size_t bufsize;
+ /** The capacity of the list of elements */
+ size_t freetotal;
+ /** The current number of free elements */
+ size_t freecurr;
+ /** The constructor to be called each time we allocate more memory */
+ cache_constructor_t* constructor;
+ /** The destructor to be called each time before we release memory */
+ cache_destructor_t* destructor;
+} cache_t;
+
+/**
+ * Create an object cache.
+ *
+ * The object cache will let you allocate objects of the same size. It is fully
+ * MT safe, so you may allocate objects from multiple threads without having to
+ * do any syncrhonization in the application code.
+ *
+ * @param name the name of the object cache. This name may be used for debug purposes
+ * and may help you track down what kind of object you have problems with
+ * (buffer overruns, leakage etc)
+ * @param bufsize the size of each object in the cache
+ * @param align the alignment requirements of the objects in the cache.
+ * @param constructor the function to be called to initialize memory when we need
+ * to allocate more memory from the os.
+ * @param destructor the function to be called before we release the memory back
+ * to the os.
+ * @return a handle to an object cache if successful, NULL otherwise.
+ */
+cache_t* cache_create(const char* name, size_t bufsize, size_t align,
+ cache_constructor_t* constructor,
+ cache_destructor_t* destructor);
+/**
+ * Destroy an object cache.
+ *
+ * Destroy and invalidate an object cache. You should return all buffers allocated
+ * with cache_alloc by using cache_free before calling this function. Not doing
+ * so results in undefined behavior (the buffers may or may not be invalidated)
+ *
+ * @param handle the handle to the object cache to destroy.
+ */
+void cache_destroy(cache_t* handle);
+/**
+ * Allocate an object from the cache.
+ *
+ * @param handle the handle to the object cache to allocate from
+ * @return a pointer to an initialized object from the cache, or NULL if
+ * the allocation cannot be satisfied.
+ */
+void* cache_alloc(cache_t* handle);
+/**
+ * Return an object back to the cache.
+ *
+ * The caller should return the object in an initialized state so that
+ * the object may be returned in an expected state from cache_alloc.
+ *
+ * @param handle handle to the object cache to return the object to
+ * @param ptr pointer to the object to return.
+ */
+void cache_free(cache_t* handle, void* ptr);
+#endif // HAVE_UMEM_H
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "config.h"
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+#include <assert.h>
+
+#include <libmemcachedprotocol-0.0/handler.h>
+#include <libmemcachedprotocol/cache.h>
+#include <libmemcached/byteorder.h>
+
+/*
+ * I don't really need the following two functions as function pointers
+ * in the instance handle, but I don't want to put them in the global
+ * namespace for those linking statically (personally I don't like that,
+ * but some people still do). If it ever shows up as a performance thing
+ * I'll look into optimizing this ;-)
+ */
+typedef bool (*drain_func)(memcached_protocol_client_st *client);
+typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
+ const void *data,
+ size_t length);
+
+/**
+ * Definition of the per instance structure.
+ */
+struct memcached_protocol_st {
+ memcached_binary_protocol_callback_st *callback;
+ memcached_protocol_recv_func recv;
+ memcached_protocol_send_func send;
+
+ /*
+ * I really don't need these as funciton pointers, but I don't want
+ * to clutter the namespace if someone links statically.
+ */
+ drain_func drain;
+ spool_func spool;
+
+ /*
+ * To avoid keeping a buffer in each client all the time I have a
+ * bigger buffer in the instance that I read to initially, and then
+ * I try to parse and execute as much from the buffer. If I wasn't able
+ * to process all data I'll keep that in a per-connection buffer until
+ * the next time I can read from the socket.
+ */
+ uint8_t *input_buffer;
+ size_t input_buffer_size;
+
+ bool pedantic;
+ /* @todo use multiple sized buffers */
+ cache_t *buffer_cache;
+};
+
+struct chunk_st {
+ /* Pointer to the data */
+ char *data;
+ /* The offset to the first byte into the buffer that is used */
+ size_t offset;
+ /* The offset into the buffer for the first free byte */
+ size_t nbytes;
+ /* The number of bytes in the buffer */
+ size_t size;
+ /* Pointer to the next buffer in the chain */
+ struct chunk_st *next;
+};
+
+#define CHUNK_BUFFERSIZE 2048
+
+typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
+
+enum ascii_cmd {
+ GET_CMD,
+ GETS_CMD,
+ SET_CMD,
+ ADD_CMD,
+ REPLACE_CMD,
+ CAS_CMD,
+ APPEND_CMD,
+ PREPEND_CMD,
+ DELETE_CMD,
+ INCR_CMD,
+ DECR_CMD,
+ STATS_CMD,
+ FLUSH_ALL_CMD,
+ VERSION_CMD,
+ QUIT_CMD,
+ VERBOSITY_CMD,
+ UNKNOWN_CMD
+};
+
+struct memcached_protocol_client_st {
+ memcached_protocol_st *root;
+ memcached_socket_t sock;
+ int error;
+
+ /* Linked list of data to send */
+ struct chunk_st *output;
+ struct chunk_st *output_tail;
+
+ /*
+ * While we process input data, this is where we spool incomplete commands
+ * if we need to receive more data....
+ * @todo use the buffercace
+ */
+ uint8_t *input_buffer;
+ size_t input_buffer_size;
+ size_t input_buffer_offset;
+
+ /* The callback to the protocol handler to use (ascii or binary) */
+ process_data work;
+
+ /*
+ * Should the spool data discard the data to send or not? (aka noreply in
+ * the ascii protocol..
+ */
+ bool mute;
+
+ /* Members used by the binary protocol */
+ protocol_binary_request_header *current_command;
+
+ /* Members used by the ascii protocol */
+ enum ascii_cmd ascii_command;
+};
+
+#include "ascii_handler.h"
+#include "binary_handler.h"
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#include <libmemcachedprotocol/common.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdio.h>
+
+/*
+** **********************************************************************
+** INTERNAL INTERFACE
+** **********************************************************************
+*/
+
+/**
+ * The default function to receive data from the client. This function
+ * just wraps the recv function to receive from a socket.
+ * See man -s3socket recv for more information.
+ *
+ * @param cookie cookie indentifying a client, not used
+ * @param sock socket to read from
+ * @param buf the destination buffer
+ * @param nbytes the number of bytes to read
+ * @return the number of bytes transferred of -1 upon error
+ */
+static ssize_t default_recv(const void *cookie,
+ memcached_socket_t sock,
+ void *buf,
+ size_t nbytes)
+{
+ (void)cookie;
+ return recv(sock, buf, nbytes, 0);
+}
+
+/**
+ * The default function to send data to the server. This function
+ * just wraps the send function to send through a socket.
+ * See man -s3socket send for more information.
+ *
+ * @param cookie cookie indentifying a client, not used
+ * @param sock socket to send to
+ * @param buf the source buffer
+ * @param nbytes the number of bytes to send
+ * @return the number of bytes transferred of -1 upon error
+ */
+static ssize_t default_send(const void *cookie,
+ memcached_socket_t fd,
+ const void *buf,
+ size_t nbytes)
+{
+ (void)cookie;
+ return send(fd, buf, nbytes, 0);
+}
+
+/**
+ * Try to drain the output buffers without blocking
+ *
+ * @param client the client to drain
+ * @return false if an error occured (connection should be shut down)
+ * true otherwise (please note that there may be more data to
+ * left in the buffer to send)
+ */
+static bool drain_output(struct memcached_protocol_client_st *client)
+{
+ ssize_t len;
+
+ /* Do we have pending data to send? */
+ while (client->output != NULL)
+ {
+ len= client->root->send(client,
+ client->sock,
+ client->output->data + client->output->offset,
+ client->output->nbytes - client->output->offset);
+
+ if (len == -1)
+ {
+ if (get_socket_errno() == EWOULDBLOCK)
+ {
+ return true;
+ }
+ else if (get_socket_errno() != EINTR)
+ {
+ client->error= get_socket_errno();
+ return false;
+ }
+ }
+ else
+ {
+ client->output->offset += (size_t)len;
+ if (client->output->offset == client->output->nbytes)
+ {
+ /* This was the complete buffer */
+ struct chunk_st *old= client->output;
+ client->output= client->output->next;
+ if (client->output == NULL)
+ {
+ client->output_tail= NULL;
+ }
+ cache_free(client->root->buffer_cache, old);
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Allocate an output buffer and chain it into the output list
+ *
+ * @param client the client that needs the buffer
+ * @return pointer to the new chunk if the allocation succeeds, NULL otherwise
+ */
+static struct chunk_st *allocate_output_chunk(struct memcached_protocol_client_st *client)
+{
+ struct chunk_st *ret= cache_alloc(client->root->buffer_cache);
+
+ if (ret == NULL)
+ {
+ return NULL;
+ }
+
+ ret->offset= ret->nbytes= 0;
+ ret->next= NULL;
+ ret->size= CHUNK_BUFFERSIZE;
+ ret->data= (void*)(ret + 1);
+ if (client->output == NULL)
+ {
+ client->output= client->output_tail= ret;
+ }
+ else
+ {
+ client->output_tail->next= ret;
+ client->output_tail= ret;
+ }
+
+ return ret;
+}
+
+/**
+ * Spool data into the send-buffer for a client.
+ *
+ * @param client the client to spool the data for
+ * @param data the data to spool
+ * @param length the number of bytes of data to spool
+ * @return PROTOCOL_BINARY_RESPONSE_SUCCESS if success,
+ * PROTOCOL_BINARY_RESPONSE_ENOMEM if we failed to allocate memory
+ */
+static protocol_binary_response_status spool_output(struct memcached_protocol_client_st *client,
+ const void *data,
+ size_t length)
+{
+ if (client->mute)
+ {
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+ }
+
+ size_t offset= 0;
+
+ struct chunk_st *chunk= client->output;
+ while (offset < length)
+ {
+ if (chunk == NULL || (chunk->size - chunk->nbytes) == 0)
+ {
+ if ((chunk= allocate_output_chunk(client)) == NULL)
+ {
+ return PROTOCOL_BINARY_RESPONSE_ENOMEM;
+ }
+ }
+
+ size_t bulk= length - offset;
+ if (bulk > chunk->size - chunk->nbytes)
+ {
+ bulk= chunk->size - chunk->nbytes;
+ }
+
+ memcpy(chunk->data + chunk->nbytes, data, bulk);
+ chunk->nbytes += bulk;
+ offset += bulk;
+ }
+
+ return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Try to determine the protocol used on this connection.
+ * If the first byte contains the magic byte PROTOCOL_BINARY_REQ we should
+ * be using the binary protocol on the connection. I implemented the support
+ * for the ASCII protocol by wrapping into the simple interface (aka v1),
+ * so the implementors needs to provide an implementation of that interface
+ *
+ */
+static memcached_protocol_event_t determine_protocol(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr)
+{
+ if (*client->root->input_buffer == (uint8_t)PROTOCOL_BINARY_REQ)
+ {
+ client->work= memcached_binary_protocol_process_data;
+ }
+ else if (client->root->callback->interface_version == 1)
+ {
+ /*
+ * The ASCII protocol can only be used if the implementors provide
+ * an implementation for the version 1 of the interface..
+ *
+ * @todo I should allow the implementors to provide an implementation
+ * for version 0 and 1 at the same time and set the preferred
+ * interface to use...
+ */
+ client->work= memcached_ascii_protocol_process_data;
+ }
+ else
+ {
+ /* Let's just output a warning the way it is supposed to look like
+ * in the ASCII protocol...
+ */
+ const char *err= "CLIENT_ERROR: Unsupported protocol\r\n";
+ client->root->spool(client, err, strlen(err));
+ client->root->drain(client);
+ return MEMCACHED_PROTOCOL_ERROR_EVENT; /* Unsupported protocol */
+ }
+
+ return client->work(client, length, endptr);
+}
+
+/*
+** **********************************************************************
+** * PUBLIC INTERFACE
+** * See protocol_handler.h for function description
+** **********************************************************************
+*/
+struct memcached_protocol_st *memcached_protocol_create_instance(void)
+{
+ struct memcached_protocol_st *ret= calloc(1, sizeof(*ret));
+ if (ret != NULL)
+ {
+ ret->recv= default_recv;
+ ret->send= default_send;
+ ret->drain= drain_output;
+ ret->spool= spool_output;
+ ret->input_buffer_size= 1 * 1024 * 1024;
+ ret->input_buffer= malloc(ret->input_buffer_size);
+ if (ret->input_buffer == NULL)
+ {
+ free(ret);
+ ret= NULL;
+ return NULL;
+ }
+
+ ret->buffer_cache= cache_create("protocol_handler",
+ CHUNK_BUFFERSIZE + sizeof(struct chunk_st),
+ 0, NULL, NULL);
+ if (ret->buffer_cache == NULL)
+ {
+ free(ret->input_buffer);
+ free(ret);
+ }
+ }
+
+ return ret;
+}
+
+void memcached_protocol_destroy_instance(struct memcached_protocol_st *instance)
+{
+ cache_destroy(instance->buffer_cache);
+ free(instance->input_buffer);
+ free(instance);
+}
+
+struct memcached_protocol_client_st *memcached_protocol_create_client(struct memcached_protocol_st *instance, memcached_socket_t sock)
+{
+ struct memcached_protocol_client_st *ret= calloc(1, sizeof(*ret));
+ if (ret != NULL)
+ {
+ ret->root= instance;
+ ret->sock= sock;
+ ret->work= determine_protocol;
+ }
+
+ return ret;
+}
+
+void memcached_protocol_client_destroy(struct memcached_protocol_client_st *client)
+{
+ free(client);
+}
+
+memcached_protocol_event_t memcached_protocol_client_work(struct memcached_protocol_client_st *client)
+{
+ /* Try to send data and read from the socket */
+ bool more_data= true;
+ do
+ {
+ ssize_t len= client->root->recv(client,
+ client->sock,
+ client->root->input_buffer + client->input_buffer_offset,
+ client->root->input_buffer_size - client->input_buffer_offset);
+
+ if (len > 0)
+ {
+ /* Do we have the complete packet? */
+ if (client->input_buffer_offset > 0)
+ {
+ memcpy(client->root->input_buffer, client->input_buffer,
+ client->input_buffer_offset);
+ len += (ssize_t)client->input_buffer_offset;
+
+ /* @todo use buffer-cache! */
+ free(client->input_buffer);
+ client->input_buffer_offset= 0;
+ }
+
+ void *endptr;
+ memcached_protocol_event_t events= client->work(client, &len, &endptr);
+ if (events == MEMCACHED_PROTOCOL_ERROR_EVENT)
+ {
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+
+ if (len > 0)
+ {
+ /* save the data for later on */
+ /* @todo use buffer-cache */
+ client->input_buffer= malloc((size_t)len);
+ if (client->input_buffer == NULL)
+ {
+ client->error= ENOMEM;
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+ memcpy(client->input_buffer, endptr, (size_t)len);
+ client->input_buffer_offset= (size_t)len;
+ more_data= false;
+ }
+ }
+ else if (len == 0)
+ {
+ /* Connection closed */
+ drain_output(client);
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+ else
+ {
+ if (get_socket_errno() != EWOULDBLOCK)
+ {
+ client->error= get_socket_errno();
+ /* mark this client as terminated! */
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+ more_data= false;
+ }
+ } while (more_data);
+
+ if (!drain_output(client))
+ {
+ return MEMCACHED_PROTOCOL_ERROR_EVENT;
+ }
+
+ memcached_protocol_event_t ret= MEMCACHED_PROTOCOL_READ_EVENT;
+ if (client->output)
+ ret|= MEMCACHED_PROTOCOL_READ_EVENT;
+
+ return ret;
+}
--- /dev/null
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+
+
+lib_LTLIBRARIES+= libmemcached/libmemcachedprotocol.la
+
+noinst_HEADERS+= \
+ libmemcachedprotocol/ascii_handler.h \
+ libmemcachedprotocol/binary_handler.h \
+ libmemcachedprotocol/cache.h \
+ libmemcachedprotocol/common.h
+
+libmemcached_libmemcachedprotocol_la_SOURCES= \
+ libmemcached/byteorder.cc \
+ libmemcachedprotocol/ascii_handler.c \
+ libmemcachedprotocol/binary_handler.c \
+ libmemcachedprotocol/cache.c \
+ libmemcachedprotocol/handler.c \
+ libmemcachedprotocol/pedantic.c
+
+libmemcached_libmemcachedprotocol_la_CFLAGS= \
+ ${AM_CFLAGS} \
+ ${NO_CONVERSION} \
+ -DBUILDING_LIBMEMCACHED
+libmemcached_libmemcachedprotocol_la_CFLAGS+= ${PTHREAD_CFLAGS}
+
+libmemcached_libmemcachedprotocol_la_CXXFLAGS= \
+ ${AM_CXXFLAGS} \
+ -DBUILDING_LIBMEMCACHED
+libmemcached_libmemcachedprotocol_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
+
+libmemcached_libmemcachedprotocol_la_LIBADD= ${PTHREAD_LIBS}
+libmemcached_libmemcachedprotocol_la_LDFLAGS= ${AM_LDFLAGS}
+libmemcached_libmemcachedprotocol_la_LDFLAGS+= -version-info ${MEMCACHED_PROTOCAL_LIBRARY_VERSION}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#include <libmemcachedprotocol/common.h>
+
+#include <sys/types.h>
+
+#define ensure(a) if (!(a)) { return false; }
+
+bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request)
+{
+ ensure(request->request.magic == PROTOCOL_BINARY_REQ);
+ ensure(request->request.datatype == PROTOCOL_BINARY_RAW_BYTES);
+
+ ensure(request->bytes[6] == 0);
+ ensure(request->bytes[7] == 0);
+
+ uint8_t opcode= request->request.opcode;
+ uint16_t keylen= ntohs(request->request.keylen);
+ uint8_t extlen= request->request.extlen;
+ uint32_t bodylen= ntohl(request->request.bodylen);
+
+ ensure(bodylen >= (keylen + extlen));
+
+ switch (opcode) {
+ case PROTOCOL_BINARY_CMD_GET:
+ case PROTOCOL_BINARY_CMD_GETK:
+ case PROTOCOL_BINARY_CMD_GETKQ:
+ case PROTOCOL_BINARY_CMD_GETQ:
+ ensure(extlen == 0);
+ ensure(keylen > 0);
+ ensure(keylen == bodylen);
+ ensure(request->request.cas == 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_ADD:
+ case PROTOCOL_BINARY_CMD_ADDQ:
+ /* it makes no sense to run add with a cas value */
+ ensure(request->request.cas == 0);
+ /* FALLTHROUGH */
+ case PROTOCOL_BINARY_CMD_SET:
+ case PROTOCOL_BINARY_CMD_SETQ:
+ case PROTOCOL_BINARY_CMD_REPLACE:
+ case PROTOCOL_BINARY_CMD_REPLACEQ:
+ ensure(keylen > 0);
+ ensure(extlen == 8);
+ break;
+
+ case PROTOCOL_BINARY_CMD_DELETE:
+ case PROTOCOL_BINARY_CMD_DELETEQ:
+ ensure(extlen == 0);
+ ensure(keylen > 0);
+ ensure(keylen == bodylen);
+ break;
+
+ case PROTOCOL_BINARY_CMD_INCREMENT:
+ case PROTOCOL_BINARY_CMD_INCREMENTQ:
+ case PROTOCOL_BINARY_CMD_DECREMENT:
+ case PROTOCOL_BINARY_CMD_DECREMENTQ:
+ ensure(extlen == 20);
+ ensure(keylen > 0);
+ ensure(keylen + extlen == bodylen);
+ break;
+
+ case PROTOCOL_BINARY_CMD_QUIT:
+ case PROTOCOL_BINARY_CMD_QUITQ:
+ case PROTOCOL_BINARY_CMD_NOOP:
+ case PROTOCOL_BINARY_CMD_VERSION:
+ ensure(extlen == 0);
+ ensure(keylen == 0);
+ ensure(bodylen == 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_FLUSH:
+ case PROTOCOL_BINARY_CMD_FLUSHQ:
+ ensure(extlen == 0 || extlen == 4);
+ ensure(keylen == 0);
+ ensure(bodylen == extlen);
+ break;
+
+ case PROTOCOL_BINARY_CMD_STAT:
+ ensure(extlen == 0);
+ /* May have key, but not value */
+ ensure(keylen == bodylen);
+ break;
+
+ case PROTOCOL_BINARY_CMD_APPEND:
+ case PROTOCOL_BINARY_CMD_APPENDQ:
+ case PROTOCOL_BINARY_CMD_PREPEND:
+ case PROTOCOL_BINARY_CMD_PREPENDQ:
+ ensure(extlen == 0);
+ ensure(keylen > 0);
+ break;
+ default:
+ /* Unknown command */
+ ;
+ }
+
+ return true;
+}
+
+bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
+ const protocol_binary_response_header *response)
+{
+ ensure(response->response.magic == PROTOCOL_BINARY_RES);
+ ensure(response->response.datatype == PROTOCOL_BINARY_RAW_BYTES);
+ ensure(response->response.opaque == request->request.opaque);
+
+ uint16_t status= ntohs(response->response.status);
+ uint8_t opcode= response->response.opcode;
+
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+ {
+ switch (opcode) {
+ case PROTOCOL_BINARY_CMD_ADDQ:
+ case PROTOCOL_BINARY_CMD_APPENDQ:
+ case PROTOCOL_BINARY_CMD_DECREMENTQ:
+ case PROTOCOL_BINARY_CMD_DELETEQ:
+ case PROTOCOL_BINARY_CMD_FLUSHQ:
+ case PROTOCOL_BINARY_CMD_INCREMENTQ:
+ case PROTOCOL_BINARY_CMD_PREPENDQ:
+ case PROTOCOL_BINARY_CMD_QUITQ:
+ case PROTOCOL_BINARY_CMD_REPLACEQ:
+ case PROTOCOL_BINARY_CMD_SETQ:
+ /* Quiet command shouldn't return on success */
+ return false;
+ default:
+ break;
+ }
+
+ switch (opcode) {
+ case PROTOCOL_BINARY_CMD_ADD:
+ case PROTOCOL_BINARY_CMD_REPLACE:
+ case PROTOCOL_BINARY_CMD_SET:
+ case PROTOCOL_BINARY_CMD_APPEND:
+ case PROTOCOL_BINARY_CMD_PREPEND:
+ ensure(response->response.keylen == 0);
+ ensure(response->response.extlen == 0);
+ ensure(response->response.bodylen == 0);
+ ensure(response->response.cas != 0);
+ break;
+ case PROTOCOL_BINARY_CMD_FLUSH:
+ case PROTOCOL_BINARY_CMD_NOOP:
+ case PROTOCOL_BINARY_CMD_QUIT:
+ case PROTOCOL_BINARY_CMD_DELETE:
+ ensure(response->response.keylen == 0);
+ ensure(response->response.extlen == 0);
+ ensure(response->response.bodylen == 0);
+ ensure(response->response.cas == 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_DECREMENT:
+ case PROTOCOL_BINARY_CMD_INCREMENT:
+ ensure(response->response.keylen == 0);
+ ensure(response->response.extlen == 0);
+ ensure(ntohl(response->response.bodylen) == 8);
+ ensure(response->response.cas != 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_STAT:
+ ensure(response->response.extlen == 0);
+ /* key and value exists in all packets except in the terminating */
+ ensure(response->response.cas == 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_VERSION:
+ ensure(response->response.keylen == 0);
+ ensure(response->response.extlen == 0);
+ ensure(response->response.bodylen != 0);
+ ensure(response->response.cas == 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_GET:
+ case PROTOCOL_BINARY_CMD_GETQ:
+ ensure(response->response.keylen == 0);
+ ensure(response->response.extlen == 4);
+ ensure(response->response.cas != 0);
+ break;
+
+ case PROTOCOL_BINARY_CMD_GETK:
+ case PROTOCOL_BINARY_CMD_GETKQ:
+ ensure(response->response.keylen != 0);
+ ensure(response->response.extlen == 4);
+ ensure(response->response.cas != 0);
+ break;
+
+ default:
+ /* Undefined command code */
+ break;
+ }
+ }
+ else
+ {
+ ensure(response->response.cas == 0);
+ ensure(response->response.extlen == 0);
+ if (opcode != PROTOCOL_BINARY_CMD_GETK)
+ {
+ ensure(response->response.keylen == 0);
+ }
+ }
+
+ return true;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+
+
+nobase_include_HEADERS+= \
+ libmemcachedutil-1.0/flush.h \
+ libmemcachedutil-1.0/pid.h \
+ libmemcachedutil-1.0/ping.h \
+ libmemcachedutil-1.0/pool.h \
+ libmemcachedutil-1.0/util.h \
+ libmemcachedutil-1.0/version.h
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifndef WIN32
+#include <netdb.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+LIBMEMCACHED_API
+pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+LIBMEMCACHED_API
+bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#include <libmemcached-1.0/memcached.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct memcached_pool_st;
+typedef struct memcached_pool_st memcached_pool_st;
+
+LIBMEMCACHED_API
+memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max);
+
+LIBMEMCACHED_API
+memcached_pool_st *memcached_pool(const char *option_string, size_t option_string_length);
+
+LIBMEMCACHED_API
+memcached_st* memcached_pool_destroy(memcached_pool_st* pool);
+
+LIBMEMCACHED_API
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+ bool block,
+ memcached_return_t* rc);
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_push(memcached_pool_st* pool,
+ memcached_st* mmc);
+LIBMEMCACHED_API
+ memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st* mmc);
+
+LIBMEMCACHED_API
+memcached_st* memcached_pool_fetch(memcached_pool_st*, struct timespec* relative_time, memcached_return_t* rc);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *ptr,
+ memcached_behavior_t flag,
+ uint64_t data);
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *ptr,
+ memcached_behavior_t flag,
+ uint64_t *value);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libmemcached-1.0/memcached.h>
+
+#include <libmemcachedutil-1.0/pid.h>
+#include <libmemcachedutil-1.0/flush.h>
+#include <libmemcachedutil-1.0/ping.h>
+#include <libmemcachedutil-1.0/pool.h>
+#include <libmemcachedutil-1.0/version.h>
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+ bool libmemcached_util_version_check(memcached_st *memc,
+ uint8_t major_version,
+ uint8_t minor_version,
+ uint8_t micro_version);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached Utility library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and then flushes it (memcached_flush(3)).
+ *
+ */
+
+#pragma once
+
+#include <config.h>
+
+#include <libmemcachedutil-1.0/util.h>
+#include <libmemcached/assert.hpp>
+#include <libmemcached/backtrace.hpp>
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and then flushes it (memcached_flush(3)).
+ *
+ */
+
+#include <libmemcachedutil/common.h>
+
+
+bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+ memcached_st *memc_ptr= memcached_create(NULL);
+
+ memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+ if (memcached_success(rc))
+ {
+ rc= memcached_flush(memc_ptr, 0);
+ }
+
+ memcached_free(memc_ptr);
+
+ if (ret)
+ {
+ *ret= rc;
+ }
+
+ return memcached_success(rc);
+}
--- /dev/null
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+
+lib_LTLIBRARIES+= libmemcached/libmemcachedutil.la
+
+noinst_HEADERS+= \
+ libmemcachedutil/common.h
+
+libmemcached_libmemcachedutil_la_SOURCES= \
+ libmemcached/backtrace.cc \
+ libmemcachedutil/flush.cc \
+ libmemcachedutil/pid.cc \
+ libmemcachedutil/ping.cc \
+ libmemcachedutil/pool.cc \
+ libmemcachedutil/version.cc
+libmemcached_libmemcachedutil_la_CXXFLAGS= \
+ ${AM_CXXFLAGS} \
+ ${NO_CONVERSION} \
+ -DBUILDING_LIBMEMCACHED
+libmemcached_libmemcachedutil_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
+libmemcached_libmemcachedutil_la_LIBADD= libmemcached/libmemcached.la
+libmemcached_libmemcachedutil_la_LIBADD+= ${PTHREAD_LIBS}
+libmemcached_libmemcachedutil_la_LDFLAGS= ${AM_LDFLAGS} -version-info ${MEMCACHED_UTIL_LIBRARY_VERSION}
+libmemcached_libmemcachedutil_la_DEPENDENCIES= libmemcached/libmemcached.la
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and determines what its pid is
+ *
+ */
+
+#include <libmemcachedutil/common.h>
+
+
+// Never look at the stat object directly.
+
+
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+ pid_t pid= -1;
+
+ memcached_return_t unused;
+ if (not ret)
+ ret= &unused;
+
+ memcached_st *memc_ptr= memcached_create(NULL);
+ if (not memc_ptr)
+ {
+ *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return -1;
+ }
+
+ memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+ if (memcached_success(rc))
+ {
+ memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+ if (memcached_success(rc) and stat and stat->pid != -1)
+ {
+ pid= stat->pid;
+ }
+ else if (memcached_success(rc))
+ {
+ rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+ }
+ else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
+ {
+ memcached_server_instance_st instance=
+ memcached_server_instance_by_position(memc_ptr, 0);
+
+ assert_msg(instance and instance->error_messages, " ");
+ if (instance and instance->error_messages)
+ {
+ rc= memcached_server_error_return(instance);
+ }
+ }
+
+ memcached_stat_free(memc_ptr, stat);
+ }
+ memcached_free(memc_ptr);
+
+ *ret= rc;
+
+ return pid;
+}
+
+pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret)
+{
+ if (username == NULL)
+ {
+ return libmemcached_util_getpid(hostname, port, ret);
+ }
+
+ pid_t pid= -1;
+
+ memcached_return_t unused;
+ if (not ret)
+ ret= &unused;
+
+ if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+ {
+ *ret= MEMCACHED_NOT_SUPPORTED;
+ return pid;
+ }
+
+ memcached_st *memc_ptr= memcached_create(NULL);
+ if (not memc_ptr)
+ {
+ *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return -1;
+ }
+
+ if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
+ {
+ memcached_free(memc_ptr);
+ return false;
+ }
+
+
+ memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+ if (memcached_success(rc))
+ {
+ memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+ if (memcached_success(rc) and stat and stat->pid != -1)
+ {
+ pid= stat->pid;
+ }
+ else if (memcached_success(rc))
+ {
+ rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+ }
+ else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
+ {
+ memcached_server_instance_st instance=
+ memcached_server_instance_by_position(memc_ptr, 0);
+
+#if 0
+ assert_msg(instance and instance->error_messages, " ");
+#endif
+ if (instance and instance->error_messages)
+ {
+ rc= memcached_server_error_return(instance);
+ }
+ }
+
+ memcached_stat_free(memc_ptr, stat);
+ }
+ memcached_free(memc_ptr);
+
+ *ret= rc;
+
+ return pid;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and makes sure it is alive.
+ *
+ */
+
+#include <libmemcachedutil/common.h>
+
+bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+ memcached_return_t unused;
+ if (not ret)
+ ret= &unused;
+
+ memcached_st *memc_ptr= memcached_create(NULL);
+ if (not memc_ptr)
+ {
+ *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return false;
+ }
+
+ memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+ if (memcached_success(rc))
+ {
+ rc= memcached_version(memc_ptr);
+ }
+
+ if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+ {
+ memcached_server_instance_st instance=
+ memcached_server_instance_by_position(memc_ptr, 0);
+
+ assert_msg(instance and instance->error_messages, " ");
+ if (instance and instance->error_messages)
+ {
+ rc= memcached_server_error_return(instance);
+ }
+ }
+ memcached_free(memc_ptr);
+
+ *ret= rc;
+
+ return memcached_success(rc);
+}
+
+bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password, memcached_return_t *ret)
+{
+ if (username == NULL)
+ {
+ return libmemcached_util_ping(hostname, port, ret);
+ }
+
+ memcached_return_t unused;
+ if (not ret)
+ ret= &unused;
+
+ if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+ {
+ *ret= MEMCACHED_NOT_SUPPORTED;
+ return false;
+ }
+
+ memcached_st *memc_ptr= memcached_create(NULL);
+ if (not memc_ptr)
+ {
+ *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return false;
+ }
+
+ if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
+ {
+ memcached_free(memc_ptr);
+ return false;
+ }
+
+ memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+ if (memcached_success(rc))
+ {
+ rc= memcached_version(memc_ptr);
+ }
+
+ if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+ {
+ memcached_server_instance_st instance=
+ memcached_server_instance_by_position(memc_ptr, 0);
+
+ assert_msg(instance and instance->error_messages, " ");
+ if (instance and instance->error_messages)
+ {
+ rc= memcached_server_error_return(instance);
+ }
+ }
+ memcached_free(memc_ptr);
+
+ *ret= rc;
+
+ return memcached_success(rc);
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcachedutil/common.h>
+
+#include <cassert>
+#include <cerrno>
+#include <pthread.h>
+#include <memory>
+
+struct memcached_pool_st
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ memcached_st *master;
+ memcached_st **server_pool;
+ int firstfree;
+ const uint32_t size;
+ uint32_t current_size;
+ bool _owns_master;
+ struct timespec _timeout;
+
+ memcached_pool_st(memcached_st *master_arg, size_t max_arg) :
+ master(master_arg),
+ server_pool(NULL),
+ firstfree(-1),
+ size(max_arg),
+ current_size(0),
+ _owns_master(false)
+ {
+ pthread_mutex_init(&mutex, NULL);
+ pthread_cond_init(&cond, NULL);
+ _timeout.tv_sec= 5;
+ _timeout.tv_nsec= 0;
+ }
+
+ const struct timespec& timeout() const
+ {
+ return _timeout;
+ }
+
+ bool release(memcached_st*, memcached_return_t& rc);
+
+ memcached_st *fetch(memcached_return_t& rc);
+ memcached_st *fetch(const struct timespec&, memcached_return_t& rc);
+
+ bool init(uint32_t initial);
+
+ ~memcached_pool_st()
+ {
+ for (int x= 0; x <= firstfree; ++x)
+ {
+ memcached_free(server_pool[x]);
+ server_pool[x] = NULL;
+ }
+
+ pthread_mutex_destroy(&mutex);
+ pthread_cond_destroy(&cond);
+ delete [] server_pool;
+ if (_owns_master)
+ {
+ memcached_free(master);
+ }
+ }
+
+ void increment_version()
+ {
+ ++master->configure.version;
+ }
+
+ bool compare_version(const memcached_st *arg) const
+ {
+ return (arg->configure.version == version());
+ }
+
+ int32_t version() const
+ {
+ return master->configure.version;
+ }
+};
+
+
+/**
+ * Grow the connection pool by creating a connection structure and clone the
+ * original memcached handle.
+ */
+static bool grow_pool(memcached_pool_st* pool)
+{
+ assert(pool);
+
+ memcached_st *obj;
+ if (not (obj= memcached_clone(NULL, pool->master)))
+ {
+ return false;
+ }
+
+ pool->server_pool[++pool->firstfree]= obj;
+ pool->current_size++;
+ obj->configure.version= pool->version();
+
+ return true;
+}
+
+bool memcached_pool_st::init(uint32_t initial)
+{
+ server_pool= new (std::nothrow) memcached_st *[size];
+ if (not server_pool)
+ return false;
+
+ /*
+ Try to create the initial size of the pool. An allocation failure at
+ this time is not fatal..
+ */
+ for (unsigned int x= 0; x < initial; ++x)
+ {
+ if (grow_pool(this) == false)
+ {
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+static inline memcached_pool_st *_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
+{
+ if (initial == 0 or max == 0 or (initial > max))
+ {
+ return NULL;
+ }
+
+ memcached_pool_st *object= new (std::nothrow) memcached_pool_st(master, max);
+ if (object == NULL)
+ {
+ return NULL;
+ }
+
+ /*
+ Try to create the initial size of the pool. An allocation failure at
+ this time is not fatal..
+ */
+ if (not object->init(initial))
+ {
+ delete object;
+ return NULL;
+ }
+
+ return object;
+}
+
+memcached_pool_st *memcached_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
+{
+ return _pool_create(master, initial, max);
+}
+
+memcached_pool_st * memcached_pool(const char *option_string, size_t option_string_length)
+{
+ memcached_st *memc= memcached(option_string, option_string_length);
+
+ if (memc == NULL)
+ {
+ return NULL;
+ }
+
+ memcached_pool_st *self= memcached_pool_create(memc, memc->configure.initial_pool_size, memc->configure.max_pool_size);
+ if (self == NULL)
+ {
+ memcached_free(memc);
+ return NULL;
+ }
+
+ self->_owns_master= true;
+
+ return self;
+}
+
+memcached_st* memcached_pool_destroy(memcached_pool_st* pool)
+{
+ if (pool == NULL)
+ {
+ return NULL;
+ }
+
+ // Legacy that we return the original structure
+ memcached_st *ret= NULL;
+ if (pool->_owns_master)
+ { }
+ else
+ {
+ ret= pool->master;
+ }
+
+ delete pool;
+
+ return ret;
+}
+
+memcached_st* memcached_pool_st::fetch(memcached_return_t& rc)
+{
+ static struct timespec relative_time= { 0, 0 };
+ return fetch(relative_time, rc);
+}
+
+memcached_st* memcached_pool_st::fetch(const struct timespec& relative_time, memcached_return_t& rc)
+{
+ rc= MEMCACHED_SUCCESS;
+
+ if (pthread_mutex_lock(&mutex))
+ {
+ rc= MEMCACHED_IN_PROGRESS;
+ return NULL;
+ }
+
+ memcached_st *ret= NULL;
+ do
+ {
+ if (firstfree > -1)
+ {
+ ret= server_pool[firstfree--];
+ }
+ else if (current_size == size)
+ {
+ if (relative_time.tv_sec == 0 and relative_time.tv_nsec == 0)
+ {
+ pthread_mutex_unlock(&mutex);
+ rc= MEMCACHED_NOTFOUND;
+
+ return NULL;
+ }
+
+ struct timespec time_to_wait= {0, 0};
+ time_to_wait.tv_sec= time(NULL) +relative_time.tv_sec;
+ time_to_wait.tv_nsec= relative_time.tv_nsec;
+
+ int thread_ret;
+ if ((thread_ret= pthread_cond_timedwait(&cond, &mutex, &time_to_wait)) != 0)
+ {
+ pthread_mutex_unlock(&mutex);
+
+ if (thread_ret == ETIMEDOUT)
+ {
+ rc= MEMCACHED_TIMEOUT;
+ }
+ else
+ {
+ errno= thread_ret;
+ rc= MEMCACHED_ERRNO;
+ }
+
+ return NULL;
+ }
+ }
+ else if (grow_pool(this) == false)
+ {
+ (void)pthread_mutex_unlock(&mutex);
+ return NULL;
+ }
+ } while (ret == NULL);
+
+ pthread_mutex_unlock(&mutex);
+
+ return ret;
+}
+
+bool memcached_pool_st::release(memcached_st *released, memcached_return_t& rc)
+{
+ rc= MEMCACHED_SUCCESS;
+ if (released == NULL)
+ {
+ rc= MEMCACHED_INVALID_ARGUMENTS;
+ return false;
+ }
+
+ if (pthread_mutex_lock(&mutex))
+ {
+ rc= MEMCACHED_IN_PROGRESS;
+ return false;
+ }
+
+ /*
+ Someone updated the behavior on the object, so we clone a new memcached_st with the new settings. If we fail to clone, we keep the old one around.
+ */
+ if (compare_version(released) == false)
+ {
+ memcached_st *memc;
+ if ((memc= memcached_clone(NULL, master)))
+ {
+ memcached_free(released);
+ released= memc;
+ }
+ }
+
+ server_pool[++firstfree]= released;
+
+ if (firstfree == 0 and current_size == size)
+ {
+ /* we might have people waiting for a connection.. wake them up :-) */
+ pthread_cond_broadcast(&cond);
+ }
+
+ (void)pthread_mutex_unlock(&mutex);
+
+ return true;
+}
+
+memcached_st* memcached_pool_fetch(memcached_pool_st* pool, struct timespec* relative_time, memcached_return_t* rc)
+{
+ if (pool == NULL)
+ {
+ return NULL;
+ }
+
+ memcached_return_t unused;
+ if (rc == NULL)
+ {
+ rc= &unused;
+ }
+
+ if (relative_time == NULL)
+ {
+ return pool->fetch(*rc);
+ }
+
+ return pool->fetch(*relative_time, *rc);
+}
+
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+ bool block,
+ memcached_return_t *rc)
+{
+ if (pool == NULL)
+ {
+ return NULL;
+ }
+
+ memcached_return_t unused;
+ if (rc == NULL)
+ {
+ rc= &unused;
+ }
+
+ memcached_st *memc;
+ if (block)
+ {
+ memc= pool->fetch(pool->timeout(), *rc);
+ }
+ else
+ {
+ memc= pool->fetch(*rc);
+ }
+
+ return memc;
+}
+
+memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st *released)
+{
+ if (pool == NULL)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
+ memcached_return_t rc;
+
+ (void) pool->release(released, rc);
+
+ return rc;
+}
+
+memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *released)
+{
+ return memcached_pool_release(pool, released);
+}
+
+
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
+ memcached_behavior_t flag,
+ uint64_t data)
+{
+ if (pool == NULL)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
+ if (pthread_mutex_lock(&pool->mutex))
+ {
+ return MEMCACHED_IN_PROGRESS;
+ }
+
+ /* update the master */
+ memcached_return_t rc= memcached_behavior_set(pool->master, flag, data);
+ if (memcached_failed(rc))
+ {
+ (void)pthread_mutex_unlock(&pool->mutex);
+ return rc;
+ }
+
+ pool->increment_version();
+ /* update the clones */
+ for (int xx= 0; xx <= pool->firstfree; ++xx)
+ {
+ if (memcached_success(memcached_behavior_set(pool->server_pool[xx], flag, data)))
+ {
+ pool->server_pool[xx]->configure.version= pool->version();
+ }
+ else
+ {
+ memcached_st *memc;
+ if ((memc= memcached_clone(NULL, pool->master)))
+ {
+ memcached_free(pool->server_pool[xx]);
+ pool->server_pool[xx]= memc;
+ /* I'm not sure what to do in this case.. this would happen
+ if we fail to push the server list inside the client..
+ I should add a testcase for this, but I believe the following
+ would work, except that you would add a hole in the pool list..
+ in theory you could end up with an empty pool....
+ */
+ }
+ }
+ }
+
+ (void)pthread_mutex_unlock(&pool->mutex);
+
+ return rc;
+}
+
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
+ memcached_behavior_t flag,
+ uint64_t *value)
+{
+ if (pool == NULL)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
+ if (pthread_mutex_lock(&pool->mutex))
+ {
+ return MEMCACHED_IN_PROGRESS;
+ }
+
+ *value= memcached_behavior_get(pool->master, flag);
+
+ (void)pthread_mutex_unlock(&pool->mutex);
+
+ return MEMCACHED_SUCCESS;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcachedutil/common.h>
+#include <cassert>
+
+struct local_context
+{
+ uint8_t major_version;
+ uint8_t minor_version;
+ uint8_t micro_version;
+
+ bool truth;
+};
+
+static memcached_return_t check_server_version(const memcached_st *,
+ const memcached_server_st *instance,
+ void *context)
+{
+ /* Do Nothing */
+ struct local_context *check= (struct local_context *)context;
+
+ if (instance->major_version != UINT8_MAX &&
+ instance->major_version >= check->major_version and
+ instance->minor_version >= check->minor_version and
+ instance->micro_version >= check->micro_version )
+ {
+ return MEMCACHED_SUCCESS;
+ }
+
+ check->truth= false;
+
+ return MEMCACHED_FAILURE;
+}
+
+bool libmemcached_util_version_check(memcached_st *memc,
+ uint8_t major_version,
+ uint8_t minor_version,
+ uint8_t micro_version)
+{
+ if (memcached_failed(memcached_version(memc)))
+ {
+ return false;
+ }
+
+ struct local_context check= { major_version, minor_version, micro_version, true };
+
+ memcached_server_fn callbacks[1];
+ callbacks[0]= check_server_version;
+ memcached_server_cursor(memc, callbacks, (void *)&check, 1);
+
+ return check.truth;
+}
} \
} while (0)
+#define test_compare_hint test_compare_got
+
#define test_compare_warn(__expected, __actual) \
do \
{ \
+++ /dev/null
-# progtest.m4 serial 6 (gettext-0.18)
-dnl Copyright (C) 1996-2003, 2005, 2008-2010 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-dnl
-dnl This file can can be used in projects which are not available under
-dnl the GNU General Public License or the GNU Library General Public
-dnl License but which still want to provide support for the GNU gettext
-dnl functionality.
-dnl Please note that the actual code of the GNU gettext library is covered
-dnl by the GNU Library General Public License, and the rest of the GNU
-dnl gettext package package is covered by the GNU General Public License.
-dnl They are *not* in the public domain.
-
-dnl Authors:
-dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
-
-AC_PREREQ([2.50])
-
-# Search path for a program which passes the given test.
-
-dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
-dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
-AC_DEFUN([AM_PATH_PROG_WITH_TEST],
-[
-# Prepare PATH_SEPARATOR.
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-# Find out how to test for executable files. Don't use a zero-byte file,
-# as systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- ac_executable_p="test -x"
-else
- ac_executable_p="test -f"
-fi
-rm -f conf$$.file
-
-# Extract the first word of "$2", so it can be a program name with args.
-set dummy $2; ac_word=[$]2
-AC_MSG_CHECKING([for $ac_word])
-AC_CACHE_VAL([ac_cv_path_$1],
-[case "[$]$1" in
- [[\\/]]* | ?:[[\\/]]*)
- ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
- ;;
- *)
- ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in ifelse([$5], , $PATH, [$5]); do
- IFS="$ac_save_IFS"
- test -z "$ac_dir" && ac_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
- echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
- if [$3]; then
- ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
- break 2
- fi
- fi
- done
- done
- IFS="$ac_save_IFS"
-dnl If no 4th arg is given, leave the cache variable unset,
-dnl so AC_PATH_PROGS will keep looking.
-ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
-])dnl
- ;;
-esac])dnl
-$1="$ac_cv_path_$1"
-if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
- AC_MSG_RESULT([$][$1])
-else
- AC_MSG_RESULT([no])
-fi
-AC_SUBST([$1])dnl
-])
memcp - Copy files to memcached servers.
memerror - Creates human readable messages from libmemecached error codes.
memcapable - Verify a memcached server for protocol behavior.
+memexist - Check for the existance of a key.
+memtouch - Update the expiration value of a key.
%package devel
%files devel
%defattr (-,root,root,-)
%doc examples
-%{_includedir}/libhashkit/algorithm.h
-%{_includedir}/libhashkit/behavior.h
-%{_includedir}/libhashkit/configure.h
-%{_includedir}/libhashkit/digest.h
-%{_includedir}/libhashkit/function.h
-%{_includedir}/libhashkit/has.h
%{_includedir}/libhashkit/hashkit.h
-%{_includedir}/libhashkit/hashkit.hpp
-%{_includedir}/libhashkit/str_algorithm.h
-%{_includedir}/libhashkit/strerror.h
-%{_includedir}/libhashkit/types.h
-%{_includedir}/libhashkit/visibility.h
-
-%{_includedir}/libmemcached/allocators.h
-%{_includedir}/libmemcached/analyze.h
-%{_includedir}/libmemcached/array.h
-%{_includedir}/libmemcached/auto.h
-%{_includedir}/libmemcached/basic_string.h
-%{_includedir}/libmemcached/behavior.h
-%{_includedir}/libmemcached/callback.h
-%{_includedir}/libmemcached/configure.h
-%{_includedir}/libmemcached/constants.h
-%{_includedir}/libmemcached/delete.h
-%{_includedir}/libmemcached/dump.h
-%{_includedir}/libmemcached/error.h
-%{_includedir}/libmemcached/exist.h
-%{_includedir}/libmemcached/exception.hpp
-%{_includedir}/libmemcached/fetch.h
-%{_includedir}/libmemcached/flush.h
-%{_includedir}/libmemcached/flush_buffers.h
-%{_includedir}/libmemcached/get.h
-%{_includedir}/libmemcached/hash.h
+%{_includedir}/libhashkit-1.0/algorithm.h
+%{_includedir}/libhashkit-1.0/behavior.h
+%{_includedir}/libhashkit-1.0/configure.h
+%{_includedir}/libhashkit-1.0/digest.h
+%{_includedir}/libhashkit-1.0/function.h
+%{_includedir}/libhashkit-1.0/has.h
+%{_includedir}/libhashkit-1.0/hashkit.h
+%{_includedir}/libhashkit-1.0/hashkit.hpp
+%{_includedir}/libhashkit-1.0/str_algorithm.h
+%{_includedir}/libhashkit-1.0/strerror.h
+%{_includedir}/libhashkit-1.0/types.h
+%{_includedir}/libhashkit-1.0/visibility.h
+
+%{_includedir}/libmemcachedprotocol-0.0/binary.h
+%{_includedir}/libmemcachedprotocol-0.0/callback.h
+%{_includedir}/libmemcachedprotocol-0.0/handler.h
+%{_includedir}/libmemcachedprotocol-0.0/vbucket.h
+
+%{_includedir}/libmemcachedutil-1.0/util.h
+%{_includedir}/libmemcachedutil-1.0/flush.h
+%{_includedir}/libmemcachedutil-1.0/pid.h
+%{_includedir}/libmemcachedutil-1.0/ping.h
+%{_includedir}/libmemcachedutil-1.0/pool.h
+%{_includedir}/libmemcachedutil-1.0/version.h
+
%{_includedir}/libmemcached/memcached.h
%{_includedir}/libmemcached/memcached.hpp
-%{_includedir}/libmemcached/memcached/protocol_binary.h
-%{_includedir}/libmemcached/memcached/vbucket.h
-%{_includedir}/libmemcached/memcached_util.h
-%{_includedir}/libmemcached/namespace.h
-%{_includedir}/libmemcached/options.h
-%{_includedir}/libmemcached/parse.h
-%{_includedir}/libmemcached/platform.h
-%{_includedir}/libmemcached/protocol/cache.h
-%{_includedir}/libmemcached/protocol/callback.h
-%{_includedir}/libmemcached/protocol_handler.h
-%{_includedir}/libmemcached/quit.h
-%{_includedir}/libmemcached/result.h
-%{_includedir}/libmemcached/return.h
-%{_includedir}/libmemcached/sasl.h
-%{_includedir}/libmemcached/server.h
-%{_includedir}/libmemcached/server_list.h
-%{_includedir}/libmemcached/stats.h
-%{_includedir}/libmemcached/storage.h
-%{_includedir}/libmemcached/strerror.h
-%{_includedir}/libmemcached/string.h
-%{_includedir}/libmemcached/types.h
%{_includedir}/libmemcached/util.h
-%{_includedir}/libmemcached/util/flush.h
-%{_includedir}/libmemcached/util/pid.h
-%{_includedir}/libmemcached/util/ping.h
-%{_includedir}/libmemcached/util/pool.h
-%{_includedir}/libmemcached/util/version.h
-%{_includedir}/libmemcached/verbosity.h
-%{_includedir}/libmemcached/version.h
-%{_includedir}/libmemcached/visibility.h
-%{_includedir}/libmemcached/watchpoint.h
+
+%{_includedir}/libmemcached-1.0/allocators.h
+%{_includedir}/libmemcached-1.0/analyze.h
+%{_includedir}/libmemcached-1.0/auto.h
+%{_includedir}/libmemcached-1.0/basic_string.h
+%{_includedir}/libmemcached-1.0/behavior.h
+%{_includedir}/libmemcached-1.0/callback.h
+%{_includedir}/libmemcached-1.0/configure.h
+%{_includedir}/libmemcached-1.0/constants.h
+%{_includedir}/libmemcached-1.0/delete.h
+%{_includedir}/libmemcached-1.0/dump.h
+%{_includedir}/libmemcached-1.0/error.h
+%{_includedir}/libmemcached-1.0/exist.h
+%{_includedir}/libmemcached-1.0/touch.h
+%{_includedir}/libmemcached-1.0/exception.hpp
+%{_includedir}/libmemcached-1.0/fetch.h
+%{_includedir}/libmemcached-1.0/flush.h
+%{_includedir}/libmemcached-1.0/flush_buffers.h
+%{_includedir}/libmemcached-1.0/get.h
+%{_includedir}/libmemcached-1.0/hash.h
+%{_includedir}/libmemcached-1.0/memcached.h
+%{_includedir}/libmemcached-1.0/memcached.hpp
+%{_includedir}/libmemcached-1.0/options.h
+%{_includedir}/libmemcached-1.0/parse.h
+%{_includedir}/libmemcached-1.0/platform.h
+%{_includedir}/libmemcached-1.0/quit.h
+%{_includedir}/libmemcached-1.0/result.h
+%{_includedir}/libmemcached-1.0/return.h
+%{_includedir}/libmemcached-1.0/sasl.h
+%{_includedir}/libmemcached-1.0/server.h
+%{_includedir}/libmemcached-1.0/server_list.h
+%{_includedir}/libmemcached-1.0/stats.h
+%{_includedir}/libmemcached-1.0/storage.h
+%{_includedir}/libmemcached-1.0/strerror.h
+%{_includedir}/libmemcached-1.0/string.h
+%{_includedir}/libmemcached-1.0/types.h
+%{_includedir}/libmemcached-1.0/verbosity.h
+%{_includedir}/libmemcached-1.0/version.h
+%{_includedir}/libmemcached-1.0/visibility.h
+
%{_libdir}/libhashkit.so
%{_libdir}/libmemcached.so
%{_libdir}/libmemcachedprotocol.so
%{_mandir}/man3/memcached_strerror.3.gz
%{_mandir}/man3/memcached_exist.3.gz
%{_mandir}/man3/memcached_exist_by_key.3.gz
+%{_mandir}/man3/memcached_touch.3.gz
+%{_mandir}/man3/memcached_touch_by_key.3.gz
%{_mandir}/man3/memcached_verbosity.3.gz
%{_mandir}/man3/memcached_version.3.gz
#include <libtest/test.hpp>
#include <libmemcached/memcached.h>
-#include <libmemcached/watchpoint.h>
#include <cstdio>
#include <cstdlib>
}
else
{
- WATCHPOINT_ERROR(rc);
- WATCHPOINT_ASSERT(rc);
+ test_compare(MEMCACHED_SUCCESS, rc);
}
}
else
0, 0);
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
{
- WATCHPOINT_ERROR(rc);
- WATCHPOINT_ASSERT(0);
+ test_compare(MEMCACHED_SUCCESS, rc);
}
}
}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached Client and Server
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <libtest/test.hpp>
+
+#include <tests/callbacks.h>
+
+using namespace libtest;
+
+static memcached_return_t delete_trigger(memcached_st *,
+ const char *key,
+ size_t key_length)
+{
+ assert(key);
+ assert(key_length);
+
+ return MEMCACHED_SUCCESS;
+}
+
+
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY(memcached_st *)
+{
+ memcached_st *memc= memcached(test_literal_param("--NOREPLY"));
+ test_true(memc);
+
+ memcached_trigger_delete_key_fn callback;
+
+ callback= (memcached_trigger_delete_key_fn)delete_trigger;
+
+ test_compare(MEMCACHED_INVALID_ARGUMENTS,
+ memcached_callback_set(memc, MEMCACHED_CALLBACK_DELETE_TRIGGER, *(void**)&callback));
+
+ memcached_free(memc);
+
+ return TEST_SUCCESS;
+}
+
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER(memcached_st *memc)
+{
+ memcached_trigger_delete_key_fn callback;
+
+ callback= (memcached_trigger_delete_key_fn)delete_trigger;
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_callback_set(memc, MEMCACHED_CALLBACK_DELETE_TRIGGER, *(void**)&callback));
+
+ return TEST_SUCCESS;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached Client and Server
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY(memcached_st *);
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER(memcached_st *);
/*
C++ interface test
*/
-#include <libmemcached/memcached.hpp>
+#include <libmemcached-1.0/memcached.hpp>
#include <libmemcached/server_instance.h>
#include <libtest/test.hpp>
#include <cstdlib>
#include <cstring>
-#include <libhashkit/hashkit.hpp>
+#include <libhashkit-1.0/hashkit.hpp>
using namespace libtest;
#include <cstdlib>
#include <cstring>
-#include <libhashkit/hashkit.h>
+#include <libhashkit-1.0/hashkit.h>
+#include <libhashkit/is.h>
-#include "hash_results.h"
+#include "tests/hash_results.h"
static hashkit_st global_hashk;
noinst_HEADERS+= \
tests/basic.h \
+ tests/callbacks.h \
tests/debug.h \
tests/error_conditions.h \
tests/exist.h \
tests/libmemcached_world.h \
tests/namespace.h \
tests/parser.h \
+ tests/touch.h \
tests/deprecated.h \
tests/pool.h \
tests/print.h \
tests/mem_functions.cc \
tests/namespace.cc \
tests/parser.cc \
+ tests/touch.cc \
+ tests/callbacks.cc \
tests/pool.cc \
tests/print.cc \
tests/replication.cc \
tests_memcapable_SOURCES= tests/memcapable.cc
tests_memcapable_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memcapable_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memcapable_LDADD= $(tests_memcapable_DEPENDENCIES)
+tests_memcapable_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memcapable
+tests_memcapable_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memcapable
noinst_PROGRAMS+= tests/memcapable
tests_memstat_SOURCES= tests/memstat.cc
tests_memstat_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memstat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memstat_LDADD= $(tests_memstat_DEPENDENCIES)
+tests_memstat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memstat
+tests_memstat_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memstat
noinst_PROGRAMS+= tests/memstat
tests_memcp_SOURCES= tests/memcp.cc
tests_memcp_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memcp_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memcp_LDADD= $(tests_memcp_DEPENDENCIES)
+tests_memcp_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memcp
+tests_memcp_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memcp
noinst_PROGRAMS+= tests/memcp
tests_memflush_SOURCES= tests/memflush.cc
tests_memflush_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memflush_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memflush_LDADD= $(tests_memflush_DEPENDENCIES)
+tests_memflush_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memflush
+tests_memflush_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memflush
noinst_PROGRAMS+= tests/memflush
tests_memrm_SOURCES= tests/memrm.cc
tests_memrm_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memrm_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memrm_LDADD= $(tests_memrm_DEPENDENCIES)
+tests_memrm_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memrm
+tests_memrm_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memrm
noinst_PROGRAMS+= tests/memrm
tests_memexist_SOURCES= tests/memexist.cc
tests_memexist_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memexist_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memexist_LDADD= $(tests_memexist_DEPENDENCIES)
+tests_memexist_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memexist
+tests_memexist_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memexist
noinst_PROGRAMS+= tests/memexist
+tests_memtouch_SOURCES= tests/memtouch.cc
+tests_memtouch_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
+tests_memtouch_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memtouch
+tests_memtouch_LDADD= libtest/libtest.la $(TESTS_LDADDS)
+check_PROGRAMS+= tests/memtouch
+noinst_PROGRAMS+= tests/memtouch
+
tests_memcat_SOURCES= tests/memcat.cc
tests_memcat_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memcat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memcat_LDADD= $(tests_memcat_DEPENDENCIES)
+tests_memcat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memcat
+tests_memcat_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memcat
noinst_PROGRAMS+= tests/memcat
tests_memerror_SOURCES= tests/memerror.cc
tests_memerror_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memerror_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memerror_LDADD= $(tests_memerror_DEPENDENCIES)
+tests_memerror_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memerror
+tests_memerror_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memerror
noinst_PROGRAMS+= tests/memerror
tests_memslap_SOURCES= tests/memslap.cc
tests_memslap_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memslap_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memslap_LDADD= $(tests_memslap_DEPENDENCIES)
+tests_memslap_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memslap
+tests_memslap_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memslap
noinst_PROGRAMS+= tests/memslap
tests_memdump_SOURCES= tests/memdump.cc
tests_memdump_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memdump_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memdump_LDADD= $(tests_memdump_DEPENDENCIES)
+tests_memdump_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memdump
+tests_memdump_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memdump
noinst_PROGRAMS+= tests/memdump
buffer, sizeof(buffer)),
container->construct.option_string().c_str());
- test_true(not container->parent);
+ test_null(container->parent);
container->parent= memcached(container->construct.option_string().c_str(), container->construct.option_string().size());
test_true(container->parent);
+ test_compare(MEMCACHED_SUCCESS, memcached_version(container->parent));
if (container->construct.sasl())
{
static test_return_t world_test_startup(libmemcached_test_container_st *container)
{
test_true(container);
- test_true(not container->memc);
+ test_null(container->memc);
test_true(container->parent);
container->memc= memcached_clone(NULL, container->parent);
test_true(container->memc);
return TEST_SUCCESS;
}
-static test_return_t world_on_error(test_return_t test_state, libmemcached_test_container_st *container)
+static test_return_t world_on_error(test_return_t , libmemcached_test_container_st *container)
{
- (void)test_state;
test_true(container->memc);
memcached_free(container->memc);
container->memc= NULL;
Test cases
*/
-#include <libmemcached/memcached.h>
+#include <libmemcached-1.0/memcached.h>
#include <libmemcached/is.h>
#include <libmemcached/server_instance.h>
-#include <libhashkit/hashkit.h>
+#include <libhashkit-1.0/hashkit.h>
#include <cassert>
#include <cerrno>
#include "tests/ketama.h"
#include "tests/namespace.h"
#include "tests/parser.h"
+#include "tests/touch.h"
+#include "tests/callbacks.h"
#include "tests/pool.h"
#include "tests/print.h"
#include "tests/replication.h"
using namespace libtest;
-#include <libmemcached/memcached_util.h>
+#include <libmemcached/util.h>
#include "hash_results.h"
static const char *global_keys[GLOBAL_COUNT];
static size_t global_keys_length[GLOBAL_COUNT];
-// Prototype
-static test_return_t pre_binary(memcached_st *memc);
+/**
+ @note This should be testing to see if the server really supports the binary protocol.
+*/
+static test_return_t pre_binary(memcached_st *memc)
+{
+ memcached_return_t rc= MEMCACHED_FAILURE;
+
+ if (libmemcached_util_version_check(memc, 1, 4, 4))
+ {
+ rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
+ test_compare(MEMCACHED_SUCCESS, rc);
+ test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
+ }
+
+ return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
+}
static test_return_t init_test(memcached_st *not_used)
return TEST_SUCCESS;
}
-static memcached_return_t delete_trigger(memcached_st *,
- const char *key,
- size_t key_length)
-{
- assert(key);
- assert(key_length);
-
- return MEMCACHED_SUCCESS;
-}
-
-static test_return_t delete_through(memcached_st *memc)
-{
- memcached_trigger_delete_key_fn callback;
-
- callback= (memcached_trigger_delete_key_fn)delete_trigger;
-
- test_compare(MEMCACHED_SUCCESS,
- memcached_callback_set(memc, MEMCACHED_CALLBACK_DELETE_TRIGGER, *(void**)&callback));
-
- return TEST_SUCCESS;
-}
-
static test_return_t get_test(memcached_st *memc)
{
memcached_return_t rc;
/* Do a large mget() over all the keys we think exist */
static test_return_t user_supplied_bug3(memcached_st *memc)
{
- unsigned int setter= 1;
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, setter);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, setter);
+ test_compare(true, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1));
+ test_compare(true, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1));
#ifdef NOT_YET
setter = 20 * 1024576;
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE, setter);
{
char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
int key_length= snprintf(key, sizeof(key), "%u", x);
+ test_true(key_length);
keys[x]= strdup(key);
test_true(keys[x]);
key_lengths[x]= key_length;
memcached_return_t rc;
value= memcached_get(memc, keys[0], key_length[0],
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_false(value);
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 4));
memcached_return_t rc;
uint32_t count= 0;
while ((value= memcached_fetch(memc, return_key, &return_key_length,
- &value_length, &flags, &rc)))
+ &value_length, &flags, &rc)))
{
count++;
}
flags= 0;
value= memcached_get(memc, keys, key_length,
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_true(flags == 245);
test_true(value);
free(value);
value, value_length, 0, 0);
test_true_got((rc == MEMCACHED_SUCCESS or rc == MEMCACHED_WRITE_FAILURE or rc == MEMCACHED_BUFFERED or rc == MEMCACHED_TIMEOUT or rc == MEMCACHED_CONNECTION_FAILURE
- or rc == MEMCACHED_SERVER_TEMPORARILY_DISABLED),
+ or rc == MEMCACHED_SERVER_TEMPORARILY_DISABLED),
memcached_strerror(NULL, rc));
if (rc == MEMCACHED_WRITE_FAILURE or rc == MEMCACHED_TIMEOUT)
uint64_t number_value;
value= memcached_get(memc, "autoincrement", strlen("autoincrement"),
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_true(value == NULL);
test_compare(MEMCACHED_NOTFOUND, rc);
rc= memcached_set(memc, "autoincrement", strlen("autoincrement"), "1", 1, 0, 0);
value= memcached_get(memc, "autoincrement", strlen("autoincrement"),
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_true(value);
test_compare(MEMCACHED_SUCCESS, rc);
free(value);
/*
Bug found where command total one more than MEMCACHED_MAX_BUFFER
set key34567890 0 0 8169 \r\n is sent followed by buffer of size 8169, followed by 8169
- */
+*/
static test_return_t user_supplied_bug13(memcached_st *memc)
{
char key[] = "key34567890";
Bug found where command total one more than MEMCACHED_MAX_BUFFER
set key34567890 0 0 8169 \r\n
is sent followed by buffer of size 8169, followed by 8169
- */
+*/
static test_return_t user_supplied_bug14(memcached_st *memc)
{
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true);
/*
Look for zero length value problems
- */
+*/
static test_return_t user_supplied_bug15(memcached_st *memc)
{
for (uint32_t x= 0; x < 2; x++)
size_t length;
uint32_t flags;
char *value= memcached_get(memc, test_literal_param("mykey"),
- &length, &flags, &rc);
+ &length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_true(value == NULL);
/* Check the validity of chinese key*/
static test_return_t user_supplied_bug17(memcached_st *memc)
{
- const char *key= "豆瓣";
- const char *value="我们在炎热抑郁的夏天无法停止豆瓣";
- memcached_return_t rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, 0);
+ const char *key= "豆瓣";
+ const char *value="我们在炎热抑郁的夏天无法停止豆瓣";
+ memcached_return_t rc= memcached_set(memc, key, strlen(key),
+ value, strlen(value),
+ (time_t)0, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS, rc);
- size_t length;
- uint32_t flags;
- char *value2= memcached_get(memc, key, strlen(key),
- &length, &flags, &rc);
+ size_t length;
+ uint32_t flags;
+ char *value2= memcached_get(memc, key, strlen(key),
+ &length, &flags, &rc);
- test_true(length==strlen(value));
- test_compare(MEMCACHED_SUCCESS, rc);
- test_memcmp(value, value2, length);
- free(value2);
+ test_true(length==strlen(value));
+ test_compare(MEMCACHED_SUCCESS, rc);
+ test_memcmp(value, value2, length);
+ free(value2);
- return TEST_SUCCESS;
+ return TEST_SUCCESS;
}
#endif
static test_return_t user_supplied_bug21(memcached_st *memc)
{
- test_return_t test_rc;
- test_rc= pre_binary(memc);
-
- if (test_rc != TEST_SUCCESS)
- {
- return test_rc;
- }
+ test_skip(TEST_SUCCESS, pre_binary(memc));
/* should work as of r580 */
test_compare(TEST_SUCCESS,
snprintf(buffer, SMALL_STRING_LEN, "%lu.example.com", (unsigned long)(400 +x));
servers= memcached_server_list_append_with_weight(servers, buffer, 401, 0,
- &rc);
+ &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_compare(x, memcached_server_list_count(servers));
}
return TEST_SUCCESS;
}
-/**
- @note This should be testing to see if the server really supports the binary protocol.
-*/
-static test_return_t pre_binary(memcached_st *memc)
-{
- memcached_return_t rc= MEMCACHED_FAILURE;
-
- if (libmemcached_util_version_check(memc, 1, 4, 4))
- {
- rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
- test_compare(MEMCACHED_SUCCESS, rc);
- test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
- }
-
- return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
-}
-
static test_return_t pre_replication(memcached_st *memc)
{
test_skip(TEST_SUCCESS, pre_binary(memc));
/*
* Make sure that we store the item on all servers
* (master + replicas == number of servers)
- */
+ */
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, memcached_server_count(memc) - 1));
test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS), uint64_t(memcached_server_count(memc) - 1));
/* Make sure be default none exists */
value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
test_null(value);
- test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc));
+ test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
/* Test a clean set */
test_compare(MEMCACHED_SUCCESS,
memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, NULL));
value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
- test_false(value);
- test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc));
+ test_null(value);
+ test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
/* Now setup for main test */
test_compare(MEMCACHED_SUCCESS,
memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, NULL));
value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
- test_false(value);
- test_true(rc == MEMCACHED_FAILURE);
- test_true(value == NULL);
+ test_null(value);
+ test_compare(MEMCACHED_SUCCESS, rc);
/* Test a long key for failure */
/* TODO, extend test to determine based on setting, what result should be */
const char *key= "mine";
char *value;
- /* Make sure be default none exists */
+ // Make sure we default to a null namespace
value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
test_null(value);
- test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc));
+ test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
/* Test a clean set */
test_compare(MEMCACHED_SUCCESS,
}
/*
- ** NOTE: Don't ever do this in your code! this is not a supported use of the
- ** API and is _ONLY_ done this way to verify that the library works the
- ** way it is supposed to do!!!!
- */
+ ** NOTE: Don't ever do this in your code! this is not a supported use of the
+ ** API and is _ONLY_ done this way to verify that the library works the
+ ** way it is supposed to do!!!!
+ */
int no_msg=0;
for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
{
/*
** Now validate that all items was set properly!
- */
+ */
for (size_t x= 0; x < 100; ++x)
{
char key[10];
/* Try setting an illegal cas value (should not return an error to
* the caller (because we don't expect a return message from the server)
- */
+ */
const char* keys[]= {"0"};
size_t lengths[]= {1};
size_t length;
/*
* The item will have a new cas value, so try to set it again with the old
* value. This should fail!
- */
+ */
test_compare(MEMCACHED_SUCCESS,
memcached_cas(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0, cas));
test_true(memcached_flush_buffers(memc) == MEMCACHED_SUCCESS);
/* verify that I can set behaviors on the pool when I don't have all
* of the connections in the pool. It should however be enabled
* when I push the item into the pool
- */
+ */
mmc[0]= memcached_pool_fetch(pool, NULL, NULL);
test_true(mmc[0]);
static test_return_t connection_pool3_test(memcached_st *memc)
{
+#ifdef __APPLE__
+ return TEST_SKIPPED;
+#endif
+
memcached_pool_st* pool= memcached_pool_create(memc, 1, 1);
test_true(pool);
memcached_return_t rc;
memcached_st *pop_memc;
+ // We do a hard loop, and try N times
int counter= 5;
do
{
struct timespec relative_time= { 0, 0 };
pop_memc= memcached_pool_fetch(pool, &relative_time, &rc);
+ if (memcached_success(rc))
+ {
+ break;
+ }
+
if (memcached_failed(rc))
{
test_null(pop_memc);
+ test_true(rc != MEMCACHED_TIMEOUT); // As long as relative_time is zero, MEMCACHED_TIMEOUT is invalid
}
- } while (rc == MEMCACHED_TIMEOUT and --counter);
+ } while (--counter);
if (memcached_failed(rc)) // Cleanup thread since we will exit once we test.
{
static test_return_t util_version_test(memcached_st *memc)
{
- bool if_successful= libmemcached_util_version_check(memc, 0, 0, 0);
- test_true(if_successful);
+ test_compare_hint(MEMCACHED_SUCCESS, memcached_version(memc), memcached_last_error_message(memc));
+ test_true(libmemcached_util_version_check(memc, 0, 0, 0));
- if_successful= libmemcached_util_version_check(memc, 9, 9, 9);
+ bool if_successful= libmemcached_util_version_check(memc, 9, 9, 9);
// We expect failure
if (if_successful)
static test_return_t regression_bug_434484(memcached_st *memc)
{
- test_return_t test_rc;
- test_rc= pre_binary(memc);
-
- if (test_rc != TEST_SUCCESS)
- return test_rc;
+ test_skip(TEST_SUCCESS, pre_binary(memc));
const char *key= "regression_bug_434484";
size_t keylen= strlen(key);
static test_return_t regression_bug_434843(memcached_st *memc)
{
- test_return_t test_rc;
- test_rc= pre_binary(memc);
-
- if (test_rc != TEST_SUCCESS)
- return test_rc;
+ test_skip(TEST_SUCCESS, pre_binary(memc));
memcached_return_t rc;
size_t counter= 0;
* sending in the pipleine to the server. Let's try to do a multiget of
* 1024 (that should satisfy most users don't you think?). Future versions
* will include a mget_execute function call if you need a higher number.
- */
+ */
uint32_t number_of_hosts= memcached_server_count(memc);
memc->number_of_hosts= 1;
const size_t max_keys= 1024;
for (size_t x= 0; x < max_keys; ++x)
{
- char k[251];
+ char k[251];
- key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%lu", (unsigned long)x);
- keys[x]= strdup(k);
- test_true(keys[x]);
+ key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%lu", (unsigned long)x);
+ keys[x]= strdup(k);
+ test_true(keys[x]);
}
/*
* Run two times.. the first time we should have 100% cache miss,
* and the second time we should have 100% cache hits
- */
+ */
for (size_t y= 0; y < 2; y++)
{
test_compare(MEMCACHED_SUCCESS,
else
{
/* Verify that we received all of the key/value pairs */
- test_compare(counter, max_keys);
+ test_compare(counter, max_keys);
}
}
for (uint32_t x= 0; x < 250; ++x)
{
- len= (size_t)snprintf(k, sizeof(k), "%0250u", x);
- memcached_return_t rc= memcached_delete(memc, k, len, 0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ len= (size_t)snprintf(k, sizeof(k), "%0250u", x);
+ memcached_return_t rc= memcached_delete(memc, k, len, 0);
+ test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
}
(void)snprintf(k, sizeof(k), "%037u", 251U);
}
/*
- ** We are using the quiet commands to store the replicas, so we need
- ** to ensure that all of them are processed before we can continue.
- ** In the test we go directly from storing the object to trying to
- ** receive the object from all of the different servers, so we
- ** could end up in a race condition (the memcached server hasn't yet
- ** processed the quiet command from the replication set when it process
- ** the request from the other client (created by the clone)). As a
- ** workaround for that we call memcached_quit to send the quit command
- ** to the server and wait for the response ;-) If you use the test code
- ** as an example for your own code, please note that you shouldn't need
- ** to do this ;-)
- */
+ ** We are using the quiet commands to store the replicas, so we need
+ ** to ensure that all of them are processed before we can continue.
+ ** In the test we go directly from storing the object to trying to
+ ** receive the object from all of the different servers, so we
+ ** could end up in a race condition (the memcached server hasn't yet
+ ** processed the quiet command from the replication set when it process
+ ** the request from the other client (created by the clone)). As a
+ ** workaround for that we call memcached_quit to send the quit command
+ ** to the server and wait for the response ;-) If you use the test code
+ ** as an example for your own code, please note that you shouldn't need
+ ** to do this ;-)
+ */
memcached_quit(memc);
/* Verify that all messages are stored, and we didn't stuff too much
* into the servers
- */
+ */
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
* within the library, and this is not a supported interface.
* This is to verify correct behavior in the library. Fake that two servers
* are dead..
- */
+ */
instance_one= memcached_server_instance_by_position(memc, 0);
instance_two= memcached_server_instance_by_position(memc, 2);
in_port_t port0= instance_one->port;
/* but there is a bug in some of the memcached servers (1.4) that treats
* the counter as noreply so it doesn't send the proper error message
- */
+ */
test_true_got(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR || rc == MEMCACHED_INVALID_ARGUMENTS, memcached_strerror(NULL, rc));
/* And buffered mode should be disabled and we should get protocol error */
* Please note that I'm abusing the internal structures in libmemcached
* in a non-portable way and you shouldn't be doing this. I'm only
* doing this in order to verify that the library works the way it should
- */
+ */
uint32_t number_of_hosts= memcached_server_count(memc);
memc->number_of_hosts= 1;
/* The test is to see that the memcached_quit doesn't increase the
* the server failure conter, so let's ensure that it is zero
* before sending quit
- */
+ */
((memcached_server_write_instance_st)instance)->server_failure_counter= 0;
memcached_quit(memc);
/* Verify that it memcached_quit didn't increment the failure counter
* Please note that this isn't bullet proof, because an error could
* occur...
- */
+ */
test_zero(instance->server_failure_counter);
/* restore the instance */
/*
* I only want to hit _one_ server so I know the number of requests I'm
* sending in the pipeline.
- */
+ */
uint32_t number_of_hosts= memc->number_of_hosts;
memc->number_of_hosts= 1;
size_t max_keys= 20480;
test_compare(MEMCACHED_INVALID_ARGUMENTS, libmemcached_check_configuration(0, 0, buffer, 0));
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, 0));
-
+
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, 1));
test_compare(buffer[0], 0);
-
+
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, 10));
test_true(strlen(buffer));
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, sizeof(buffer)));
test_true(strlen(buffer));
-
+
return TEST_SUCCESS;
}
{"bad_key", true, (test_callback_fn*)bad_key_test },
{"memcached_server_cursor", true, (test_callback_fn*)memcached_server_cursor_test },
{"read_through", true, (test_callback_fn*)read_through },
- {"delete_through", true, (test_callback_fn*)delete_through },
+ {"delete_through", true, (test_callback_fn*)test_MEMCACHED_CALLBACK_DELETE_TRIGGER },
{"noreply", true, (test_callback_fn*)noreply_test},
{"analyzer", true, (test_callback_fn*)analyzer_test},
{"memcached_pool_st", true, (test_callback_fn*)connection_pool_test },
{"memcached_exist(MEMCACHED_SUCCESS)", true, (test_callback_fn*)memcached_exist_SUCCESS },
{"memcached_exist_by_key(MEMCACHED_NOTFOUND)", true, (test_callback_fn*)memcached_exist_by_key_NOTFOUND },
{"memcached_exist_by_key(MEMCACHED_SUCCESS)", true, (test_callback_fn*)memcached_exist_by_key_SUCCESS },
+ {"memcached_touch", 0, (test_callback_fn*)test_memcached_touch},
+ {"memcached_touch_with_prefix", 0, (test_callback_fn*)test_memcached_touch_by_key},
+ {0, 0, 0}
+};
+
+test_st touch_tests[] ={
+ {"memcached_touch", 0, (test_callback_fn*)test_memcached_touch},
+ {"memcached_touch_with_prefix", 0, (test_callback_fn*)test_memcached_touch_by_key},
{0, 0, 0}
};
{"MEMCACHED_BEHAVIOR_TCP_KEEPALIVE", false, (test_callback_fn*)MEMCACHED_BEHAVIOR_TCP_KEEPALIVE_test},
{"MEMCACHED_BEHAVIOR_TCP_KEEPIDLE", false, (test_callback_fn*)MEMCACHED_BEHAVIOR_TCP_KEEPIDLE_test},
{"MEMCACHED_BEHAVIOR_POLL_TIMEOUT", false, (test_callback_fn*)MEMCACHED_BEHAVIOR_POLL_TIMEOUT_test},
+ {"MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY", false, (test_callback_fn*)test_MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY},
{0, 0, 0}
};
{"user_supplied_bug16", true, (test_callback_fn*)user_supplied_bug16 },
#if !defined(__sun) && !defined(__OpenBSD__)
/*
- ** It seems to be something weird with the character sets..
- ** value_fetch is unable to parse the value line (iscntrl "fails"), so I
- ** guess I need to find out how this is supposed to work.. Perhaps I need
- ** to run the test in a specific locale (I tried zh_CN.UTF-8 without success,
- ** so just disable the code for now...).
- */
+ ** It seems to be something weird with the character sets..
+ ** value_fetch is unable to parse the value line (iscntrl "fails"), so I
+ ** guess I need to find out how this is supposed to work.. Perhaps I need
+ ** to run the test in a specific locale (I tried zh_CN.UTF-8 without success,
+ ** so just disable the code for now...).
+ */
{"user_supplied_bug17", true, (test_callback_fn*)user_supplied_bug17 },
#endif
{"user_supplied_bug18", true, (test_callback_fn*)user_supplied_bug18 },
{0, 0, (test_callback_fn*)0}
};
-
test_st parser_tests[] ={
{"behavior", false, (test_callback_fn*)behavior_parser_test },
{"boolean_options", false, (test_callback_fn*)parser_boolean_options_test },
{"parser", 0, 0, parser_tests},
{"virtual buckets", 0, 0, virtual_bucket_tests},
{"memcached_server_get_last_disconnect", 0, 0, memcached_server_get_last_disconnect_tests},
+ {"touch", 0, 0, touch_tests},
{0, 0, 0, 0}
};
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Test memtouch
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/*
+ Test that we are cycling the servers we are creating during testing.
+*/
+
+#include <config.h>
+
+#include <libtest/test.hpp>
+#include <libmemcached/memcached.h>
+
+using namespace libtest;
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+
+static std::string executable;
+
+static test_return_t quiet_test(void *)
+{
+ const char *args[]= { "--quiet", 0 };
+
+ test_true(exec_cmdline(executable, args));
+ return TEST_SUCCESS;
+}
+
+static test_return_t help_test(void *)
+{
+ const char *args[]= { "--quiet", "--help", 0 };
+
+ test_true(exec_cmdline(executable, args));
+ return TEST_SUCCESS;
+}
+
+static test_return_t touch_test(void *)
+{
+ char buffer[1024];
+ snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
+ const char *args[]= { "--quiet", "--expire=30", buffer, "foo", 0 };
+
+ memcached_st *memc= memcached(buffer, strlen(buffer));
+ test_true(memc);
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, test_literal_param("foo"), 0, 0, 0, 0));
+
+ test_compare(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("foo")));
+
+ test_true(exec_cmdline(executable, args));
+
+ test_compare(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("foo")));
+
+ memcached_free(memc);
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t NOT_FOUND_test(void *)
+{
+ char buffer[1024];
+ snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
+ const char *args[]= { "--quiet", "--expire=30", buffer, "foo", 0 };
+
+ memcached_st *memc= memcached(buffer, strlen(buffer));
+ test_true(memc);
+
+ test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
+
+ test_compare(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("foo")));
+
+ test_true(exec_cmdline(executable, args));
+
+ test_compare(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("foo")));
+
+ memcached_free(memc);
+
+ return TEST_SUCCESS;
+}
+
+test_st memtouch_tests[] ={
+ {"--quiet", true, quiet_test },
+ {"--help", true, help_test },
+ {"touch(FOUND)", true, touch_test },
+ {"touch(NOT_FOUND)", true, NOT_FOUND_test },
+ {0, 0, 0}
+};
+
+collection_st collection[] ={
+ {"memtouch", 0, 0, memtouch_tests },
+ {0, 0, 0, 0}
+};
+
+static void *world_create(server_startup_st& servers, test_return_t& error)
+{
+ if (HAVE_MEMCACHED_BINARY == 0)
+ {
+ error= TEST_FATAL;
+ return NULL;
+ }
+
+ const char *argv[1]= { "memtouch" };
+ if (not server_startup(servers, "memcached", MEMCACHED_DEFAULT_PORT +10, 1, argv))
+ {
+ error= TEST_FAILURE;
+ }
+
+ return &servers;
+}
+
+
+void get_world(Framework *world)
+{
+ executable= "./clients/memtouch";
+ world->collections= collection;
+ world->_create= world_create;
+}
+
}
// Check and make sure the prefix_key is what we expect it to be
-static test_return_t __check_namespace(memcached_st *memc, const scanner_string_st &arg)
+static test_return_t __check_namespace(memcached_st *, const scanner_string_st &)
{
+#if 0
const char *_namespace = memcached_get_namespace(memc);
test_true(_namespace);
test_strcmp(_namespace, arg.c_str);
+#endif
return TEST_SUCCESS;
}
char *value= memcached_get(memc, test_literal_param("test"), &value_len, NULL, &rc);
test_false(value);
test_zero(value_len);
-#ifdef __APPLE__
- test_compare_got(MEMCACHED_CONNECTION_FAILURE, rc, memcached_last_error_message(memc));
-#else
test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_last_error_message(memc));
-#endif
memcached_free(memc);
}
/*
C++ interface test
*/
-#include <libmemcached/memcached.hpp>
+#include <libmemcached-1.0/memcached.hpp>
#include <libtest/test.hpp>
#include <cstdio>
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached Client and Server
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
+
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcachedutil-1.0/util.h>
+
+#include "tests/touch.h"
+
+static test_return_t pre_touch(memcached_st *memc)
+{
+ test_compare(MEMCACHED_SUCCESS, memcached_version(memc));
+ test_skip(true, libmemcached_util_version_check(memc, 1, 4, 8));
+
+ return TEST_SUCCESS;
+}
+
+test_return_t test_memcached_touch(memcached_st *memc)
+{
+
+ test_skip(TEST_SUCCESS, pre_touch(memc));
+
+ size_t len;
+ uint32_t flags;
+ memcached_return rc;
+
+ test_null(memcached_get(memc,
+ test_literal_param("touchkey"),
+ &len, &flags, &rc));
+ test_zero(len);
+ test_compare(MEMCACHED_NOTFOUND, rc);
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param("touchkey"),
+ test_literal_param("touchval"),
+ 2, 0));
+
+ {
+ char *value= memcached_get(memc,
+ test_literal_param("touchkey"),
+ &len, &flags, &rc);
+ test_compare(8U, test_literal_param_size("touchval"));
+ test_true(value);
+ test_strcmp(value, "touchval");
+ test_compare(MEMCACHED_SUCCESS, rc);
+ free(value);
+ }
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_touch(memc, test_literal_param("touchkey"), 60 *60));
+
+ test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+ rc= memcached_touch(memc, test_literal_param("touchkey"), 60 *60 *24 *60);
+ test_compare_hint(MEMCACHED_SUCCESS, rc, memcached_last_error_message(memc));
+
+ test_compare(MEMCACHED_NOTFOUND,
+ memcached_exist(memc, test_literal_param("touchkey")));
+
+ return TEST_SUCCESS;
+}
+
+test_return_t test_memcached_touch_by_key(memcached_st *memc)
+{
+
+ test_skip(TEST_SUCCESS, pre_touch(memc));
+
+ size_t len;
+ uint32_t flags;
+ memcached_return rc;
+
+ test_null(memcached_get_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ &len, &flags, &rc));
+ test_zero(len);
+ test_compare(MEMCACHED_NOTFOUND, rc);
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ test_literal_param("touchval"),
+ 2, 0));
+
+ {
+ char *value= memcached_get_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ &len, &flags, &rc);
+ test_compare(8U, test_literal_param_size("touchval"));
+ test_true(value);
+ test_strcmp(value, "touchval");
+ test_compare(MEMCACHED_SUCCESS, rc);
+ free(value);
+ }
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_touch_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ 60 *60));
+
+ test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_touch_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ 60 *60 *24 *60));
+ test_compare(MEMCACHED_NOTFOUND,
+ memcached_exist_by_key(memc, test_literal_param("grouping_key"),test_literal_param("touchkey")));
+
+ return TEST_SUCCESS;
+}
+
+
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t test_memcached_touch(memcached_st *);
+test_return_t test_memcached_touch_by_key(memcached_st *);
noinst_HEADERS+= win32/wrappers.h
if BUILD_WIN32_WRAPPERS
+libhashkit_libhashkit_la_LDFLAGS+=-no-undefined
libmemcached_libmemcached_la_LDFLAGS+=-no-undefined
libmemcached_libmemcachedprotocol_la_LDFLAGS+=-no-undefined
libmemcached_libmemcachedutil_la_LDFLAGS+=-no-undefined
-libhashkit_libhashkit_la_LDFLAGS+=-no-undefined
endif