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_DEFINE([HAVE_CXXABI_H], [1], [Have cxxabi.h]),
+ AC_DEFINE([HAVE_CXXABI_H], [0], [Have cxxabi.h]))
+
+AX_COMPILER_VENDOR
AC_CXX_HEADER_STDCXX_98
+AX_TLS
AC_FUNC_ALLOCA
AC_FUNC_ERROR_AT_LINE
AC_CHECK_LIB([rt], [clock_gettime],
[
- rt_lib="-lrt"
+ RT_LIB="-lrt"
+ AC_SUBST(RT_LIB)
AC_DEFINE([HAVE_LIBRT], [ 1 ], [Have clock_gettime])
],
[
static inline bool memcached_fatal(memcached_return_t rc)
{
- return (rc != MEMCACHED_SUCCESS &&
+ return (
+ rc != MEMCACHED_BUFFERED &&
+ rc != MEMCACHED_DATA_EXISTS &&
+ rc != MEMCACHED_DELETED &&
+ rc != MEMCACHED_E2BIG &&
rc != MEMCACHED_END &&
- rc != MEMCACHED_STORED &&
+ rc != MEMCACHED_ITEM &&
+ rc != MEMCACHED_ERROR &&
+ rc != MEMCACHED_NOTFOUND &&
+ rc != MEMCACHED_NOTSTORED &&
+ rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE &&
rc != MEMCACHED_STAT &&
- rc != MEMCACHED_DELETED &&
- rc != MEMCACHED_BUFFERED &&
+ rc != MEMCACHED_STORED &&
+ rc != MEMCACHED_SUCCESS &&
rc != MEMCACHED_VALUE);
}
MEMCACHED_UNKNOWN_READ_FAILURE,
MEMCACHED_PROTOCOL_ERROR,
MEMCACHED_CLIENT_ERROR,
- MEMCACHED_SERVER_ERROR,
- MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE, // DEPRECATED
+ MEMCACHED_SERVER_ERROR, // Server returns "SERVER_ERROR"
+ MEMCACHED_ERROR, // Server returns "ERROR"
MEMCACHED_DATA_EXISTS,
MEMCACHED_DATA_DOES_NOT_EXIST,
MEMCACHED_NOTSTORED,
MEMCACHED_IN_PROGRESS,
MEMCACHED_SERVER_TEMPORARILY_DISABLED,
MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE,
- MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
+ MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */
+ MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE= MEMCACHED_ERROR
};
#ifndef __cplusplus
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
- {
- return rc;
- }
-
if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ return rc;
}
uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ return rc;
}
if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ return rc;
}
uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
- return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ return rc;
}
uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
extern "C" {
#endif
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_connect(memcached_server_write_instance_st ptr);
-
LIBMEMCACHED_LOCAL
memcached_return_t run_distribution(memcached_st *ptr);
return memcached_set_errno(*server, get_socket_errno(), MEMCACHED_AT);
}
-memcached_return_t set_hostinfo(memcached_server_st *server)
+static memcached_return_t set_hostinfo(memcached_server_st *server)
{
+ assert(server->type != MEMCACHED_CONNECTION_UNIX_SOCKET);
if (server->address_info)
{
freeaddrinfo(server->address_info);
return MEMCACHED_SUCCESS;
}
-memcached_return_t memcached_connect(memcached_server_write_instance_st server)
+static memcached_return_t _memcached_connect(memcached_server_write_instance_st server, const bool set_last_disconnected)
{
if (server->fd != INVALID_SOCKET)
{
return memcached_set_error(*server, MEMCACHED_INVALID_HOST_PROTOCOL, MEMCACHED_AT, memcached_literal_param("SASL is not supported for UDP connections"));
}
+ if (server->hostname[0] == '/')
+ {
+ server->type= MEMCACHED_CONNECTION_UNIX_SOCKET;
+ }
+
/* We need to clean up the multi startup piece */
switch (server->type)
{
memcached_mark_server_as_clean(server);
return rc;
}
-
- set_last_disconnected_host(server);
- if (memcached_has_current_error(*server))
+ else if (set_last_disconnected)
{
- memcached_mark_server_for_timeout(server);
- assert(memcached_failed(memcached_server_error_return(server)));
- }
- else
- {
- memcached_set_error(*server, rc, MEMCACHED_AT);
- memcached_mark_server_for_timeout(server);
- }
+ set_last_disconnected_host(server);
+ if (memcached_has_current_error(*server))
+ {
+ memcached_mark_server_for_timeout(server);
+ assert(memcached_failed(memcached_server_error_return(server)));
+ }
+ else
+ {
+ memcached_set_error(*server, rc, MEMCACHED_AT);
+ memcached_mark_server_for_timeout(server);
+ }
- LIBMEMCACHED_MEMCACHED_CONNECT_END();
+ LIBMEMCACHED_MEMCACHED_CONNECT_END();
- if (in_timeout)
- {
- return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT);
+ if (in_timeout)
+ {
+ char buffer[1024];
+ int snprintf_length= snprintf(buffer, sizeof(buffer), "%s:%d", server->hostname, int(server->port));
+ return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT, buffer, snprintf_length);
+ }
}
return rc;
}
+
+memcached_return_t memcached_connect_try(memcached_server_write_instance_st server)
+{
+ return _memcached_connect(server, false);
+}
+
+memcached_return_t memcached_connect(memcached_server_write_instance_st server)
+{
+ return _memcached_connect(server, true);
+}
#pragma once
-memcached_return_t set_hostinfo(memcached_server_st *server);
+memcached_return_t memcached_connect_try(memcached_server_write_instance_st ptr);
+memcached_return_t memcached_connect(memcached_server_write_instance_st ptr);
+
return rc;
}
- rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
- if (memcached_failed(rc))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
return rc;
}
msg.msg_iov= (struct iovec*)vector;
msg.msg_iovlen= count;
- if (::sendmsg(instance->fd, &msg, 0) < 1)
+ uint32_t retry= 5;
+ while (--retry)
{
- return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ ssize_t sendmsg_length= ::sendmsg(instance->fd, &msg, 0);
+ if (sendmsg_length > 0)
+ {
+ break;
+ }
+ else if (sendmsg_length < 0)
+ {
+ if (errno == EMSGSIZE)
+ {
+ return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ }
+
+ perror(__func__);
+ return memcached_set_errno(*instance, errno, MEMCACHED_AT);
+ }
}
return MEMCACHED_SUCCESS;
#include <libmemcached/common.h>
-static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
+static memcached_return_t ascii_dump(memcached_st *memc, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
{
- memcached_return_t rc= MEMCACHED_SUCCESS;
-
- for (uint32_t server_key= 0; server_key < memcached_server_count(ptr); server_key++)
+ /* MAX_NUMBER_OF_SLAB_CLASSES is defined to 200 in Memcached 1.4.10 */
+ for (uint32_t x= 0; x < 200; x++)
{
- memcached_server_write_instance_st instance;
- instance= memcached_server_instance_fetch(ptr, server_key);
-
- /* 256 I BELIEVE is the upper limit of slabs */
- for (uint32_t x= 0; x < 256; x++)
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
+ if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0)
{
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- 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)"));
- }
+ return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+ }
- libmemcached_io_vector_st vector[]=
- {
- { memcached_literal_param("stats cachedump ") },
- { buffer, buffer_length },
- { memcached_literal_param(" 0 0\r\n") }
- };
+ // @NOTE the hard coded zero means "no limit"
+ libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("stats cachedump ") },
+ { buffer, buffer_length },
+ { memcached_literal_param(" 0\r\n") }
+ };
- rc= memcached_vdo(instance, vector, 3, true);
+ // Send message to all servers
+ for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++)
+ {
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key);
- if (rc != MEMCACHED_SUCCESS)
+ memcached_return_t vdo_rc;
+ if (memcached_success((vdo_rc= memcached_vdo(instance, vector, 3, true))))
{
- goto error;
+ // We have sent the message to the server successfully
}
-
- while (1)
+ else
{
- uint32_t callback_counter;
- rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ return memcached_set_error(*instance, vdo_rc, MEMCACHED_AT);
+ }
+ }
- if (rc == MEMCACHED_ITEM)
- {
- char *string_ptr, *end_ptr;
+ // Collect the returned items
+ memcached_server_write_instance_st instance;
+ while ((instance= memcached_io_get_readable_server(memc)))
+ {
+ memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ if (response_rc == MEMCACHED_ITEM)
+ {
+ char *string_ptr, *end_ptr;
- string_ptr= buffer;
- string_ptr+= 5; /* Move past ITEM */
+ string_ptr= buffer;
+ string_ptr+= 5; /* Move past ITEM */
- for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ;
+ for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ;
- char *key= string_ptr;
- key[(size_t)(end_ptr-string_ptr)]= 0;
+ char *key= string_ptr;
+ key[(size_t)(end_ptr-string_ptr)]= 0;
- for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
+ for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
+ {
+ memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context);
+ if (callback_rc != MEMCACHED_SUCCESS)
{
- rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context);
- if (rc != MEMCACHED_SUCCESS)
- {
- break;
- }
+ // @todo build up a message for the error from the value
+ memcached_set_error(*instance, callback_rc, MEMCACHED_AT);
+ break;
}
}
- else if (rc == MEMCACHED_END)
- {
- break;
- }
- else if (rc == MEMCACHED_SERVER_ERROR or rc == MEMCACHED_CLIENT_ERROR)
- {
- /* If we try to request stats cachedump for a slab class that is too big
- * the server will return an incorrect error message:
- * "MEMCACHED_SERVER_ERROR failed to allocate memory"
- * 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;
- }
- else
- {
- goto error;
- }
+ }
+ else if (response_rc == MEMCACHED_END)
+ {
+ // All items have been returned
+ }
+ else if (response_rc == MEMCACHED_SERVER_ERROR or response_rc == MEMCACHED_CLIENT_ERROR or response_rc == MEMCACHED_ERROR)
+ {
+ /* If we try to request stats cachedump for a slab class that is too big
+ * the server will return an incorrect error message:
+ * "MEMCACHED_SERVER_ERROR failed to allocate memory"
+ * 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.
+ */
+ assert(response_rc == MEMCACHED_SUCCESS); // Just fail
+ return response_rc;
+ }
+ else
+ {
+ // IO error of some sort must have occurred
+ return memcached_set_error(*instance, response_rc, MEMCACHED_AT);
}
}
}
-error:
- if (rc == MEMCACHED_END)
- {
- return MEMCACHED_SUCCESS;
- }
- else
- {
- return rc;
- }
+ return memcached_has_current_error(*memc) ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
}
memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
No support for Binary protocol yet
@todo Fix this so that we just flush, switch to ascii, and then go back to binary.
*/
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
- return MEMCACHED_FAILURE;
+ return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, memcached_literal_param("Binary protocol is not supported for memcached_dump()"));
}
return ascii_dump(ptr, callback, context, number_of_callbacks);
server.error_messages= error;
}
+#if 0
+static int error_log_fd= -1;
+#endif
+
static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
{
if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
if (str and str->size and local_errno)
{
- error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s), %.*s -> %s",
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s(%s), %.*s -> %s",
+ long(error->root),
memcached_strerror(&memc, rc),
errmsg_ptr,
memcached_string_printf(*str), at);
}
else if (local_errno)
{
- error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s) -> %s",
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s(%s) -> %s",
+ long(error->root),
memcached_strerror(&memc, rc),
errmsg_ptr,
at);
}
else if (rc == MEMCACHED_PARSE_ERROR and str and str->size)
{
- error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%.*s -> %s",
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %.*s -> %s",
+ long(error->root),
int(str->size), str->c_str, at);
}
else if (str and str->size)
{
- error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s",
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s, %.*s -> %s",
+ long(error->root),
memcached_strerror(&memc, rc),
int(str->size), str->c_str, at);
}
else
{
- error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s",
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s -> %s",
+ long(error->root),
memcached_strerror(&memc, rc), at);
}
error->next= memc.error_messages;
memc.error_messages= error;
+
+#if 0
+ if (error_log_fd == -1)
+ {
+// unlink("/tmp/libmemcachd.log");
+ if ((error_log_fd= open("/tmp/libmemcachd.log", O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
+ {
+ perror("open");
+ error_log_fd= -1;
+ }
+ }
+ ::write(error_log_fd, error->message, error->size);
+ ::write(error_log_fd, "\n", 1);
+#endif
}
memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
- if (memcached_success(rc))
+ if (memcached_fatal(rc) == false)
{
return rc;
}
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
- if (memcached_success(rc))
+ if (memcached_fatal(rc) == false)
{
return rc;
}
memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at)
{
assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
- if (memcached_success(rc))
+ if (memcached_fatal(rc) == false)
{
return rc;
}
memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc, const char *at)
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
- if (memcached_success(rc))
+ if (memcached_fatal(rc) == false)
{
return rc;
}
memcached_string_t error_host= { hostname_port_message, size };
memcached_return_t rc= MEMCACHED_ERRNO;
- if (not self.root)
+ if (self.root == NULL)
+ {
return rc;
+ }
_set(*self.root, &error_host, rc, at, local_errno);
_set(self, (*self.root));
memcached_string_t error_host= { hostname_port_message, size };
memcached_return_t rc= MEMCACHED_ERRNO;
- if (not self.root)
+ if (self.root == NULL)
+ {
return rc;
+ }
_set(*self.root, &error_host, rc, at, local_errno);
_set(self, (*self.root));
}
if (not memc->error_messages)
+ {
return MEMCACHED_SUCCESS;
+ }
return memc->error_messages->rc;
}
}
if (not server->error_messages)
+ {
return memcached_strerror(server->root, MEMCACHED_SUCCESS);
+ }
if (not server->error_messages->size)
+ {
return memcached_strerror(server->root, server->error_messages->rc);
+ }
return server->error_messages->message;
}
};
/* Send command header */
- memcached_return_t rc= memcached_vdo(instance, vector, 9, true);
- if (rc == MEMCACHED_SUCCESS)
+ memcached_return_t rc;
+ if (memcached_fatal(rc= memcached_vdo(instance, vector, 9, true)))
{
- 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;
- }
+ return rc;
}
- if (rc == MEMCACHED_WRITE_FAILURE)
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+
+ if (rc == MEMCACHED_NOTSTORED)
{
- memcached_io_reset(instance);
+ rc= MEMCACHED_SUCCESS;
+ }
+
+ if (rc == MEMCACHED_STORED)
+ {
+ rc= MEMCACHED_NOTFOUND;
}
return rc;
/* write the header */
memcached_return_t rc;
- if ((rc= memcached_vdo(instance, vector, 4, true)) != MEMCACHED_SUCCESS)
+ if (memcached_fatal(rc= memcached_vdo(instance, vector, 4, true)))
{
- memcached_io_reset(instance);
- return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
+ return rc;
}
rc= memcached_response(instance, NULL, 0, NULL);
if (rc == MEMCACHED_SUCCESS)
+ {
rc= MEMCACHED_NOTFOUND;
+ }
if (rc == MEMCACHED_DATA_EXISTS)
+ {
rc= MEMCACHED_SUCCESS;
+ }
return rc;
}
if (memcached_is_udp(memc))
{
- return MEMCACHED_NOT_SUPPORTED;
+ return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
}
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_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key);
- if (memc->flags.binary_protocol)
+ if (memcached_is_binary(memc))
{
- return binary_exist(memc, instance, key, key_length);
+ rc= binary_exist(memc, instance, key, key_length);
}
else
{
- return ascii_exist(memc, instance, key, key_length);
+ rc= ascii_exist(memc, instance, key, key_length);
}
+
+ if (memcached_fatal(rc))
+ {
+ memcached_io_reset(instance);
+ }
+
+ return rc;
}
/* This is for historical reasons */
if (*error == MEMCACHED_END)
+ {
*error= MEMCACHED_NOTFOUND;
+ }
if (value == NULL)
{
memcached_return_t rc= ptr->get_key_failure(ptr, key, key_length, &ptr->result);
/* On all failure drop to returning NULL */
- if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
+ if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED)
{
if (rc == MEMCACHED_BUFFERED)
{
uint64_t latch; /* We use latch to track the state of the original socket */
latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
if (latch == 0)
+ {
memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
+ }
rc= memcached_set(ptr, key, key_length,
(memcached_result_value(&ptr->result)),
if (memcached_failed(memcached_key_test(*ptr, keys, key_length, number_of_keys)))
{
- return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("A bad key value was provided"));
+ return memcached_last_error(ptr);
}
bool is_group_key_set= false;
if (memcached_is_binary(ptr) == false)
{
- return MEMCACHED_NOT_SUPPORTED;
+ return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT,
+ memcached_literal_param("ASCII protocol is not supported for memcached_mget_execute_by_key()"));
}
memcached_callback_st *original_callbacks= ptr->callbacks;
protocol_binary_request_getk request= { }; //= {.bytes= {0}};
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
if (mget_mode)
+ {
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
+ }
else
+ {
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
+ }
memcached_return_t vk;
vk= memcached_validate_key_length(key_length[x],
ptr->flags.binary_protocol);
- unlikely (vk != MEMCACHED_SUCCESS)
+ if (vk != MEMCACHED_SUCCESS)
{
if (x > 0)
{
if (sent_length == SOCKET_ERROR)
{
- memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
#if 0 // @todo I should look at why we hit this bit of code hard frequently
WATCHPOINT_ERRNO(get_socket_errno());
WATCHPOINT_NUMBER(get_socket_errno());
{
if (keys == NULL or key_length == NULL)
{
- return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+ return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key was NULL or length of key was zero."));
}
// If we don't need to verify the key, or we are using the binary protoocol,
memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false /* memc.flags.binary_protocol */);
if (memcached_failed(rc))
{
- return rc;
+ return memcached_set_error(memc, rc, MEMCACHED_AT, memcached_literal_param("Key provided was too long."));
}
}
memcached_return_t rc= memcached_validate_key_length(*(key_length + x), false);
if (memcached_failed(rc))
{
- return rc;
+ return memcached_set_error(memc, rc, MEMCACHED_AT, memcached_literal_param("Key provided was too long."));
}
for (size_t y= 0; y < *(key_length + x); y++)
{
if ((isgraph(keys[x][y])) == 0)
{
- return MEMCACHED_BAD_KEY_PROVIDED;
+ return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key provided had invalid character."));
}
}
}
if (memcached_failed(memcached_key_test(*self, (const char **)&key, &key_length, 1)))
{
self->flags.verify_key= orig;
- return memcached_set_error(*self, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+ return memcached_last_error(self);
}
self->flags.verify_key= orig;
return MEMCACHED_SERVER_ERROR;
}
- if (total_read > memcached_literal_param_size("SERVER_ERROR object too large for cache") and
+ if (total_read >= memcached_literal_param_size("SERVER_ERROR object too large for cache") and
(memcmp(buffer, memcached_literal_param("SERVER_ERROR object too large for cache")) == 0))
{
return MEMCACHED_E2BIG;
}
+ if (total_read >= memcached_literal_param_size("SERVER_ERROR out of memory storing object") and
+ (memcmp(buffer, memcached_literal_param("SERVER_ERROR out of memory storing object")) == 0))
+ {
+ return MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE;
+ }
+
// Move past the basic error message and whitespace
char *startptr= buffer + memcached_literal_param_size("SERVER_ERROR");
if (startptr[0] == ' ')
return MEMCACHED_PROTOCOL_ERROR;
}
#endif
+ // ERROR
+ else if (buffer[1] == 'R' and buffer[2] == 'R' and buffer[3] == 'O' and buffer[4] == 'R')
+ {
+ return MEMCACHED_ERROR;
+ }
// EXISTS
else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S')
{
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)
+ if (memcached_fatal(rc))
{
memcached_io_reset(ptr);
}
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
+ if (
+ rc != MEMCACHED_DATA_EXISTS and
rc != MEMCACHED_DELETED and
+ rc != MEMCACHED_E2BIG and
+ rc != MEMCACHED_END and
+ rc != MEMCACHED_ERROR and
+ rc != MEMCACHED_ITEM and
rc != MEMCACHED_NOTFOUND and
rc != MEMCACHED_NOTSTORED and
- rc != MEMCACHED_DATA_EXISTS)
+ rc != MEMCACHED_SERVER_ERROR and
+ rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE and
+ rc != MEMCACHED_STAT and
+ rc != MEMCACHED_STORED and
+ rc != MEMCACHED_SUCCESS and
+ rc != MEMCACHED_VALUE
+ )
{
memcached_result_free(junked_result_ptr);
return rc;
if (memc)
{
- set_hostinfo(self);
+ memcached_connect_try(self);
}
return self;
memcached_server_execute_fn callback,
void *context)
{
+ if (callback == NULL)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
+ bool some_errors= false;;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
- unsigned int iferror= (*callback)(ptr, instance, context);
-
- if (iferror)
+ memcached_return_t rc= (*callback)(ptr, instance, context);
+ if (rc == MEMCACHED_INVALID_ARGUMENTS)
+ {
+ return rc;
+ }
+ else if (memcached_fatal(rc))
{
- continue;
+ some_errors= true;
}
}
+ (void)some_errors;
return MEMCACHED_SUCCESS;
}
return NULL;
}
- 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))))
{
*error= rc;
return NULL;
}
- if (memcached_failed((memcached_key_test(*ptr, (const char **)&key, &key_length, 1))))
- {
- *error= MEMCACHED_BAD_KEY_PROVIDED;
- return NULL;
- }
-
uint32_t server_key= memcached_generate_hash(ptr, key, key_length);
return memcached_server_instance_by_position(ptr, server_key);
void memcached_server_error_reset(memcached_server_st *self)
{
WATCHPOINT_ASSERT(self);
- if (not self)
+ if (self == NULL)
{
return;
}
};
-static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char *value)
+static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key, const char *value)
{
if (strlen(key) < 1)
else if (not strcmp("rusage_user", key))
{
char *walk_ptr;
- for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++) {};
+ for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
*walk_ptr= 0;
walk_ptr++;
memc_stat->rusage_user_seconds= strtoul(value, (char **)NULL, 10);
else if (not strcmp("rusage_system", key))
{
char *walk_ptr;
- for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++) {};
+ for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
*walk_ptr= 0;
walk_ptr++;
memc_stat->rusage_system_seconds= strtoul(value, (char **)NULL, 10);
return rc;
}
- if (memc_stat)
- {
- if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
- {
- WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
- WATCHPOINT_ASSERT(0);
- }
- }
-
if (check && check->func)
{
size_t key_length= strlen(buffer);
buffer+key_length+1, strlen(buffer+key_length+1),
check->context);
}
+
+ if (memc_stat)
+ {
+ 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);
/*
if (memcached_success(rc))
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- while ((rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL)) == MEMCACHED_STAT)
+ while ((rc= memcached_response(instance, buffer, sizeof(buffer), NULL)) == MEMCACHED_STAT)
{
- char *string_ptr, *end_ptr;
- char *key, *value;
-
- string_ptr= buffer;
+ char *string_ptr= buffer;
string_ptr+= 5; /* Move past STAT */
+
+ char *end_ptr;
for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {};
- key= string_ptr;
- key[(size_t)(end_ptr-string_ptr)]= 0;
+ char *key= string_ptr;
+ key[size_t(end_ptr-string_ptr)]= 0;
string_ptr= end_ptr + 1;
for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++) {};
- value= string_ptr;
+ char *value= string_ptr;
value[(size_t)(end_ptr -string_ptr)]= 0;
- if (memc_stat)
- {
- unlikely((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
- {
- WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
- WATCHPOINT_ASSERT(0);
- }
- }
+#if 0
+ bool check_bool= bool(check);
+ bool check_func_bool= bool(check) ? bool(check->func) : false;
+ fprintf(stderr, "%s:%d %s %s %d:%d\n", __FILE__, __LINE__, key, value, check_bool, check_func_bool);
+#endif
- if (check && check->func)
+ if (check and check->func)
{
check->func(instance,
key, strlen(key),
value, strlen(value),
check->context);
}
+
+ if (memc_stat)
+ {
+ if((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
+ {
+ WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+ WATCHPOINT_ASSERT(0);
+ }
+ }
}
}
+ if (rc == MEMCACHED_ERROR)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
if (rc == MEMCACHED_END)
{
return MEMCACHED_SUCCESS;
temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL);
}
+ // Special case where "args" is invalid
+ if (temp_return == MEMCACHED_INVALID_ARGUMENTS)
+ {
+ rc= MEMCACHED_INVALID_ARGUMENTS;
+ break;
+ }
+
if (memcached_failed(temp_return))
{
rc= MEMCACHED_SOME_ERRORS;
memcached_stat_st *,
memcached_return_t *error)
{
- if (not ptr)
+ if (ptr == NULL)
+ {
return NULL;
+ }
char **list= static_cast<char **>(libmemcached_malloc(ptr, sizeof(memcached_stat_keys)));
if (not list)
void *context)
{
memcached_return_t rc;
- struct local_context *check= (struct local_context *)context;
+ local_context *check= (struct local_context *)context;
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
rc= binary_stats_fetch(NULL, check->args, check->args_length, instance, check);
}
{
memcached_version(memc);
- struct local_context check(func, context, args, args ? strlen(args) : 0);
+ local_context check(func, context, args, args ? strlen(args) : 0);
return memcached_server_execute(memc, call_stat_fn, (void *)&check);
}
return rc;
}
- if (memcached_failed(rc= memcached_validate_key_length(key_length, memcached_is_binary(ptr))))
+ if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
{
return rc;
}
- if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
- {
- return MEMCACHED_BAD_KEY_PROVIDED;
- }
-
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);
case MEMCACHED_WRITE_FAILURE:
return "WRITE FAILURE";
- case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: // DEPRECATED
- return "CONNECTION SOCKET CREATE FAILURE";
+ case MEMCACHED_ERROR:
+ return "ERROR was returned by server";
case MEMCACHED_DATA_EXISTS:
return "CONNECTION DATA EXISTS";
if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
{
size_t current_offset= (size_t) (string->end - string->string);
- size_t adjust;
- size_t new_size;
/* This is the block multiplier. To keep it larger and surive division errors we must round it up */
- adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE;
+ size_t adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE;
adjust++;
- new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size);
+ size_t new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size);
/* Test for overflow */
if (new_size < need)
- return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+ {
+ char error_message[1024];
+ int error_message_length= snprintf(error_message, sizeof(error_message),"Needed %ld, got %ld", (long)need, (long)new_size);
+ return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, error_message, error_message_length);
+ }
char *new_value= libmemcached_xrealloc(string->root, string->string, new_size, char);
if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
{
- return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ return rc;
}
uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPILER_VENDOR
+#
+# DESCRIPTION
+#
+# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
+# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
+# watcom, etc. The vendor is returned in the cache variable
+# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2008 Matteo Frigo
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 11
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+ [# note: don't check for gcc first since some other compilers define __GNUC__
+ vendors="intel: __ICC,__ECC,__INTEL_COMPILER
+ ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__
+ pathscale: __PATHCC__,__PATHSCALE__
+ clang: __clang__
+ gnu: __GNUC__
+ sun: __SUNPRO_C,__SUNPRO_CC
+ hp: __HP_cc,__HP_aCC
+ dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
+ borland: __BORLANDC__,__TURBOC__
+ comeau: __COMO__
+ cray: _CRAYC
+ kai: __KCC
+ lcc: __LCC__
+ sgi: __sgi,sgi
+ microsoft: _MSC_VER
+ metrowerks: __MWERKS__
+ watcom: __WATCOMC__
+ portland: __PGI
+ unknown: UNKNOWN"
+ for ventest in $vendors; do
+ case $ventest in
+ *:) vendor=$ventest; continue ;;
+ *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
+ esac
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+ #if !($vencpp)
+ thisisanerror;
+ #endif
+ ])], [break])
+ done
+ ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
+ ])
+])
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_tls.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_TLS([action-if-found], [action-if-not-found])
+#
+# DESCRIPTION
+#
+# Provides a test for the compiler support of thread local storage (TLS)
+# extensions. Defines TLS if it is found. Currently knows about GCC/ICC
+# and MSVC. I think SunPro uses the same as GCC, and Borland apparently
+# supports either.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
+# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 10
+
+AC_DEFUN([AX_TLS], [
+ AC_MSG_CHECKING(for thread local storage (TLS) class)
+ AC_CACHE_VAL(ac_cv_tls, [
+ ax_tls_keywords="__thread __declspec(thread) none"
+ for ax_tls_keyword in $ax_tls_keywords; do
+ AS_CASE([$ax_tls_keyword],
+ [none], [ac_cv_tls=none ; break],
+ [AC_TRY_COMPILE(
+ [#include <stdlib.h>
+ static void
+ foo(void) {
+ static ] $ax_tls_keyword [ int bar;
+ exit(1);
+ }],
+ [],
+ [ac_cv_tls=$ax_tls_keyword ; break],
+ ac_cv_tls=none
+ )])
+ done
+ ])
+ AC_MSG_RESULT($ac_cv_tls)
+
+ AS_IF([test "$ac_cv_tls" != "none"],
+ AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here])
+ m4_ifnblank([$1], [$1]),
+ m4_ifnblank([$2], [$2])
+ )
+])
%setup -q
%{__mkdir} examples
-%{__cp} tests/*.{cc,cpp,h} examples/
+#%{__cp} tests/*.{cc,h} examples/
%build
%exclude %{_libdir}/libmemcachedutil.a
%exclude %{_libdir}/libmemcachedprotocol.a
%{_libdir}/libhashkit.so.1.0.0
-%{_libdir}/libmemcached.so.8.0.0
+%{_libdir}/libmemcached.so.9.0.0
%{_libdir}/libmemcachedutil.so.2.0.0
%{_libdir}/libmemcachedprotocol.so.0.0.0
%{_libdir}/libhashkit.so.1
-%{_libdir}/libmemcached.so.8
+%{_libdir}/libmemcached.so.9
%{_libdir}/libmemcachedprotocol.so.0
%{_libdir}/libmemcachedutil.so.2
%{_mandir}/man1/memcapable.1.gz
%{_includedir}/libmemcached/memcached.hpp
%{_includedir}/libmemcached/util.h
+%{_includedir}/libmemcached-1.0/alloc.h
%{_includedir}/libmemcached-1.0/allocators.h
%{_includedir}/libmemcached-1.0/analyze.h
%{_includedir}/libmemcached-1.0/auto.h
%{_includedir}/libmemcached-1.0/basic_string.h
%{_includedir}/libmemcached-1.0/behavior.h
%{_includedir}/libmemcached-1.0/callback.h
+%{_includedir}/libmemcached-1.0/callbacks.h
%{_includedir}/libmemcached-1.0/configure.h
-%{_includedir}/libmemcached-1.0/constants.h
+%{_includedir}/libmemcached-1.0/defaults.h
%{_includedir}/libmemcached-1.0/delete.h
+%{_includedir}/libmemcached-1.0/deprecated_types.h
%{_includedir}/libmemcached-1.0/dump.h
%{_includedir}/libmemcached-1.0/error.h
-%{_includedir}/libmemcached-1.0/exist.h
-%{_includedir}/libmemcached-1.0/touch.h
%{_includedir}/libmemcached-1.0/exception.hpp
+%{_includedir}/libmemcached-1.0/exist.h
%{_includedir}/libmemcached-1.0/fetch.h
%{_includedir}/libmemcached-1.0/flush.h
%{_includedir}/libmemcached-1.0/flush_buffers.h
%{_includedir}/libmemcached-1.0/get.h
%{_includedir}/libmemcached-1.0/hash.h
+%{_includedir}/libmemcached-1.0/limits.h
%{_includedir}/libmemcached-1.0/memcached.h
%{_includedir}/libmemcached-1.0/memcached.hpp
%{_includedir}/libmemcached-1.0/options.h
%{_includedir}/libmemcached-1.0/stats.h
%{_includedir}/libmemcached-1.0/storage.h
%{_includedir}/libmemcached-1.0/strerror.h
-%{_includedir}/libmemcached-1.0/string.h
+%{_includedir}/libmemcached-1.0/struct/allocator.h
+%{_includedir}/libmemcached-1.0/struct/analysis.h
+%{_includedir}/libmemcached-1.0/struct/callback.h
+%{_includedir}/libmemcached-1.0/struct/memcached.h
+%{_includedir}/libmemcached-1.0/struct/result.h
+%{_includedir}/libmemcached-1.0/struct/sasl.h
+%{_includedir}/libmemcached-1.0/struct/server.h
+%{_includedir}/libmemcached-1.0/struct/stat.h
+%{_includedir}/libmemcached-1.0/struct/string.h
+%{_includedir}/libmemcached-1.0/touch.h
+%{_includedir}/libmemcached-1.0/triggers.h
%{_includedir}/libmemcached-1.0/types.h
+%{_includedir}/libmemcached-1.0/types/behavior.h
+%{_includedir}/libmemcached-1.0/types/callback.h
+%{_includedir}/libmemcached-1.0/types/connection.h
+%{_includedir}/libmemcached-1.0/types/hash.h
+%{_includedir}/libmemcached-1.0/types/return.h
+%{_includedir}/libmemcached-1.0/types/server_distribution.h
%{_includedir}/libmemcached-1.0/verbosity.h
%{_includedir}/libmemcached-1.0/version.h
%{_includedir}/libmemcached-1.0/visibility.h
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 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 <config.h>
+
+#include <cstdlib>
+#include <climits>
+
+#include <libtest/test.hpp>
+
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcached/util.h>
+
+using namespace libtest;
+
+#include "tests/libmemcached-1.0/dump.h"
+
+static memcached_return_t callback_dump_counter(const memcached_st *,
+ const char*, // key,
+ size_t, // length,
+ void *context)
+{
+ size_t *counter= (size_t *)context;
+
+#if 0
+ std::cerr.write(key, length);
+ std::cerr << std::endl;
+#endif
+
+ *counter= *counter +1;
+
+ return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t item_counter(memcached_server_instance_st ,
+ const char *key, size_t key_length,
+ const char *value, size_t, // value_length,
+ void *context)
+{
+ if ((key_length == (sizeof("curr_items") -1)) and (strncmp("curr_items", key, (sizeof("curr_items") -1)) == 0))
+ {
+ uint64_t* counter= (uint64_t*)context;
+ unsigned long number_value= strtoul(value, (char **)NULL, 10);
+ if (number_value == ULONG_MAX)
+ {
+ return MEMCACHED_FAILURE;
+ }
+ *counter= *counter +number_value;
+ }
+
+ return MEMCACHED_SUCCESS;
+}
+
+#if 0
+test_return_t memcached_dump_TEST(memcached_st *memc)
+{
+ test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+ size_t count= 0;
+ memcached_dump_fn callbacks[1];
+ callbacks[0]= &callback_dump_counter;
+
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, NULL, item_counter, &counter),
+ memcached_last_error_message(memc));
+ test_zero(counter);
+
+ test_compare_got(MEMCACHED_SUCCESS, memcached_dump(memc, callbacks, &count, 1), memcached_last_error_message(memc));
+
+ return TEST_SUCCESS;
+}
+#endif
+
+#define memcached_dump_TEST2_COUNT 64
+test_return_t memcached_dump_TEST2(memcached_st *memc)
+{
+ test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+ /* The dump test relies on there being at least 32 items in memcached */
+ for (uint32_t x= 0; x < memcached_dump_TEST2_COUNT; x++)
+ {
+ char key[1024];
+
+ int length= snprintf(key, sizeof(key), "%s%u", __func__, x);
+
+ test_true(length > 0);
+
+ test_compare_hint(MEMCACHED_SUCCESS,
+ memcached_set(memc, key, length,
+ NULL, 0, // Zero length values
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
+ }
+ memcached_quit(memc);
+
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, NULL, item_counter, &counter),
+ memcached_last_error_message(memc));
+ test_true_got(counter > 0, counter);
+
+ size_t count= 0;
+ memcached_dump_fn callbacks[1];
+ callbacks[0]= &callback_dump_counter;
+
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_dump(memc, callbacks, &count, 1),
+ memcached_last_error_message(memc));
+
+ test_true(count);
+
+ return TEST_SUCCESS;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t memcached_dump_TEST(memcached_st *);
+test_return_t memcached_dump_TEST2(memcached_st *);
test_return_t memcached_exist_SUCCESS(memcached_st *memc)
{
- test_compare(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("frog"), 0, 0, 0, 0));
- test_compare(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("frog")));
- test_compare(MEMCACHED_SUCCESS, memcached_delete(memc, test_literal_param("frog"), 0));
- test_compare(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("frog")));
+ test_compare_got(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("frog"), 0, 0, 0, 0), memcached_last_error_message(memc));
+ test_compare_got(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("frog")), memcached_last_error_message(memc));
+ test_compare_got(MEMCACHED_SUCCESS, memcached_delete(memc, test_literal_param("frog"), 0), memcached_last_error_message(memc));
+ test_compare_got(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("frog")), memcached_last_error_message(memc));
return TEST_SUCCESS;
}
test_return_t memcached_exist_by_key_SUCCESS(memcached_st *memc)
{
- test_compare(MEMCACHED_SUCCESS, memcached_set_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0, 0, 0, 0));
- test_compare(MEMCACHED_SUCCESS, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog")));
- test_compare(MEMCACHED_SUCCESS, memcached_delete_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0));
- test_compare(MEMCACHED_NOTFOUND, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog")));
+ test_compare_got(MEMCACHED_SUCCESS, memcached_set_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0, 0, 0, 0), memcached_last_error_message(memc));
+ test_compare_got(MEMCACHED_SUCCESS, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog")), memcached_last_error_message(memc));
+ test_compare_got(MEMCACHED_SUCCESS, memcached_delete_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0), memcached_last_error_message(memc));
+ test_compare_got(MEMCACHED_NOTFOUND, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog")), memcached_last_error_message(memc));
return TEST_SUCCESS;
}
tests/basic.h \
tests/callbacks.h \
tests/debug.h \
+ tests/deprecated.h \
tests/error_conditions.h \
tests/exist.h \
tests/ketama.h \
tests/ketama_test_cases.h \
tests/ketama_test_cases_spy.h \
+ tests/libmemcached-1.0/dump.h \
+ tests/libmemcached-1.0/stat.h \
tests/namespace.h \
tests/parser.h \
- tests/touch.h \
- tests/deprecated.h \
tests/pool.h \
tests/print.h \
tests/replication.h \
tests/server_add.h \
tests/string.h \
+ tests/touch.h \
tests/virtual_buckets.h
# Test internals
tests_libmemcached_1_0_testapp_CXXFLAGS = $(AM_CXXFLAGS) ${PTHREAD_CFLAGS}
tests_libmemcached_1_0_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
tests_libmemcached_1_0_testapp_SOURCES= \
+ tests/libmemcached-1.0/pool.cc \
+ tests/libmemcached-1.0/print.cc \
+ tests/libmemcached-1.0/replication.cc \
tests/libmemcached-1.0/basic.cc \
tests/libmemcached-1.0/callbacks.cc \
tests/libmemcached-1.0/debug.cc \
tests/libmemcached-1.0/deprecated.cc \
+ tests/libmemcached-1.0/dump.cc \
tests/libmemcached-1.0/error_conditions.cc \
tests/libmemcached-1.0/exist.cc \
tests/libmemcached-1.0/ketama.cc \
tests/libmemcached-1.0/mem_functions.cc \
tests/libmemcached-1.0/namespace.cc \
- tests/libmemcached-1.0/pool.cc \
- tests/libmemcached-1.0/print.cc \
- tests/libmemcached-1.0/replication.cc \
tests/libmemcached-1.0/parser.cc \
tests/libmemcached-1.0/server_add.cc \
+ tests/libmemcached-1.0/stat.cc \
tests/libmemcached-1.0/touch.cc \
tests/libmemcached-1.0/virtual_buckets.cc
#include "tests/ketama.h"
#include "tests/namespace.h"
#include "tests/parser.h"
+#include "tests/libmemcached-1.0/dump.h"
+#include "tests/libmemcached-1.0/stat.h"
#include "tests/touch.h"
#include "tests/callbacks.h"
#include "tests/pool.h"
{
uint32_t values[] = { 851992627U, 2337886783U, 4109241422U, 4001849190U,
982370485U, 1263635348U, 4242906218U, 3829656100U,
- 1891735253U, 334139633U, 2257084983U, 3088286104U,
+ 1891735253U, 334139633U, 2257084983U, 3351789013U,
13199785U, 2542027183U, 1097051614U, 199566778U,
2748246961U, 2465192557U, 1664094137U, 2405439045U,
1842224848U, 692413798U, 3479807801U, 919913813U,
test_compare(query_id, memcached_query_id(memc_clone)); // We should not increase the query_id for memcached_behavior_set()
/* All keys are valid in the binary protocol (except for length) */
- if (not memcached_behavior_get(memc_clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL))
+ if (memcached_behavior_get(memc_clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == false)
{
uint64_t before_query_id= memcached_query_id(memc_clone);
{
return TEST_SUCCESS;
}
-static test_return_t binary_increment_with_prefix_test(memcached_st *orig_memc)
+static test_return_t binary_increment_with_prefix_test(memcached_st *memc)
{
- memcached_st *memc= memcached_clone(NULL, orig_memc);
-
- test_skip(TEST_SUCCESS, pre_binary(memc));
+ test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
test_compare(MEMCACHED_SUCCESS, memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)"namespace:"));
test_literal_param("number"),
1, &new_number));
test_compare(uint64_t(2), new_number);
- memcached_free(memc);
return TEST_SUCCESS;
}
{
for (size_t x= 0; x < 100; ++x)
{
- char key[10];
+ char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
int check_length= (size_t)snprintf(key, sizeof(key), "%lu", (unsigned long)x);
test_false((size_t)check_length >= sizeof(key) || check_length < 0);
static test_return_t analyzer_test(memcached_st *memc)
{
- memcached_return_t rc;
memcached_analysis_st *report;
+ memcached_return_t rc;
memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
return TEST_SUCCESS;
}
-/* Count the objects */
-
-static test_return_t dump_test(memcached_st *memc)
-{
- /* No support for Binary protocol yet */
- test_skip(false, memc->flags.binary_protocol);
-
- test_compare(TEST_SUCCESS, set_test3(memc));
-
- // confirm_key_count() call dump
- size_t counter= confirm_key_count(memc);
-
- /* We may have more then 32 if our previous flush has not completed */
- test_true(counter >= 32);
-
- return TEST_SUCCESS;
-}
-
static test_return_t util_version_test(memcached_st *memc)
{
test_compare_hint(MEMCACHED_SUCCESS, memcached_version(memc), memcached_last_error_message(memc));
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, (const char**)keys, key_length, max_keys));
+ // One the first run we should get a NOT_FOUND, but on the second some data
+ // should be returned.
test_compare(y ? MEMCACHED_SUCCESS : MEMCACHED_NOTFOUND,
memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
}
- (void)snprintf(k, sizeof(k), "%037u", 251U);
- len= strlen(k);
+ len= snprintf(k, sizeof(k), "%037u", 251U);
memcached_return_t rc= memcached_delete(memc, k, len, 0);
test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
static test_return_t regression_bug_463297(memcached_st *memc)
{
+ test_compare(MEMCACHED_INVALID_ARGUMENTS, memcached_delete(memc, "foo", 3, 1));
+
+ // Since we blocked timed delete, this test is no longer valid.
+#if 0
memcached_st *memc_clone= memcached_clone(NULL, memc);
test_true(memc_clone);
test_true(memcached_version(memc_clone) == MEMCACHED_SUCCESS);
}
memcached_free(memc_clone);
+#endif
+
return TEST_SUCCESS;
}
test_true(keys[x]);
memcached_return rc= memcached_set(memc, keys[x], key_length[x], blob, sizeof(blob), 0, 0);
- test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+ test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_last_error_message(memc));
}
for (uint32_t x= 0; x < regression_bug_490520_COUNT; ++x)
{"connection_test", false, (test_callback_fn*)connection_test},
{"callback_test", false, (test_callback_fn*)callback_test},
{"userdata_test", false, (test_callback_fn*)userdata_test},
- {"set", false, (test_callback_fn*)set_test },
- {"set2", false, (test_callback_fn*)set_test2 },
- {"set3", false, (test_callback_fn*)set_test3 },
- {"dump", true, (test_callback_fn*)dump_test},
+ {"memcached_set()", false, (test_callback_fn*)set_test },
+ {"memcached_set() 2", false, (test_callback_fn*)set_test2 },
+ {"memcached_set() 3", false, (test_callback_fn*)set_test3 },
{"add", true, (test_callback_fn*)add_test },
{"memcached_fetch_result(MEMCACHED_NOTFOUND)", true, (test_callback_fn*)memcached_fetch_result_NOT_FOUND },
{"replace", true, (test_callback_fn*)replace_test },
{"memcached_exist_by_key(MEMCACHED_SUCCESS)", true, (test_callback_fn*)memcached_exist_by_key_SUCCESS },
{"memcached_touch", 0, (test_callback_fn*)test_memcached_touch},
{"memcached_touch_with_prefix", 0, (test_callback_fn*)test_memcached_touch_by_key},
+#if 0
+ {"memcached_dump() no data", true, (test_callback_fn*)memcached_dump_TEST },
+#endif
+ {"memcached_dump() with data", true, (test_callback_fn*)memcached_dump_TEST2 },
{0, 0, 0}
};
{0, 0, 0}
};
+test_st memcached_stat_tests[] ={
+ {"memcached_stat() INVALID ARG", 0, (test_callback_fn*)memcached_stat_TEST},
+ {"memcached_stat()", 0, (test_callback_fn*)memcached_stat_TEST2},
+ {0, 0, 0}
+};
+
test_st behavior_tests[] ={
{"libmemcached_string_behavior()", false, (test_callback_fn*)libmemcached_string_behavior_test},
{"libmemcached_string_distribution()", false, (test_callback_fn*)libmemcached_string_distribution_test},
{"virtual buckets", 0, 0, virtual_bucket_tests},
{"memcached_server_get_last_disconnect", 0, 0, memcached_server_get_last_disconnect_tests},
{"touch", 0, 0, touch_tests},
+ {"touch", (test_callback_fn*)pre_binary, 0, touch_tests},
+ {"memcached_stat()", 0, 0, memcached_stat_tests},
{0, 0, 0, 0}
};
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 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 <config.h>
+
+#include <cstdlib>
+#include <climits>
+
+#include <libtest/test.hpp>
+
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcached/util.h>
+
+using namespace libtest;
+
+#include "tests/libmemcached-1.0/stat.h"
+
+static memcached_return_t item_counter(memcached_server_instance_st ,
+ const char *key, size_t key_length,
+ const char *value, size_t, // value_length,
+ void *context)
+{
+ if ((key_length == (sizeof("curr_items") -1)) and (strncmp("curr_items", key, (sizeof("curr_items") -1)) == 0))
+ {
+ uint64_t* counter= (uint64_t*)context;
+ unsigned long number_value= strtoul(value, (char **)NULL, 10);
+ if (number_value == ULONG_MAX)
+ {
+ return MEMCACHED_FAILURE;
+ }
+ *counter= *counter +number_value;
+ }
+
+ return MEMCACHED_SUCCESS;
+}
+
+test_return_t memcached_stat_TEST(memcached_st *memc)
+{
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_INVALID_ARGUMENTS,
+ memcached_stat_execute(memc, "BAD_ARG_VALUE", item_counter, &counter),
+ memcached_last_error_message(memc));
+
+ return TEST_SUCCESS;
+}
+
+#define memcached_dump_TEST2_COUNT 64
+test_return_t memcached_stat_TEST2(memcached_st *memc)
+{
+ test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+ /* The dump test relies on there being at least 32 items in memcached */
+ for (uint32_t x= 0; x < memcached_dump_TEST2_COUNT; x++)
+ {
+ char key[1024];
+
+ int length= snprintf(key, sizeof(key), "%s%u", __func__, x);
+
+ test_true(length > 0);
+
+ test_compare_hint(MEMCACHED_SUCCESS,
+ memcached_set(memc, key, length,
+ NULL, 0, // Zero length values
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
+ }
+ memcached_quit(memc);
+
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, NULL, item_counter, &counter),
+ memcached_last_error_message(memc));
+ test_true_got(counter > 0, counter);
+
+ return TEST_SUCCESS;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t memcached_stat_TEST(memcached_st *);
+test_return_t memcached_stat_TEST2(memcached_st *);
memcached_return rc;
test_null(memcached_get(memc,
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
&len, &flags, &rc));
test_zero(len);
test_compare(MEMCACHED_NOTFOUND, rc);
test_compare(MEMCACHED_SUCCESS,
memcached_set(memc,
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
test_literal_param("touchval"),
2, 0));
{
char *value= memcached_get(memc,
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
&len, &flags, &rc);
test_compare(8U, test_literal_param_size("touchval"));
test_true(value);
}
test_compare(MEMCACHED_SUCCESS,
- memcached_touch(memc, test_literal_param("touchkey"), 60 *60));
+ memcached_touch(memc, test_literal_param(__func__), 60 *60));
test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
- rc= memcached_touch(memc, test_literal_param("touchkey"), 60 *60 *24 *60);
+ rc= memcached_touch(memc, test_literal_param(__func__), 60 *60 *24 *60);
test_compare_hint(MEMCACHED_SUCCESS, rc, memcached_last_error_message(memc));
test_compare(MEMCACHED_NOTFOUND,
- memcached_exist(memc, test_literal_param("touchkey")));
+ memcached_exist(memc, test_literal_param(__func__)));
return TEST_SUCCESS;
}
test_null(memcached_get_by_key(memc,
test_literal_param("grouping_key"),
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
&len, &flags, &rc));
test_zero(len);
test_compare(MEMCACHED_NOTFOUND, rc);
test_compare(MEMCACHED_SUCCESS,
memcached_set_by_key(memc,
test_literal_param("grouping_key"),
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
test_literal_param("touchval"),
2, 0));
{
char *value= memcached_get_by_key(memc,
test_literal_param("grouping_key"),
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
&len, &flags, &rc);
test_compare(8U, test_literal_param_size("touchval"));
test_true(value);
test_compare(MEMCACHED_SUCCESS,
memcached_touch_by_key(memc,
test_literal_param("grouping_key"),
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
60 *60));
test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
test_compare(MEMCACHED_SUCCESS,
memcached_touch_by_key(memc,
test_literal_param("grouping_key"),
- test_literal_param("touchkey"),
+ test_literal_param(__func__),
60 *60 *24 *60));
test_compare(MEMCACHED_NOTFOUND,
- memcached_exist_by_key(memc, test_literal_param("grouping_key"),test_literal_param("touchkey")));
+ memcached_exist_by_key(memc, test_literal_param("grouping_key"),test_literal_param(__func__)));
return TEST_SUCCESS;
}