OPT_HASH,
OPT_BINARY,
OPT_UDP,
+ OPT_BUFFER,
OPT_USERNAME,
OPT_PASSWD,
OPT_STAT_ARGS,
*/
#include <config.h>
-#include "execute.h"
+#include "clients/execute.h"
unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
{
memcached_return_t rc= memcached_set(memc, pairs[x].key, pairs[x].key_length,
pairs[x].value, pairs[x].value_length,
0, 0);
- if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
+ if (rc != MEMCACHED_SUCCESS and rc != MEMCACHED_BUFFERED)
{
- fprintf(stderr, "Failured on insert of %.*s\n",
+ fprintf(stderr, "%s:%d Failure on insert (%s) of %.*s\n",
+ __FILE__, __LINE__,
+ memcached_last_error_message(memc),
(unsigned int)pairs[x].key_length, pairs[x].key);
+
+ // We will try to reconnect and see if that fixes the issue
+ memcached_quit(memc);
}
else
{
for (retrieved= 0,x= 0; x < number_of; x++)
{
- char *value;
size_t value_length;
uint32_t flags;
- unsigned int fetch_key;
- fetch_key= (unsigned int)((unsigned int)random() % number_of);
+ unsigned int fetch_key= (unsigned int)((unsigned int)random() % number_of);
- value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
- &value_length, &flags, &rc);
+ char *value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
+ &value_length, &flags, &rc);
if (rc != MEMCACHED_SUCCESS)
- fprintf(stderr, "Failured on read of %.*s\n",
+ {
+ fprintf(stderr, "%s:%d Failure on read(%s) of %.*s\n",
+ __FILE__, __LINE__,
+ memcached_last_error_message(memc),
(unsigned int)pairs[fetch_key].key_length, pairs[fetch_key].key);
+ }
else
+ {
retrieved++;
+ }
- free(value);
+ ::free(value);
}
return retrieved;
rc= memcached_fetch_execute(memc, callbacks, (void *)&retrieved, 1);
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_END)
{
- fprintf(stderr, "Failed to execute mget: %s\n",
+ fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
+ __FILE__, __LINE__,
memcached_strerror(memc, rc));
memcached_quit(memc);
return 0;
}
else
{
- fprintf(stderr, "Failed to execute mget: %s\n",
+ fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
+ __FILE__, __LINE__,
memcached_strerror(memc, rc));
memcached_quit(memc);
return 0;
static void options_parse(int argc, char *argv[]);
static bool opt_binary= false;
+static bool opt_udp= false;
+static bool opt_buffer= false;
static int opt_verbose= 0;
static char *opt_servers= NULL;
static char *opt_hash= NULL;
/* Check for various possible errors */
- if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
- || (errno != 0 && val == 0))
+ if ((errno == ERANGE and (val == LONG_MAX or val == LONG_MIN))
+ or (errno != 0 && val == 0))
{
*error= true;
return EXIT_SUCCESS;
initialize_sockets();
memcached_st *memc= memcached_create(NULL);
+
+ if (opt_udp)
+ {
+ if (opt_verbose)
+ {
+ std::cout << "Enabling UDP" << std::endl;
+ }
+
+ if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp)))
+ {
+ memcached_free(memc);
+ std::cerr << "Could not enable UDP protocol." << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (opt_buffer)
+ {
+ if (opt_verbose)
+ {
+ std::cout << "Enabling MEMCACHED_BEHAVIOR_BUFFER_REQUESTS" << std::endl;
+ }
+
+ if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, opt_buffer)))
+ {
+ memcached_free(memc);
+ std::cerr << "Could not enable MEMCACHED_BEHAVIOR_BUFFER_REQUESTS." << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
process_hash_option(memc, opt_hash);
if (opt_servers == NULL)
memcached_server_push(memc, servers);
memcached_server_list_free(servers);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
- (uint64_t)opt_binary);
-
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
{
memcached_free(memc);
{
if (opt_verbose)
{
- fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno));
+ std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
optind++;
}
exit_code= EXIT_FAILURE;
char *file_buffer_ptr;
if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
{
- fprintf(stderr, "malloc: %s\n", strerror(errno));
+ std::cerr << "Error allocating file buffer(" << strerror(errno) << ")" << std::endl;
exit(EXIT_FAILURE);
}
ssize_t read_length;
- if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
+ if ((read_length= ::read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
{
- fprintf(stderr, "read: %s\n", strerror(errno));
+ std::cerr << "Error while reading file " << file_buffer_ptr << " (" << strerror(errno) << ")" << std::endl;
exit(EXIT_FAILURE);
}
if (read_length != sbuf.st_size)
{
- fprintf(stderr, "Failure reading from file\n");
- exit(1);
+ std::cerr << "Failure while reading file. Read length was not equal to stat() length" << std::endl;
+ exit(EXIT_FAILURE);
}
memcached_return_t rc;
if (opt_method == OPT_ADD)
+ {
rc= memcached_add(memc, ptr, strlen(ptr),
file_buffer_ptr, (size_t)sbuf.st_size,
opt_expires, opt_flags);
+ }
else if (opt_method == OPT_REPLACE)
+ {
rc= memcached_replace(memc, ptr, strlen(ptr),
file_buffer_ptr, (size_t)sbuf.st_size,
opt_expires, opt_flags);
+ }
else
+ {
rc= memcached_set(memc, ptr, strlen(ptr),
file_buffer_ptr, (size_t)sbuf.st_size,
opt_expires, opt_flags);
+ }
- if (rc != MEMCACHED_SUCCESS)
+ if (memcached_failed(rc))
{
- fprintf(stderr, "memcp: %s: memcache error %s",
- ptr, memcached_strerror(memc, rc));
- if (memcached_last_error_errno(memc))
- fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
- fprintf(stderr, "\n");
-
+ std::cerr << "Error occrrured during operation: " << memcached_last_error_message(memc) << std::endl;
exit_code= EXIT_FAILURE;
}
- free(file_buffer_ptr);
- close(fd);
+ ::free(file_buffer_ptr);
+ ::close(fd);
optind++;
}
memcached_free(memc);
if (opt_servers)
+ {
free(opt_servers);
+ }
+
if (opt_hash)
+ {
free(opt_hash);
+ }
return exit_code;
}
{(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
{(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
{(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+ {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP},
+ {(OPTIONSTRING)"buffer", no_argument, NULL, OPT_BUFFER},
{(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
{(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
{(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
{
case 0:
break;
+
case OPT_BINARY:
opt_binary= true;
break;
close_stdio();
break;
+ case OPT_UDP:
+ opt_udp= true;
+ break;
+
+ case OPT_BUFFER:
+ opt_buffer= true;
+ break;
+
case '?':
/* getopt_long already printed an error message. */
exit(1);
#include <sys/types.h>
#include <unistd.h>
+#include <iostream>
+
#include <libmemcached/memcached.h>
#include "client_options.h"
static unsigned int opt_concurrency= 0;
static int opt_displayflag= 0;
static char *opt_servers= NULL;
-static int opt_udp_io= 0;
+static bool opt_udp_io= false;
test_t opt_test= SET_TEST;
extern "C" {
memcached_st *memc= memcached_create(NULL);
+ memcached_server_push(memc, servers);
+
/* We need to set udp behavior before adding servers to the client */
if (opt_udp_io)
{
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,
- (uint64_t)opt_udp_io);
- for (uint32_t x= 0; x < memcached_server_list_count(servers); x++ )
+ if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp_io)))
{
- servers[x].type= MEMCACHED_CONNECTION_UDP;
+ std::cerr << "Failed to enable UDP." << std::endl;
+ memcached_free(memc);
+ exit(EXIT_FAILURE);
}
}
- memcached_server_push(memc, servers);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
(uint64_t)opt_binary);
if (opt_flush)
+ {
flush_all(memc);
+ }
if (opt_createial_load)
+ {
pairs= load_create_data(memc, opt_createial_load, &actual_loaded);
+ }
char **keys= static_cast<char **>(calloc(actual_loaded, sizeof(char*)));
size_t *key_lengths= static_cast<size_t *>(calloc(actual_loaded, sizeof(size_t)));
"does not currently support get ops.\n");
exit(1);
}
- opt_udp_io= 1;
+ opt_udp_io= true;
break;
case OPT_BINARY:
case OPT_BINARY: return("Switch to binary protocol.");
case OPT_ANALYZE: return("Analyze the provided servers.");
case OPT_UDP: return("Use UDP protocol when communicating with server.");
+ case OPT_BUFFER: return("Enable request buffering.");
case OPT_USERNAME: return "Username to use for SASL authentication";
case OPT_PASSWD: return "Password to use for SASL authentication";
case OPT_FILE: return "Path to file in which to save result";
AC_CHECK_HEADERS([stddef.h])
AC_CHECK_HEADERS([sys/time.h])
AC_CHECK_HEADERS([sasl/sasl.h])
+AC_CHECK_HEADERS([execinfo.h])
+AC_CHECK_HEADERS([cxxabi.h],
+ AC_DEFINE([HAVE_CXXABI_H], [1], [Have cxxabi.h]),
+ AC_DEFINE([HAVE_CXXABI_H], [0], [Have cxxabi.h]))
AC_CXX_HEADER_STDCXX_98
AC_FUNC_ALLOCA
AC_C_VOLATILE
AC_C_RESTRICT
+AX_CXX_GCC_ABI_DEMANGLE
+
dnl The sasl functions should only be visible if we build with sasl support
AS_IF([test "x$ac_cv_sasl" = "xyes"],
[
bool buffer_requests:1;
bool hash_with_namespace:1;
bool no_block:1; // Don't block
- bool no_reply:1;
+ bool reply:1;
bool randomize_replica_read:1;
bool support_cas:1;
bool tcp_nodelay:1;
{ \
if (not (__expr)) \
{ \
- fprintf(stderr, "\nAssertion \"%s\" failed for function \"%s\" likely for %s, at %s:%d\n", #__expr, __func__, (#__mesg), __FILE__, __LINE__);\
+ fprintf(stderr, "\n%s:%d Assertion \"%s\" failed for function \"%s\" likely for %s\n", __FILE__, __LINE__, #__expr, __func__, (#__mesg));\
custom_backtrace(); \
abort(); \
} \
#include <libmemcached/common.h>
-static memcached_return_t text_incr_decr(memcached_st *ptr,
- const char *verb,
- const char *group_key, size_t group_key_length,
+static memcached_return_t text_incr_decr(memcached_server_write_instance_st instance,
+ const bool is_incr,
const char *key, size_t key_length,
- uint64_t offset,
- uint64_t *value)
+ const uint64_t offset,
+ const bool reply,
+ uint64_t& numeric_value)
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- uint32_t server_key;
- memcached_server_write_instance_st instance;
- bool no_reply= ptr->flags.no_reply;
- if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+ int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
+ if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
{
- return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
}
- server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
- instance= memcached_server_instance_fetch(ptr, server_key);
+ libmemcached_io_vector_st vector[]=
+ {
+ { NULL, 0 },
+ { memcached_literal_param("incr ") },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length },
+ { buffer, send_length },
+ { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+ { memcached_literal_param("\r\n") }
+ };
- int send_length;
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "%s %.*s%.*s %" PRIu64 "%s\r\n", verb,
- memcached_print_array(ptr->_namespace),
- (int)key_length, key,
- offset, no_reply ? " noreply" : "");
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+ if (is_incr == false)
{
- return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+ vector[1].buffer= "decr ";
}
- memcached_return_t rc= memcached_do(instance, buffer, (size_t)send_length, true);
- if (no_reply or memcached_failed(rc))
- return rc;
-
- rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ memcached_return_t rc= memcached_vdo(instance, vector, 7, true);
- if (rc != MEMCACHED_SUCCESS)
+ if (reply == false)
{
- return memcached_set_error(*instance, rc, MEMCACHED_AT);
+ return MEMCACHED_SUCCESS;
}
- /*
- So why recheck responce? Because the protocol is brain dead :)
- The number returned might end up equaling one of the string
- values. Less chance of a mistake with strncmp() so we will
- use it. We still called memcached_response() though since it
- worked its magic for non-blocking IO.
- */
- if (not strncmp(buffer, memcached_literal_param("ERROR\r\n")))
+ if (memcached_failed(rc))
{
- *value= 0;
- rc= MEMCACHED_PROTOCOL_ERROR;
- }
- else if (not strncmp(buffer, memcached_literal_param("CLIENT_ERROR\r\n")))
- {
- *value= 0;
- rc= MEMCACHED_PROTOCOL_ERROR;
- }
- else if (not strncmp(buffer, memcached_literal_param("NOT_FOUND\r\n")))
- {
- *value= 0;
- rc= MEMCACHED_NOTFOUND;
- }
- else
- {
- *value= strtoull(buffer, (char **)NULL, 10);
- rc= MEMCACHED_SUCCESS;
+ numeric_value= UINT64_MAX;
+ return rc;
}
+ rc= memcached_response(instance, buffer, sizeof(buffer), NULL, numeric_value);
+
return memcached_set_error(*instance, rc, MEMCACHED_AT);
}
-static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
- const char *group_key, size_t group_key_length,
- const char *key, size_t key_length,
- uint64_t offset, uint64_t initial,
- uint32_t expiration,
+static memcached_return_t binary_incr_decr(memcached_server_write_instance_st instance,
+ protocol_binary_command cmd,
+ const char *key, const size_t key_length,
+ const uint64_t offset,
+ const uint64_t initial,
+ const uint32_t expiration,
+ const bool reply,
uint64_t *value)
{
- bool no_reply= ptr->flags.no_reply;
-
- 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 (no_reply)
+ if (reply == false)
{
if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
+ {
cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
+ }
if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
+ {
cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
+ }
}
protocol_binary_request_incr request= {}; // = {.bytes= {0}};
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
request.message.header.request.opcode= cmd;
- request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
+ request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
request.message.header.request.extlen= 20;
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
- request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace) +request.message.header.request.extlen));
+ request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
request.message.body.delta= memcached_htonll(offset);
request.message.body.initial= memcached_htonll(initial);
request.message.body.expiration= htonl((uint32_t) expiration);
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ request.bytes, sizeof(request.bytes) },
- { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { 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)))
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
{
memcached_io_reset(instance);
- return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
+ return MEMCACHED_WRITE_FAILURE;
}
- if (no_reply)
+ if (reply == false)
{
return MEMCACHED_SUCCESS;
}
value= &local_value;
}
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
return rc;
}
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+ {
+ 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);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_INCREMENT_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
- group_key, group_key_length, key, key_length,
- (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
+ key, key_length,
+ uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ reply,
value);
}
else
{
- rc= text_incr_decr(ptr, "incr", group_key, group_key_length, key, key_length, offset, value);
+ rc= text_incr_decr(instance, true, key, key_length, offset, reply, *value);
}
LIBMEMCACHED_MEMCACHED_INCREMENT_END();
}
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return rc;
+ 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);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_DECREMENT_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
- group_key, group_key_length, key, key_length,
- (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
+ key, key_length,
+ offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+ reply,
value);
}
else
{
- rc= text_incr_decr(ptr, "decr", group_key, group_key_length, key, key_length, offset, value);
+ rc= text_incr_decr(instance, false, key, key_length, offset, reply, *value);
}
LIBMEMCACHED_MEMCACHED_DECREMENT_END();
time_t expiration,
uint64_t *value)
{
- uint64_t local_value;
- if (value == NULL)
- {
- value= &local_value;
- }
-
return memcached_increment_with_initial_by_key(ptr, key, key_length,
key, key_length,
offset, initial, expiration, value);
}
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return rc;
+ 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);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
- group_key, group_key_length, key, key_length,
- offset, initial, (uint32_t)expiration,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
+ key, key_length,
+ offset, initial, uint32_t(expiration),
+ reply,
value);
}
else
{
- rc= MEMCACHED_PROTOCOL_ERROR;
+ rc= memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("memcached_increment_with_initial_by_key() is not supported via the ASCII protocol"));
}
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
time_t expiration,
uint64_t *value)
{
- uint64_t local_value;
- if (value == NULL)
- {
- value= &local_value;
- }
-
return memcached_decrement_with_initial_by_key(ptr, key, key_length,
key, key_length,
offset, initial, expiration, value);
}
memcached_return_t rc;
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return rc;
+ 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);
+
+ bool reply= memcached_is_replying(instance->root);
+
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
- group_key, group_key_length, key, key_length,
- offset, initial, (uint32_t)expiration,
+ rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
+ key, key_length,
+ offset, initial, uint32_t(expiration),
+ reply,
value);
}
else
{
- rc= MEMCACHED_PROTOCOL_ERROR;
+ rc= memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("memcached_decrement_with_initial_by_key() is not supported via the ASCII protocol"));
}
LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
return rc;
}
-
#include <cstring>
#include <cstdlib>
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
+#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
+#endif
+
+#ifdef HAVE_CXXABI_H
#include <cxxabi.h>
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+#endif
+#ifdef HAVE_GCC_ABI_DEMANGLE
+#define USE_DEMANGLE 1
+#else
+#define USE_DEMANGLE 0
+#endif
void custom_backtrace(void)
{
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
+#ifdef HAVE_EXECINFO_H
void *array[50];
size_t size= backtrace(array, 50);
char **strings= backtrace_symbols(array, size);
+ if (strings == NULL)
+ {
+ return;
+ }
+
fprintf(stderr, "Number of stack frames obtained: %lu\n", (unsigned long)size);
- for (size_t x= 1; x < size; x++)
+ char *named_function= (char *)::realloc(NULL, 1024);
+
+ if (named_function == NULL)
{
- size_t sz= 200;
- char *function= (char *)malloc(sz);
- char *begin= 0;
- char *end= 0;
+ ::free(strings);
+ return;
+ }
- for (char *j = strings[x]; *j; ++j)
+ for (size_t x= 1; x < size; x++)
+ {
+ if (USE_DEMANGLE)
{
- if (*j == '(') {
- begin = j;
+ size_t sz= 200;
+ char *named_function_ptr= (char *)::realloc(named_function, sz);
+ if (named_function_ptr == NULL)
+ {
+ continue;
}
- else if (*j == '+') {
- end = j;
+ named_function= named_function_ptr;
+
+ char *begin_name= 0;
+ char *begin_offset= 0;
+ char *end_offset= 0;
+
+ for (char *j= strings[x]; *j; ++j)
+ {
+ if (*j == '(')
+ {
+ begin_name= j;
+ }
+ else if (*j == '+')
+ {
+ begin_offset= j;
+ }
+ else if (*j == ')' and begin_offset)
+ {
+ end_offset= j;
+ break;
+ }
}
- }
- if (begin && end)
- {
- begin++;
- *end= '\0';
- int status;
- char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
- if (ret)
+ if (begin_name and begin_offset and end_offset and begin_name < begin_offset)
{
- function= ret;
+ *begin_name++= '\0';
+ *begin_offset++= '\0';
+ *end_offset= '\0';
+
+ int status;
+ char *ret= abi::__cxa_demangle(begin_name, named_function, &sz, &status);
+ if (ret) // realloc()'ed string
+ {
+ named_function= ret;
+ fprintf(stderr, " %s : %s()+%s\n", strings[x], begin_name, begin_offset);
+ }
+ else
+ {
+ fprintf(stderr, " %s : %s()+%s\n", strings[x], begin_name, begin_offset);
+ }
}
else
{
- strncpy(function, begin, sz);
- strncat(function, "()", sz);
- function[sz-1] = '\0';
+ fprintf(stderr, " %s\n", strings[x]);
}
- fprintf(stderr, "%s\n", function);
}
else
{
- fprintf(stderr, "%s\n", strings[x]);
+ fprintf(stderr, " unmangled: %s\n", strings[x]);
}
- free(function);
}
-
- free (strings);
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+ ::free(named_function);
+ ::free(strings);
+#endif // HAVE_EXECINFO_H
}
#pragma once
-LIBMEMCACHED_LOCAL
void custom_backtrace(void);
break;
case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
- if (ptr->flags.use_udp)
+ if (memcached_is_udp(ptr))
{
return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
memcached_literal_param("MEMCACHED_BEHAVIOR_BUFFER_REQUESTS cannot be set while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
ptr->flags.use_udp= bool(data);
if (bool(data))
{
- ptr->flags.no_reply= true;
+ ptr->flags.reply= false;
ptr->flags.buffer_requests= false;
}
+ else
+ {
+ ptr->flags.reply= true;
+ }
break;
case MEMCACHED_BEHAVIOR_TCP_NODELAY:
break;
case MEMCACHED_BEHAVIOR_NOREPLY:
- if (ptr->flags.use_udp and bool(data) == false)
+ if (memcached_is_udp(ptr) and bool(data) == false)
{
return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
memcached_literal_param("MEMCACHED_BEHAVIOR_NOREPLY cannot be disabled while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
}
- ptr->flags.no_reply= bool(data);
+ // We reverse the logic here to make it easier to understand throughout the
+ // code.
+ ptr->flags.reply= bool(data) ? false : true;
break;
case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
return ptr->flags.buffer_requests;
case MEMCACHED_BEHAVIOR_USE_UDP:
- return ptr->flags.use_udp;
+ return memcached_is_udp(ptr);
case MEMCACHED_BEHAVIOR_TCP_NODELAY:
return ptr->flags.tcp_nodelay;
socklen_t sock_length= sizeof(int);
if (ptr->send_size != -1) // If value is -1 then we are using the default
+ {
return (uint64_t) ptr->send_size;
+ }
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, 0);
return ptr->flags.hash_with_namespace;
case MEMCACHED_BEHAVIOR_NOREPLY:
- return ptr->flags.no_reply;
+ return ptr->flags.reply ? false : true;
case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
return ptr->flags.auto_eject_hosts;
#ifdef __cplusplus
#include <libmemcached/string.hpp>
#include <libmemcached/io.hpp>
+#include <libmemcached/udp.hpp>
#include <libmemcached/do.hpp>
#include <libmemcached/close_socket.hpp>
#include <libmemcached/connect.hpp>
#include <libmemcached/memcached/protocol_binary.h>
#include <libmemcached/byteorder.h>
#include <libmemcached/initialize_query.h>
+#ifdef __cplusplus
#include <libmemcached/response.h>
+#endif
#include <libmemcached/namespace.h>
#include <libmemcached/virtual_bucket.h>
static void set_socket_options(memcached_server_st *server)
{
- assert_msg(server->fd != -1, "invalid socket was passed to set_socket_options()");
+ assert_msg(server->fd != INVALID_SOCKET, "invalid socket was passed to set_socket_options()");
if (memcached_is_udp(server->root))
{
return memcached_delete_by_key(ptr, key, key_length, key, key_length, expiration);
}
-static inline memcached_return_t ascii_delete(memcached_st *ptr,
- memcached_server_write_instance_st instance,
+static inline memcached_return_t ascii_delete(memcached_server_write_instance_st instance,
uint32_t ,
const char *key,
- size_t key_length,
- bool& reply,
- bool& flush)
+ const size_t key_length,
+ const bool reply,
+ const bool flush)
{
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- int 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 (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+ libmemcached_io_vector_st vector[]=
{
- return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
- }
-
- if (ptr->flags.use_udp and flush == 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);
- }
- }
+ { NULL, 0 },
+ { memcached_literal_param("delete ") },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length },
+ { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+ { memcached_literal_param("\r\n") }
+ };
- return memcached_do(instance, buffer, (size_t)send_length, flush);
+ /* Send command header */
+ return memcached_vdo(instance, vector, 6, flush);
}
-static inline memcached_return_t binary_delete(memcached_st *ptr,
- memcached_server_write_instance_st instance,
+static inline memcached_return_t binary_delete(memcached_server_write_instance_st instance,
uint32_t server_key,
const char *key,
- size_t key_length,
- bool& reply,
- bool& flush)
+ const size_t key_length,
+ const bool reply,
+ const bool flush)
{
protocol_binary_request_delete request= {};
{
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.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(ptr->_namespace)));
-
- 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)
- {
- memcached_io_write(instance, NULL, 0, true);
- }
- }
+ request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace)));
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ request.bytes, sizeof(request.bytes) },
- { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
{ key, key_length }
};
memcached_return_t rc= MEMCACHED_SUCCESS;
- if ((rc= memcached_vdo(instance, vector, 3, flush)) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_vdo(instance, vector, 4, flush)) != MEMCACHED_SUCCESS)
{
memcached_io_reset(instance);
}
- if (ptr->number_of_replicas > 0)
+ if (instance->root->number_of_replicas > 0)
{
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
- for (uint32_t x= 0; x < ptr->number_of_replicas; ++x)
+ for (uint32_t x= 0; x < instance->root->number_of_replicas; ++x)
{
- memcached_server_write_instance_st replica;
++server_key;
- if (server_key == memcached_server_count(ptr))
+ if (server_key == memcached_server_count(instance->root))
+ {
server_key= 0;
+ }
- replica= memcached_server_instance_fetch(ptr, server_key);
+ memcached_server_write_instance_st replica= memcached_server_instance_fetch(instance->root, server_key);
- if (memcached_vdo(replica, vector, 3, flush) != MEMCACHED_SUCCESS)
+ if (memcached_vdo(replica, vector, 4, flush) != MEMCACHED_SUCCESS)
{
memcached_io_reset(replica);
}
LIBMEMCACHED_MEMCACHED_DELETE_START();
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
memcached_literal_param("Memcached server version does not allow expiration of deleted items"));
}
+
+ 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 buffering= memcached_is_buffering(instance->root);
+ bool reply= memcached_is_replying(instance->root);
+
// If a delete trigger exists, we need a response, so no buffering/noreply
if (ptr->delete_trigger)
{
- if (ptr->flags.buffer_requests)
+ if (buffering)
{
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)
+ if (reply == false)
{
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)
+ if (memcached_is_binary(ptr))
{
- rc= binary_delete(ptr, instance, server_key, key, key_length, reply, to_write);
+ rc= binary_delete(instance, server_key, key, key_length, reply, buffering ? false : true);
}
else
{
- rc= ascii_delete(ptr, instance, server_key, key, key_length, reply, to_write);
+ rc= ascii_delete(instance, server_key, key, key_length, reply, buffering ? false : true);
}
if (rc == MEMCACHED_SUCCESS)
{
- if (to_write == false)
+ if (buffering == true)
{
rc= MEMCACHED_BUFFERED;
}
- else if (reply)
+ else if (reply == false)
+ {
+ rc= MEMCACHED_SUCCESS;
+ }
+ else
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
if (rc == MEMCACHED_DELETED)
{
rc= MEMCACHED_SUCCESS;
+ if (ptr->delete_trigger)
+ {
+ ptr->delete_trigger(ptr, key, key_length);
+ }
}
}
-
- if (rc == MEMCACHED_SUCCESS and ptr->delete_trigger)
- {
- ptr->delete_trigger(ptr, key, key_length);
- }
}
LIBMEMCACHED_MEMCACHED_DELETE_END();
- return rc;
+ return memcached_set_error(*ptr, rc, MEMCACHED_AT );
}
#include <libmemcached/common.h>
-memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const void *command,
- size_t command_length, bool with_flush)
+memcached_return_t memcached_vdo(memcached_server_write_instance_st instance,
+ libmemcached_io_vector_st vector[],
+ const size_t count,
+ const bool with_flush)
{
- 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)))
+
+ assert_msg(vector, "Invalid vector passed");
+
+ if (memcached_failed(rc= memcached_connect(instance)))
{
- WATCHPOINT_ASSERT(rc == memcached_last_error(ptr->root));
WATCHPOINT_ERROR(rc);
+ assert_msg(instance->error_messages, "memcached_connect() returned an error but the memcached_server_write_instance_st showed none.");
return rc;
}
** before they start writing, if there is any data in buffer, clear it out,
** otherwise we might get a partial write.
**/
- if (memcached_is_udp(ptr->root) and with_flush and ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH)
- {
- memcached_io_write(ptr, NULL, 0, true);
- }
-
- ssize_t sent_length= memcached_io_write(ptr, command, command_length, with_flush);
-
- if (sent_length == -1 or size_t(sent_length) != command_length)
+ if (memcached_is_udp(instance->root))
{
- rc= MEMCACHED_WRITE_FAILURE;
- }
- else if ((ptr->root->flags.no_reply) == 0)
- {
- memcached_server_response_increment(ptr);
- }
-
- return rc;
-}
+ if (vector[0].buffer or vector[0].length)
+ {
+ return memcached_set_error(*instance->root, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT,
+ memcached_literal_param("UDP messages was attempted, but vector was not setup for it"));
+ }
-memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr,
- const struct libmemcached_io_vector_st *vector, size_t count,
- bool with_flush)
-{
- memcached_return_t rc;
+ struct msghdr msg;
+ memset(&msg, 0, sizeof(msg));
- WATCHPOINT_ASSERT(count);
- WATCHPOINT_ASSERT(vector);
+ increment_udp_message_id(instance);
+ vector[0].buffer= instance->write_buffer;
+ vector[0].length= UDP_DATAGRAM_HEADER_LENGTH;
- if (memcached_failed(rc= memcached_connect(ptr)))
- {
- WATCHPOINT_ERROR(rc);
- assert_msg(ptr->error_messages, "memcached_connect() returned an error but the memcached_server_write_instance_st showed none.");
- return rc;
- }
+ msg.msg_iov= (struct iovec*)vector;
+ msg.msg_iovlen= count;
- /*
- ** Since non buffering ops in UDP mode dont check to make sure they will fit
- ** before they start writing, if there is any data in buffer, clear it out,
- ** otherwise we might get a partial write.
- **/
- if (memcached_is_udp(ptr->root) and with_flush and ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH)
- {
- if (memcached_io_write(ptr, NULL, 0, true) == -1)
+ if (::sendmsg(instance->fd, &msg, 0) < 1)
{
- memcached_io_reset(ptr);
- return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
}
- }
- ssize_t sent_length= memcached_io_writev(ptr, vector, count, with_flush);
+ return MEMCACHED_SUCCESS;
+ }
+ ssize_t sent_length= memcached_io_writev(instance, vector, count, with_flush);
size_t command_length= 0;
for (uint32_t x= 0; x < count; ++x, vector++)
{
WATCHPOINT_ERROR(rc);
WATCHPOINT_ERRNO(errno);
}
- else if ((ptr->root->flags.no_reply) == 0)
+ else if (memcached_is_replying(instance->root))
{
- memcached_server_response_increment(ptr);
+ memcached_server_response_increment(instance);
}
return rc;
#pragma once
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_do(memcached_server_write_instance_st ptr,
- const void *commmand,
- size_t command_length,
- bool with_flush);
-
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr,
- const struct libmemcached_io_vector_st *vector, size_t count,
- bool with_flush);
+ libmemcached_io_vector_st vector[],
+ const size_t count,
+ const bool with_flush);
+/* 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.
+ *
+ */
+
/*
We use this to dump all keys.
for (uint32_t x= 0; x < 256; x++)
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- int send_length;
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "stats cachedump %u 0 0\r\n", x);
-
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+ int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
+ if (buffer_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or buffer_length < 0)
{
return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
}
- rc= memcached_do(instance, buffer, (size_t)send_length, true);
+ libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("stats cachedump ") },
+ { buffer, buffer_length },
+ { memcached_literal_param(" 0 0\r\n") }
+ };
+
+ rc= memcached_vdo(instance, vector, 3, true);
if (rc != MEMCACHED_SUCCESS)
{
* This isn't really a fatal error, so let's just skip it. I want to
* fix the return value from the memcached server to a CLIENT_ERROR,
* so let's add support for that as well right now.
- */
+ */
rc= MEMCACHED_END;
break;
}
memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
{
memcached_return_t rc;
- if ((rc= initialize_query(ptr)) != MEMCACHED_SUCCESS)
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
if (error->size == 0)
{
- fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
+ fprintf(stderr, "\t%s\n", memcached_strerror(NULL, error->rc) );
}
else
{
- fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
+ fprintf(stderr, "\t%s %s\n", memcached_strerror(NULL, error->rc), error->message);
}
_error_print(error->next);
void memcached_error_print(const memcached_st *self)
{
- if (not self)
+ if (self == NULL)
+ {
return;
+ }
_error_print(self->error_messages);
+
+ for (uint32_t x= 0; x < memcached_server_count(self); x++)
+ {
+ memcached_server_instance_st instance= memcached_server_instance_by_position(self, x);
+
+ _error_print(instance->error_messages);
+ }
}
static void _error_free(memcached_error_t *error)
static memcached_return_t ascii_exist(memcached_st *memc, memcached_server_write_instance_st instance, const char *key, size_t key_length)
{
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ memcached_literal_param("add ") },
{ memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
{ key, key_length },
};
/* Send command header */
- memcached_return_t rc= memcached_vdo(instance, vector, 8, true);
+ memcached_return_t rc= memcached_vdo(instance, vector, 9, true);
if (rc == MEMCACHED_SUCCESS)
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
if (rc == MEMCACHED_NOTSTORED)
+ {
rc= MEMCACHED_SUCCESS;
+ }
if (rc == MEMCACHED_STORED)
+ {
rc= MEMCACHED_NOTFOUND;
+ }
}
if (rc == MEMCACHED_WRITE_FAILURE)
+ {
memcached_io_reset(instance);
+ }
return rc;
}
+memcached_array_size(memc->_namespace)
+request.message.header.request.extlen));
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ request.bytes, send_length },
{ memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
{ key, key_length }
/* write the header */
memcached_return_t rc;
- if ((rc= memcached_vdo(instance, vector, 3, true)) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_vdo(instance, vector, 4, true)) != MEMCACHED_SUCCESS)
{
memcached_io_reset(instance);
return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
const char *key, size_t key_length)
{
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(memc)))
+ if (memcached_failed(rc= initialize_query(memc, true)))
{
return rc;
}
- if (memc->flags.use_udp)
+ if (memcached_is_udp(memc))
{
return MEMCACHED_NOT_SUPPORTED;
}
-
uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
memcached_server_write_instance_st instance;
instance= memcached_server_instance_fetch(memc, server_key);
{
memcached_result_st *result_buffer= &ptr->result;
memcached_return_t unused;
- if (not error)
+ if (error == NULL)
+ {
error= &unused;
+ }
-
- unlikely (ptr->flags.use_udp)
+ if (memcached_is_udp(ptr))
{
if (value_length)
+ {
*value_length= 0;
+ }
if (key_length)
+ {
*key_length= 0;
+ }
if (flags)
+ {
*flags= 0;
+ }
if (key)
+ {
*key= 0;
+ }
*error= MEMCACHED_NOT_SUPPORTED;
return NULL;
{
WATCHPOINT_ASSERT(result_buffer == NULL);
if (value_length)
+ {
*value_length= 0;
+ }
if (key_length)
+ {
*key_length= 0;
+ }
if (flags)
+ {
*flags= 0;
+ }
if (key)
+ {
*key= 0;
+ }
return NULL;
}
{
*error= MEMCACHED_KEY_TOO_BIG;
if (value_length)
+ {
*value_length= 0;
+ }
- if (key_length)
- *key_length= 0;
+ if (key_length)
+ {
+ *key_length= 0;
+ }
- if (flags)
- *flags= 0;
+ if (flags)
+ {
+ *flags= 0;
+ }
- if (key)
- *key= 0;
+ if (key)
+ {
+ *key= 0;
+ }
return NULL;
}
+
strncpy(key, result_buffer->item_key, result_buffer->key_length); // For the binary protocol we will cut off the key :(
if (key_length)
+ {
*key_length= result_buffer->key_length;
+ }
}
if (flags)
+ {
*flags= result_buffer->item_flags;
+ }
return memcached_string_take_value(&result_buffer->value);
}
return NULL;
}
- if (ptr->flags.use_udp)
+ if (memcached_is_udp(ptr))
{
*error= MEMCACHED_NOT_SUPPORTED;
return NULL;
}
- if (not result)
+ if (result == NULL)
{
// If we have already initialized (ie it is in use) our internal, we
// create one.
#include <libmemcached/common.h>
static memcached_return_t memcached_flush_binary(memcached_st *ptr,
- time_t expiration);
-static memcached_return_t memcached_flush_textual(memcached_st *ptr,
- time_t expiration);
-
-memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)
+ time_t expiration,
+ const bool reply)
{
- memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
- {
- return rc;
- }
+ protocol_binary_request_flush request= {};
- LIBMEMCACHED_MEMCACHED_FLUSH_START();
- if (ptr->flags.binary_protocol)
+ request.message.header.request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+ request.message.header.request.extlen= 4;
+ request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+ request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
+ request.message.body.expiration= htonl((uint32_t) expiration);
+
+ memcached_return_t rc= MEMCACHED_SUCCESS;
+
+ for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- rc= memcached_flush_binary(ptr, expiration);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
+
+ if (reply)
+ {
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+ }
+ else
+ {
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
+ }
+
+ libmemcached_io_vector_st vector[]=
+ {
+ { NULL, 0 },
+ { request.bytes, sizeof(request.bytes) }
+ };
+
+ memcached_return_t rrc;
+ if (memcached_failed(rrc= memcached_vdo(instance, vector, 2, true)))
+ {
+ if (instance->error_messages == NULL or instance->root->error_messages == NULL)
+ {
+ memcached_set_error(*instance, rrc, MEMCACHED_AT);
+ }
+ memcached_io_reset(instance);
+ rc= MEMCACHED_SOME_ERRORS;
+ }
}
- else
+
+ for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- rc= memcached_flush_textual(ptr, expiration);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
+
+ if (memcached_server_response_count(instance) > 0)
+ {
+ (void)memcached_response(instance, NULL, 0, NULL);
+ }
}
- LIBMEMCACHED_MEMCACHED_FLUSH_END();
return rc;
}
static memcached_return_t memcached_flush_textual(memcached_st *ptr,
- time_t expiration)
+ time_t expiration,
+ const bool reply)
{
- bool reply= ptr->flags.no_reply ? false : true;
-
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- int send_length;
+ char buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+ int send_length= 0;
if (expiration)
{
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "flush_all %llu%s\r\n",
- (unsigned long long)expiration, reply ? "" : " noreply");
- }
- else
- {
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "flush_all%s\r\n", reply ? "" : " noreply");
+ send_length= snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long)expiration);
}
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or send_length < 0)
+ if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
{
return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
}
-
memcached_return_t rc= MEMCACHED_SUCCESS;
- for (unsigned int x= 0; x < memcached_server_count(ptr); x++)
+ for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
- memcached_return_t rrc= memcached_do(instance, buffer, (size_t)send_length, true);
- if (rrc == MEMCACHED_SUCCESS and reply == true)
+ libmemcached_io_vector_st vector[]=
+ {
+ { NULL, 0 },
+ { memcached_literal_param("flush_all ") },
+ { buffer, send_length },
+ { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+ { memcached_literal_param("\r\n") }
+ };
+
+ memcached_return_t rrc= memcached_vdo(instance, vector, 5, true);
+ if (memcached_success(rrc) and reply == true)
{
char response_buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
rrc= memcached_response(instance, response_buffer, sizeof(response_buffer), NULL);
if (memcached_failed(rrc))
{
// If an error has already been reported, then don't add to it
- if (instance->error_messages == NULL)
+ if (instance->error_messages == NULL or instance->root->error_messages == NULL)
{
memcached_set_error(*instance, rrc, MEMCACHED_AT);
}
return rc;
}
-static memcached_return_t memcached_flush_binary(memcached_st *ptr,
- time_t expiration)
+memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)
{
- protocol_binary_request_flush request= {};
-
- request.message.header.request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
- request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
- request.message.header.request.extlen= 4;
- request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
- request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
- request.message.body.expiration= htonl((uint32_t) expiration);
-
- memcached_return_t rc= MEMCACHED_SUCCESS;
-
- for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
- memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
+ return rc;
+ }
- if (ptr->flags.no_reply)
- {
- request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
- }
- else
- {
- request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
- }
+ bool reply= memcached_is_replying(ptr);
- memcached_return_t rrc;
- if ((rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true)))
- {
- memcached_set_error(*instance, rrc, MEMCACHED_AT);
- memcached_io_reset(instance);
- rc= MEMCACHED_SOME_ERRORS;
- }
+ LIBMEMCACHED_MEMCACHED_FLUSH_START();
+ if (memcached_is_binary(ptr))
+ {
+ rc= memcached_flush_binary(ptr, expiration, reply);
}
-
- for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+ else
{
- memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
-
- if (memcached_server_response_count(instance) > 0)
- {
- (void)memcached_response(instance, NULL, 0, NULL);
- }
+ rc= memcached_flush_textual(ptr, expiration, reply);
}
+ LIBMEMCACHED_MEMCACHED_FLUSH_END();
return rc;
}
if (instance->write_buffer_offset != 0)
{
- if (instance->fd == -1 &&
+ if (instance->fd == INVALID_SOCKET and
(ret= memcached_connect(instance)) != MEMCACHED_SUCCESS)
{
WATCHPOINT_ERROR(ret);
return ret;
}
- if (memcached_io_write(instance, NULL, 0, true) == -1)
+ if (memcached_io_write(instance) == false)
{
ret= MEMCACHED_SOME_ERRORS;
}
error= &unused;
}
- if (ptr->flags.use_udp)
+ uint64_t query_id= 0;
+ if (ptr)
{
- if (value_length)
- {
- *value_length= 0;
- }
-
- *error= memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
- return NULL;
+ query_id= ptr->query_id;
}
- uint64_t query_id= ptr->query_id;
- (void)query_id;
-
/* Request the key */
*error= memcached_mget_by_key_real(ptr, group_key, group_key_length,
(const char * const *)&key, &key_length,
1, false);
- assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
-
+ if (ptr)
+ {
+ assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
+ }
if (memcached_failed(*error))
{
- if (memcached_has_current_error(*ptr)) // Find the most accurate error
+ if (ptr)
{
- *error= memcached_last_error(ptr);
+ if (memcached_has_current_error(*ptr)) // Find the most accurate error
+ {
+ *error= memcached_last_error(ptr);
+ }
}
if (value_length)
+ {
*value_length= 0;
+ }
return NULL;
}
unsigned int master_server_key= (unsigned int)-1; /* 0 is a valid server id! */
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (ptr->flags.use_udp)
+ if (memcached_is_udp(ptr))
{
return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
}
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
if (ptr->flags.no_block)
- (void)memcached_io_write(instance, NULL, 0, true);
+ {
+ memcached_io_write(instance);
+ }
while(memcached_server_response_count(instance))
+ {
(void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
+ }
}
}
instance= memcached_server_instance_fetch(ptr, server_key);
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
{ get_command, get_command_length },
{ memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
LIBMEMCACHED_MEMCACHED_MGET_END();
if (memcached_failed(rc))
+ {
return rc;
+ }
return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
}
void *context,
unsigned int number_of_callbacks)
{
- if ((ptr->flags.binary_protocol) == 0)
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr, false)))
+ {
+ return rc;
+ }
+
+ if (memcached_is_udp(ptr))
+ {
+ return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ }
+
+ if (memcached_is_binary(ptr) == false)
{
return MEMCACHED_NOT_SUPPORTED;
}
- memcached_return_t rc;
memcached_callback_st *original_callbacks= ptr->callbacks;
memcached_callback_st cb= {
callback,
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + memcached_array_size(ptr->_namespace)));
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
{ request.bytes, sizeof(request.bytes) },
{ memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
for (uint32_t x= 0; x < memcached_server_count(ptr); ++x)
{
- 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 (memcached_server_response_count(instance))
{
- if (memcached_io_write(instance, NULL, 0, true) == -1)
+ if (memcached_io_write(instance) == false)
{
memcached_server_response_reset(instance);
memcached_io_reset(instance);
* that we might have processed some of the responses etc. For now,
* just make sure we work _correctly_
*/
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
{ request.bytes, sizeof(request.bytes) },
{ memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
libmemcached/server.hpp \
libmemcached/server_instance.h \
libmemcached/string.hpp \
+ libmemcached/udp.hpp \
libmemcached/virtual_bucket.h \
libmemcached/watchpoint.h
libmemcached/touch.cc \
libmemcached/verbosity.cc \
libmemcached/version.cc \
+ libmemcached/udp.cc \
libmemcached/virtual_bucket.c
libmemcached/options.cc: libmemcached/csl/parser.h
#include <libmemcached/common.h>
-memcached_return_t initialize_query(memcached_st *self)
+memcached_return_t initialize_query(memcached_st *self, bool increment_query_id)
{
if (self == NULL)
{
return MEMCACHED_INVALID_ARGUMENTS;
}
- self->query_id++;
+ if (increment_query_id)
+ {
+ self->query_id++;
+ }
if (self->state.is_time_for_rebuild)
{
#pragma once
-#ifdef __cplusplus
-extern "C" {
-#endif
+memcached_return_t initialize_query(memcached_st *self, bool increment_query_id);
-LIBMEMCACHED_LOCAL
- memcached_return_t initialize_query(memcached_st *self);
-
-LIBMEMCACHED_LOCAL
memcached_return_t initialize_const_query(const memcached_st *self);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
MEM_WRITE
};
-/*
- * The udp request id consists of two seperate sections
- * 1) The thread id
- * 2) The message number
- * The thread id should only be set when the memcached_st struct is created
- * and should not be changed.
- *
- * The message num is incremented for each new message we send, this function
- * extracts the message number from message_id, increments it and then
- * writes the new value back into the header
- */
-static void increment_udp_message_id(memcached_server_write_instance_st ptr)
-{
- struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
- uint16_t cur_req= get_udp_datagram_request_id(header);
- int msg_num= get_msg_num_from_request_id(cur_req);
- int thread_id= get_thread_id_from_request_id(cur_req);
-
- if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
- msg_num= 0;
-
- header->request_id= htons((uint16_t) (thread_id | msg_num));
-}
-
/**
* Try to fill the input buffer for a server with as much
* data as possible.
}
static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
- memc_read_or_write read_or_write)
+ const memc_read_or_write read_or_write)
{
struct pollfd fds;
fds.fd= ptr->fd;
return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
}
-static ssize_t io_flush(memcached_server_write_instance_st ptr,
- const bool with_flush,
- memcached_return_t *error)
+static bool io_flush(memcached_server_write_instance_st ptr,
+ const bool with_flush,
+ memcached_return_t& error)
{
/*
** We might want to purge the input buffer if we haven't consumed
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
{
- return -1;
+ return false;
}
}
- size_t return_length;
char *local_write_ptr= ptr->write_buffer;
size_t write_length= ptr->write_buffer_offset;
- *error= MEMCACHED_SUCCESS;
+ error= MEMCACHED_SUCCESS;
WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
// UDP Sanity check, make sure that we are not sending somthing too big
if (memcached_is_udp(ptr->root) and write_length > MAX_UDP_DATAGRAM_LENGTH)
{
- *error= MEMCACHED_WRITE_FAILURE;
- return -1;
+ error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ return false;
}
if (ptr->write_buffer_offset == 0 or (memcached_is_udp(ptr->root) and ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH))
{
- return 0;
+ return true;
}
/* Looking for memory overflows */
WATCHPOINT_ASSERT((ptr->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
#endif
- return_length= 0;
while (write_length)
{
WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
if (with_flush)
{
- sent_length= send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT);
+ sent_length= ::send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT);
}
else
{
- sent_length= send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT|MSG_MORE);
+ sent_length= ::send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT|MSG_MORE);
}
if (sent_length == SOCKET_ERROR)
}
else if (rc == MEMCACHED_TIMEOUT)
{
- *error= memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
- return -1;
+ error= memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
+ return false;
}
memcached_quit_server(ptr, true);
- *error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
- return -1;
+ error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
+ return false;
}
case ENOTCONN:
case EPIPE:
default:
memcached_quit_server(ptr, true);
- *error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
- WATCHPOINT_ASSERT(ptr->fd == -1);
- return -1;
+ error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
+ WATCHPOINT_ASSERT(ptr->fd == INVALID_SOCKET);
+ return false;
}
}
if (memcached_is_udp(ptr->root) and size_t(sent_length) != write_length)
{
memcached_quit_server(ptr, true);
- *error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
- return -1;
+ error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ return false;
}
ptr->io_bytes_sent+= uint32_t(sent_length);
local_write_ptr+= sent_length;
write_length-= uint32_t(sent_length);
- return_length+= uint32_t(sent_length);
}
WATCHPOINT_ASSERT(write_length == 0);
- // Need to study this assert() WATCHPOINT_ASSERT(return_length ==
- // ptr->write_buffer_offset);
-
- // if we are a udp server, the begining of the buffer is reserverd for
- // the upd frame header
if (memcached_is_udp(ptr->root))
{
ptr->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
ptr->write_buffer_offset= 0;
}
- return (ssize_t) return_length;
+ return true;
}
memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr)
}
memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
- void *buffer, size_t length, ssize_t *nread)
+ void *buffer, size_t length, ssize_t& nread)
{
assert_msg(ptr, "Programmer error, memcached_io_read() recieved an invalid memcached_server_write_instance_st"); // Programmer error
char *buffer_ptr= static_cast<char *>(buffer);
if (ptr->fd == INVALID_SOCKET)
{
+#if 0
assert_msg(int(ptr->state) <= int(MEMCACHED_SERVER_STATE_ADDRINFO), "Programmer error, invalid socket state");
+#endif
return MEMCACHED_CONNECTION_FAILURE;
}
ssize_t data_read;
do
{
- data_read= recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT);
+ data_read= ::recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT);
if (data_read == SOCKET_ERROR)
{
switch (get_socket_errno())
default:
{
memcached_quit_server(ptr, true);
- *nread= -1;
+ nread= -1;
return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
}
}
*/
WATCHPOINT_STRING("We had a zero length recv()");
memcached_quit_server(ptr, true);
- *nread= -1;
- return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+ nread= -1;
+ return memcached_set_error(*ptr, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("::rec() returned zero, server has disconnected"));
}
} while (data_read <= 0);
}
}
- *nread = (ssize_t)(buffer_ptr - (char*)buffer);
+ nread= ssize_t(buffer_ptr - (char*)buffer);
return MEMCACHED_SUCCESS;
}
WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
memcached_return_t rc;
- ssize_t sent_length= io_flush(ptr, with_flush, &rc);
- if (sent_length == -1)
+ if (io_flush(ptr, with_flush, rc) == false)
{
return -1;
}
-
- /* If io_flush calls memcached_purge, sent_length may be 0 */
- unlikely (sent_length != 0)
- {
- WATCHPOINT_ASSERT(sent_length == (ssize_t)buffer_end);
- }
}
}
{
memcached_return_t rc;
WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
- if (io_flush(ptr, with_flush, &rc) == -1)
+ if (io_flush(ptr, with_flush, rc) == false)
{
return -1;
}
return (ssize_t) original_length;
}
+bool memcached_io_write(memcached_server_write_instance_st ptr)
+{
+ return (_io_write(ptr, NULL, 0, true) >= 0);
+}
+
ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
- const void *buffer, size_t length, bool with_flush)
+ const void *buffer, const size_t length, const bool with_flush)
{
return _io_write(ptr, buffer, length, with_flush);
}
ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
- const struct libmemcached_io_vector_st *vector,
- size_t number_of, bool with_flush)
+ libmemcached_io_vector_st vector[],
+ const size_t number_of, const bool with_flush)
{
ssize_t total= 0;
{
ssize_t returnable;
- if ((returnable= _io_write(ptr, vector->buffer, vector->length, false)) == -1)
+ if (vector->length)
{
- return -1;
+ if ((returnable= _io_write(ptr, vector->buffer, vector->length, false)) == -1)
+ {
+ return -1;
+ }
+ total+= returnable;
}
- total+= returnable;
}
if (with_flush)
{
- if (memcached_io_write(ptr, NULL, 0, true) == -1)
+ if (memcached_io_write(ptr) == false)
{
return -1;
}
for (uint32_t x= 0; x < memcached_server_count(memc) && host_index < MAX_SERVERS_TO_POLL; ++x)
{
- memcached_server_write_instance_st instance=
- memcached_server_instance_fetch(memc, x);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, x);
if (instance->read_buffer_length > 0) /* I have data in the buffer */
+ {
return instance;
+ }
if (memcached_server_response_count(instance) > 0)
{
*/
memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
void *dta,
- size_t size)
+ const size_t size)
{
size_t offset= 0;
char *data= static_cast<char *>(dta);
ssize_t nread;
memcached_return_t rc;
- while (memcached_continue(rc= memcached_io_read(ptr, data + offset, size - offset, &nread))) { };
+ while (memcached_continue(rc= memcached_io_read(ptr, data + offset, size - offset, nread))) { };
if (memcached_failed(rc))
{
return rc;
}
- offset+= (size_t) nread;
+ offset+= size_t(nread);
}
return MEMCACHED_SUCCESS;
total_nr= 0;
bool line_complete= false;
- while (not line_complete)
+ while (line_complete == false)
{
if (ptr->read_buffer_length == 0)
{
* the logic.
*/
ssize_t nread;
- memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, &nread);
+ memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, nread);
if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS)
{
memcached_quit_server(ptr, true);
}
if (*buffer_ptr == '\n')
+ {
line_complete= true;
+ }
++buffer_ptr;
++total_nr;
{
*buffer_ptr = *ptr->read_ptr;
if (*buffer_ptr == '\n')
+ {
line_complete = true;
+ }
--ptr->read_buffer_length;
++ptr->read_ptr;
++total_nr;
}
if (total_nr == size)
+ {
return MEMCACHED_PROTOCOL_ERROR;
+ }
}
return MEMCACHED_SUCCESS;
}
-
-memcached_return_t memcached_io_init_udp_header(memcached_server_write_instance_st ptr, uint16_t thread_id)
-{
- if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
- return MEMCACHED_FAILURE;
-
- struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
- header->request_id= htons((uint16_t) (generate_udp_request_thread_id(thread_id)));
- header->num_datagrams= htons(1);
- header->sequence_number= htons(0);
-
- return MEMCACHED_SUCCESS;
-}
#pragma once
-#define MAX_UDP_DATAGRAM_LENGTH 1400
-#define UDP_DATAGRAM_HEADER_LENGTH 8
-#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
-#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
-#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
-#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
-#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
-#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
-
-struct udp_datagram_header_st
-{
- uint16_t request_id;
- uint16_t sequence_number;
- uint16_t num_datagrams;
- uint16_t reserved;
-};
-
struct libmemcached_io_vector_st
{
const void *buffer;
size_t length;
};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_LOCAL
-ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
- const void *buffer, size_t length, bool with_flush);
-
-LIBMEMCACHED_LOCAL
-ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
- const struct libmemcached_io_vector_st *vector,
- size_t number_of, bool with_flush);
-
-#ifdef __cplusplus
-}
-#endif
#pragma once
-LIBMEMCACHED_LOCAL
+bool memcached_io_write(memcached_server_write_instance_st ptr);
+
+ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
+ const void *buffer, size_t length, bool with_flush);
+
+ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
+ libmemcached_io_vector_st vector[],
+ const size_t number_of, const bool with_flush);
+
memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr);
-LIBMEMCACHED_LOCAL
void memcached_io_reset(memcached_server_write_instance_st ptr);
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
- void *buffer, size_t length, ssize_t *nread);
+ void *buffer, size_t length, ssize_t& nread);
/* Read a line (terminated by '\n') into the buffer */
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
char *buffer_ptr,
size_t size,
size_t& total);
-LIBMEMCACHED_LOCAL
void memcached_io_close(memcached_server_write_instance_st ptr);
/* Read n bytes of data from the server and store them in dta */
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
void *dta,
- size_t size);
-
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_io_init_udp_header(memcached_server_write_instance_st ptr,
- uint16_t thread_id);
+ const size_t size);
-LIBMEMCACHED_LOCAL
memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st *memc);
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_io_slurp(memcached_server_write_instance_st ptr);
/* These are private */
#define memcached_is_allocated(__object) ((__object)->options.is_allocated)
#define memcached_is_udp(__object) ((__object)->flags.use_udp)
+#define memcached_is_verify_key(__object) ((__object)->flags.verify_key)
+#define memcached_is_binary(__object) ((__object)->flags.binary_protocol)
#define memcached_is_initialized(__object) ((__object)->options.is_initialized)
#define memcached_is_purging(__object) ((__object)->state.is_purging)
#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input)
+
+#define memcached_is_buffering(__object) ((__object)->flags.buffer_requests)
+#define memcached_is_replying(__object) ((__object)->flags.reply)
+
+#define memcached_has_error(__object) ((__object)->error_messages)
+
#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value))
#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value))
return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
}
- if (not memc.flags.verify_key)
+ // If we don't need to verify the key, or we are using the binary protoocol,
+ // we just check the size of the key
+ if (memc.flags.verify_key == false or memc.flags.binary_protocol == true)
{
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);
+ // We should set binary key, but the memcached server is broken for
+ // longer keys at the moment.
+ memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false /* memc.flags.binary_protocol */);
if (memcached_failed(rc))
{
return rc;
#include <libmemcached/options.hpp>
#include <libmemcached/virtual_bucket.h>
-#if 0
-static const memcached_st global_copy= {
- .state= {
- .is_purging= false, // .is_purging
- .is_processing_input= false, // is_processing_input
- .is_time_for_rebuild= false,
- },
- .flags= {
- .auto_eject_hosts= false,
- .binary_protocol= false,
- .buffer_requests= false,
- .hash_with_namespace= false,
- .no_block= false,
- .no_reply= false,
- .randomize_replica_read= false,
- .support_cas= false,
- .tcp_nodelay= false,
- .use_sort_hosts= false,
- .use_udp= false,
- .verify_key= false,
- .tcp_keepalive= false,
- },
-};
-#endif
-
static inline bool _memcached_init(memcached_st *self)
{
self->state.is_purging= false;
self->flags.buffer_requests= false;
self->flags.hash_with_namespace= false;
self->flags.no_block= false;
- self->flags.no_reply= false;
+ self->flags.reply= true;
self->flags.randomize_replica_read= false;
self->flags.support_cas= false;
self->flags.tcp_nodelay= false;
-#include "common.h"
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * LibMemcached
+ *
+ * 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>
+
memcached_return_t memcached_purge(memcached_server_write_instance_st ptr)
{
return MEMCACHED_SUCCESS;
}
- /* memcached_io_write and memcached_response may call memcached_purge
- so we need to be able stop any recursion.. */
+ /*
+ memcached_io_write and memcached_response may call memcached_purge
+ so we need to be able stop any recursion..
+ */
memcached_set_purging(root, true);
- WATCHPOINT_ASSERT(ptr->fd != -1);
- /* Force a flush of the buffer to ensure that we don't have the n-1 pending
- requests buffered up.. */
- if (memcached_io_write(ptr, NULL, 0, true) == -1)
+ WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
+ /*
+ Force a flush of the buffer to ensure that we don't have the n-1 pending
+ requests buffered up..
+ */
+ if (memcached_io_write(ptr) == false)
{
memcached_set_purging(root, true);
return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
}
- WATCHPOINT_ASSERT(ptr->fd != -1);
+ WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
uint32_t no_msg= memcached_server_response_count(ptr) - 1;
if (no_msg > 0)
{
memcached_result_st result;
memcached_result_st *result_ptr;
- char buffer[SMALL_STRING_LEN];
/*
* We need to increase the timeout, because we might be waiting for
for (uint32_t x= 0; x < no_msg; x++)
{
memcached_result_reset(result_ptr);
- memcached_return_t rc= memcached_read_one_response(ptr, buffer,
- sizeof (buffer),
- result_ptr);
+ memcached_return_t rc= memcached_read_one_response(ptr, result_ptr);
/*
* Purge doesn't care for what kind of command results that is received.
* The only kind of errors I care about if is I'm out of sync with the
* protocol or have problems reading data from the network..
*/
- if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE)
+ if (rc== MEMCACHED_PROTOCOL_ERROR or rc == MEMCACHED_UNKNOWN_READ_FAILURE or rc == MEMCACHED_READ_FAILURE)
{
WATCHPOINT_ERROR(rc);
- ret= rc;
memcached_io_reset(ptr);
- memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ ret= rc;
+#if 0
+ ret= memcached_set_error(*ptr, rc, MEMCACHED_AT);
+#endif
}
if (ptr->root->callbacks != NULL)
{
memcached_callback_st cb = *ptr->root->callbacks;
- if (rc == MEMCACHED_SUCCESS)
+ if (memcached_success(rc))
{
for (uint32_t y= 0; y < cb.number_of_callback; y++)
{
rc = (*cb.callback[y])(ptr->root, result_ptr, cb.context);
if (rc != MEMCACHED_SUCCESS)
+ {
break;
+ }
}
}
}
request.message.header.request.magic = PROTOCOL_BINARY_REQ;
request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
- rc= memcached_do(ptr, request.bytes, sizeof(request.bytes), true);
+
+ libmemcached_io_vector_st vector[]=
+ {
+ { request.bytes, sizeof(request.bytes) }
+ };
+
+ rc= memcached_vdo(ptr, vector, 1, true);
}
else
{
- rc= memcached_do(ptr, memcached_literal_param("quit\r\n"), true);
+ libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("quit\r\n") }
+ };
+
+ rc= memcached_vdo(ptr, vector, 1, true);
}
WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_FETCH_NOTFINISHED);
void memcached_quit(memcached_st *ptr)
{
- if (memcached_failed(initialize_query(ptr)))
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return;
}
#include <libmemcached/common.h>
#include <libmemcached/string.hpp>
-static memcached_return_t textual_read_one_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
- memcached_result_st *result);
-static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
- memcached_result_st *result);
-
-memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
- memcached_result_st *result)
-{
- memcached_server_response_decrement(ptr);
-
- if (result == NULL)
- {
- memcached_st *root= (memcached_st *)ptr->root;
- result = &root->result;
- }
-
- memcached_return_t rc;
- if (ptr->root->flags.binary_protocol)
- {
- rc= binary_read_one_response(ptr, buffer, buffer_length, result);
- }
- else
- {
- rc= textual_read_one_response(ptr, buffer, buffer_length, result);
- }
-
- unlikely(rc == MEMCACHED_UNKNOWN_READ_FAILURE or
- rc == MEMCACHED_PROTOCOL_ERROR or
- rc == MEMCACHED_CLIENT_ERROR or
- rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
- {
- memcached_io_reset(ptr);
- }
-
- return rc;
-}
-
-memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
- memcached_result_st *result)
-{
- /* We may have old commands in the buffer not set, first purge */
- if ((ptr->root->flags.no_block) && (memcached_is_processing_input(ptr->root) == false))
- {
- (void)memcached_io_write(ptr, NULL, 0, true);
- }
-
- /*
- * The previous implementation purged all pending requests and just
- * returned the last one. Purge all pending messages to ensure backwards
- * compatibility.
- */
- if (ptr->root->flags.binary_protocol == false)
- {
- while (memcached_server_response_count(ptr) > 1)
- {
- memcached_return_t rc= memcached_read_one_response(ptr, buffer, buffer_length, result);
-
- unlikely (rc != MEMCACHED_END &&
- rc != MEMCACHED_STORED &&
- rc != MEMCACHED_SUCCESS &&
- rc != MEMCACHED_STAT &&
- rc != MEMCACHED_DELETED &&
- rc != MEMCACHED_NOTFOUND &&
- rc != MEMCACHED_NOTSTORED &&
- rc != MEMCACHED_DATA_EXISTS)
- return rc;
- }
- }
-
- return memcached_read_one_response(ptr, buffer, buffer_length, result);
-}
-
static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
char *buffer,
memcached_result_st *result)
{
- char *string_ptr;
- char *end_ptr;
char *next_ptr;
- size_t value_length;
- size_t to_read;
ssize_t read_length= 0;
-
- if (ptr->root->flags.use_udp)
- {
- return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
- }
+ size_t value_length;
WATCHPOINT_ASSERT(ptr->root);
- end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
+ char *end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
memcached_result_reset(result);
- string_ptr= buffer;
+ char *string_ptr= buffer;
string_ptr+= 6; /* "VALUE " */
}
if (end_ptr == string_ptr)
+ {
goto read_error;
+ }
/* Flags fetch move past space */
string_ptr++;
if (end_ptr == string_ptr)
+ {
goto read_error;
+ }
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
if (end_ptr == string_ptr)
+ {
goto read_error;
+ }
/* Length fetch move past space*/
string_ptr++;
if (end_ptr == string_ptr)
+ {
goto read_error;
+ }
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
if (end_ptr == string_ptr)
+ {
goto read_error;
+ }
/* Skip spaces */
if (*string_ptr == '\r')
}
if (end_ptr < string_ptr)
+ {
goto read_error;
+ }
/* We add two bytes so that we can walk the \r\n */
if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
We are null terminating through, which will most likely make
some people lazy about using the return length.
*/
- to_read= (value_length) + 2;
- memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
+ size_t to_read= (value_length) + 2;
+ memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, read_length);
if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
{
memcached_quit_server(ptr, true);
}
static memcached_return_t textual_read_one_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
- memcached_result_st *result)
+ char *buffer, const size_t buffer_length,
+ memcached_result_st *result,
+ uint64_t& numeric_value)
{
+ numeric_value= UINT64_MAX;
size_t total_read;
memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length, total_read);
{
return rc;
}
+ assert(total_read);
switch(buffer[0])
{
- case 'V': /* VALUE || VERSION */
- if (buffer[1] == 'A') /* VALUE */
- {
- /* We add back in one because we will need to search for END */
- memcached_server_response_increment(ptr);
- return textual_value_fetch(ptr, buffer, result);
- }
- else if (buffer[1] == 'E') /* VERSION */
+ case 'V':
{
- return MEMCACHED_SUCCESS;
+ // VALUE
+ if (buffer[1] == 'A' and buffer[2] == 'L' and buffer[3] == 'U' and buffer[4] == 'E') /* VALUE */
+ {
+ /* We add back in one because we will need to search for END */
+ memcached_server_response_increment(ptr);
+ return textual_value_fetch(ptr, buffer, result);
+ }
+ // VERSION
+ else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'S' and buffer[4] == 'I' and buffer[5] == 'O' and buffer[6] == 'N') /* VERSION */
+ {
+ return MEMCACHED_SUCCESS;
+ }
}
- else
+ break;
+
+ case 'O':
{
- WATCHPOINT_STRING(buffer);
- return MEMCACHED_UNKNOWN_READ_FAILURE;
+ // OK
+ if (buffer[1] == 'K')
+ {
+ return MEMCACHED_SUCCESS;
+ }
}
- case 'O': /* OK */
- return MEMCACHED_SUCCESS;
+ break;
- case 'S': /* STORED STATS SERVER_ERROR */
+ case 'S':
{
- if (buffer[2] == 'A') /* STORED STATS */
+ // STAT
+ if (buffer[1] == 'T' and buffer[2] == 'A' and buffer[3] == 'T') /* STORED STATS */
{
memcached_server_response_increment(ptr);
return MEMCACHED_STAT;
}
- else if (buffer[1] == 'E') /* SERVER_ERROR */
+ // SERVER_ERROR
+ else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'V' and buffer[4] == 'E' and buffer[5] == 'R'
+ and buffer[6] == '_'
+ and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R' )
{
if (total_read == memcached_literal_param_size("SERVER_ERROR"))
{
return memcached_set_error(*ptr, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
}
- else if (buffer[1] == 'T')
+ // STORED
+ else if (buffer[1] == 'T' and buffer[2] == 'O' and buffer[3] == 'R') // and buffer[4] == 'E' and buffer[5] == 'D')
{
return MEMCACHED_STORED;
}
- else
+ }
+ break;
+
+ case 'D':
+ {
+ // DELETED
+ if (buffer[1] == 'E' and buffer[2] == 'L' and buffer[3] == 'E' and buffer[4] == 'T' and buffer[5] == 'E' and buffer[6] == 'D')
{
- WATCHPOINT_STRING(buffer);
- return MEMCACHED_UNKNOWN_READ_FAILURE;
+ return MEMCACHED_DELETED;
}
}
- case 'D': /* DELETED */
- return MEMCACHED_DELETED;
+ break;
- case 'N': /* NOT_FOUND */
+ case 'N':
{
- if (buffer[4] == 'F')
+ // NOT_FOUND
+ if (buffer[1] == 'O' and buffer[2] == 'T'
+ and buffer[3] == '_'
+ and buffer[4] == 'F' and buffer[5] == 'O' and buffer[6] == 'U' and buffer[7] == 'N' and buffer[8] == 'D')
{
return MEMCACHED_NOTFOUND;
}
- else if (buffer[4] == 'S')
+ // NOT_STORED
+ else if (buffer[1] == 'O' and buffer[2] == 'T'
+ and buffer[3] == '_'
+ and buffer[4] == 'S' and buffer[5] == 'T' and buffer[6] == 'O' and buffer[7] == 'R' and buffer[8] == 'E' and buffer[9] == 'D')
{
return MEMCACHED_NOTSTORED;
}
- else
- {
- WATCHPOINT_STRING(buffer);
- return MEMCACHED_UNKNOWN_READ_FAILURE;
- }
}
+ break;
+
case 'E': /* PROTOCOL ERROR or END */
{
- if (buffer[1] == 'N')
+ // END
+ if (buffer[1] == 'N' and buffer[2] == 'D')
{
return MEMCACHED_END;
}
- else if (buffer[1] == 'R')
+#if 0
+ // PROTOCOL_ERROR
+ else if (buffer[1] == 'R' and buffer[2] == 'O' and buffer[3] == 'T' and buffer[4] == 'O' and buffer[5] == 'C' and buffer[6] == 'O' and buffer[7] == 'L'
+ and buffer[8] == '_'
+ and buffer[9] == 'E' and buffer[10] == 'R' and buffer[11] == 'R' and buffer[12] == 'O' and buffer[13] == 'R')
{
return MEMCACHED_PROTOCOL_ERROR;
}
- else if (buffer[1] == 'X')
+#endif
+ // EXISTS
+ else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S')
{
return MEMCACHED_DATA_EXISTS;
}
- else
- {
- WATCHPOINT_STRING(buffer);
- return MEMCACHED_UNKNOWN_READ_FAILURE;
- }
-
}
+ break;
+
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')
+ // 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;
+ break;
- 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 'I': /* ITEM */
+ {
+ // ITEM
+ if (buffer[1] == 'T' and buffer[2] == 'E' and buffer[3] == 'M')
+ {
+ /* We add back in one because we will need to search for END */
+ memcached_server_response_increment(ptr);
+ return MEMCACHED_ITEM;
+ }
+ }
+ break;
case 'C': /* CLIENT ERROR */
- return MEMCACHED_CLIENT_ERROR;
-
- default:
{
- unsigned long long auto_return_value;
+ // CLIENT_ERROR
+ if (buffer[1] == 'L' and buffer[2] == 'I' and buffer[3] == 'E' and buffer[4] == 'N' and buffer[5] == 'T'
+ and buffer[6] == '_'
+ and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R')
+ {
+ return MEMCACHED_CLIENT_ERROR;
+ }
+ }
+ break;
+
+ case '0': /* INCR/DECR response */
+ case '1': /* INCR/DECR response */
+ case '2': /* INCR/DECR response */
+ case '3': /* INCR/DECR response */
+ case '4': /* INCR/DECR response */
+ case '5': /* INCR/DECR response */
+ case '6': /* INCR/DECR response */
+ case '7': /* INCR/DECR response */
+ case '8': /* INCR/DECR response */
+ case '9': /* INCR/DECR response */
+ {
+ unsigned long long int auto_return_value= strtoull(buffer, (char **)NULL, 10);
- if (sscanf(buffer, "%llu", &auto_return_value) == 1)
- return MEMCACHED_SUCCESS;
+ if (auto_return_value == ULLONG_MAX and errno == ERANGE)
+ {
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("Numeric response was out of range"));
+ }
+ else if (errno == EINVAL)
+ {
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("Numeric response was out of range"));
+ }
+
+ numeric_value= uint64_t(auto_return_value);
WATCHPOINT_STRING(buffer);
- return MEMCACHED_UNKNOWN_READ_FAILURE;
+ return MEMCACHED_SUCCESS;
}
+
+ default:
+ break;
}
- /* NOTREACHED */
+ buffer[total_read]= 0;
+#if 0
+ if (total_read >= sizeof("STORSTORED") -1)
+ {
+ fprintf(stderr, "%s:%d '%s', %.*s\n", __FILE__, __LINE__,
+ buffer, MEMCACHED_MAX_BUFFER, ptr->read_buffer);
+ assert(memcmp(buffer,"STORSTORED", sizeof("STORSTORED") -1));
+ }
+#endif
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+ buffer, total_read);
}
static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
+ char *buffer, const size_t buffer_length,
memcached_result_st *result)
{
memcached_return_t rc;
if (header.response.magic != PROTOCOL_BINARY_RES)
{
- return MEMCACHED_PROTOCOL_ERROR;
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
/*
case PROTOCOL_BINARY_CMD_INCREMENT:
case PROTOCOL_BINARY_CMD_DECREMENT:
{
- if (bodylen != sizeof(uint64_t) || buffer_length != sizeof(uint64_t))
+ if (bodylen != sizeof(uint64_t) or buffer_length != sizeof(uint64_t))
{
- return MEMCACHED_PROTOCOL_ERROR;
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
WATCHPOINT_ASSERT(bodylen == buffer_length);
default:
{
/* Command not implemented yet! */
- WATCHPOINT_ASSERT(0);
- return MEMCACHED_PROTOCOL_ERROR;
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
}
}
case PROTOCOL_BINARY_RESPONSE_EINVAL:
case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
default:
- /* @todo fix the error mappings */
- rc= MEMCACHED_PROTOCOL_ERROR;
+ return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
break;
}
}
return rc;
}
+
+static memcached_return_t _read_one_response(memcached_server_write_instance_st ptr,
+ char *buffer, const size_t buffer_length,
+ memcached_result_st *result,
+ uint64_t& numeric_value)
+{
+ memcached_server_response_decrement(ptr);
+
+ if (result == NULL)
+ {
+ memcached_st *root= (memcached_st *)ptr->root;
+ result = &root->result;
+ }
+
+ memcached_return_t rc;
+ if (memcached_is_binary(ptr->root))
+ {
+ rc= binary_read_one_response(ptr, buffer, buffer_length, result);
+ }
+ else
+ {
+ rc= textual_read_one_response(ptr, buffer, buffer_length, result, numeric_value);
+ assert(rc != MEMCACHED_PROTOCOL_ERROR);
+ }
+
+ if (rc == MEMCACHED_UNKNOWN_READ_FAILURE or
+ rc == MEMCACHED_READ_FAILURE or
+ rc == MEMCACHED_PROTOCOL_ERROR or
+ rc == MEMCACHED_CLIENT_ERROR or
+ rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
+ {
+ memcached_io_reset(ptr);
+ }
+
+ return rc;
+}
+
+memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
+ memcached_result_st *result)
+{
+ uint64_t numeric_value;
+ char buffer[SMALL_STRING_LEN];
+
+ if (memcached_is_udp(ptr->root))
+ {
+ return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ }
+
+
+ return _read_one_response(ptr, buffer, sizeof(buffer), result, numeric_value);
+}
+
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+ char *buffer, size_t buffer_length,
+ memcached_result_st *result)
+{
+ uint64_t numeric_value;
+
+ return memcached_response(ptr, buffer, buffer_length, result, numeric_value);
+}
+
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+ char *buffer, size_t buffer_length,
+ memcached_result_st *result,
+ uint64_t& numeric_value)
+{
+ if (memcached_is_udp(ptr->root))
+ {
+ return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ }
+
+ /* We may have old commands in the buffer not set, first purge */
+ if ((ptr->root->flags.no_block) and (memcached_is_processing_input(ptr->root) == false))
+ {
+ (void)memcached_io_write(ptr);
+ }
+
+ /*
+ * The previous implementation purged all pending requests and just
+ * returned the last one. Purge all pending messages to ensure backwards
+ * compatibility.
+ */
+ if (memcached_is_binary(ptr->root) == false and memcached_server_response_count(ptr) > 1)
+ {
+ memcached_result_st junked_result;
+ memcached_result_st *junked_result_ptr= memcached_result_create(ptr->root, &junked_result);
+
+ assert(junked_result_ptr);
+
+ while (memcached_server_response_count(ptr) > 1)
+ {
+ memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr, numeric_value);
+
+ // @TODO should we return an error on another but a bad read case?
+ if (rc != MEMCACHED_END and
+ rc != MEMCACHED_STORED and
+ rc != MEMCACHED_SUCCESS and
+ rc != MEMCACHED_STAT and
+ rc != MEMCACHED_DELETED and
+ rc != MEMCACHED_NOTFOUND and
+ rc != MEMCACHED_NOTSTORED and
+ rc != MEMCACHED_DATA_EXISTS)
+ {
+ memcached_result_free(junked_result_ptr);
+ return rc;
+ }
+ }
+ memcached_result_free(junked_result_ptr);
+ }
+
+ return _read_one_response(ptr, buffer, buffer_length, result, numeric_value);
+}
#pragma once
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* Read a single response from the server */
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
- char *buffer, size_t buffer_length,
memcached_result_st *result);
-LIBMEMCACHED_LOCAL
memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
char *buffer, size_t buffer_length,
memcached_result_st *result);
-#ifdef __cplusplus
-}
-#endif
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+ char *buffer, size_t buffer_length,
+ memcached_result_st *result,
+ uint64_t& numeric_value);
}
/* SANITY CHECK: SASL can only be used with the binary protocol */
- if (server->root->flags.binary_protocol == false)
+ if (memcached_is_binary(server->root) == false)
{
- return MEMCACHED_PROTOCOL_ERROR;
+ return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+ memcached_literal_param("memcached_sasl_authenticate_connection() is not supported via the ASCII protocol"));
}
/* Try to get the supported mech from the server. Servers without SASL
do {
/* send the packet */
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
{ request.bytes, sizeof(request.bytes) },
{ chosenmech, keylen },
self->number_of_hosts= 0;
self->cursor_active= 0;
self->port= port;
- self->fd= -1;
+ self->fd= INVALID_SOCKET;
self->io_bytes_sent= 0;
self->server_failure_counter= 0;
self->server_failure_counter_query_id= 0;
static memcached_server_st *_server_create(memcached_server_st *self, const memcached_st *memc)
{
- if (not self)
+ if (self == NULL)
{
self= libmemcached_xmalloc(memc, struct memcached_server_st);
- if (not self)
+ if (self == NULL)
{
return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
}
_server_init(self, const_cast<memcached_st *>(memc), hostname, port, weight, type);
-
if (memc and memcached_is_udp(memc))
- {
+ {
self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
memcached_io_init_udp_header(self, 0);
}
memcached_string_t _hostname= { memcached_string_make_from_cstr(hostname) };
/* @todo Check return type */
- if (not __server_create_with(NULL, &new_host_list[count-1], _hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET))
+ if (__server_create_with(NULL, &new_host_list[count-1], _hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET) == NULL)
{
*error= memcached_set_errno(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
return 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 "common.h"
+#include <libmemcached/common.h>
static const char *memcached_stat_keys[] = {
"pid",
memcached_stat_fn func;
void *context;
const char *args;
+ const size_t args_length;
local_context(memcached_stat_fn func_arg,
- void *context_arg,
- const char *args_arg) :
+ void *context_arg,
+ const char *args_arg,
+ const size_t args_length_arg) :
func(func_arg),
context(context_arg),
- args(args_arg)
+ args(args_arg),
+ args_length(args_length_arg)
{ }
};
WATCHPOINT_STRING(key);
return MEMCACHED_UNKNOWN_STAT_KEY;
}
- else if (not strcmp("pid", key))
+ else if (strcmp("pid", key) == 0)
{
int64_t temp= strtoll(value, (char **)NULL, 10);
*error= MEMCACHED_SUCCESS;
- if (not memcmp("pid", key, sizeof("pid") -1))
+ if (memcmp("pid", key, sizeof("pid") -1) == 0)
{
length= snprintf(buffer, SMALL_STRING_LEN,"%lld", (signed long long)memc_stat->pid);
}
static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
const char *args,
+ const size_t args_length,
memcached_server_write_instance_st instance,
struct local_context *check)
{
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT;
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
- if (args)
+ if (args_length)
{
- size_t len= strlen(args);
+ request.message.header.request.keylen= htons(uint16_t(args_length));
+ request.message.header.request.bodylen= htonl(uint32_t( args_length));
- memcached_return_t rc= memcached_validate_key_length(len, true);
- 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[]=
+ libmemcached_io_vector_st vector[]=
{
{ request.bytes, sizeof(request.bytes) },
- { args, len }
+ { args, args_length }
};
if (memcached_vdo(instance, vector, 2, true) != MEMCACHED_SUCCESS)
}
else
{
- if (memcached_do(instance, request.bytes,
- sizeof(request.bytes), true) != MEMCACHED_SUCCESS)
+ libmemcached_io_vector_st vector[]=
+ {
+ { request.bytes, sizeof(request.bytes) }
+ };
+
+ if (memcached_vdo(instance, vector, 1, true) != MEMCACHED_SUCCESS)
{
memcached_io_reset(instance);
return MEMCACHED_WRITE_FAILURE;
memcached_return_t rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
if (rc == MEMCACHED_END)
+ {
break;
+ }
- unlikely (rc != MEMCACHED_SUCCESS)
+ if (rc != MEMCACHED_SUCCESS)
{
memcached_io_reset(instance);
return rc;
if (memc_stat)
{
- unlikely((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
+ if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
{
WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
WATCHPOINT_ASSERT(0);
}
} while (1);
- /* shit... memcached_response will decrement the counter, so I need to
- ** reset it.. todo: look at this and try to find a better solution.
- */
+ /*
+ * memcached_response will decrement the counter, so I need to reset it..
+ * todo: look at this and try to find a better solution.
+ * */
instance->cursor_active= 0;
return MEMCACHED_SUCCESS;
static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat,
const char *args,
+ const size_t args_length,
memcached_server_write_instance_st instance,
struct local_context *check)
{
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- int send_length;
-
- if (args)
+ libmemcached_io_vector_st vector[]=
{
- send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "stats %s\r\n", args);
- }
- else
- {
- send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "stats\r\n");
- }
+ { memcached_literal_param("stats ") },
+ { args, args_length },
+ { memcached_literal_param("\r\n") }
+ };
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
- {
- return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
- }
-
- memcached_return_t rc= memcached_do(instance, buffer, (size_t)send_length, true);
+ memcached_return_t rc= memcached_vdo(instance, vector, 3, true);
if (memcached_success(rc))
{
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
while ((rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL)) == MEMCACHED_STAT)
{
char *string_ptr, *end_ptr;
}
if (rc == MEMCACHED_END)
+ {
return MEMCACHED_SUCCESS;
- else
- return rc;
+ }
+
+ return rc;
}
memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_return_t *error)
error= &unused;
}
- memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(self)))
+ if (memcached_failed(*error= initialize_query(self, true)))
{
- *error= rc;
-
return NULL;
}
- WATCHPOINT_ASSERT(error);
-
- if (self->flags.use_udp)
+ if (memcached_is_udp(self))
{
*error= memcached_set_error(*self, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-
return NULL;
}
- memcached_stat_st *stats= libmemcached_xcalloc(self, memcached_server_count(self), memcached_stat_st);
-
- if (not stats)
+ memcached_return_t rc;
+ size_t args_length= 0;
+ if (args)
{
- *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ args_length= strlen(args);
+ rc= memcached_validate_key_length(args_length, self->flags.binary_protocol);
+ if (memcached_failed(rc))
+ {
+ *error= memcached_set_error(*self, rc, MEMCACHED_AT);
+ return NULL;
+ }
+ }
+
+ WATCHPOINT_ASSERT(error);
+ memcached_stat_st *stats= libmemcached_xcalloc(self, memcached_server_count(self), memcached_stat_st);
+ if (stats == NULL)
+ {
+ *error= memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
return NULL;
}
rc= MEMCACHED_SUCCESS;
for (uint32_t x= 0; x < memcached_server_count(self); x++)
{
- memcached_return_t temp_return;
- memcached_server_write_instance_st instance;
- memcached_stat_st *stat_instance;
-
- stat_instance= stats +x;
+ memcached_stat_st* stat_instance= stats +x;
stat_instance->pid= -1;
stat_instance->root= self;
- instance= memcached_server_instance_fetch(self, x);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(self, x);
- if (self->flags.binary_protocol)
+ memcached_return_t temp_return;
+ if (memcached_is_binary(self))
{
- temp_return= binary_stats_fetch(stat_instance, args, instance, NULL);
+ temp_return= binary_stats_fetch(stat_instance, args, args_length, instance, NULL);
}
else
{
- temp_return= ascii_stats_fetch(stat_instance, args, instance, NULL);
+ temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL);
}
if (memcached_failed(temp_return))
const char *hostname, in_port_t port)
{
memcached_st memc;
- memcached_server_write_instance_st instance;
memset(memc_stat, 0, sizeof(memcached_stat_st));
memcached_st *memc_ptr= memcached_create(&memc);
- if (not memc_ptr)
+ if (memc_ptr == NULL)
+ {
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
- memcached_server_add(&memc, hostname, port);
+ }
memcached_return_t rc;
- if ((rc= initialize_query(memc_ptr)) != MEMCACHED_SUCCESS)
+ if (memcached_failed(rc= memcached_server_add(&memc, hostname, port)))
{
+ memcached_free(&memc);
return rc;
}
- instance= memcached_server_instance_fetch(memc_ptr, 0);
-
- if (memc.flags.binary_protocol)
+ if (memcached_success(rc= initialize_query(memc_ptr, true)))
{
- rc= binary_stats_fetch(memc_stat, args, instance, NULL);
- }
- else
- {
- rc= ascii_stats_fetch(memc_stat, args, instance, NULL);
+ size_t args_length= 0;
+ if (args)
+ {
+ args_length= strlen(args);
+ rc= memcached_validate_key_length(args_length, memc.flags.binary_protocol);
+ }
+
+ if (memcached_success(rc))
+ {
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc_ptr, 0);
+ if (memc.flags.binary_protocol)
+ {
+ rc= binary_stats_fetch(memc_stat, args, args_length, instance, NULL);
+ }
+ else
+ {
+ rc= ascii_stats_fetch(memc_stat, args, args_length, instance, NULL);
+ }
+ }
}
memcached_free(&memc);
if (ptr->flags.binary_protocol)
{
- rc= binary_stats_fetch(NULL, check->args, instance, check);
+ rc= binary_stats_fetch(NULL, check->args, check->args_length, instance, check);
}
else
{
- rc= ascii_stats_fetch(NULL, check->args, instance, check);
+ rc= ascii_stats_fetch(NULL, check->args, check->args_length, instance, check);
}
return rc;
{
memcached_version(memc);
- struct local_context check(func, context, args);
+ struct local_context check(func, context, args, args ? strlen(args) : 0);
return memcached_server_execute(memc, call_stat_fn, (void *)&check);
}
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
*
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
*
- * Summary: Storage related functions, aka set, replace,..
+ * 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>
enum memcached_storage_action_t {
return "set ";
}
-static inline uint8_t get_com_code(memcached_storage_action_t verb, bool noreply)
+static inline uint8_t get_com_code(const memcached_storage_action_t verb, const bool reply)
{
- if (noreply)
+ if (reply == false)
{
switch (verb)
{
memcached_server_write_instance_st server,
uint32_t server_key,
const char *key,
- size_t key_length,
+ const size_t key_length,
const char *value,
- size_t value_length,
- time_t expiration,
- uint32_t flags,
- uint64_t cas,
- bool flush,
+ const size_t value_length,
+ const time_t expiration,
+ const uint32_t flags,
+ const uint64_t cas,
+ const bool flush,
+ const bool reply,
memcached_storage_action_t verb)
{
protocol_binary_request_set request= {};
size_t send_length= sizeof(request.bytes);
- bool noreply= server->root->flags.no_reply;
-
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
- request.message.header.request.opcode= get_com_code(verb, noreply);
+ request.message.header.request.opcode= get_com_code(verb, reply);
request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
if (verb == APPEND_OP or verb == PREPEND_OP)
request.message.header.request.cas= memcached_htonll(cas);
}
- if (server->root->flags.use_udp and flush == false)
- {
- size_t cmd_size= send_length + key_length + value_length;
-
- if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
- {
- return MEMCACHED_WRITE_FAILURE;
- }
- if (cmd_size + server->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
- {
- memcached_io_write(server, NULL, 0, true);
- }
- }
-
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ request.bytes, send_length },
{ memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
{ key, key_length },
/* write the header */
memcached_return_t rc;
- if ((rc= memcached_vdo(server, vector, 4, flush)) != MEMCACHED_SUCCESS)
+ if ((rc= memcached_vdo(server, vector, 5, flush)) != MEMCACHED_SUCCESS)
{
memcached_io_reset(server);
- if (ptr->error_messages == NULL)
+ if (memcached_has_error(ptr))
{
memcached_set_error(*server, rc, MEMCACHED_AT);
}
return MEMCACHED_WRITE_FAILURE;
}
- if (verb == SET_OP && ptr->number_of_replicas > 0)
+ if (verb == SET_OP and ptr->number_of_replicas > 0)
{
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
WATCHPOINT_STRING("replicating");
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
- if (memcached_vdo(instance, vector, 4, false) != MEMCACHED_SUCCESS)
+ if (memcached_vdo(instance, vector, 5, false) != MEMCACHED_SUCCESS)
{
memcached_io_reset(instance);
}
return MEMCACHED_BUFFERED;
}
- if (noreply)
+ // No reply always assumes success
+ if (reply == false)
{
return MEMCACHED_SUCCESS;
}
static memcached_return_t memcached_send_ascii(memcached_st *ptr,
memcached_server_write_instance_st instance,
const char *key,
- size_t key_length,
+ const size_t key_length,
const char *value,
- size_t value_length,
- time_t expiration,
- uint32_t flags,
- uint64_t cas,
- bool flush,
- memcached_storage_action_t verb)
+ const size_t value_length,
+ const time_t expiration,
+ const uint32_t flags,
+ const uint64_t cas,
+ const bool flush,
+ const bool reply,
+ const memcached_storage_action_t verb)
{
- size_t write_length;
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
- if (cas)
+ char flags_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+ int flags_buffer_length= snprintf(flags_buffer, sizeof(flags_buffer), " %u", flags);
+ if (size_t(flags_buffer_length) >= sizeof(flags_buffer) or flags_buffer_length < 0)
{
- int check_length;
- check_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "%s %.*s%.*s %u %llu %lu %llu%s\r\n",
- storage_op_string(verb),
- memcached_print_array(ptr->_namespace),
- (int)key_length, key, flags,
- (unsigned long long)expiration, (unsigned long)value_length,
- (unsigned long long)cas,
- (ptr->flags.no_reply) ? " noreply" : "");
- if (check_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or check_length < 0)
- {
- return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
- }
- write_length= check_length;
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
}
- else
- {
- char *buffer_ptr= buffer;
- const char *command= storage_op_string(verb);
-
- /* Copy in the command, no space needed, we handle that in the command function*/
- memcpy(buffer_ptr, command, strlen(command));
-
- /* Copy in the key prefix, switch to the buffer_ptr */
- buffer_ptr= (char *)memcpy((char *)(buffer_ptr + strlen(command)), (char *)memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace));
-
- /* Copy in the key, adjust point if a key prefix was used. */
- buffer_ptr= (char *)memcpy(buffer_ptr + memcached_array_size(ptr->_namespace),
- key, key_length);
- buffer_ptr+= key_length;
- buffer_ptr[0]= ' ';
- buffer_ptr++;
-
- write_length= (size_t)(buffer_ptr - buffer);
- int check_length= snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE -(size_t)(buffer_ptr - buffer),
- "%u %llu %lu%s\r\n",
- flags,
- (unsigned long long)expiration, (unsigned long)value_length,
- ptr->flags.no_reply ? " noreply" : "");
- if ((size_t)check_length >= MEMCACHED_DEFAULT_COMMAND_SIZE -size_t(buffer_ptr - buffer) or check_length < 0)
- {
- return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
- }
- write_length+= (size_t)check_length;
- WATCHPOINT_ASSERT(write_length < MEMCACHED_DEFAULT_COMMAND_SIZE);
+ char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+ int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
+ if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer) or expiration_buffer_length < 0)
+ {
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
}
- if (ptr->flags.use_udp)
+ char value_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+ int value_buffer_length= snprintf(value_buffer, sizeof(value_buffer), " %llu", (unsigned long long)value_length);
+ if (size_t(value_buffer_length) >= sizeof(value_buffer) or value_buffer_length < 0)
{
- size_t cmd_size= write_length + value_length +2;
- if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
- {
- return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
- }
-
- if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
- {
- memcached_io_write(instance, NULL, 0, true);
- }
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
}
- if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+ char cas_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+ int cas_buffer_length= 0;
+ if (cas)
{
- return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ cas_buffer_length= snprintf(cas_buffer, sizeof(cas_buffer), " %llu", (unsigned long long)cas);
+ if (size_t(cas_buffer_length) >= sizeof(cas_buffer) or cas_buffer_length < 0)
+ {
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+ }
}
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
- { buffer, write_length },
+ { NULL, 0 },
+ { storage_op_string(verb), strlen(storage_op_string(verb))},
+ { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+ { key, key_length },
+ { flags_buffer, flags_buffer_length },
+ { expiration_buffer, expiration_buffer_length },
+ { value_buffer, value_buffer_length },
+ { cas_buffer, cas_buffer_length },
+ { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+ { memcached_literal_param("\r\n") },
{ value, value_length },
{ memcached_literal_param("\r\n") }
};
- if (memcached_is_udp(instance->root) and (write_length +value_length +memcached_literal_param_size("\r\n") +UDP_DATAGRAM_HEADER_LENGTH > MAX_UDP_DATAGRAM_LENGTH))
+ /* Send command header */
+ memcached_return_t rc= memcached_vdo(instance, vector, 12, flush);
+
+ // If we should not reply, return with MEMCACHED_SUCCESS, unless error
+ if (reply == false)
{
- return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT, memcached_literal_param("UDP packet is too large"));
+ return memcached_success(rc) ? MEMCACHED_SUCCESS : rc;
+ }
+
+ if (flush == false)
+ {
+ return memcached_success(rc) ? MEMCACHED_BUFFERED : rc;
}
- /* Send command header */
- memcached_return_t rc= memcached_vdo(instance, vector, 3, flush);
if (rc == MEMCACHED_SUCCESS)
{
- if (ptr->flags.no_reply and flush)
- {
- rc= MEMCACHED_SUCCESS;
- }
- else if (flush == false)
- {
- rc= MEMCACHED_BUFFERED;
- }
- else
- {
- rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
- if (rc == MEMCACHED_STORED)
- {
- rc= MEMCACHED_SUCCESS;
- }
+ if (rc == MEMCACHED_STORED)
+ {
+ return MEMCACHED_SUCCESS;
}
}
memcached_io_reset(instance);
}
- if (memcached_failed(rc) and ptr->error_messages == NULL)
+ assert(memcached_failed(rc));
+ if (memcached_has_error(ptr) == false)
{
- memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ return memcached_set_error(*ptr, rc, MEMCACHED_AT);
}
return rc;
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,
+ const time_t expiration,
+ const uint32_t flags,
+ const uint64_t cas,
memcached_storage_action_t verb)
{
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ if (memcached_failed(rc= memcached_validate_key_length(key_length, memcached_is_binary(ptr))))
{
return rc;
}
WATCHPOINT_SET(instance->io_wait_count.read= 0);
WATCHPOINT_SET(instance->io_wait_count.write= 0);
- bool flush= (bool) ((instance->root->flags.buffer_requests && verb == SET_OP) ? 0 : 1);
- if (ptr->flags.binary_protocol)
+
+ bool flush= true;
+ if (memcached_is_buffering(instance->root) and verb == SET_OP)
{
- rc= memcached_send_binary(ptr, instance, server_key,
- key, key_length,
- value, value_length, expiration,
- flags, cas, flush, verb);
+ flush= false;
}
- else
+
+ bool reply= memcached_is_replying(ptr);
+
+ if (memcached_is_binary(ptr))
{
- rc= memcached_send_ascii(ptr, instance,
- key, key_length,
- value, value_length, expiration,
- flags, cas, flush, verb);
+ return memcached_send_binary(ptr, instance, server_key,
+ key, key_length,
+ value, value_length, expiration,
+ flags, cas, flush, reply, verb);
}
- return rc;
+ return memcached_send_ascii(ptr, instance,
+ key, key_length,
+ value, value_length, expiration,
+ flags, cas, flush, reply, verb);
}
rc= memcached_send(ptr, key, key_length,
key, key_length, value, value_length,
expiration, flags, 0, ADD_OP);
+
+ if (rc == MEMCACHED_NOTSTORED or rc == MEMCACHED_DATA_EXISTS)
+ {
+ memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ }
LIBMEMCACHED_MEMCACHED_ADD_END();
return rc;
}
time_t expiration,
uint32_t flags)
{
- memcached_return_t rc;
- rc= memcached_send(ptr, group_key, group_key_length,
- key, key_length, value, value_length,
- expiration, flags, 0, PREPEND_OP);
- return rc;
+ return memcached_send(ptr, group_key, group_key_length,
+ key, key_length, value, value_length,
+ expiration, flags, 0, PREPEND_OP);
}
memcached_return_t memcached_append_by_key(memcached_st *ptr,
time_t expiration,
uint32_t flags)
{
- memcached_return_t rc;
- rc= memcached_send(ptr, group_key, group_key_length,
- key, key_length, value, value_length,
- expiration, flags, 0, APPEND_OP);
- return rc;
+ return memcached_send(ptr, group_key, group_key_length,
+ key, key_length, value, value_length,
+ expiration, flags, 0, APPEND_OP);
}
memcached_return_t memcached_cas_by_key(memcached_st *ptr,
uint32_t flags,
uint64_t cas)
{
- memcached_return_t rc;
- rc= memcached_send(ptr, group_key, group_key_length,
- key, key_length, value, value_length,
- expiration, flags, cas, CAS_OP);
- return rc;
+ return memcached_send(ptr, group_key, group_key_length,
+ key, key_length, value, value_length,
+ expiration, flags, cas, CAS_OP);
}
const char *key, size_t key_length,
time_t expiration)
{
- char buffer[21];
+ char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+ int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
+ if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer) or expiration_buffer_length < 0)
+ {
+ return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+ }
- int buffer_length= snprintf(buffer, sizeof(buffer), " %u", uint32_t(expiration));
- struct libmemcached_io_vector_st vector[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ memcached_literal_param("touch ") },
{ memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
{ key, key_length },
- { buffer, buffer_length },
+ { expiration_buffer, expiration_buffer_length },
{ memcached_literal_param("\r\n") }
};
memcached_return_t rc;
- if (memcached_failed(rc= memcached_vdo(instance, vector, 5, true)))
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 6, true)))
{
memcached_io_reset(instance);
return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
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[]=
+ libmemcached_io_vector_st vector[]=
{
+ { NULL, 0 },
{ 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)))
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
{
memcached_io_reset(instance);
return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
LIBMEMCACHED_MEMCACHED_TOUCH_START();
memcached_return_t rc;
- if (memcached_failed(rc= initialize_query(ptr)))
+ if (memcached_failed(rc= initialize_query(ptr, true)))
{
return rc;
}
}
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- rc= memcached_read_one_response(instance, buffer, sizeof(buffer), NULL);
+ rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_NOTFOUND)
{
--- /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.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+/*
+ * The udp request id consists of two seperate sections
+ * 1) The thread id
+ * 2) The message number
+ * The thread id should only be set when the memcached_st struct is created
+ * and should not be changed.
+ *
+ * The message num is incremented for each new message we send, this function
+ * extracts the message number from message_id, increments it and then
+ * writes the new value back into the header
+ */
+void increment_udp_message_id(memcached_server_write_instance_st ptr)
+{
+ struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+ uint16_t cur_req= get_udp_datagram_request_id(header);
+ int msg_num= get_msg_num_from_request_id(cur_req);
+ int thread_id= get_thread_id_from_request_id(cur_req);
+
+ if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
+ msg_num= 0;
+
+ header->request_id= htons((uint16_t) (thread_id | msg_num));
+}
+
+bool memcached_io_init_udp_header(memcached_server_write_instance_st ptr, const uint16_t thread_id)
+{
+ if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
+ {
+ return MEMCACHED_FAILURE;
+ }
+
+ struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+ header->request_id= htons(uint16_t((generate_udp_request_thread_id(thread_id))));
+ header->num_datagrams= htons(1);
+ header->sequence_number= htons(0);
+
+ return MEMCACHED_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.
+ *
+ */
+
+#define MAX_UDP_DATAGRAM_LENGTH 1400
+#define UDP_DATAGRAM_HEADER_LENGTH 8
+#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
+#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
+#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
+#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
+#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
+#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
+
+struct udp_datagram_header_st
+{
+ uint16_t request_id;
+ uint16_t sequence_number;
+ uint16_t num_datagrams;
+ uint16_t reserved;
+};
+
+bool memcached_io_init_udp_header(memcached_server_write_instance_st ptr, const uint16_t thread_id);
+void increment_udp_message_id(memcached_server_write_instance_st ptr);
const memcached_server_st *server,
void *context)
{
- struct context_st *execute= (struct context_st *)context;
+ libmemcached_io_vector_st *vector= (libmemcached_io_vector_st *)context;
memcached_st local_memc;
memcached_st *memc_ptr= memcached_create(&local_memc);
if (rc == MEMCACHED_SUCCESS)
{
- 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);
+ rc= memcached_vdo(instance, vector, 4, true);
if (rc == MEMCACHED_SUCCESS)
{
- rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
}
}
memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity)
{
- int send_length;
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr, false)))
+ {
+ return rc;
+ }
+
memcached_server_fn callbacks[1];
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
- "verbosity %u\r\n", verbosity);
- if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+ int send_length= snprintf(buffer, sizeof(buffer), "%u", verbosity);
+ if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or send_length < 0)
{
return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
}
- struct context_st context = { (size_t)send_length, buffer };
+ libmemcached_io_vector_st vector[]=
+ {
+ { NULL, 0 },
+ { memcached_literal_param("verbosity ") },
+ { buffer, send_length },
+ { memcached_literal_param("\r\n") }
+ };
callbacks[0]= _set_verbosity;
- return memcached_server_cursor(ptr, callbacks, &context, 1);
+ return memcached_server_cursor(ptr, callbacks, vector, 1);
}
return LIBMEMCACHED_VERSION_STRING;
}
-static inline memcached_return_t memcached_version_binary(memcached_st *ptr);
-static inline memcached_return_t memcached_version_textual(memcached_st *ptr);
-
-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;
- }
-
- 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)
{
+ libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("version\r\n") },
+ };
memcached_return_t rc= MEMCACHED_SUCCESS;
+
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
continue;
}
- memcached_return_t rrc= memcached_do(instance, memcached_literal_param("version\r\n"), true);
+ memcached_return_t rrc= memcached_vdo(instance, vector, 1, true);
if (memcached_failed(rrc))
{
(void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
}
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
if (memcached_failed(rrc))
{
memcached_set_error(*instance, rrc, MEMCACHED_AT);
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+ libmemcached_io_vector_st vector[]=
+ {
+ { request.bytes, sizeof(request.bytes) }
+ };
+
memcached_return_t rc= MEMCACHED_SUCCESS;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
continue;
}
- memcached_return_t rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
+ memcached_return_t rrc= memcached_vdo(instance, vector, 1, true);
if (memcached_failed(rrc))
{
memcached_io_reset(instance);
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- 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)
{
return rc;
}
+
+memcached_return_t memcached_version(memcached_st *ptr)
+{
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr, true)))
+ {
+ return rc;
+ }
+
+ if (memcached_is_udp(ptr))
+ {
+ return MEMCACHED_NOT_SUPPORTED;
+ }
+
+ if (memcached_is_binary(ptr))
+ {
+ rc= memcached_version_binary(ptr);
+ }
+ else
+ {
+ rc= memcached_version_textual(ptr);
+ }
+
+ return rc;
+}
pid_t pid= -1;
memcached_return_t unused;
- if (not ret)
+ if (ret == NULL)
+ {
ret= &unused;
+ }
memcached_st *memc_ptr= memcached_create(NULL);
- if (not memc_ptr)
+ if (memc_ptr == NULL)
{
*ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
return -1;
}
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);
+ 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)
set environment LIBTEST_IN_GDB=1
run
-quit
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cxx_gcc_abi_demangle.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_GCC_ABI_DEMANGLE
+#
+# DESCRIPTION
+#
+# If the compiler supports GCC C++ ABI name demangling (has header
+# cxxabi.h and abi::__cxa_demangle() function), define
+# HAVE_GCC_ABI_DEMANGLE
+#
+# Adapted from AX_CXX_RTTI by Luc Maisonobe
+#
+# LICENSE
+#
+# Copyright (c) 2008 Neil Ferguson <nferguso@eso.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 9
+
+AC_DEFUN([AX_CXX_GCC_ABI_DEMANGLE],
+[AC_CACHE_CHECK(whether the compiler supports GCC C++ ABI name demangling,
+ax_cv_cxx_gcc_abi_demangle,
+[AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <typeinfo>
+#include <cxxabi.h>
+#include <cstdlib>
+#include <string>
+
+template<typename TYPE>
+class A {};
+],[A<int> instance;
+int status = 0;
+char* c_name = 0;
+
+c_name = abi::__cxa_demangle(typeid(instance).name(), 0, 0, &status);
+
+std::string name(c_name);
+::free(c_name);
+
+return name == "A<int>";
+],
+ ax_cv_cxx_gcc_abi_demangle=yes, ax_cv_cxx_gcc_abi_demangle=no)
+ AC_LANG_RESTORE
+])
+if test "$ax_cv_cxx_gcc_abi_demangle" = yes; then
+ AC_DEFINE(HAVE_GCC_ABI_DEMANGLE,1,
+ [define if the compiler supports GCC C++ ABI name demangling])
+fi
+])
@cat tests/Xumemc.pid | xargs kill || echo "Failed to kill memcached server"
@rm tests/Xumemc.pid
-test-mem: tests/var tests/testapp
- @tests/testapp
+test-mem: tests/var tests/libmemcached-1.0/testapp
+ @tests/libmemcached-1.0/testapp
test-sasl: tests/sasl
@tests/sasl
pahole-mem: tests/testapp
@$(PAHOLE_COMMAND) tests/testapp
-gdb-mem: tests/testapp
- @$(DEBUG_COMMAND) tests/testapp
+gdb-mem: tests/var tests/libmemcached-1.0/testapp
+ @$(DEBUG_COMMAND) tests/libmemcached-1.0/testapp
gdb-sasl: tests/sasl
@$(DEBUG_COMMAND) tests/sasl
gdb-atom: tests/atomsmasher
@$(DEBUG_COMMAND) tests/atomsmasher
-gdb-udp: tests/testudp
- @$(DEBUG_COMMAND) tests/testudp
-
gdb-plus: tests/testplus
$(DEBUG_COMMAND) tests/testplus
valgrind-atom: tests/atomsmasher
$(VALGRIND_COMMAND) tests/atomsmasher
-valgrind-udp: tests/testudp
- $(VALGRIND_COMMAND) tests/testudp
-
valgrind-plus: tests/testplus
@$(VALGRIND_COMMAND) tests/testplus
helgrind-atom: tests/atomsmasher
@$(HELGRIND_COMMAND) tests/atomsmasher
-helgrind-udp: tests/testudp
- @$(HELGRIND_COMMAND) tests/testudp
-
helgrind-plus: tests/testplus
@$(HELGRIND_COMMAND) tests/testplus
check_PROGRAMS+= tests/testudp
noinst_PROGRAMS+= tests/testudp
+test-udp: tests/testudp
+ @tests/testudp
+
tests_testplus_SOURCES= tests/libmemcached-1.0/plus.cpp
tests_testplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX)
tests_testplus_DEPENDENCIES= $(TESTS_LDADDS)
#define GLOBAL_COUNT 10000
#define GLOBAL2_COUNT 100
#define SERVERS_TO_CREATE 5
-static uint32_t global_count;
+static uint32_t global_count= GLOBAL2_COUNT;
static pairs_st *global_pairs;
static const char *global_keys[GLOBAL_COUNT];
return TEST_SUCCESS;
}
+static memcached_return_t return_value_based_on_buffering(memcached_st *memc)
+{
+ if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS))
+ {
+ return MEMCACHED_BUFFERED;
+ }
+
+ return MEMCACHED_SUCCESS;
+}
+
static memcached_st * create_single_instance_memcached(const memcached_st *original_memc, const char *options)
{
/*
test_true(memc_clone->ketama.weighted == memc->ketama.weighted);
test_true(memc_clone->flags.binary_protocol == memc->flags.binary_protocol);
test_true(memc_clone->flags.hash_with_namespace == memc->flags.hash_with_namespace);
- test_true(memc_clone->flags.no_reply == memc->flags.no_reply);
+ test_true(memc_clone->flags.reply == memc->flags.reply);
test_true(memc_clone->flags.use_udp == memc->flags.use_udp);
test_true(memc_clone->flags.auto_eject_hosts == memc->flags.auto_eject_hosts);
test_true(memc_clone->flags.randomize_replica_read == memc->flags.randomize_replica_read);
test_literal_param("foo"),
test_literal_param("when we sanitize"),
time_t(0), (uint32_t)0);
- test_true_got(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+ test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
return TEST_SUCCESS;
}
static test_return_t append_test(memcached_st *memc)
{
memcached_return_t rc;
- const char *key= "fig";
const char *in_value= "we";
- char *out_value= NULL;
size_t value_length;
uint32_t flags;
- rc= memcached_flush(memc, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
-
- rc= memcached_set(memc, key, strlen(key),
- in_value, strlen(in_value),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_flush(memc, 0));
- rc= memcached_append(memc, key, strlen(key),
- " the", strlen(" the"),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param(__func__),
+ in_value, strlen(in_value),
+ time_t(0), uint32_t(0)));
- rc= memcached_append(memc, key, strlen(key),
- " people", strlen(" people"),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_append(memc,
+ test_literal_param(__func__),
+ " the", strlen(" the"),
+ time_t(0), uint32_t(0)));
- out_value= memcached_get(memc, key, strlen(key),
- &value_length, &flags, &rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_append(memc,
+ test_literal_param(__func__),
+ " people", strlen(" people"),
+ time_t(0), uint32_t(0)));
+
+ char *out_value= memcached_get(memc,
+ test_literal_param(__func__),
+ &value_length, &flags, &rc);
test_memcmp(out_value, "we the people", strlen("we the people"));
test_compare(strlen("we the people"), value_length);
test_compare(MEMCACHED_SUCCESS, rc);
static test_return_t append_binary_test(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "numbers";
uint32_t store_list[] = { 23, 56, 499, 98, 32847, 0 };
- uint32_t *value;
- size_t value_length;
- uint32_t flags;
- uint32_t x;
- rc= memcached_flush(memc, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_flush(memc, 0));
- rc= memcached_set(memc,
- key, strlen(key),
- NULL, 0,
- (time_t)0, (uint32_t)0);
- test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param(__func__),
+ NULL, 0,
+ time_t(0), uint32_t(0)));
- for (x= 0; store_list[x] ; x++)
+ size_t count= 0;
+ for (uint32_t x= 0; store_list[x] ; x++)
{
- rc= memcached_append(memc,
- key, strlen(key),
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_append(memc,
+ test_literal_param(__func__),
(char *)&store_list[x], sizeof(uint32_t),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ time_t(0), uint32_t(0)));
+ count++;
}
- value= (uint32_t *)memcached_get(memc, key, strlen(key),
- &value_length, &flags, &rc);
- test_compare(value_length, sizeof(uint32_t) * x);
+ size_t value_length;
+ uint32_t flags;
+ memcached_return_t rc;
+ uint32_t *value= (uint32_t *)memcached_get(memc,
+ test_literal_param(__func__),
+ &value_length, &flags, &rc);
+ test_compare(value_length, sizeof(uint32_t) * count);
test_compare(MEMCACHED_SUCCESS, rc);
- for (uint32_t counter= x, *ptr= value; counter; counter--)
+ for (uint32_t counter= count, *ptr= value; counter; counter--)
{
- test_compare(*ptr, store_list[x - counter]);
+ test_compare(*ptr, store_list[count - counter]);
ptr++;
}
free(value);
static test_return_t cas2_test(memcached_st *memc)
{
- memcached_return_t rc;
const char *keys[]= {"fudge", "son", "food"};
size_t key_length[]= {5, 3, 4};
const char *value= "we the people";
size_t value_length= strlen("we the people");
- memcached_result_st results_obj;
- memcached_result_st *results;
- unsigned int set= 1;
test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, set);
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true));
for (uint32_t x= 0; x < 3; x++)
{
- rc= memcached_set(memc, keys[x], key_length[x],
- keys[x], key_length[x],
- (time_t)50, (uint32_t)9);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, keys[x], key_length[x],
+ keys[x], key_length[x],
+ time_t(50), uint32_t(9)));
}
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 3));
- results= memcached_result_create(memc, &results_obj);
+ memcached_result_st *results= memcached_result_create(memc, NULL);
test_true(results);
- results= memcached_fetch_result(memc, &results_obj, &rc);
+ memcached_return_t rc;
+ results= memcached_fetch_result(memc, results, &rc);
test_true(results);
test_true(results->item_cas);
test_compare(MEMCACHED_SUCCESS, rc);
test_compare(strlen("we the people"), value_length);
test_compare(MEMCACHED_SUCCESS, rc);
- memcached_result_free(&results_obj);
+ memcached_result_free(results);
return TEST_SUCCESS;
}
static test_return_t cas_test(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "fun";
- size_t key_length= strlen(key);
- const char *value= "we the people";
- const char* keys[2] = { key, NULL };
- size_t keylengths[2] = { strlen(key), 0 };
- size_t value_length= strlen(value);
- const char *value2= "change the value";
- size_t value2_length= strlen(value2);
+ const char* keys[2] = { __func__, NULL };
+ size_t keylengths[2] = { strlen(__func__), 0 };
memcached_result_st results_obj;
- memcached_result_st *results;
- unsigned int set= 1;
- rc= memcached_flush(memc, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, set);
+ test_skip(true, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true));
- rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param(__func__),
+ test_literal_param("we the people"),
+ (time_t)0, (uint32_t)0));
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, keylengths, 1));
- results= memcached_result_create(memc, &results_obj);
+ memcached_result_st *results= memcached_result_create(memc, &results_obj);
test_true(results);
+ memcached_return_t rc;
results= memcached_fetch_result(memc, &results_obj, &rc);
test_true(results);
test_compare(MEMCACHED_SUCCESS, rc);
test_true(memcached_result_cas(results));
- test_memcmp(value, memcached_result_value(results), value_length);
- test_compare(strlen(memcached_result_value(results)), value_length);
- test_compare(MEMCACHED_SUCCESS, rc);
- uint64_t cas = memcached_result_cas(results);
+ test_memcmp("we the people", memcached_result_value(results), test_literal_param_size("we the people"));
+ test_compare(test_literal_param_size("we the people"),
+ strlen(memcached_result_value(results)));
+
+ uint64_t cas= memcached_result_cas(results);
#if 0
results= memcached_fetch_result(memc, &results_obj, &rc);
test_true(results == NULL);
#endif
- rc= memcached_cas(memc, key, key_length, value2, value2_length, 0, 0, cas);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_cas(memc,
+ test_literal_param(__func__),
+ test_literal_param("change the value"),
+ 0, 0, cas));
/*
* The item will have a new cas value, so try to set it again with the old
* value. This should fail!
*/
- rc= memcached_cas(memc, key, key_length, value2, value2_length, 0, 0, cas);
- test_compare(MEMCACHED_DATA_EXISTS, rc);
+ test_compare(MEMCACHED_DATA_EXISTS,
+ memcached_cas(memc,
+ test_literal_param(__func__),
+ test_literal_param("change the value"),
+ 0, 0, cas));
memcached_result_free(&results_obj);
static test_return_t prepend_test(memcached_st *memc)
{
- memcached_return_t rc;
const char *key= "fig";
const char *value= "people";
- char *out_value= NULL;
- size_t value_length;
- uint32_t flags;
- rc= memcached_flush(memc, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_flush(memc, 0));
- rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, key, strlen(key),
+ value, strlen(value),
+ time_t(0), uint32_t(0)));
- rc= memcached_prepend(memc, key, strlen(key),
- "the ", strlen("the "),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_prepend(memc, key, strlen(key),
+ "the ", strlen("the "),
+ time_t(0), uint32_t(0)));
- rc= memcached_prepend(memc, key, strlen(key),
- "we ", strlen("we "),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_prepend(memc, key, strlen(key),
+ "we ", strlen("we "),
+ time_t(0), uint32_t(0)));
- out_value= memcached_get(memc, key, strlen(key),
+ size_t value_length;
+ uint32_t flags;
+ memcached_return_t rc;
+ char *out_value= memcached_get(memc, key, strlen(key),
&value_length, &flags, &rc);
test_memcmp(out_value, "we the people", strlen("we the people"));
test_compare(strlen("we the people"), value_length);
*/
static test_return_t add_test(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "foo";
- const char *value= "when we sanitize";
- unsigned long long setting_value;
-
- setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK);
+ test_compare_hint(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ test_literal_param("when we sanitize"),
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
- rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
memcached_quit(memc);
- rc= memcached_add(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
- if (setting_value)
- {
- test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED);
- }
- else
- {
- test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_DATA_EXISTS);
- }
+ test_compare_hint(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_DATA_EXISTS : MEMCACHED_NOTSTORED,
+ memcached_add(memc,
+ test_literal_param(__func__),
+ test_literal_param("try something else"),
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
return TEST_SUCCESS;
}
static test_return_t replace_test(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "foo";
- const char *value= "when we sanitize";
- const char *original= "first we insert some data";
-
- rc= memcached_set(memc, key, strlen(key),
- original, strlen(original),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ test_literal_param("when we sanitize"),
+ time_t(0), uint32_t(0)));
test_compare(MEMCACHED_SUCCESS,
- memcached_replace(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0));
+ memcached_replace(memc,
+ test_literal_param(__func__),
+ test_literal_param("first we insert some data"),
+ time_t(0), uint32_t(0)));
return TEST_SUCCESS;
}
static test_return_t delete_test(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "foo";
- const char *value= "when we sanitize";
-
- rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ test_literal_param("when we sanitize"),
+ time_t(0), uint32_t(0)));
- rc= memcached_delete(memc, key, strlen(key), (time_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_compare_hint(return_value_based_on_buffering(memc),
+ memcached_delete(memc,
+ test_literal_param(__func__),
+ time_t(0)),
+ memcached_last_error_message(memc));
return TEST_SUCCESS;
}
return TEST_SUCCESS;
}
-static memcached_return_t server_function(const memcached_st *ptr,
- const memcached_server_st *server,
- void *context)
+static memcached_return_t server_function(const memcached_st *,
+ const memcached_server_st *,
+ void *)
{
- (void)ptr; (void)server; (void)context;
/* Do Nothing */
-
return MEMCACHED_SUCCESS;
}
memcached_return_t rc;
const char *key= "foo bad";
uint32_t flags;
- memcached_st *memc_clone;
uint64_t query_id= memcached_query_id(memc);
test_compare(query_id, memcached_query_id(memc)); // We should not increase the query_id for memcached_behavior_get()
- memc_clone= memcached_clone(NULL, memc);
+ memcached_st *memc_clone= memcached_clone(NULL, memc);
test_true(memc_clone);
query_id= memcached_query_id(memc_clone);
static test_return_t read_through(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "foo";
- char *string;
- size_t string_length;
- uint32_t flags;
memcached_trigger_key_fn cb= (memcached_trigger_key_fn)read_through_trigger;
- string= memcached_get(memc, key, strlen(key),
- &string_length, &flags, &rc);
+ size_t string_length;
+ uint32_t flags;
+ memcached_return_t rc;
+ char *string= memcached_get(memc,
+ test_literal_param(__func__),
+ &string_length, &flags, &rc);
test_compare(MEMCACHED_NOTFOUND, rc);
test_false(string_length);
test_false(string);
- rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_GET_FAILURE, *(void **)&cb);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_callback_set(memc, MEMCACHED_CALLBACK_GET_FAILURE, *(void **)&cb));
- string= memcached_get(memc, key, strlen(key),
+ string= memcached_get(memc,
+ test_literal_param(__func__),
&string_length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_strcmp(READ_THROUGH_VALUE, string);
free(string);
- string= memcached_get(memc, key, strlen(key),
+ string= memcached_get(memc,
+ test_literal_param(__func__),
&string_length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
static test_return_t get_test(memcached_st *memc)
{
memcached_return_t rc;
- const char *key= "foo";
char *string;
size_t string_length;
uint32_t flags;
uint64_t query_id= memcached_query_id(memc);
- rc= memcached_delete(memc, key, strlen(key), (time_t)0);
- test_true(rc == MEMCACHED_BUFFERED || rc == MEMCACHED_NOTFOUND);
+ rc= memcached_delete(memc,
+ test_literal_param(__func__),
+ time_t(0));
+ test_true_got(rc == MEMCACHED_BUFFERED or rc == MEMCACHED_NOTFOUND, memcached_last_error_message(memc));
test_compare(query_id +1, memcached_query_id(memc));
- string= memcached_get(memc, key, strlen(key),
+ string= memcached_get(memc,
+ test_literal_param(__func__),
&string_length, &flags, &rc);
test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_strerror(NULL, rc));
static test_return_t get_test2(memcached_st *memc)
{
- const char *key= "foo";
const char *value= "when we sanitize";
uint64_t query_id= memcached_query_id(memc);
- memcached_return_t rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ value, strlen(value),
+ time_t(0), uint32_t(0)));
test_compare(query_id +1, memcached_query_id(memc));
query_id= memcached_query_id(memc);
uint32_t flags;
size_t string_length;
- char *string= memcached_get(memc, key, strlen(key),
+ memcached_return_t rc;
+ char *string= memcached_get(memc,
+ test_literal_param(__func__),
&string_length, &flags, &rc);
test_compare(query_id +1, memcached_query_id(memc));
{
for (uint32_t x= 0; x < 10; x++)
{
- memcached_return_t rc= memcached_set(memc,
- test_literal_param("foo"),
- test_literal_param("train in the brain"),
- time_t(0), uint32_t(0));
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param("foo"),
+ test_literal_param("train in the brain"),
+ time_t(0), uint32_t(0)));
}
return TEST_SUCCESS;
snprintf(key, sizeof(key), "foo%u", x);
uint64_t query_id= memcached_query_id(memc);
- memcached_return_t rc= memcached_set(memc, key, strlen(key),
- &value[0], value.size(),
- (time_t)0, (uint32_t)0);
- test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+ test_compare_hint(return_value_based_on_buffering(memc),
+ memcached_set(memc, key, strlen(key),
+ &value[0], value.size(),
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
test_compare(query_id +1, memcached_query_id(memc));
}
static test_return_t get_test3(memcached_st *memc)
{
- const char *key= "foo";
size_t value_length= 8191;
std::vector<char> value;
value.push_back(char(x % 127));
}
- memcached_return_t rc;
- rc= memcached_set(memc, key, strlen(key),
- &value[0], value.size(),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare_hint(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ &value[0], value.size(),
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
size_t string_length;
uint32_t flags;
- char *string= memcached_get(memc, key, strlen(key),
+ memcached_return_t rc;
+ char *string= memcached_get(memc,
+ test_literal_param(__func__),
&string_length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_true(string);
- test_compare(string_length, value_length);
+ test_compare(value.size(), string_length);
test_memcmp(string, &value[0], string_length);
free(string);
static test_return_t get_test4(memcached_st *memc)
{
- const char *key= "foo";
size_t value_length= 8191;
std::vector<char> value;
value.push_back(char(x % 127));
}
- memcached_return_t rc= memcached_set(memc, key, strlen(key),
- &value[0], value.size(),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare_hint(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ &value[0], value.size(),
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
for (uint32_t x= 0; x < 10; x++)
{
uint32_t flags;
size_t string_length;
- char *string= memcached_get(memc, key, strlen(key),
+ memcached_return_t rc;
+ char *string= memcached_get(memc,
+ test_literal_param(__func__),
&string_length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_true(string);
- test_compare(string_length, value_length);
+ test_compare(value.size(), string_length);
test_memcmp(string, &value[0], string_length);
free(string);
}
uint32_t flags;
size_t rlen;
- memcached_return_t rc= memcached_set(memc, keys[0], lengths[0],
- keys[0], lengths[0], 0, 0);
+ test_compare_hint(return_value_based_on_buffering(memc),
+ memcached_set(memc, keys[0], lengths[0],
+ keys[0], lengths[0],
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys)));
memcached_result_st results_obj;
memcached_result_st *results= memcached_result_create(memc, &results_obj);
test_true(results);
+ memcached_return_t rc;
results= memcached_fetch_result(memc, &results_obj, &rc);
test_true(results);
size_t lengths[]= { 3, 4 };
const char *values[]= { "fjord", "41" };
- memcached_return_t rc;
-
// Set foo and foo2
for (size_t x= 0; x < test_array_length(keys); x++)
{
- test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[x], lengths[x], values[x], strlen(values[x]), (time_t)0, (uint32_t)0));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ keys[x], lengths[x],
+ values[x], strlen(values[x]),
+ time_t(0), uint32_t(0)));
}
char *string;
uint32_t flags;
// retrieve both via mget
- test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys)));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_mget(memc,
+ keys, lengths,
+ test_array_length(keys)));
char key[MEMCACHED_MAX_KEY];
size_t key_length;
+ memcached_return_t rc;
// this should get both
for (size_t x= 0; x < test_array_length(keys); x++)
test_null(string);
// now get just one
- rc= memcached_mget(memc, keys, lengths, 1);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_mget(memc, keys, lengths, 1));
string= memcached_fetch(memc, key, &key_length, &string_length, &flags, &rc);
test_compare(key_length, lengths[0]);
static test_return_t decrement_test(memcached_st *memc)
{
- uint64_t new_number;
- memcached_return_t rc;
- const char *value= "3";
-
- rc= memcached_set(memc,
- test_literal_param("number"),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ test_literal_param("3"),
+ time_t(0), uint32_t(0)));
+ // Make sure we flush the value we just set
+ test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+ uint64_t new_number;
test_compare(MEMCACHED_SUCCESS,
memcached_decrement(memc,
- test_literal_param("number"),
+ test_literal_param(__func__),
1, &new_number));
test_compare(uint64_t(2), new_number);
test_compare(MEMCACHED_SUCCESS,
memcached_decrement(memc,
- test_literal_param("number"),
+ test_literal_param(__func__),
1, &new_number));
test_compare(uint64_t(1), new_number);
{
test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
- uint64_t new_number;
uint64_t initial= 3;
test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+ uint64_t new_number;
test_compare(MEMCACHED_SUCCESS,
memcached_decrement_with_initial(memc,
- test_literal_param("number"),
- 1, initial, 0, &new_number));
+ test_literal_param(__func__),
+ 1, initial,
+ 0, &new_number));
test_compare(new_number, initial);
test_compare(MEMCACHED_SUCCESS,
memcached_decrement_with_initial(memc,
- test_literal_param("number"),
- 1, initial, 0, &new_number));
+ test_literal_param(__func__),
+ 1, initial,
+ 0, &new_number));
test_compare(new_number, (initial - 1));
return TEST_SUCCESS;
static test_return_t increment_by_key_test(memcached_st *memc)
{
- uint64_t new_number;
- memcached_return_t rc;
const char *master_key= "foo";
const char *key= "number";
const char *value= "0";
- rc= memcached_set_by_key(memc, master_key, strlen(master_key),
- key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set_by_key(memc, master_key, strlen(master_key),
+ key, strlen(key),
+ value, strlen(value),
+ time_t(0), uint32_t(0)));
+
+ // Make sure we flush the value we just set
+ test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+ uint64_t new_number;
test_compare(MEMCACHED_SUCCESS,
- memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), 1, &new_number));
+ memcached_increment_by_key(memc, master_key, strlen(master_key),
+ key, strlen(key), 1, &new_number));
test_compare(uint64_t(1), new_number);
test_compare(MEMCACHED_SUCCESS,
- memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), 1, &new_number));
+ memcached_increment_by_key(memc, master_key, strlen(master_key),
+ key, strlen(key), 1, &new_number));
test_compare(uint64_t(2), new_number);
return TEST_SUCCESS;
test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
uint64_t new_number;
- memcached_return_t rc;
const char *master_key= "foo";
const char *key= "number";
uint64_t initial= 0;
- rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
- key, strlen(key),
- 1, initial, 0, &new_number);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
+ key, strlen(key),
+ 1, initial, 0, &new_number));
test_compare(new_number, initial);
- rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
- key, strlen(key),
- 1, initial, 0, &new_number);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
+ key, strlen(key),
+ 1, initial, 0, &new_number));
test_compare(new_number, (initial +1));
return TEST_SUCCESS;
static test_return_t decrement_by_key_test(memcached_st *memc)
{
uint64_t new_number;
- memcached_return_t rc;
const char *value= "3";
- rc= memcached_set_by_key(memc,
- test_literal_param("foo"),
- test_literal_param("number"),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set_by_key(memc,
+ test_literal_param("foo"),
+ test_literal_param("number"),
+ value, strlen(value),
+ (time_t)0, (uint32_t)0));
test_compare(MEMCACHED_SUCCESS,
memcached_decrement_by_key(memc,
test_compare(MEMCACHED_SUCCESS, memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)"namespace:"));
- memcached_return_t rc;
- rc= memcached_set(memc,
- test_literal_param("number"),
- test_literal_param("0"),
- (time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param("number"),
+ test_literal_param("0"),
+ (time_t)0, (uint32_t)0));
uint64_t new_number;
test_compare(MEMCACHED_SUCCESS, memcached_increment(memc,
static test_return_t quit_test(memcached_st *memc)
{
- memcached_return_t rc;
- const char *key= "fudge";
const char *value= "sanford and sun";
- rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)10, (uint32_t)3);
- test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ value, strlen(value),
+ (time_t)10, (uint32_t)3));
memcached_quit(memc);
- rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)50, (uint32_t)9);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc,
+ test_literal_param(__func__),
+ value, strlen(value),
+ (time_t)50, (uint32_t)9));
return TEST_SUCCESS;
}
size_t counter;
memcached_execute_fn callbacks[1];
- /* We need to empty the server before continueing test */
- test_compare(MEMCACHED_SUCCESS,
- memcached_flush(memc, 0));
for (uint32_t x= 0; x < 3; x++)
{
- memcached_return_t rc= memcached_set(memc, keys[x], key_length[x],
- keys[x], key_length[x],
- (time_t)50, (uint32_t)9);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_compare(return_value_based_on_buffering(memc),
+ memcached_set(memc, keys[x], key_length[x],
+ keys[x], key_length[x],
+ time_t(50), uint32_t(9)));
}
+ test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+ memcached_quit(memc);
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 3));
char *return_value;
size_t return_value_length;
- /* We need to empty the server before continueing test */
- test_compare(MEMCACHED_SUCCESS,
- memcached_flush(memc, 0));
-
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 3));
return TEST_SUCCESS;
}
-static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned, const memcached_return_t expect)
+static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned, memcached_return_t& rc)
{
- memcached_return_t rc;
- char return_key[MEMCACHED_MAX_KEY];
- size_t return_key_length;
- char *return_value;
- size_t return_value_length;
- uint32_t flags;
-
keys_returned= 0;
- while ((return_value= memcached_fetch(memc, return_key, &return_key_length,
- &return_value_length, &flags, &rc)))
+
+ memcached_result_st* result= NULL;
+ while ((result= memcached_fetch_result(memc, result, &rc)))
{
- test_true(return_value);
- test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
- free(return_value);
+ test_compare(MEMCACHED_SUCCESS, rc);
keys_returned+= 1;
}
+ memcached_result_free(result);
- if (memcached_success(expect) and memcached_success(rc))
- {
- return TEST_SUCCESS;
- }
- else if (expect == rc)
- {
- return TEST_SUCCESS;
- }
- fprintf(stderr, "\n%s:%u %s(#%u)\n", __FILE__, __LINE__, memcached_strerror(NULL, rc), keys_returned);
+ return TEST_SUCCESS;
+}
- return TEST_FAILURE;
+static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned)
+{
+ memcached_return_t rc;
+ return fetch_all_results(memc, keys_returned, rc);
}
/* Test case provided by Cal Haldenbrand */
}
total+= size;
- char key[22];
+ char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
int key_length= snprintf(key, sizeof(key), "%u", x);
test_compare(MEMCACHED_SUCCESS,
- memcached_set(memc, key, key_length, randomstuff, strlen(randomstuff), time_t(0), HALDENBRAND_FLAG_KEY));
+ memcached_set(memc, key, key_length,
+ randomstuff, strlen(randomstuff),
+ time_t(0), HALDENBRAND_FLAG_KEY));
}
test_true(total > HALDENBRAND_KEY_COUNT);
continue;
}
test_compare(uint32_t(HALDENBRAND_FLAG_KEY), flags);
+ test_true(getval);
total_value_length+= val_len;
errors= 0;
- free(getval);
+ ::free(getval);
}
return TEST_SUCCESS;
/* Do a large mget() over all the keys we think exist */
static test_return_t user_supplied_bug3(memcached_st *memc)
{
- test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1));
- test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1));
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, true));
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true));
#ifdef NOT_YET
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE, 20 * 1024576);
memcached_mget(memc, &keys[0], &key_lengths[0], key_lengths.size()));
unsigned int keys_returned;
- test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS));
+ test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned));
test_compare(HALDENBRAND_KEY_COUNT, keys_returned);
for (std::vector<char *>::iterator iter= keys.begin();
iter != keys.end();
iter++)
{
- free(*iter);
+ ::free(*iter);
}
return TEST_SUCCESS;
test_compare(MEMCACHED_NO_SERVERS,
memcached_mget(memc, keys, key_length, 3));
- unsigned int keys_returned;
- test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_NOTFOUND));
- test_zero(keys_returned);
+ {
+ unsigned int keys_returned;
+ memcached_return_t rc;
+ test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, rc));
+ test_compare(MEMCACHED_NOTFOUND, rc);
+ test_zero(keys_returned);
+ }
for (uint32_t x= 0; x < 3; x++)
{
memcached_mget(memc, keys, key_length, 4));
unsigned int count;
- test_compare(TEST_SUCCESS, fetch_all_results(memc, count, MEMCACHED_NOTFOUND));
+ test_compare(TEST_SUCCESS, fetch_all_results(memc, count, rc));
+ test_compare(MEMCACHED_NOTFOUND, rc);
test_zero(count);
for (uint32_t x= 0; x < 4; x++)
&value_length, &flags, &rc);
test_compare(rc, MEMCACHED_SUCCESS);
test_true(value);
- free(value);
+ ::free(value);
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 4));
- test_compare(TEST_SUCCESS, fetch_all_results(memc, count, MEMCACHED_SUCCESS));
+ test_compare(TEST_SUCCESS, fetch_all_results(memc, count));
test_compare(4U, count);
}
delete [] insert_data;
/* Test flag store/retrieve */
static test_return_t user_supplied_bug7(memcached_st *memc)
{
- const char *keys= "036790384900";
- size_t key_length= strlen(keys);
- char return_key[MEMCACHED_MAX_KEY];
- size_t return_key_length;
- char *value;
- size_t value_length;
- uint32_t flags;
char *insert_data= new (std::nothrow) char[VALUE_SIZE_BUG5];
+ test_true(insert_data);
- for (unsigned int x= 0; x < VALUE_SIZE_BUG5; x++)
+ for (size_t x= 0; x < VALUE_SIZE_BUG5; x++)
{
insert_data[x]= (signed char)rand();
}
memcached_flush(memc, 0);
- flags= 245;
- test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys, key_length,
- insert_data, VALUE_SIZE_BUG5,
- (time_t)0, flags));
+ const char *keys= "036790384900";
+ size_t key_length= strlen(keys);
+ test_compare_hint(MEMCACHED_SUCCESS, memcached_set(memc, keys, key_length,
+ insert_data, VALUE_SIZE_BUG5,
+ time_t(0), 245U),
+ memcached_last_error_message(memc));
memcached_return_t rc;
- flags= 0;
- value= memcached_get(memc, keys, key_length,
- &value_length, &flags, &rc);
+ size_t value_length;
+ uint32_t flags= 0;
+ char *value= memcached_get(memc, keys, key_length,
+ &value_length, &flags, &rc);
test_compare(245U, flags);
test_true(value);
free(value);
test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, &keys, &key_length, 1));
+ char return_key[MEMCACHED_MAX_KEY];
+ size_t return_key_length;
flags= 0;
value= memcached_fetch(memc, return_key, &return_key_length,
&value_length, &flags, &rc);
/* Check the return sizes on FLAGS to make sure it stores 32bit unsigned values correctly */
static test_return_t user_supplied_bug16(memcached_st *memc)
{
- memcached_return_t rc= memcached_set(memc, test_literal_param("mykey"),
- NULL, 0,
- (time_t)0, UINT32_MAX);
+ test_compare_hint(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("mykey"),
+ NULL, 0,
+ (time_t)0, UINT32_MAX),
+ memcached_last_error_message(memc));
- test_compare(MEMCACHED_SUCCESS, rc);
size_t length;
uint32_t flags;
+ memcached_return_t rc;
char *value= memcached_get(memc, test_literal_param("mykey"),
&length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
- test_true(value == NULL);
+ test_null(value);
test_zero(length);
test_compare(flags, UINT32_MAX);
{
unsigned int check_execute= execute_set(memc, global_pairs, global_count);
- test_compare(check_execute, global_count);
+ test_compare_warn_hint(global_count, check_execute, "Possible false, positive, memcached may have ejected key/value based on memory needs");
return TEST_SUCCESS;
}
static test_return_t get_read(memcached_st *memc)
{
+ size_t keys_returned= 0;
for (size_t x= 0; x < global_count; x++)
{
size_t return_value_length;
*/
if (rc == MEMCACHED_SUCCESS && return_value)
{
+ keys_returned++;
free(return_value);
}
}
+ test_compare_warn_hint(global_count, keys_returned, "Possible false, positive, memcached may have ejected key/value based on memory needs");
return TEST_SUCCESS;
}
// Go fetch the keys and test to see if all of them were returned
{
unsigned int keys_returned;
- test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS));
+ test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned));
test_true(keys_returned > 0);
test_compare_warn_hint(global_count, keys_returned, "Possible false, positive, memcached may have ejected key/value based on memory needs");
}
static test_return_t delete_generate(memcached_st *memc)
{
+ size_t total= 0;
for (size_t x= 0; x < global_count; x++)
{
- (void)memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0);
+ if (memcached_success(memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0)))
+ {
+ total++;
+ }
}
+ test_compare_warn_hint(global_count, total, "Possible false, positive, memcached may have ejected key/value based on memory needs");
return TEST_SUCCESS;
}
{
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true);
+ size_t total= 0;
for (size_t x= 0; x < global_count; x++)
{
- (void)memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0);
+ if (memcached_success(memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0)))
+ {
+ total++;
+ }
}
+ test_compare_warn_hint(global_count, total, "Possible false, positive, memcached may have ejected key/value based on memory needs");
return TEST_SUCCESS;
}
static test_return_t noreply_test(memcached_st *memc)
{
test_compare(MEMCACHED_SUCCESS,
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1));
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, true));
test_compare(MEMCACHED_SUCCESS,
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1));
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true));
test_compare(MEMCACHED_SUCCESS,
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1));
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true));
test_compare(1LLU, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NOREPLY));
test_compare(1LLU, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS));
test_compare(1LLU, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS));
memcached_return_t rc= memcached_stat_execute(memc, NULL, stat_printer, NULL);
test_compare(MEMCACHED_SUCCESS, rc);
- rc= memcached_stat_execute(memc, "slabs", stat_printer, NULL);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, "slabs", stat_printer, NULL));
- rc= memcached_stat_execute(memc, "items", stat_printer, NULL);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, "items", stat_printer, NULL));
- rc= memcached_stat_execute(memc, "sizes", stat_printer, NULL);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, "sizes", stat_printer, NULL));
return TEST_SUCCESS;
}
rc= memcached_set(memc, key, strlen(key),
value, strlen(value),
(time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
instance= memcached_server_instance_by_position(memc, 0);
*/
static test_return_t wrong_failure_counter_two_test(memcached_st *memc)
{
- memcached_return rc;
-
- memcached_st *memc_clone;
- memc_clone= memcached_clone(NULL, memc);
- test_true(memc_clone);
-
/* Set value to force connection to the server */
const char *key= "marmotte";
const char *value= "milka";
- char *string = NULL;
- size_t string_length;
- uint32_t flags;
- rc= memcached_set(memc_clone, key, strlen(key),
- value, strlen(value),
- (time_t)0, (uint32_t)0);
- test_true_got(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+ test_compare_hint(MEMCACHED_SUCCESS,
+ memcached_set(memc, key, strlen(key),
+ value, strlen(value),
+ (time_t)0, (uint32_t)0),
+ memcached_last_error_message(memc));
/* put failure limit to 1 */
test_compare(MEMCACHED_SUCCESS,
- memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 1));
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, true));
/* Put a retry timeout to effectively activate failure_limit effect */
test_compare(MEMCACHED_SUCCESS,
- memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 1));
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, true));
/* change behavior that triggers memcached_quit()*/
test_compare(MEMCACHED_SUCCESS,
- memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1));
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true));
/* Check if we still are connected */
- string= memcached_get(memc_clone, key, strlen(key),
- &string_length, &flags, &rc);
+ uint32_t flags;
+ size_t string_length;
+ memcached_return rc;
+ char *string= memcached_get(memc, key, strlen(key),
+ &string_length, &flags, &rc);
test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
test_true(string);
free(string);
- memcached_free(memc_clone);
return TEST_SUCCESS;
}
-
-
/*
* Test that ensures mget_execute does not end into recursive calls that finally fails
*/
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);
}
-/* libMemcached Functions Test
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
+/* 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.
*
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
*/
+
/*
Sample test application.
*/
#include <libmemcached-1.0/memcached.h>
#include <libmemcached/server_instance.h>
#include <libmemcached/io.h>
+#include <libmemcached/udp.hpp>
#include <libmemcachedutil-1.0/util.h>
#include <cassert>
return TEST_SUCCESS;
}
+static test_return_t init_udp_valgrind(memcached_st *memc)
+{
+ if (getenv("TESTS_ENVIRONMENT"))
+ {
+ return TEST_SKIPPED;
+ }
+
+ test_skip(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, true));
+
+ return TEST_SUCCESS;
+}
+
static test_return_t binary_init_udp(memcached_st *memc)
{
+ if (getenv("TESTS_ENVIRONMENT"))
+ {
+ return TEST_SKIPPED;
+ }
+
test_skip(TEST_SUCCESS, pre_binary(memc));
return init_udp(memc);
return TEST_SUCCESS;
}
+static test_return_t version_TEST(memcached_st *memc)
+{
+ test_compare(MEMCACHED_NOT_SUPPORTED, memcached_version(memc));
+ return TEST_SUCCESS;
+}
+
+static test_return_t verbosity_TEST(memcached_st *memc)
+{
+ test_compare(MEMCACHED_SUCCESS, memcached_verbosity(memc, 0));
+ return TEST_SUCCESS;
+}
+
+static test_return_t memcached_get_TEST(memcached_st *memc)
+{
+ memcached_return_t rc;
+ test_null(memcached_get(memc,
+ test_literal_param(__func__),
+ 0, 0, &rc));
+ test_compare(MEMCACHED_NOT_SUPPORTED, rc);
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t memcached_mget_execute_by_key_TEST(memcached_st *memc)
+{
+ char **keys= NULL;
+ size_t *key_length= NULL;
+ test_compare(MEMCACHED_NOT_SUPPORTED,
+ memcached_mget_execute_by_key(memc,
+ test_literal_param(__func__), // Group key
+ keys, key_length, // Actual key
+ 0, // Number of keys
+ 0, // callbacks
+ 0, // context
+ 0)); // Number of callbacks
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t memcached_stat_TEST(memcached_st *memc)
+{
+ memcached_return_t rc;
+ test_null(memcached_stat(memc, 0, &rc));
+ test_compare(MEMCACHED_NOT_SUPPORTED, rc);
+
+ return TEST_SUCCESS;
+}
+
static test_return_t set_udp_behavior_test(memcached_st *memc)
{
memcached_quit(memc);
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution));
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, true));
- test_true(memc->flags.use_udp);
- test_true(memc->flags.no_reply);
+ test_compare(true, memc->flags.use_udp);
+ test_compare(false, memc->flags.reply);
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, false));
- test_false(memc->flags.use_udp);
+ test_compare(false, memc->flags.use_udp);
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, false));
- test_false(memc->flags.no_reply);
+ test_compare(true, memc->flags.reply);
return TEST_SUCCESS;
}
static test_return_t udp_set_test(memcached_st *memc)
{
- unsigned int num_iters= 1025; //request id rolls over at 1024
+ // Assume we are running under valgrind, and bail
+ if (getenv("TESTS_ENVIRONMENT"))
+ {
+ return TEST_SUCCESS;
+ }
+
+ const unsigned int num_iters= 1025; //request id rolls over at 1024
test_true(memc);
memcached_server_instance_st instance= memcached_server_instance_by_position(memc, server_key);
size_t init_offset= instance->write_buffer_offset;
- memcached_return_t rc= memcached_set(memc, test_literal_param("foo"),
- test_literal_param("when we sanitize"),
- time_t(0), uint32_t(0));
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
- /** NB, the check below assumes that if new write_ptr is less than
- * the original write_ptr that we have flushed. For large payloads, this
- * maybe an invalid assumption, but for the small payload we have it is OK
- */
- if (rc == MEMCACHED_SUCCESS or instance->write_buffer_offset < init_offset)
+ test_compare_hint(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param("foo"),
+ test_literal_param("when we sanitize"),
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
+
+ /*
+ NB, the check below assumes that if new write_ptr is less than
+ the original write_ptr that we have flushed. For large payloads, this
+ maybe an invalid assumption, but for the small payload we have it is OK
+ */
+ if (instance->write_buffer_offset < init_offset)
{
increment_request_id(&expected_ids[server_key]);
}
- if (rc == MEMCACHED_SUCCESS)
- {
- test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
- }
- else
- {
- test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH);
- test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH);
- }
-
test_compare(TEST_SUCCESS, post_udp_op_check(memc, expected_ids));
}
static test_return_t udp_buffered_set_test(memcached_st *memc)
{
test_true(memc);
- test_compare(MEMCACHED_INVALID_ARGUMENTS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true));
+ test_compare(MEMCACHED_INVALID_ARGUMENTS,
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true));
return TEST_SUCCESS;
}
static test_return_t udp_set_too_big_test(memcached_st *memc)
{
test_true(memc);
- char value[MAX_UDP_DATAGRAM_LENGTH];
Expected expected_ids;
get_udp_request_ids(memc, expected_ids);
- memset(value, int('f'), sizeof(value));
+ std::vector<char> value;
+ value.resize(1024 * 1024 * 10);
- test_compare_hint(MEMCACHED_WRITE_FAILURE, memcached_set(memc, test_literal_param("bar"), value, sizeof(value), time_t(0), uint32_t(0)),
+ test_compare_hint(MEMCACHED_WRITE_FAILURE,
+ memcached_set(memc,
+ test_literal_param(__func__),
+ &value[0], value.size(),
+ time_t(0), uint32_t(0)),
memcached_last_error_message(memc));
+ memcached_quit(memc);
return post_udp_op_check(memc, expected_ids);
}
memcached_server_instance_st instance= memcached_server_instance_by_position(memc, server_key);
size_t init_offset= instance->write_buffer_offset;
- memcached_return_t rc= memcached_delete(memc, test_literal_param("foo"), 0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_delete(memc, test_literal_param("foo"), 0));
- if (rc == MEMCACHED_SUCCESS or instance->write_buffer_offset < init_offset)
+ if (instance->write_buffer_offset < init_offset)
{
increment_request_id(&expected_ids[server_key]);
}
- if (rc == MEMCACHED_SUCCESS)
- {
- test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
- }
- else
- {
- test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH);
- test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH);
- }
test_compare(TEST_SUCCESS, post_udp_op_check(memc, expected_ids));
}
{
increment_request_id(&expected_ids[x]);
}
+ memcached_error_print(memc);
test_compare_hint(MEMCACHED_SUCCESS, memcached_flush(memc, 0), memcached_last_error_message(memc));
return post_udp_op_check(memc, expected_ids);
static test_return_t udp_incr_test(memcached_st *memc)
{
- test_compare(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("incr"),
- test_literal_param("1"),
- (time_t)0, (uint32_t)0));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, test_literal_param("incr"),
+ test_literal_param("1"),
+ (time_t)0, (uint32_t)0));
Expected expected_ids;
get_udp_request_ids(memc, expected_ids);
static test_return_t udp_decr_test(memcached_st *memc)
{
- test_compare(MEMCACHED_SUCCESS, memcached_set(memc,
- test_literal_param("decr"),
- test_literal_param("1"),
- (time_t)0, (uint32_t)0));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param(__func__),
+ test_literal_param("1"),
+ (time_t)0, (uint32_t)0));
Expected expected_ids;
get_udp_request_ids(memc, expected_ids);
- unsigned int server_key= memcached_generate_hash(memc, test_literal_param("decr"));
+ unsigned int server_key= memcached_generate_hash(memc,
+ test_literal_param(__func__));
increment_request_id(&expected_ids[server_key]);
uint64_t newvalue;
- test_compare(MEMCACHED_SUCCESS, memcached_decrement(memc, test_literal_param("decr"), 1, &newvalue));
+ test_compare(MEMCACHED_SUCCESS, memcached_decrement(memc,
+ test_literal_param(__func__),
+ 1, &newvalue));
return post_udp_op_check(memc, expected_ids);
}
Expected expected_ids;
get_udp_request_ids(memc, expected_ids);
- test_compare(MEMCACHED_NOT_SUPPORTED, memcached_version(memc));
+ test_compare(MEMCACHED_NOT_SUPPORTED,
+ memcached_version(memc));
return post_udp_op_check(memc, expected_ids);
}
return TEST_SUCCESS;
}
+test_st compatibility_TESTS[] ={
+ {"version", 0, (test_callback_fn*)version_TEST },
+ {"version", 0, (test_callback_fn*)verbosity_TEST },
+ {"memcached_get()", 0, (test_callback_fn*)memcached_get_TEST },
+ {"memcached_mget_execute_by_key()", 0, (test_callback_fn*)memcached_mget_execute_by_key_TEST },
+ {"memcached_stat()", 0, (test_callback_fn*)memcached_stat_TEST },
+ {0, 0, 0}
+};
+
test_st udp_setup_server_tests[] ={
{"set_udp_behavior_test", 0, (test_callback_fn*)set_udp_behavior_test},
{"add_tcp_server_udp_client_test", 0, (test_callback_fn*)add_tcp_server_udp_client_test},
collection_st collection[] ={
{"udp_setup", (test_callback_fn*)init_udp, 0, udp_setup_server_tests},
- {"udp_io", (test_callback_fn*)init_udp, 0, upd_io_tests},
+ {"compatibility", (test_callback_fn*)init_udp, 0, compatibility_TESTS},
+ {"udp_io", (test_callback_fn*)init_udp_valgrind, 0, upd_io_tests},
{"udp_binary_io", (test_callback_fn*)binary_init_udp, 0, upd_io_tests},
{0, 0, 0, 0}
};
switch(errno)
{
default:
- std::cerr << "Failed during send(" << strerror(errno) << ")" << std::endl;
+ std::cerr << "Failed dureng send(" << strerror(errno) << ")" << std::endl;
break;
}
}