clients/memexist
tests/memexist
libmemcached/configure.h
+clients/memtouch
+tests/memtouch
clients/memdump \
clients/memerror \
clients/memexist \
+ clients/memtouch \
clients/memflush \
clients/memparse \
clients/memping \
clients_memexist_SOURCES= clients/memexist.cc
clients_memexist_LDADD= $(CLIENTS_LDADDS)
+clients_memtouch_SOURCES= clients/memtouch.cc
+clients_memtouch_LDADD= $(CLIENTS_LDADDS)
+
clients_memflush_SOURCES= clients/memflush.cc
clients_memflush_LDADD= $(CLIENTS_LDADDS)
--- /dev/null
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include <config.h>
+
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+#include <libmemcached/memcached.h>
+
+#include "utilities.h"
+
+#define PROGRAM_NAME "memtouch"
+#define PROGRAM_DESCRIPTION "Update the expiration value of an alreasy existing value in the sever"
+
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+time_t expiration= 0;
+
+int main(int argc, char *argv[])
+{
+ int return_code= EXIT_SUCCESS;
+
+ options_parse(argc, argv);
+ initialize_sockets();
+
+ if (opt_servers == NULL)
+ {
+ char *temp;
+
+ if ((temp= getenv("MEMCACHED_SERVERS")))
+ {
+ opt_servers= strdup(temp);
+ }
+ else
+ {
+ std::cerr << "No Servers provided" << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ memcached_st *memc= memcached_create(NULL);
+ process_hash_option(memc, opt_hash);
+
+ memcached_server_st *servers= memcached_servers_parse(opt_servers);
+
+ memcached_server_push(memc, servers);
+ memcached_server_list_free(servers);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+ (uint64_t)opt_binary);
+
+ if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+ {
+ memcached_free(memc);
+ std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (opt_username)
+ {
+ memcached_return_t ret;
+ if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+ {
+ std::cerr << memcached_last_error_message(memc) << std::endl;
+ memcached_free(memc);
+ return EXIT_FAILURE;
+ }
+ }
+
+ while (optind < argc)
+ {
+ memcached_return_t rc= memcached_touch(memc, argv[optind], strlen(argv[optind]), expiration);
+ if (rc == MEMCACHED_NOTFOUND)
+ {
+ if (opt_verbose)
+ {
+ std::cout << "Could not find key \"" << argv[optind] << "\"" << std::endl;
+ }
+
+ return_code= EXIT_FAILURE;
+ }
+ else if (memcached_failed(rc))
+ {
+ if (opt_verbose)
+ {
+ std::cerr << "Fatal error for key \"" << argv[optind] << "\" :" << memcached_last_error_message(memc) << std::endl;
+ }
+
+ return_code= EXIT_FAILURE;
+ }
+ else // success
+ {
+ if (opt_verbose)
+ {
+ std::cout << "Found key " << argv[optind] << std::endl;
+ }
+ }
+
+ optind++;
+ }
+
+ memcached_free(memc);
+
+ if (opt_servers)
+ {
+ free(opt_servers);
+ }
+
+ if (opt_hash)
+ {
+ free(opt_hash);
+ }
+
+ return return_code;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+ memcached_programs_help_st help_options[]=
+ {
+ {0},
+ };
+
+ static struct option long_options[]=
+ {
+ {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+ {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+ {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+ {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+ {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+ {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+ {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+ {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+ {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+ {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+ {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+ {0, 0, 0, 0},
+ };
+
+ bool opt_version= false;
+ bool opt_help= false;
+ int option_index= 0;
+
+ while (1)
+ {
+ int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+ if (option_rv == -1)
+ {
+ break;
+ }
+
+ switch (option_rv)
+ {
+ case 0:
+ break;
+
+ case OPT_BINARY:
+ opt_binary = true;
+ break;
+
+ case OPT_VERBOSE: /* --verbose or -v */
+ opt_verbose = OPT_VERBOSE;
+ break;
+
+ case OPT_DEBUG: /* --debug or -d */
+ opt_verbose = OPT_DEBUG;
+ break;
+
+ case OPT_VERSION: /* --version or -V */
+ opt_version= true;
+ break;
+
+ case OPT_HELP: /* --help or -h */
+ opt_help= true;
+ break;
+
+ case OPT_SERVERS: /* --servers or -s */
+ opt_servers= strdup(optarg);
+ break;
+
+ case OPT_HASH:
+ opt_hash= strdup(optarg);
+ break;
+
+ case OPT_USERNAME:
+ opt_username= optarg;
+ break;
+
+ case OPT_PASSWD:
+ opt_passwd= optarg;
+ break;
+
+ case OPT_EXPIRE:
+ expiration= time_t(strtoul(optarg, (char **)NULL, 10));
+ break;
+
+ case OPT_QUIET:
+ close_stdio();
+ break;
+
+ case '?':
+ /* getopt_long already printed an error message. */
+ exit(EXIT_FAILURE);
+
+ default:
+ abort();
+ }
+ }
+
+ if (opt_version)
+ {
+ version_command(PROGRAM_NAME);
+ exit(EXIT_SUCCESS);
+ }
+
+ if (opt_help)
+ {
+ help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+ exit(EXIT_SUCCESS);
+ }
+}
libmemcached-1.0/storage.h \
libmemcached-1.0/strerror.h \
libmemcached-1.0/string.h \
+ libmemcached-1.0/touch.h \
libmemcached-1.0/types.h \
libmemcached-1.0/verbosity.h \
libmemcached-1.0/version.h \
#include <libmemcached-1.0/server_list.h>
#include <libmemcached-1.0/storage.h>
#include <libmemcached-1.0/strerror.h>
+#include <libmemcached-1.0/touch.h>
#include <libmemcached-1.0/verbosity.h>
#include <libmemcached-1.0/version.h>
#include <libmemcached-1.0/sasl.h>
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+LIBMEMCACHED_API
+memcached_return_t memcached_touch(memcached_st *ptr,
+ const char *key, size_t key_length,
+ time_t expiration);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_touch_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const void *command,
size_t command_length, bool with_flush)
{
- memcached_return_t rc;
- ssize_t sent_length;
-
- WATCHPOINT_ASSERT(command_length);
- WATCHPOINT_ASSERT(command);
+ assert_msg(command_length, "Programming error, somehow a command had a length of zero");
+ assert_msg(command, "Programming error, somehow a command was NULL");
+ memcached_return_t rc;
if (memcached_failed(rc= memcached_connect(ptr)))
{
WATCHPOINT_ASSERT(rc == memcached_last_error(ptr->root));
memcached_io_write(ptr, NULL, 0, true);
}
- sent_length= memcached_io_write(ptr, command, command_length, with_flush);
+ ssize_t sent_length= memcached_io_write(ptr, command, command_length, with_flush);
- if (sent_length == -1 || (size_t)sent_length != command_length)
+ if (sent_length == -1 or size_t(sent_length) != command_length)
{
rc= MEMCACHED_WRITE_FAILURE;
}
bool with_flush)
{
memcached_return_t rc;
- ssize_t sent_length;
WATCHPOINT_ASSERT(count);
WATCHPOINT_ASSERT(vector);
memcached_io_write(ptr, NULL, 0, true);
}
- sent_length= memcached_io_writev(ptr, vector, count, with_flush);
+ ssize_t sent_length= memcached_io_writev(ptr, vector, count, with_flush);
size_t command_length= 0;
for (uint32_t x= 0; x < count; ++x, vector++)
}
if (memc.error_messages == NULL)
+ {
return;
+ }
memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
- if (not error) // Bad business if this happens
+ if (error == NULL) // Bad business if this happens
{
return;
}
static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
{
- (void)at;
if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
{
memcached_error_free(memc);
}
memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
- if (not error) // Bad business if this happens
+ if (error == NULL) // Bad business if this happens
+ {
return;
+ }
error->root= &memc;
error->query_id= memc.query_id;
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
_set(memc, &str, rc, at);
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
char hostname_port_message[MAX_ERROR_LENGTH];
int size;
memcached_string_t error_host= { hostname_port_message, size };
- if (not self.root)
+ assert(self.root);
+ if (self.root == NULL)
+ {
return rc;
+ }
_set(*self.root, &error_host, rc, at);
_set(self, (*self.root));
+ assert(self.root->error_messages);
+ assert(self.error_messages);
return rc;
}
memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at)
{
- assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port));
memcached_string_t error_host= { hostname_port, size};
- if (not self.root)
+ if (self.root == NULL)
+ {
return rc;
+ }
_set(*self.root, &error_host, rc, at);
_set(self, *self.root);
{
assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
if (memcached_success(rc))
- return MEMCACHED_SUCCESS;
+ {
+ return rc;
+ }
_set(self, NULL, rc, at);
memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
memcached_return_t rc= MEMCACHED_ERRNO;
_set(self, NULL, rc, at, local_errno);
memcached_return_t memcached_set_errno(memcached_st& memc, int local_errno, const char *at, memcached_string_t& str)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
memcached_return_t rc= MEMCACHED_ERRNO;
_set(memc, &str, rc, at, local_errno);
memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, memcached_string_t& str)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
char hostname_port_message[MAX_ERROR_LENGTH];
int size;
memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at)
{
- if (not local_errno)
+ if (local_errno == 0)
+ {
return MEMCACHED_SUCCESS;
+ }
char hostname_port_message[MAX_ERROR_LENGTH];
int size = snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
static void _error_free(memcached_error_t *error)
{
if (not error)
+ {
return;
+ }
_error_free(error->next);
return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
}
- if (not memc->error_messages)
+ if (memc->error_messages == NULL)
+ {
return memcached_strerror(memc, MEMCACHED_SUCCESS);
+ }
- if (not memc->error_messages->size)
+ if (memc->error_messages->size == 0)
+ {
return memcached_strerror(memc, memc->error_messages->rc);
+ }
return memc->error_messages->message;
}
memcached_server_st *new_host_list= static_cast<memcached_server_st*>(libmemcached_realloc(ptr, memcached_server_list(ptr),
sizeof(memcached_server_st) * (ptr->number_of_hosts + 1)));
- if (not new_host_list)
+ if (new_host_list == NULL)
{
- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
}
memcached_server_list_set(ptr, new_host_list);
/* TODO: Check return type */
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
- if (not __server_create_with(ptr, instance, hostname, port, weight, type))
+ if (__server_create_with(ptr, instance, hostname, port, weight, type) == NULL)
{
return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
}
libmemcached/flush.cc \
libmemcached/flush_buffers.cc \
libmemcached/get.cc \
+ libmemcached/touch.cc \
libmemcached/hash.cc \
libmemcached/hosts.cc \
libmemcached/initialize_query.cc \
memcached_return_t initialize_query(memcached_st *self)
{
- if (not self)
+ if (self == NULL)
{
return MEMCACHED_INVALID_ARGUMENTS;
}
probe memcached_replace_end();
probe memcached_get_start();
probe memcached_get_end();
+ probe memcached_touch_start();
+ probe memcached_touch_end();
probe memcached_mget_start();
probe memcached_mget_end();
probe memcached_connect_start();
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
+ *
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
#define LIBMEMCACHED_MEMCACHED_GET_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_GET_START()
#define LIBMEMCACHED_MEMCACHED_GET_START_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_TOUCH_END()
+#define LIBMEMCACHED_MEMCACHED_TOUCH_END_ENABLED() (0)
+#define LIBMEMCACHED_MEMCACHED_TOUCH_START()
+#define LIBMEMCACHED_MEMCACHED_TOUCH_START_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_INCREMENT_END()
#define LIBMEMCACHED_MEMCACHED_INCREMENT_END_ENABLED() (0)
#define LIBMEMCACHED_MEMCACHED_INCREMENT_START()
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
+ *
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
PROTOCOL_BINARY_CMD_GAT = 0x1d,
PROTOCOL_BINARY_CMD_GATQ = 0x1e,
+ PROTOCOL_BINARY_CMD_GATK = 0x23,
+ PROTOCOL_BINARY_CMD_GATKQ = 0x24,
PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
+ *
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
rc == MEMCACHED_PROTOCOL_ERROR or
rc == MEMCACHED_CLIENT_ERROR or
rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
+ {
memcached_io_reset(ptr);
+ }
return rc;
}
ssize_t read_length= 0;
if (ptr->root->flags.use_udp)
+ {
return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+ }
WATCHPOINT_ASSERT(ptr->root);
end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
}
case 'O': /* OK */
return MEMCACHED_SUCCESS;
+
case 'S': /* STORED STATS SERVER_ERROR */
{
if (buffer[2] == 'A') /* STORED STATS */
case 'N': /* NOT_FOUND */
{
if (buffer[4] == 'F')
+ {
return MEMCACHED_NOTFOUND;
+ }
else if (buffer[4] == 'S')
+ {
return MEMCACHED_NOTSTORED;
+ }
else
{
WATCHPOINT_STRING(buffer);
case 'E': /* PROTOCOL ERROR or END */
{
if (buffer[1] == 'N')
+ {
return MEMCACHED_END;
+ }
else if (buffer[1] == 'R')
+ {
return MEMCACHED_PROTOCOL_ERROR;
+ }
else if (buffer[1] == 'X')
+ {
return MEMCACHED_DATA_EXISTS;
+ }
else
{
WATCHPOINT_STRING(buffer);
}
}
+ case 'T': /* TOUCHED */
+ {
+ if (buffer[1] == 'O' and buffer[2] == 'U'
+ and buffer[3] == 'C' and buffer[4] == 'H'
+ and buffer[5] == 'E' and buffer[6] == 'D')
+ {
+ return MEMCACHED_SUCCESS;
+ }
+ }
+ return MEMCACHED_UNKNOWN_READ_FAILURE;
+
case 'I': /* CLIENT ERROR */
/* We add back in one because we will need to search for END */
memcached_server_response_increment(ptr);
return MEMCACHED_ITEM;
+
case 'C': /* CLIENT ERROR */
return MEMCACHED_CLIENT_ERROR;
+
default:
{
unsigned long long auto_return_value;
case PROTOCOL_BINARY_CMD_APPEND:
case PROTOCOL_BINARY_CMD_PREPEND:
case PROTOCOL_BINARY_CMD_DELETE:
+ case PROTOCOL_BINARY_CMD_TOUCH:
{
WATCHPOINT_ASSERT(bodylen == 0);
return MEMCACHED_SUCCESS;
}
+
case PROTOCOL_BINARY_CMD_NOOP:
{
WATCHPOINT_ASSERT(bodylen == 0);
return MEMCACHED_END;
}
+
case PROTOCOL_BINARY_CMD_STAT:
{
if (bodylen == 0)
self= _server_create(self, memc);
- if (not self)
+ if (self == NULL)
{
return NULL;
}
void memcached_server_free(memcached_server_st *self)
{
- if (not self)
+ if (self == NULL)
+ {
return;
+ }
if (memcached_server_list_count(self))
{
memcached_server_st *source)
{
/* We just do a normal create if source is missing */
- if (not source)
+ if (source == NULL)
{
return NULL;
}
size_t key_length,
memcached_return_t *error)
{
- memcached_return_t rc;
memcached_return_t unused;
-
if (not error)
+ {
error= &unused;
+ }
+
+ memcached_return_t rc;
if (memcached_failed(rc= initialize_const_query(ptr)))
{
*error= rc;
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/memcached/protocol_binary.h>
+
+static memcached_return_t ascii_touch(memcached_server_write_instance_st instance,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ char buffer[21];
+
+ int buffer_length= snprintf(buffer, sizeof(buffer), " %u", uint32_t(expiration));
+ struct libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("touch ") },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length },
+ { buffer, buffer_length },
+ { memcached_literal_param("\r\n") }
+ };
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 5, true)))
+ {
+ memcached_io_reset(instance);
+ return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ }
+
+ return rc;
+}
+
+static memcached_return_t binary_touch(memcached_server_write_instance_st instance,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ protocol_binary_request_touch request= {}; //{.bytes= {0}};
+ request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+ request.message.header.request.opcode= PROTOCOL_BINARY_CMD_TOUCH;
+ request.message.header.request.extlen= 4;
+ request.message.header.request.keylen= htons((uint16_t)(key_length +memcached_array_size(instance->root->_namespace)));
+ request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+ request.message.header.request.bodylen= htonl((uint32_t)(key_length +memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
+ request.message.body.expiration= htonl((uint32_t) expiration);
+
+ struct libmemcached_io_vector_st vector[]=
+ {
+ { request.bytes, sizeof(request.bytes) },
+ { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+ { key, key_length }
+ };
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
+ {
+ memcached_io_reset(instance);
+ return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+ }
+
+ return rc;
+}
+
+memcached_return_t memcached_touch(memcached_st *ptr,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ return memcached_touch_by_key(ptr, key, key_length, key, key_length, expiration);
+}
+
+memcached_return_t memcached_touch_by_key(memcached_st *ptr,
+ const char *group_key, size_t group_key_length,
+ const char *key, size_t key_length,
+ time_t expiration)
+{
+ LIBMEMCACHED_MEMCACHED_TOUCH_START();
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr)))
+ {
+ return rc;
+ }
+
+ if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+ {
+ return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+ }
+
+ uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+ if (ptr->flags.binary_protocol)
+ {
+ rc= binary_touch(instance, key, key_length, expiration);
+ }
+ else
+ {
+ rc= ascii_touch(instance, key, key_length, expiration);
+ }
+
+ if (memcached_failed(rc))
+ {
+ return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while writing touch command to server"));
+ }
+
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ rc= memcached_read_one_response(instance, buffer, sizeof(buffer), NULL);
+
+ if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_NOTFOUND)
+ {
+ return rc;
+ }
+
+ return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while reading response"));
+}
memcached_return_t memcached_version(memcached_st *ptr)
{
+ memcached_return_t rc;
+ if (memcached_failed(rc= initialize_query(ptr)))
+ {
+ return rc;
+ }
+
if (ptr->flags.use_udp)
+ {
return MEMCACHED_NOT_SUPPORTED;
-
- memcached_return_t rc;
+ }
if (ptr->flags.binary_protocol)
+ {
rc= memcached_version_binary(ptr);
+ }
else
+ {
rc= memcached_version_textual(ptr);
+ }
return rc;
}
static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
{
- size_t send_length;
- memcached_return_t rc;
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- char *response_ptr;
- const char *command= "version\r\n";
-
- send_length= sizeof("version\r\n") -1;
-
- rc= MEMCACHED_SUCCESS;
+ memcached_return_t rc= MEMCACHED_SUCCESS;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- memcached_return_t rrc;
- memcached_server_write_instance_st instance=
- memcached_server_instance_fetch(ptr, x);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
// Optimization, we only fetch version once.
if (instance->major_version != UINT8_MAX)
+ {
continue;
+ }
- rrc= memcached_do(instance, command, send_length, true);
- if (rrc != MEMCACHED_SUCCESS)
+ memcached_return_t rrc= memcached_do(instance, memcached_literal_param("version\r\n"), true);
+ if (memcached_failed(rrc))
{
+ (void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
- if (rrc != MEMCACHED_SUCCESS)
+ if (memcached_failed(rrc))
{
+ memcached_set_error(*instance, rrc, MEMCACHED_AT);
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
/* Find the space, and then move one past it to copy version */
- response_ptr= index(buffer, ' ');
+ char *response_ptr= index(buffer, ' ');
response_ptr++;
- instance->major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
- if (errno == ERANGE)
+ long int version= strtol(response_ptr, (char **)NULL, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->major_version= uint8_t(version);
response_ptr= index(response_ptr, '.');
response_ptr++;
- instance->minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
- if (errno == ERANGE)
+ version= strtol(response_ptr, (char **)NULL, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->minor_version= uint8_t(version);
response_ptr= index(response_ptr, '.');
response_ptr++;
- instance->micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
- if (errno == ERANGE)
+
+ version= strtol(response_ptr, (char **)NULL, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->micro_version= uint8_t(version);
}
return rc;
static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
{
- memcached_return_t rc;
protocol_binary_request_version request= {};
request.message.header.request.magic= PROTOCOL_BINARY_REQ;
request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
- rc= MEMCACHED_SUCCESS;
+ memcached_return_t rc= MEMCACHED_SUCCESS;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
- memcached_return_t rrc;
-
- memcached_server_write_instance_st instance=
- memcached_server_instance_fetch(ptr, x);
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
if (instance->major_version != UINT8_MAX)
+ {
continue;
+ }
- rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
- if (rrc != MEMCACHED_SUCCESS)
+ memcached_return_t rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
+ if (memcached_failed(rrc))
{
memcached_io_reset(instance);
rc= MEMCACHED_SOME_ERRORS;
memcached_server_instance_fetch(ptr, x);
if (instance->major_version != UINT8_MAX)
+ {
continue;
+ }
if (memcached_server_response_count(instance) > 0)
{
- memcached_return_t rrc;
char buffer[32];
char *p;
- rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
- if (rrc != MEMCACHED_SUCCESS)
+ memcached_return_t rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+ if (memcached_failed(rrc))
{
memcached_io_reset(instance);
rc= MEMCACHED_SOME_ERRORS;
continue;
}
- instance->major_version= (uint8_t)strtol(buffer, &p, 10);
- if (errno == ERANGE)
+ long int version= strtol(buffer, &p, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->major_version= uint8_t(version);
- instance->minor_version= (uint8_t)strtol(p + 1, &p, 10);
- if (errno == ERANGE)
+ version= strtol(p +1, &p, 10);
+ if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
+ instance->minor_version= uint8_t(version);
- instance->micro_version= (uint8_t)strtol(p + 1, NULL, 10);
+ version= strtol(p + 1, NULL, 10);
if (errno == ERANGE)
{
+ memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
-
+ instance->micro_version= uint8_t(version);
}
}
#include <libmemcachedutil/common.h>
+#include <cassert>
struct local_context
{
struct local_context *check= (struct local_context *)context;
if (instance->major_version != UINT8_MAX &&
- instance->major_version >= check->major_version &&
- instance->minor_version >= check->minor_version &&
+ instance->major_version >= check->major_version and
+ instance->minor_version >= check->minor_version and
instance->micro_version >= check->micro_version )
{
return MEMCACHED_SUCCESS;
uint8_t minor_version,
uint8_t micro_version)
{
- if (memcached_version(memc) != MEMCACHED_SUCCESS)
+ if (memcached_failed(memcached_version(memc)))
+ {
return false;
+ }
struct local_context check= { major_version, minor_version, micro_version, true };
+++ /dev/null
-# progtest.m4 serial 6 (gettext-0.18)
-dnl Copyright (C) 1996-2003, 2005, 2008-2010 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-dnl
-dnl This file can can be used in projects which are not available under
-dnl the GNU General Public License or the GNU Library General Public
-dnl License but which still want to provide support for the GNU gettext
-dnl functionality.
-dnl Please note that the actual code of the GNU gettext library is covered
-dnl by the GNU Library General Public License, and the rest of the GNU
-dnl gettext package package is covered by the GNU General Public License.
-dnl They are *not* in the public domain.
-
-dnl Authors:
-dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
-
-AC_PREREQ([2.50])
-
-# Search path for a program which passes the given test.
-
-dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
-dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
-AC_DEFUN([AM_PATH_PROG_WITH_TEST],
-[
-# Prepare PATH_SEPARATOR.
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-# Find out how to test for executable files. Don't use a zero-byte file,
-# as systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- ac_executable_p="test -x"
-else
- ac_executable_p="test -f"
-fi
-rm -f conf$$.file
-
-# Extract the first word of "$2", so it can be a program name with args.
-set dummy $2; ac_word=[$]2
-AC_MSG_CHECKING([for $ac_word])
-AC_CACHE_VAL([ac_cv_path_$1],
-[case "[$]$1" in
- [[\\/]]* | ?:[[\\/]]*)
- ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
- ;;
- *)
- ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in ifelse([$5], , $PATH, [$5]); do
- IFS="$ac_save_IFS"
- test -z "$ac_dir" && ac_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
- echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
- if [$3]; then
- ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
- break 2
- fi
- fi
- done
- done
- IFS="$ac_save_IFS"
-dnl If no 4th arg is given, leave the cache variable unset,
-dnl so AC_PATH_PROGS will keep looking.
-ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
-])dnl
- ;;
-esac])dnl
-$1="$ac_cv_path_$1"
-if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
- AC_MSG_RESULT([$][$1])
-else
- AC_MSG_RESULT([no])
-fi
-AC_SUBST([$1])dnl
-])
memcp - Copy files to memcached servers.
memerror - Creates human readable messages from libmemecached error codes.
memcapable - Verify a memcached server for protocol behavior.
+memexist - Check for the existance of a key.
+memtouch - Update the expiration value of a key.
%package devel
%{_includedir}/libmemcached-1.0/dump.h
%{_includedir}/libmemcached-1.0/error.h
%{_includedir}/libmemcached-1.0/exist.h
+%{_includedir}/libmemcached-1.0/touch.h
%{_includedir}/libmemcached-1.0/exception.hpp
%{_includedir}/libmemcached-1.0/fetch.h
%{_includedir}/libmemcached-1.0/flush.h
%{_mandir}/man3/memcached_strerror.3.gz
%{_mandir}/man3/memcached_exist.3.gz
%{_mandir}/man3/memcached_exist_by_key.3.gz
+%{_mandir}/man3/memcached_touch.3.gz
+%{_mandir}/man3/memcached_touch_by_key.3.gz
%{_mandir}/man3/memcached_verbosity.3.gz
%{_mandir}/man3/memcached_version.3.gz
tests/libmemcached_world.h \
tests/namespace.h \
tests/parser.h \
+ tests/touch.h \
tests/deprecated.h \
tests/pool.h \
tests/print.h \
tests/mem_functions.cc \
tests/namespace.cc \
tests/parser.cc \
+ tests/touch.cc \
tests/callbacks.cc \
tests/pool.cc \
tests/print.cc \
tests_memcapable_SOURCES= tests/memcapable.cc
tests_memcapable_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memcapable_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memcapable_LDADD= $(tests_memcapable_DEPENDENCIES)
+tests_memcapable_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memcapable
+tests_memcapable_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memcapable
noinst_PROGRAMS+= tests/memcapable
tests_memstat_SOURCES= tests/memstat.cc
tests_memstat_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memstat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memstat_LDADD= $(tests_memstat_DEPENDENCIES)
+tests_memstat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memstat
+tests_memstat_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memstat
noinst_PROGRAMS+= tests/memstat
tests_memcp_SOURCES= tests/memcp.cc
tests_memcp_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memcp_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memcp_LDADD= $(tests_memcp_DEPENDENCIES)
+tests_memcp_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memcp
+tests_memcp_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memcp
noinst_PROGRAMS+= tests/memcp
tests_memflush_SOURCES= tests/memflush.cc
tests_memflush_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memflush_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memflush_LDADD= $(tests_memflush_DEPENDENCIES)
+tests_memflush_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memflush
+tests_memflush_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memflush
noinst_PROGRAMS+= tests/memflush
tests_memrm_SOURCES= tests/memrm.cc
tests_memrm_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memrm_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memrm_LDADD= $(tests_memrm_DEPENDENCIES)
+tests_memrm_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memrm
+tests_memrm_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memrm
noinst_PROGRAMS+= tests/memrm
tests_memexist_SOURCES= tests/memexist.cc
tests_memexist_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memexist_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memexist_LDADD= $(tests_memexist_DEPENDENCIES)
+tests_memexist_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memexist
+tests_memexist_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memexist
noinst_PROGRAMS+= tests/memexist
+tests_memtouch_SOURCES= tests/memtouch.cc
+tests_memtouch_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
+tests_memtouch_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memtouch
+tests_memtouch_LDADD= libtest/libtest.la $(TESTS_LDADDS)
+check_PROGRAMS+= tests/memtouch
+noinst_PROGRAMS+= tests/memtouch
+
tests_memcat_SOURCES= tests/memcat.cc
tests_memcat_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memcat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memcat_LDADD= $(tests_memcat_DEPENDENCIES)
+tests_memcat_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memcat
+tests_memcat_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memcat
noinst_PROGRAMS+= tests/memcat
tests_memerror_SOURCES= tests/memerror.cc
tests_memerror_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memerror_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memerror_LDADD= $(tests_memerror_DEPENDENCIES)
+tests_memerror_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memerror
+tests_memerror_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memerror
noinst_PROGRAMS+= tests/memerror
tests_memslap_SOURCES= tests/memslap.cc
tests_memslap_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memslap_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memslap_LDADD= $(tests_memslap_DEPENDENCIES)
+tests_memslap_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memslap
+tests_memslap_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memslap
noinst_PROGRAMS+= tests/memslap
tests_memdump_SOURCES= tests/memdump.cc
tests_memdump_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_memdump_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS)
-tests_memdump_LDADD= $(tests_memdump_DEPENDENCIES)
+tests_memdump_DEPENDENCIES= libtest/libtest.la $(TESTS_LDADDS) clients/memdump
+tests_memdump_LDADD= libtest/libtest.la $(TESTS_LDADDS)
check_PROGRAMS+= tests/memdump
noinst_PROGRAMS+= tests/memdump
buffer, sizeof(buffer)),
container->construct.option_string().c_str());
- test_true(not container->parent);
+ test_null(container->parent);
container->parent= memcached(container->construct.option_string().c_str(), container->construct.option_string().size());
test_true(container->parent);
+ test_compare(MEMCACHED_SUCCESS, memcached_version(container->parent));
if (container->construct.sasl())
{
static test_return_t world_test_startup(libmemcached_test_container_st *container)
{
test_true(container);
- test_true(not container->memc);
+ test_null(container->memc);
test_true(container->parent);
container->memc= memcached_clone(NULL, container->parent);
test_true(container->memc);
return TEST_SUCCESS;
}
-static test_return_t world_on_error(test_return_t test_state, libmemcached_test_container_st *container)
+static test_return_t world_on_error(test_return_t , libmemcached_test_container_st *container)
{
- (void)test_state;
test_true(container->memc);
memcached_free(container->memc);
container->memc= NULL;
#include "tests/ketama.h"
#include "tests/namespace.h"
#include "tests/parser.h"
+#include "tests/touch.h"
#include "tests/callbacks.h"
#include "tests/pool.h"
#include "tests/print.h"
static const char *global_keys[GLOBAL_COUNT];
static size_t global_keys_length[GLOBAL_COUNT];
-// Prototype
-static test_return_t pre_binary(memcached_st *memc);
+/**
+ @note This should be testing to see if the server really supports the binary protocol.
+*/
+static test_return_t pre_binary(memcached_st *memc)
+{
+ memcached_return_t rc= MEMCACHED_FAILURE;
+
+ if (libmemcached_util_version_check(memc, 1, 4, 4))
+ {
+ rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
+ test_compare(MEMCACHED_SUCCESS, rc);
+ test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
+ }
+
+ return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
+}
static test_return_t init_test(memcached_st *not_used)
/* Do a large mget() over all the keys we think exist */
static test_return_t user_supplied_bug3(memcached_st *memc)
{
- unsigned int setter= 1;
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, setter);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, setter);
+ test_compare(true, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1));
+ test_compare(true, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1));
#ifdef NOT_YET
setter = 20 * 1024576;
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE, setter);
{
char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
int key_length= snprintf(key, sizeof(key), "%u", x);
+ test_true(key_length);
keys[x]= strdup(key);
test_true(keys[x]);
key_lengths[x]= key_length;
memcached_return_t rc;
value= memcached_get(memc, keys[0], key_length[0],
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_false(value);
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 4));
memcached_return_t rc;
uint32_t count= 0;
while ((value= memcached_fetch(memc, return_key, &return_key_length,
- &value_length, &flags, &rc)))
+ &value_length, &flags, &rc)))
{
count++;
}
flags= 0;
value= memcached_get(memc, keys, key_length,
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_true(flags == 245);
test_true(value);
free(value);
value, value_length, 0, 0);
test_true_got((rc == MEMCACHED_SUCCESS or rc == MEMCACHED_WRITE_FAILURE or rc == MEMCACHED_BUFFERED or rc == MEMCACHED_TIMEOUT or rc == MEMCACHED_CONNECTION_FAILURE
- or rc == MEMCACHED_SERVER_TEMPORARILY_DISABLED),
+ or rc == MEMCACHED_SERVER_TEMPORARILY_DISABLED),
memcached_strerror(NULL, rc));
if (rc == MEMCACHED_WRITE_FAILURE or rc == MEMCACHED_TIMEOUT)
uint64_t number_value;
value= memcached_get(memc, "autoincrement", strlen("autoincrement"),
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_true(value == NULL);
test_compare(MEMCACHED_NOTFOUND, rc);
rc= memcached_set(memc, "autoincrement", strlen("autoincrement"), "1", 1, 0, 0);
value= memcached_get(memc, "autoincrement", strlen("autoincrement"),
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_true(value);
test_compare(MEMCACHED_SUCCESS, rc);
free(value);
/*
Bug found where command total one more than MEMCACHED_MAX_BUFFER
set key34567890 0 0 8169 \r\n is sent followed by buffer of size 8169, followed by 8169
- */
+*/
static test_return_t user_supplied_bug13(memcached_st *memc)
{
char key[] = "key34567890";
Bug found where command total one more than MEMCACHED_MAX_BUFFER
set key34567890 0 0 8169 \r\n
is sent followed by buffer of size 8169, followed by 8169
- */
+*/
static test_return_t user_supplied_bug14(memcached_st *memc)
{
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true);
/*
Look for zero length value problems
- */
+*/
static test_return_t user_supplied_bug15(memcached_st *memc)
{
for (uint32_t x= 0; x < 2; x++)
size_t length;
uint32_t flags;
char *value= memcached_get(memc, test_literal_param("mykey"),
- &length, &flags, &rc);
+ &length, &flags, &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_true(value == NULL);
/* Check the validity of chinese key*/
static test_return_t user_supplied_bug17(memcached_st *memc)
{
- const char *key= "豆瓣";
- const char *value="我们在炎热抑郁的夏天无法停止豆瓣";
- memcached_return_t rc= memcached_set(memc, key, strlen(key),
- value, strlen(value),
- (time_t)0, 0);
+ const char *key= "豆瓣";
+ const char *value="我们在炎热抑郁的夏天无法停止豆瓣";
+ memcached_return_t rc= memcached_set(memc, key, strlen(key),
+ value, strlen(value),
+ (time_t)0, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS, rc);
- size_t length;
- uint32_t flags;
- char *value2= memcached_get(memc, key, strlen(key),
- &length, &flags, &rc);
+ size_t length;
+ uint32_t flags;
+ char *value2= memcached_get(memc, key, strlen(key),
+ &length, &flags, &rc);
- test_true(length==strlen(value));
- test_compare(MEMCACHED_SUCCESS, rc);
- test_memcmp(value, value2, length);
- free(value2);
+ test_true(length==strlen(value));
+ test_compare(MEMCACHED_SUCCESS, rc);
+ test_memcmp(value, value2, length);
+ free(value2);
- return TEST_SUCCESS;
+ return TEST_SUCCESS;
}
#endif
static test_return_t user_supplied_bug21(memcached_st *memc)
{
- test_return_t test_rc;
- test_rc= pre_binary(memc);
-
- if (test_rc != TEST_SUCCESS)
- {
- return test_rc;
- }
+ test_skip(TEST_SUCCESS, pre_binary(memc));
/* should work as of r580 */
test_compare(TEST_SUCCESS,
snprintf(buffer, SMALL_STRING_LEN, "%lu.example.com", (unsigned long)(400 +x));
servers= memcached_server_list_append_with_weight(servers, buffer, 401, 0,
- &rc);
+ &rc);
test_compare(MEMCACHED_SUCCESS, rc);
test_compare(x, memcached_server_list_count(servers));
}
return TEST_SUCCESS;
}
-/**
- @note This should be testing to see if the server really supports the binary protocol.
-*/
-static test_return_t pre_binary(memcached_st *memc)
-{
- memcached_return_t rc= MEMCACHED_FAILURE;
-
- if (libmemcached_util_version_check(memc, 1, 4, 4))
- {
- rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
- test_compare(MEMCACHED_SUCCESS, rc);
- test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
- }
-
- return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
-}
-
static test_return_t pre_replication(memcached_st *memc)
{
test_skip(TEST_SUCCESS, pre_binary(memc));
/*
* Make sure that we store the item on all servers
* (master + replicas == number of servers)
- */
+ */
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, memcached_server_count(memc) - 1));
test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS), uint64_t(memcached_server_count(memc) - 1));
}
/*
- ** NOTE: Don't ever do this in your code! this is not a supported use of the
- ** API and is _ONLY_ done this way to verify that the library works the
- ** way it is supposed to do!!!!
- */
+ ** NOTE: Don't ever do this in your code! this is not a supported use of the
+ ** API and is _ONLY_ done this way to verify that the library works the
+ ** way it is supposed to do!!!!
+ */
int no_msg=0;
for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
{
/*
** Now validate that all items was set properly!
- */
+ */
for (size_t x= 0; x < 100; ++x)
{
char key[10];
/* Try setting an illegal cas value (should not return an error to
* the caller (because we don't expect a return message from the server)
- */
+ */
const char* keys[]= {"0"};
size_t lengths[]= {1};
size_t length;
/*
* The item will have a new cas value, so try to set it again with the old
* value. This should fail!
- */
+ */
test_compare(MEMCACHED_SUCCESS,
memcached_cas(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0, cas));
test_true(memcached_flush_buffers(memc) == MEMCACHED_SUCCESS);
/* verify that I can set behaviors on the pool when I don't have all
* of the connections in the pool. It should however be enabled
* when I push the item into the pool
- */
+ */
mmc[0]= memcached_pool_fetch(pool, NULL, NULL);
test_true(mmc[0]);
static test_return_t util_version_test(memcached_st *memc)
{
- bool if_successful= libmemcached_util_version_check(memc, 0, 0, 0);
- test_true(if_successful);
+ test_compare_hint(MEMCACHED_SUCCESS, memcached_version(memc), memcached_last_error_message(memc));
+ test_true(libmemcached_util_version_check(memc, 0, 0, 0));
- if_successful= libmemcached_util_version_check(memc, 9, 9, 9);
+ bool if_successful= libmemcached_util_version_check(memc, 9, 9, 9);
// We expect failure
if (if_successful)
static test_return_t regression_bug_434484(memcached_st *memc)
{
- test_return_t test_rc;
- test_rc= pre_binary(memc);
-
- if (test_rc != TEST_SUCCESS)
- return test_rc;
+ test_skip(TEST_SUCCESS, pre_binary(memc));
const char *key= "regression_bug_434484";
size_t keylen= strlen(key);
static test_return_t regression_bug_434843(memcached_st *memc)
{
- test_return_t test_rc;
- test_rc= pre_binary(memc);
-
- if (test_rc != TEST_SUCCESS)
- return test_rc;
+ test_skip(TEST_SUCCESS, pre_binary(memc));
memcached_return_t rc;
size_t counter= 0;
* sending in the pipleine to the server. Let's try to do a multiget of
* 1024 (that should satisfy most users don't you think?). Future versions
* will include a mget_execute function call if you need a higher number.
- */
+ */
uint32_t number_of_hosts= memcached_server_count(memc);
memc->number_of_hosts= 1;
const size_t max_keys= 1024;
for (size_t x= 0; x < max_keys; ++x)
{
- char k[251];
+ char k[251];
- key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%lu", (unsigned long)x);
- keys[x]= strdup(k);
- test_true(keys[x]);
+ key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%lu", (unsigned long)x);
+ keys[x]= strdup(k);
+ test_true(keys[x]);
}
/*
* Run two times.. the first time we should have 100% cache miss,
* and the second time we should have 100% cache hits
- */
+ */
for (size_t y= 0; y < 2; y++)
{
test_compare(MEMCACHED_SUCCESS,
else
{
/* Verify that we received all of the key/value pairs */
- test_compare(counter, max_keys);
+ test_compare(counter, max_keys);
}
}
for (uint32_t x= 0; x < 250; ++x)
{
- len= (size_t)snprintf(k, sizeof(k), "%0250u", x);
- memcached_return_t rc= memcached_delete(memc, k, len, 0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ len= (size_t)snprintf(k, sizeof(k), "%0250u", x);
+ memcached_return_t rc= memcached_delete(memc, k, len, 0);
+ test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
}
(void)snprintf(k, sizeof(k), "%037u", 251U);
}
/*
- ** We are using the quiet commands to store the replicas, so we need
- ** to ensure that all of them are processed before we can continue.
- ** In the test we go directly from storing the object to trying to
- ** receive the object from all of the different servers, so we
- ** could end up in a race condition (the memcached server hasn't yet
- ** processed the quiet command from the replication set when it process
- ** the request from the other client (created by the clone)). As a
- ** workaround for that we call memcached_quit to send the quit command
- ** to the server and wait for the response ;-) If you use the test code
- ** as an example for your own code, please note that you shouldn't need
- ** to do this ;-)
- */
+ ** We are using the quiet commands to store the replicas, so we need
+ ** to ensure that all of them are processed before we can continue.
+ ** In the test we go directly from storing the object to trying to
+ ** receive the object from all of the different servers, so we
+ ** could end up in a race condition (the memcached server hasn't yet
+ ** processed the quiet command from the replication set when it process
+ ** the request from the other client (created by the clone)). As a
+ ** workaround for that we call memcached_quit to send the quit command
+ ** to the server and wait for the response ;-) If you use the test code
+ ** as an example for your own code, please note that you shouldn't need
+ ** to do this ;-)
+ */
memcached_quit(memc);
/* Verify that all messages are stored, and we didn't stuff too much
* into the servers
- */
+ */
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
* within the library, and this is not a supported interface.
* This is to verify correct behavior in the library. Fake that two servers
* are dead..
- */
+ */
instance_one= memcached_server_instance_by_position(memc, 0);
instance_two= memcached_server_instance_by_position(memc, 2);
in_port_t port0= instance_one->port;
/* but there is a bug in some of the memcached servers (1.4) that treats
* the counter as noreply so it doesn't send the proper error message
- */
+ */
test_true_got(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR || rc == MEMCACHED_INVALID_ARGUMENTS, memcached_strerror(NULL, rc));
/* And buffered mode should be disabled and we should get protocol error */
* Please note that I'm abusing the internal structures in libmemcached
* in a non-portable way and you shouldn't be doing this. I'm only
* doing this in order to verify that the library works the way it should
- */
+ */
uint32_t number_of_hosts= memcached_server_count(memc);
memc->number_of_hosts= 1;
/* The test is to see that the memcached_quit doesn't increase the
* the server failure conter, so let's ensure that it is zero
* before sending quit
- */
+ */
((memcached_server_write_instance_st)instance)->server_failure_counter= 0;
memcached_quit(memc);
/* Verify that it memcached_quit didn't increment the failure counter
* Please note that this isn't bullet proof, because an error could
* occur...
- */
+ */
test_zero(instance->server_failure_counter);
/* restore the instance */
/*
* I only want to hit _one_ server so I know the number of requests I'm
* sending in the pipeline.
- */
+ */
uint32_t number_of_hosts= memc->number_of_hosts;
memc->number_of_hosts= 1;
size_t max_keys= 20480;
test_compare(MEMCACHED_INVALID_ARGUMENTS, libmemcached_check_configuration(0, 0, buffer, 0));
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, 0));
-
+
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, 1));
test_compare(buffer[0], 0);
-
+
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, 10));
test_true(strlen(buffer));
test_compare(MEMCACHED_PARSE_ERROR, libmemcached_check_configuration(test_literal_param("syntax error"), buffer, sizeof(buffer)));
test_true(strlen(buffer));
-
+
return TEST_SUCCESS;
}
{"memcached_exist(MEMCACHED_SUCCESS)", true, (test_callback_fn*)memcached_exist_SUCCESS },
{"memcached_exist_by_key(MEMCACHED_NOTFOUND)", true, (test_callback_fn*)memcached_exist_by_key_NOTFOUND },
{"memcached_exist_by_key(MEMCACHED_SUCCESS)", true, (test_callback_fn*)memcached_exist_by_key_SUCCESS },
+ {"memcached_touch", 0, (test_callback_fn*)test_memcached_touch},
+ {"memcached_touch_with_prefix", 0, (test_callback_fn*)test_memcached_touch_by_key},
+ {0, 0, 0}
+};
+
+test_st touch_tests[] ={
+ {"memcached_touch", 0, (test_callback_fn*)test_memcached_touch},
+ {"memcached_touch_with_prefix", 0, (test_callback_fn*)test_memcached_touch_by_key},
{0, 0, 0}
};
{"user_supplied_bug16", true, (test_callback_fn*)user_supplied_bug16 },
#if !defined(__sun) && !defined(__OpenBSD__)
/*
- ** It seems to be something weird with the character sets..
- ** value_fetch is unable to parse the value line (iscntrl "fails"), so I
- ** guess I need to find out how this is supposed to work.. Perhaps I need
- ** to run the test in a specific locale (I tried zh_CN.UTF-8 without success,
- ** so just disable the code for now...).
- */
+ ** It seems to be something weird with the character sets..
+ ** value_fetch is unable to parse the value line (iscntrl "fails"), so I
+ ** guess I need to find out how this is supposed to work.. Perhaps I need
+ ** to run the test in a specific locale (I tried zh_CN.UTF-8 without success,
+ ** so just disable the code for now...).
+ */
{"user_supplied_bug17", true, (test_callback_fn*)user_supplied_bug17 },
#endif
{"user_supplied_bug18", true, (test_callback_fn*)user_supplied_bug18 },
{0, 0, (test_callback_fn*)0}
};
-
test_st parser_tests[] ={
{"behavior", false, (test_callback_fn*)behavior_parser_test },
{"boolean_options", false, (test_callback_fn*)parser_boolean_options_test },
{"parser", 0, 0, parser_tests},
{"virtual buckets", 0, 0, virtual_bucket_tests},
{"memcached_server_get_last_disconnect", 0, 0, memcached_server_get_last_disconnect_tests},
+ {"touch", 0, 0, touch_tests},
{0, 0, 0, 0}
};
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Test memtouch
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/*
+ Test that we are cycling the servers we are creating during testing.
+*/
+
+#include <config.h>
+
+#include <libtest/test.hpp>
+#include <libmemcached/memcached.h>
+
+using namespace libtest;
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+
+static std::string executable;
+
+static test_return_t quiet_test(void *)
+{
+ const char *args[]= { "--quiet", 0 };
+
+ test_true(exec_cmdline(executable, args));
+ return TEST_SUCCESS;
+}
+
+static test_return_t help_test(void *)
+{
+ const char *args[]= { "--quiet", "--help", 0 };
+
+ test_true(exec_cmdline(executable, args));
+ return TEST_SUCCESS;
+}
+
+static test_return_t touch_test(void *)
+{
+ char buffer[1024];
+ snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
+ const char *args[]= { "--quiet", "--expire=30", buffer, "foo", 0 };
+
+ memcached_st *memc= memcached(buffer, strlen(buffer));
+ test_true(memc);
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, test_literal_param("foo"), 0, 0, 0, 0));
+
+ test_compare(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("foo")));
+
+ test_true(exec_cmdline(executable, args));
+
+ test_compare(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("foo")));
+
+ memcached_free(memc);
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t NOT_FOUND_test(void *)
+{
+ char buffer[1024];
+ snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
+ const char *args[]= { "--quiet", "--expire=30", buffer, "foo", 0 };
+
+ memcached_st *memc= memcached(buffer, strlen(buffer));
+ test_true(memc);
+
+ test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
+
+ test_compare(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("foo")));
+
+ test_true(exec_cmdline(executable, args));
+
+ test_compare(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("foo")));
+
+ memcached_free(memc);
+
+ return TEST_SUCCESS;
+}
+
+test_st memtouch_tests[] ={
+ {"--quiet", true, quiet_test },
+ {"--help", true, help_test },
+ {"touch(FOUND)", true, touch_test },
+ {"touch(NOT_FOUND)", true, NOT_FOUND_test },
+ {0, 0, 0}
+};
+
+collection_st collection[] ={
+ {"memtouch", 0, 0, memtouch_tests },
+ {0, 0, 0, 0}
+};
+
+static void *world_create(server_startup_st& servers, test_return_t& error)
+{
+ if (HAVE_MEMCACHED_BINARY == 0)
+ {
+ error= TEST_FATAL;
+ return NULL;
+ }
+
+ const char *argv[1]= { "memtouch" };
+ if (not server_startup(servers, "memcached", MEMCACHED_DEFAULT_PORT +10, 1, argv))
+ {
+ error= TEST_FAILURE;
+ }
+
+ return &servers;
+}
+
+
+void get_world(Framework *world)
+{
+ executable= "./clients/memtouch";
+ world->collections= collection;
+ world->_create= world_create;
+}
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached Client and Server
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
+
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcachedutil-1.0/util.h>
+
+#include "tests/touch.h"
+
+static test_return_t pre_touch(memcached_st *memc)
+{
+ test_compare(MEMCACHED_SUCCESS, memcached_version(memc));
+ test_skip(true, libmemcached_util_version_check(memc, 1, 4, 8));
+
+ return TEST_SUCCESS;
+}
+
+test_return_t test_memcached_touch(memcached_st *memc)
+{
+
+ test_skip(TEST_SUCCESS, pre_touch(memc));
+
+ size_t len;
+ uint32_t flags;
+ memcached_return rc;
+
+ test_null(memcached_get(memc,
+ test_literal_param("touchkey"),
+ &len, &flags, &rc));
+ test_zero(len);
+ test_compare(MEMCACHED_NOTFOUND, rc);
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ test_literal_param("touchkey"),
+ test_literal_param("touchval"),
+ 2, 0));
+
+ {
+ char *value= memcached_get(memc,
+ test_literal_param("touchkey"),
+ &len, &flags, &rc);
+ test_compare(8U, test_literal_param_size("touchval"));
+ test_true(value);
+ test_strcmp(value, "touchval");
+ test_compare(MEMCACHED_SUCCESS, rc);
+ free(value);
+ }
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_touch(memc, test_literal_param("touchkey"), 60 *60));
+
+ test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+ rc= memcached_touch(memc, test_literal_param("touchkey"), 60 *60 *24 *60);
+ test_compare_hint(MEMCACHED_SUCCESS, rc, memcached_last_error_message(memc));
+
+ test_compare(MEMCACHED_NOTFOUND,
+ memcached_exist(memc, test_literal_param("touchkey")));
+
+ return TEST_SUCCESS;
+}
+
+test_return_t test_memcached_touch_by_key(memcached_st *memc)
+{
+
+ test_skip(TEST_SUCCESS, pre_touch(memc));
+
+ size_t len;
+ uint32_t flags;
+ memcached_return rc;
+
+ test_null(memcached_get_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ &len, &flags, &rc));
+ test_zero(len);
+ test_compare(MEMCACHED_NOTFOUND, rc);
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ test_literal_param("touchval"),
+ 2, 0));
+
+ {
+ char *value= memcached_get_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ &len, &flags, &rc);
+ test_compare(8U, test_literal_param_size("touchval"));
+ test_true(value);
+ test_strcmp(value, "touchval");
+ test_compare(MEMCACHED_SUCCESS, rc);
+ free(value);
+ }
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_touch_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ 60 *60));
+
+ test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_touch_by_key(memc,
+ test_literal_param("grouping_key"),
+ test_literal_param("touchkey"),
+ 60 *60 *24 *60));
+ test_compare(MEMCACHED_NOTFOUND,
+ memcached_exist_by_key(memc, test_literal_param("grouping_key"),test_literal_param("touchkey")));
+
+ return TEST_SUCCESS;
+}
+
+
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t test_memcached_touch(memcached_st *);
+test_return_t test_memcached_touch_by_key(memcached_st *);