From: Brian Aker Date: Tue, 28 Jun 2011 20:42:14 +0000 (-0700) Subject: Merge in namespace fixes for binary protocol. X-Git-Tag: 0.51~1^2~9^2~16 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=d8dedbd561c7cb57daf4192fe57ce5e205bcadd7;p=m6w6%2Flibmemcached Merge in namespace fixes for binary protocol. --- diff --git a/docs/memcached_behavior.rst b/docs/memcached_behavior.rst index 59ec4839..baa2eacd 100644 --- a/docs/memcached_behavior.rst +++ b/docs/memcached_behavior.rst @@ -257,7 +257,9 @@ When enabled a host which is problematic will only be checked for usage based on .. c:type:: MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY -When enabled the prefix key will be added to the key when determining server by hash. +When enabled the prefix key will be added to the key when determining server +by hash. See :c:type:`MEMCACHED_CALLBACK_NAMESPACE` for additional +information. diff --git a/docs/memcached_callback.rst b/docs/memcached_callback.rst index e5723d90..d5be9af6 100644 --- a/docs/memcached_callback.rst +++ b/docs/memcached_callback.rst @@ -53,6 +53,10 @@ When :c:func:`memcached_delete()` is called this function will be excuted. At the point of its execution all connections are closed. .. c:type:: MEMCACHED_CALLBACK_PREFIX_KEY + + See :c:type:`MEMCACHED_CALLBACK_NAMESPACE` + +.. c:type:: MEMCACHED_CALLBACK_NAMESPACE You can set a value which will be used to create a domain for your keys. The value specified here will be prefixed to each of your keys. The value can diff --git a/libmemcached/auto.cc b/libmemcached/auto.cc index 2bfc5bba..f1494ac3 100644 --- a/libmemcached/auto.cc +++ b/libmemcached/auto.cc @@ -49,8 +49,10 @@ static memcached_return_t text_incr_decr(memcached_st *ptr, memcached_server_write_instance_st instance; bool no_reply= ptr->flags.no_reply; - if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) + if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) + { return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT); + } server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); instance= memcached_server_instance_fetch(ptr, server_key); @@ -111,15 +113,13 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd, uint32_t expiration, uint64_t *value) { - uint32_t server_key; - memcached_server_write_instance_st instance; bool no_reply= ptr->flags.no_reply; if (memcached_server_count(ptr) == 0) return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT); - server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); - instance= memcached_server_instance_fetch(ptr, server_key); + uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); + memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key); if (no_reply) { @@ -144,12 +144,12 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd, struct libmemcached_io_vector_st vector[]= { { sizeof(request.bytes), request.bytes }, - { memcached_array_size(ptr->prefix_key), ptr->prefix_key }, + { memcached_array_size(ptr->prefix_key), memcached_array_string(ptr->prefix_key) }, { key_length, key } }; memcached_return_t rc; - if ((rc= memcached_vdo(instance, vector, 3, true)) != MEMCACHED_SUCCESS) + if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true))) { memcached_io_reset(instance); return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc; @@ -166,10 +166,6 @@ memcached_return_t memcached_increment(memcached_st *ptr, uint32_t offset, uint64_t *value) { - uint64_t local_value; - if (! value) - value= &local_value; - return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value); } @@ -178,10 +174,6 @@ memcached_return_t memcached_decrement(memcached_st *ptr, uint32_t offset, uint64_t *value) { - uint64_t local_value; - if (! value) - value= &local_value; - return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value); } diff --git a/libmemcached/behavior.cc b/libmemcached/behavior.cc index 60aa6b17..330be0b8 100644 --- a/libmemcached/behavior.cc +++ b/libmemcached/behavior.cc @@ -255,6 +255,11 @@ bool _is_auto_eject_host(const memcached_st *ptr) uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag) { + if (not ptr) + { + return MEMCACHED_INVALID_ARGUMENTS; + } + switch (flag) { case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: diff --git a/libmemcached/callback.cc b/libmemcached/callback.cc index 9818af4f..3625992e 100644 --- a/libmemcached/callback.cc +++ b/libmemcached/callback.cc @@ -26,7 +26,7 @@ memcached_return_t memcached_callback_set(memcached_st *ptr, { case MEMCACHED_CALLBACK_PREFIX_KEY: { - return memcached_set_prefix_key(ptr, (char*)data, data ? strlen((char*)data) : 0); + return memcached_set_namespace(ptr, (char*)data, data ? strlen((char*)data) : 0); } case MEMCACHED_CALLBACK_USER_DATA: { @@ -78,7 +78,6 @@ memcached_return_t memcached_callback_set(memcached_st *ptr, break; } case MEMCACHED_CALLBACK_MAX: - default: return MEMCACHED_FAILURE; } diff --git a/libmemcached/common.h b/libmemcached/common.h index 40f45111..98072cb3 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -66,6 +66,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -141,10 +142,13 @@ memcached_return_t run_distribution(memcached_st *ptr); LIBMEMCACHED_LOCAL void set_last_disconnected_host(memcached_server_write_instance_st ptr); +#ifdef __cplusplus LIBMEMCACHED_LOCAL -memcached_return_t memcached_key_test(const char * const *keys, +memcached_return_t memcached_key_test(const memcached_st& memc, + const char * const *keys, const size_t *key_length, size_t number_of_keys); +#endif LIBMEMCACHED_LOCAL memcached_return_t memcached_purge(memcached_server_write_instance_st ptr); @@ -161,7 +165,9 @@ memcached_server_st *memcached_server_create_with(const memcached_st *memc, static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary) { unlikely (key_length == 0) + { return MEMCACHED_BAD_KEY_PROVIDED; + } if (binary) { diff --git a/libmemcached/constants.h b/libmemcached/constants.h index 2cf27671..165745e7 100644 --- a/libmemcached/constants.h +++ b/libmemcached/constants.h @@ -127,7 +127,8 @@ enum memcached_callback_t { #endif MEMCACHED_CALLBACK_GET_FAILURE = 7, MEMCACHED_CALLBACK_DELETE_TRIGGER = 8, - MEMCACHED_CALLBACK_MAX + MEMCACHED_CALLBACK_MAX, + MEMCACHED_CALLBACK_NAMESPACE= MEMCACHED_CALLBACK_PREFIX_KEY }; #ifndef __cplusplus diff --git a/libmemcached/delete.cc b/libmemcached/delete.cc index 1ae891a7..e4738517 100644 --- a/libmemcached/delete.cc +++ b/libmemcached/delete.cc @@ -58,26 +58,26 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr, { bool to_write; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - uint32_t server_key; memcached_server_write_instance_st instance; LIBMEMCACHED_MEMCACHED_DELETE_START(); memcached_return_t rc; - if ((rc= initialize_query(ptr)) != MEMCACHED_SUCCESS) + if (memcached_failed(rc= initialize_query(ptr))) { return rc; } rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol); - unlikely (rc != MEMCACHED_SUCCESS) + + unlikely (memcached_failed(rc)) return rc; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; - server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); + uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); instance= memcached_server_instance_fetch(ptr, server_key); to_write= (ptr->flags.buffer_requests) ? false : true; diff --git a/libmemcached/exception.hpp b/libmemcached/exception.hpp index 665c816f..4759072a 100644 --- a/libmemcached/exception.hpp +++ b/libmemcached/exception.hpp @@ -10,8 +10,7 @@ * @brief Exception declarations */ -#ifndef LIBMEMACHED_EXCEPTION_HPP -#define LIBMEMACHED_EXCEPTION_HPP +#pragma once #include #include @@ -59,5 +58,3 @@ namespace memcache }; } /* namespace libmemcached */ - -#endif /* LIBMEMACHED_EXCEPTION_HPP */ diff --git a/libmemcached/fetch.cc b/libmemcached/fetch.cc index dd0b036d..7ef608dd 100644 --- a/libmemcached/fetch.cc +++ b/libmemcached/fetch.cc @@ -122,8 +122,6 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, memcached_result_st *result, memcached_return_t *error) { - memcached_server_st *server; - memcached_return_t unused; if (not error) error= &unused; @@ -159,6 +157,7 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, } *error= MEMCACHED_MAXIMUM_RETURN; // We use this to see if we ever go into the loop + memcached_server_st *server; while ((server= memcached_io_get_readable_server(ptr))) { char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; diff --git a/libmemcached/get.cc b/libmemcached/get.cc index 0cef87f5..ae0711f0 100644 --- a/libmemcached/get.cc +++ b/libmemcached/get.cc @@ -219,7 +219,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr, return memcached_set_error(*ptr, MEMCACHED_NOTFOUND, MEMCACHED_AT, memcached_literal_param("number_of_keys was zero")); } - if (ptr->flags.verify_key && (memcached_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED)) + 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")); } @@ -227,7 +227,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr, bool is_group_key_set= false; if (group_key && group_key_length) { - if (ptr->flags.verify_key and (memcached_key_test((const char * const *)&group_key, &group_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) + if (memcached_failed(memcached_key_test(*ptr, (const char * const *)&group_key, &group_key_length, 1))) { return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("A bad group key was provided.")); } diff --git a/libmemcached/include.am b/libmemcached/include.am index e799093f..e1bed44f 100644 --- a/libmemcached/include.am +++ b/libmemcached/include.am @@ -54,7 +54,7 @@ nobase_include_HEADERS+= \ libmemcached/memcached/vbucket.h \ libmemcached/options.h \ libmemcached/parse.h \ - libmemcached/prefix_key.h \ + libmemcached/namespace.h \ libmemcached/protocol/cache.h \ libmemcached/protocol/callback.h \ libmemcached/protocol_handler.h \ @@ -130,7 +130,7 @@ libmemcached_libmemcached_la_SOURCES+= \ libmemcached/memcached.cc \ libmemcached/options.cc \ libmemcached/parse.cc \ - libmemcached/prefix_key.cc \ + libmemcached/namespace.cc \ libmemcached/purge.cc \ libmemcached/quit.cc \ libmemcached/response.cc \ diff --git a/libmemcached/key.cc b/libmemcached/key.cc index c2c2b14b..02e0c2b3 100644 --- a/libmemcached/key.cc +++ b/libmemcached/key.cc @@ -1,20 +1,67 @@ -#include "common.h" +/* 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. + * + */ -memcached_return_t memcached_key_test(const char * const *keys, +#include + +memcached_return_t memcached_key_test(const memcached_st &memc, + const char * const *keys, const size_t *key_length, size_t number_of_keys) { + if (not memc.flags.verify_key) + return MEMCACHED_SUCCESS; + + if (memc.flags.binary_protocol) + return MEMCACHED_SUCCESS; + for (uint32_t x= 0; x < number_of_keys; x++) { - memcached_return_t rc; - rc= memcached_validate_key_length(*(key_length + x), false); - if (rc != MEMCACHED_SUCCESS) + memcached_return_t rc= memcached_validate_key_length(*(key_length + x), false); + if (memcached_failed(rc)) + { return rc; + } for (size_t y= 0; y < *(key_length + x); y++) { if ((isgraph(keys[x][y])) == 0) + { return MEMCACHED_BAD_KEY_PROVIDED; + } } } diff --git a/libmemcached/namespace.cc b/libmemcached/namespace.cc new file mode 100644 index 00000000..d9961e29 --- /dev/null +++ b/libmemcached/namespace.cc @@ -0,0 +1,85 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +memcached_return_t memcached_set_namespace(memcached_st *self, const char *key, size_t key_length) +{ + WATCHPOINT_ASSERT(self); + + if (key and key_length == 0) + { + WATCHPOINT_ASSERT(key_length); + return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid namespace, namespace string had value but length was 0")); + } + else if (key_length and key == NULL) + { + WATCHPOINT_ASSERT(key); + return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid namespace, namespace string length was > 1 but namespace string was null ")); + } + else if (key and key_length) + { + bool orig= self->flags.verify_key; + self->flags.verify_key= true; + 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); + } + self->flags.verify_key= orig; + + if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1)) + { + return memcached_set_error(*self, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT); + } + + memcached_array_free(self->prefix_key); + self->prefix_key= memcached_strcpy(self, key, key_length); + + if (not self->prefix_key) + { + return memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT); + } + } + else + { + memcached_array_free(self->prefix_key); + self->prefix_key= NULL; + } + + return MEMCACHED_SUCCESS; +} diff --git a/libmemcached/namespace.h b/libmemcached/namespace.h new file mode 100644 index 00000000..60cddd65 --- /dev/null +++ b/libmemcached/namespace.h @@ -0,0 +1,49 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +LIBMEMCACHED_LOCAL + memcached_return_t memcached_set_namespace(memcached_st *self, const char *str, size_t length); + +#ifdef __cplusplus +} +#endif diff --git a/libmemcached/options/parser.cc b/libmemcached/options/parser.cc index 2e478dcc..5e9b6d36 100644 --- a/libmemcached/options/parser.cc +++ b/libmemcached/options/parser.cc @@ -1648,7 +1648,7 @@ yyreduce: /* Line 1464 of yacc.c */ #line 232 "libmemcached/options/parser.yy" { - if ((context->rc= memcached_set_prefix_key(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size)) != MEMCACHED_SUCCESS) + if ((context->rc= memcached_set_namespace(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size)) != MEMCACHED_SUCCESS) { parser_abort(context, NULL);; } diff --git a/libmemcached/options/parser.yy b/libmemcached/options/parser.yy index 722ced5f..8e87230a 100644 --- a/libmemcached/options/parser.yy +++ b/libmemcached/options/parser.yy @@ -230,7 +230,7 @@ expression: behaviors: NAMESPACE string { - if ((context->rc= memcached_set_prefix_key(context->memc, $2.c_str, $2.size)) != MEMCACHED_SUCCESS) + if ((context->rc= memcached_set_namespace(context->memc, $2.c_str, $2.size)) != MEMCACHED_SUCCESS) { parser_abort(context, NULL);; } diff --git a/libmemcached/prefix_key.cc b/libmemcached/prefix_key.cc deleted file mode 100644 index 8a24190e..00000000 --- a/libmemcached/prefix_key.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * - * Libmemcached library - * - * Copyright (C) 2011 Data Differential, http://datadifferential.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * The names of its contributors may not be used to endorse or - * promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -memcached_return_t memcached_set_prefix_key(memcached_st *self, const char *key, size_t key_length) -{ - WATCHPOINT_ASSERT(self); - - if (key and key_length) - { - if (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED) - return memcached_set_error(*self, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT); - - if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1)) - return memcached_set_error(*self, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT); - - memcached_array_free(self->prefix_key); - self->prefix_key= memcached_strcpy(self, key, key_length); - - if (not self->prefix_key) - return memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT); - } - else - { - memcached_array_free(self->prefix_key); - self->prefix_key= NULL; - } - - return MEMCACHED_SUCCESS; -} diff --git a/libmemcached/prefix_key.h b/libmemcached/prefix_key.h deleted file mode 100644 index bd81160f..00000000 --- a/libmemcached/prefix_key.h +++ /dev/null @@ -1,49 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * - * Libmemcached library - * - * Copyright (C) 2011 Data Differential, http://datadifferential.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * The names of its contributors may not be used to endorse or - * promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -LIBMEMCACHED_LOCAL - memcached_return_t memcached_set_prefix_key(memcached_st *self, const char *str, size_t length); - -#ifdef __cplusplus -} -#endif diff --git a/libmemcached/response.cc b/libmemcached/response.cc index ff1d77b1..44ce840a 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -58,9 +58,13 @@ memcached_return_t memcached_read_one_response(memcached_server_write_instance_s memcached_return_t rc; if (ptr->root->flags.binary_protocol) + { rc= binary_read_one_response(ptr, buffer, buffer_length, result); + } else + { rc= textual_read_one_response(ptr, buffer, buffer_length, result); + } unlikely(rc == MEMCACHED_UNKNOWN_READ_FAILURE or rc == MEMCACHED_PROTOCOL_ERROR or @@ -283,7 +287,6 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta } else if (buffer[1] == 'E') /* SERVER_ERROR */ { - char *rel_ptr; char *startptr= buffer + 13, *endptr= startptr; while (*endptr != '\r' && *endptr != '\n') endptr++; @@ -294,9 +297,9 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta memory in the struct, which is important, for something that rarely should happen? */ - rel_ptr= (char *)libmemcached_realloc(ptr->root, - ptr->cached_server_error, - (size_t) (endptr - startptr + 1)); + char *rel_ptr= (char *)libmemcached_realloc(ptr->root, + ptr->cached_server_error, + (size_t) (endptr - startptr + 1)); if (rel_ptr == NULL) { @@ -312,7 +315,9 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta return MEMCACHED_SERVER_ERROR; } else if (buffer[1] == 'T') + { return MEMCACHED_STORED; + } else { WATCHPOINT_STRING(buffer); @@ -321,6 +326,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta } case 'D': /* DELETED */ return MEMCACHED_DELETED; + case 'N': /* NOT_FOUND */ { if (buffer[4] == 'F') @@ -424,19 +430,35 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan bodylen -= header.response.extlen; result->key_length= keylen; - if ((rc= memcached_safe_read(ptr, result->item_key, keylen)) != MEMCACHED_SUCCESS) + if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, keylen))) { WATCHPOINT_ERROR(rc); return MEMCACHED_UNKNOWN_READ_FAILURE; } + // Only bother with doing this if key_length > 0 + if (result->key_length) + { + if (memcached_array_size(ptr->root->prefix_key) and memcached_array_size(ptr->root->prefix_key) >= result->key_length) + { + return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT); + } + + if (memcached_array_size(ptr->root->prefix_key)) + { + result->key_length-= memcached_array_size(ptr->root->prefix_key); + memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->prefix_key), result->key_length); + } + } + bodylen -= keylen; - if (memcached_string_check(&result->value, - bodylen) != MEMCACHED_SUCCESS) + if (memcached_failed(memcached_string_check(&result->value, bodylen))) + { return MEMCACHED_MEMORY_ALLOCATION_FAILURE; + } char *vptr= memcached_string_value_mutable(&result->value); - if ((rc= memcached_safe_read(ptr, vptr, bodylen)) != MEMCACHED_SUCCESS) + if (memcached_failed(rc= memcached_safe_read(ptr, vptr, bodylen))) { WATCHPOINT_ERROR(rc); return MEMCACHED_UNKNOWN_READ_FAILURE; @@ -445,11 +467,14 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan memcached_string_set_length(&result->value, bodylen); } break; + case PROTOCOL_BINARY_CMD_INCREMENT: case PROTOCOL_BINARY_CMD_DECREMENT: { if (bodylen != sizeof(uint64_t) || buffer_length != sizeof(uint64_t)) + { return MEMCACHED_PROTOCOL_ERROR; + } WATCHPOINT_ASSERT(bodylen == buffer_length); uint64_t val; @@ -463,6 +488,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan memcpy(buffer, &val, sizeof(val)); } break; + case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: case PROTOCOL_BINARY_CMD_VERSION: { diff --git a/libmemcached/server.cc b/libmemcached/server.cc index ea88967d..6d0a47d3 100644 --- a/libmemcached/server.cc +++ b/libmemcached/server.cc @@ -253,7 +253,7 @@ memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr, return NULL; } - if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) + if (memcached_failed((memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))) { *error= MEMCACHED_BAD_KEY_PROVIDED; return NULL; diff --git a/libmemcached/storage.cc b/libmemcached/storage.cc index c19f7ecc..fece7f9f 100644 --- a/libmemcached/storage.cc +++ b/libmemcached/storage.cc @@ -78,10 +78,14 @@ static inline memcached_return_t memcached_send(memcached_st *ptr, } if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol))) + { return rc; + } - if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) + 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); diff --git a/libmemcached/string.cc b/libmemcached/string.cc index 6f3b9c1c..0e174840 100644 --- a/libmemcached/string.cc +++ b/libmemcached/string.cc @@ -88,7 +88,7 @@ memcached_string_st *memcached_string_create(memcached_st *memc, memcached_strin { WATCHPOINT_ASSERT(self->options.is_initialized == false); - self->options.is_allocated= false; + memcached_set_allocated(self, false); } else { @@ -99,7 +99,7 @@ memcached_string_st *memcached_string_create(memcached_st *memc, memcached_strin return NULL; } - self->options.is_allocated= true; + memcached_set_allocated(self, true); } self->root= memc; @@ -107,7 +107,10 @@ memcached_string_st *memcached_string_create(memcached_st *memc, memcached_strin if (memcached_failed(_string_check(self, initial_size))) { - libmemcached_free(memc, self); + if (memcached_is_allocated(self)) + { + libmemcached_free(memc, self); + } return NULL; } diff --git a/libtest/test.h b/libtest/test.h index c36572ea..9939886f 100644 --- a/libtest/test.h +++ b/libtest/test.h @@ -25,7 +25,7 @@ struct test_st { do \ { \ if ((A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: ", __FILE__, __LINE__);\ + fprintf(stderr, "\n%s:%d: Assertion failed for %s: ", __FILE__, __LINE__, __func__);\ perror(#A); \ fprintf(stderr, "\n"); \ create_core(); \ @@ -37,7 +37,7 @@ do \ do \ { \ if ((A)) { \ - fprintf(stderr, "\nAssertion, %s(%s), failed at %s:%d: ", (B), #A, __FILE__, __LINE__);\ + fprintf(stderr, "\n%s:%d: Assertion failed %s, with message %s, in %s", __FILE__, __LINE__, (B), #A, __func__ );\ fprintf(stderr, "\n"); \ create_core(); \ assert((A)); \ @@ -48,7 +48,7 @@ do \ do \ { \ if (! (A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ + fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\ create_core(); \ return TEST_FAILURE; \ } \ @@ -58,7 +58,7 @@ do \ do \ { \ if (! (A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ + fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\ create_core(); \ return TEST_FAILURE; \ } \ @@ -68,7 +68,7 @@ do \ do \ { \ if (! (A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: \"%s\" received \"%s\"\n", __FILE__, __LINE__, #A, (B));\ + fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, received \"%s\"\n", __FILE__, __LINE__, #A, (B));\ create_core(); \ return TEST_FAILURE; \ } \ @@ -87,7 +87,7 @@ do \ do \ { \ if (1) { \ - fprintf(stderr, "\nFailed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ + fprintf(stderr, "\n%s:%d: Failed with %s, in %s\n", __FILE__, __LINE__, #A, __func__);\ create_core(); \ return TEST_FAILURE; \ } \ @@ -98,7 +98,7 @@ do \ do \ { \ if ((A)) { \ - fprintf(stderr, "\nAssertion failed in %s:%d: %s\n", __FILE__, __LINE__, #A);\ + fprintf(stderr, "\n%s:%d: Assertion failed %s, in %s\n", __FILE__, __LINE__, #A, __func__);\ create_core(); \ return TEST_FAILURE; \ } \ @@ -108,7 +108,7 @@ do \ do \ { \ if ((A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: %s with %s\n", __FILE__, __LINE__, #A, (B));\ + fprintf(stderr, "\n%s:%d: Assertion failed %s with %s\n", __FILE__, __LINE__, #A, (B));\ create_core(); \ return TEST_FAILURE; \ } \ @@ -160,3 +160,12 @@ do \ } \ } while (0) +#define test_return_if(__test_return_t) \ +do \ +{ \ + if ((__test_return_t) != TEST_SUCCESS) \ + { \ + return __test_return_t; \ + } \ +} while (0) + diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index ba496f32..3c2064f1 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -879,7 +879,7 @@ static test_return_t bad_key_test(memcached_st *memc) binary protocol */ test_compare(MEMCACHED_SUCCESS, - memcached_callback_set(memc_clone, MEMCACHED_CALLBACK_PREFIX_KEY, NULL)); + memcached_callback_set(memc_clone, MEMCACHED_CALLBACK_NAMESPACE, NULL)); char *longkey= (char *)malloc(max_keylen + 1); if (longkey) @@ -1252,7 +1252,10 @@ static test_return_t mget_end(memcached_st *memc) test_compare(MEMCACHED_SUCCESS, rc); int val = 0; if (key_length == 4) + { val= 1; + } + test_compare(string_length, strlen(values[val])); test_true(strncmp(values[val], string, string_length) == 0); free(string); @@ -1303,47 +1306,53 @@ static test_return_t stats_servername_test(memcached_st *memc) static test_return_t increment_test(memcached_st *memc) { uint64_t new_number; - memcached_return_t rc; - const char *key= "number"; - const char *value= "0"; - rc= memcached_set(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); + test_compare(MEMCACHED_SUCCESS, + memcached_set(memc, + test_literal_param("number"), + test_literal_param("0"), + (time_t)0, (uint32_t)0)); - rc= memcached_increment(memc, key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 1); + memcached_return_t rc; + test_compare_got(MEMCACHED_SUCCESS, + rc= memcached_increment(memc, + test_literal_param("number"), + 1, &new_number), + memcached_strerror(NULL, rc)); + test_compare(1, new_number); - rc= memcached_increment(memc, key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 2); + test_compare(MEMCACHED_SUCCESS, + memcached_increment(memc, + test_literal_param("number"), + 1, &new_number)); + test_compare(2, new_number); return TEST_SUCCESS; } static test_return_t increment_with_initial_test(memcached_st *memc) { - if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0) - { - uint64_t new_number; - memcached_return_t rc; - const char *key= "number"; - uint64_t initial= 0; + test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); - rc= memcached_increment_with_initial(memc, key, strlen(key), - 1, initial, 0, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == initial); + uint64_t new_number; + uint64_t initial= 0; + + test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc)); + + memcached_return_t rc; + test_compare_got(MEMCACHED_SUCCESS, + rc= memcached_increment_with_initial(memc, + test_literal_param("number"), + 1, initial, 0, &new_number), + memcached_strerror(NULL, rc)); + test_compare(new_number, initial); + + test_compare(MEMCACHED_SUCCESS, + memcached_increment_with_initial(memc, + test_literal_param("number"), + 1, initial, 0, &new_number)); + test_compare(new_number, (initial + 1)); - rc= memcached_increment_with_initial(memc, key, strlen(key), - 1, initial, 0, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == (initial + 1)); - } return TEST_SUCCESS; } @@ -1351,46 +1360,50 @@ static test_return_t decrement_test(memcached_st *memc) { uint64_t new_number; memcached_return_t rc; - const char *key= "number"; const char *value= "3"; - rc= memcached_set(memc, key, strlen(key), + rc= memcached_set(memc, + test_literal_param("number"), value, strlen(value), (time_t)0, (uint32_t)0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); - rc= memcached_decrement(memc, key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 2); + test_compare(MEMCACHED_SUCCESS, + memcached_decrement(memc, + test_literal_param("number"), + 1, &new_number)); + test_compare(new_number, 2); - rc= memcached_decrement(memc, key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 1); + test_compare(MEMCACHED_SUCCESS, + memcached_decrement(memc, + test_literal_param("number"), + 1, &new_number)); + test_compare(new_number, 1); return TEST_SUCCESS; } static test_return_t decrement_with_initial_test(memcached_st *memc) { - if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0) - { - uint64_t new_number; - memcached_return_t rc; - const char *key= "number"; - uint64_t initial= 3; + test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); - rc= memcached_decrement_with_initial(memc, key, strlen(key), - 1, initial, 0, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == initial); + uint64_t new_number; + uint64_t initial= 3; + + test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc)); + + test_compare(MEMCACHED_SUCCESS, + memcached_decrement_with_initial(memc, + test_literal_param("number"), + 1, initial, 0, &new_number)); + test_compare(new_number, initial); + + test_compare(MEMCACHED_SUCCESS, + memcached_decrement_with_initial(memc, + test_literal_param("number"), + 1, initial, 0, &new_number)); + test_compare(new_number, (initial - 1)); - rc= memcached_decrement_with_initial(memc, key, strlen(key), - 1, initial, 0, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == (initial - 1)); - } return TEST_SUCCESS; } @@ -1406,43 +1419,43 @@ static test_return_t increment_by_key_test(memcached_st *memc) key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); + test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED); - rc= memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 1); + test_compare(MEMCACHED_SUCCESS, + memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), + 1, &new_number)); + test_compare(new_number, 1); - rc= memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 2); + test_compare(MEMCACHED_SUCCESS, + memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), + 1, &new_number)); + test_compare(new_number, 2); return TEST_SUCCESS; } static test_return_t increment_with_initial_by_key_test(memcached_st *memc) { - if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0) - { - uint64_t new_number; - memcached_return_t rc; - const char *master_key= "foo"; - const char *key= "number"; - uint64_t initial= 0; + test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); - rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key), - key, strlen(key), - 1, initial, 0, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == initial); + uint64_t new_number; + memcached_return_t rc; + const char *master_key= "foo"; + const char *key= "number"; + uint64_t initial= 0; + + rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key), + key, strlen(key), + 1, initial, 0, &new_number); + test_compare(MEMCACHED_SUCCESS, rc); + test_true(new_number == initial); + + rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key), + key, strlen(key), + 1, initial, 0, &new_number); + test_compare(MEMCACHED_SUCCESS, rc); + test_true(new_number == (initial + 1)); - rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key), - key, strlen(key), - 1, initial, 0, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == (initial + 1)); - } return TEST_SUCCESS; } @@ -1450,52 +1463,53 @@ static test_return_t decrement_by_key_test(memcached_st *memc) { uint64_t new_number; memcached_return_t rc; - const char *master_key= "foo"; - const char *key= "number"; const char *value= "3"; - rc= memcached_set_by_key(memc, master_key, strlen(master_key), - key, strlen(key), + rc= memcached_set_by_key(memc, + test_literal_param("foo"), + test_literal_param("number"), value, strlen(value), (time_t)0, (uint32_t)0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); - rc= memcached_decrement_by_key(memc, master_key, strlen(master_key), - key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 2); + test_compare(MEMCACHED_SUCCESS, + memcached_decrement_by_key(memc, + test_literal_param("foo"), + test_literal_param("number"), + 1, &new_number)); + test_compare(new_number, 2); - rc= memcached_decrement_by_key(memc, master_key, strlen(master_key), - key, strlen(key), - 1, &new_number); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(new_number == 1); + test_compare(MEMCACHED_SUCCESS, + memcached_decrement_by_key(memc, + test_literal_param("foo"), + test_literal_param("number"), + 1, &new_number)); + test_compare(new_number, 1); return TEST_SUCCESS; } static test_return_t decrement_with_initial_by_key_test(memcached_st *memc) { - if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0) - { - uint64_t new_number; - const char *master_key= "foo"; - const char *key= "number"; - uint64_t initial= 3; + test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); - test_compare(MEMCACHED_SUCCESS, - memcached_decrement_with_initial_by_key(memc, master_key, strlen(master_key), - key, strlen(key), - 1, initial, 0, &new_number)); - test_compare(new_number, initial); + uint64_t new_number; + uint64_t initial= 3; + + test_compare(MEMCACHED_SUCCESS, + memcached_decrement_with_initial_by_key(memc, + test_literal_param("foo"), + test_literal_param("number"), + 1, initial, 0, &new_number)); + test_compare(new_number, initial); + + test_compare(MEMCACHED_SUCCESS, + memcached_decrement_with_initial_by_key(memc, + test_literal_param("foo"), + test_literal_param("number"), + 1, initial, 0, &new_number)); + test_compare(new_number, (initial - 1)); - test_compare(MEMCACHED_SUCCESS, - memcached_decrement_with_initial_by_key(memc, master_key, strlen(master_key), - key, strlen(key), - 1, initial, 0, &new_number)); - test_compare(new_number, (initial - 1)); - } return TEST_SUCCESS; } @@ -1564,10 +1578,10 @@ static test_return_t mget_result_test(memcached_st *memc) test_true(results); test_true(&results_obj == results); test_compare(MEMCACHED_SUCCESS, rc); - test_compare(memcached_result_key_length(results), memcached_result_length(results)); test_memcmp(memcached_result_key_value(results), memcached_result_value(results), memcached_result_length(results)); + test_compare(memcached_result_key_length(results), memcached_result_length(results)); } memcached_result_free(&results_obj); @@ -1613,7 +1627,7 @@ static test_return_t mget_result_alloc_test(memcached_st *memc) { test_true(results); test_compare(MEMCACHED_SUCCESS, rc); - test_true(memcached_result_key_length(results) == memcached_result_length(results)); + test_compare(memcached_result_key_length(results), memcached_result_length(results)); test_memcmp(memcached_result_key_value(results), memcached_result_value(results), memcached_result_length(results)); @@ -1712,8 +1726,11 @@ static test_return_t mget_test(memcached_st *memc) { test_true(return_value); test_compare(MEMCACHED_SUCCESS, rc); - test_true(return_key_length == return_value_length); - test_memcmp(return_value, return_key, return_value_length); + if (not memc->prefix_key) + { + test_compare(return_key_length, return_value_length); + test_memcmp(return_value, return_key, return_value_length); + } free(return_value); x++; } @@ -3900,38 +3917,38 @@ static void *my_calloc(const memcached_st *ptr, size_t nelem, const size_t size, #endif } -static test_return_t set_prefix(memcached_st *memc) +static test_return_t selection_of_namespace_tests(memcached_st *memc) { memcached_return_t rc; const char *key= "mine"; char *value; /* Make sure be default none exists */ - value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); + value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc)); /* Test a clean set */ - rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key); - test_compare_got(MEMCACHED_SUCCESS, rc , memcached_last_error_message(memc)); + test_compare(MEMCACHED_SUCCESS, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, (void *)key)); - value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); + value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); test_true(value); test_memcmp(value, key, 4); test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); /* Test that we can turn it off */ - rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL); - test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); + test_compare(MEMCACHED_SUCCESS, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, NULL)); - value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); + value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); test_false(value); test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc)); /* Now setup for main test */ - rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key); - test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); + test_compare(MEMCACHED_SUCCESS, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, (void *)key)); - value= (char *)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); + value= (char *)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); test_true(value); test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); test_memcmp(value, key, 4); @@ -3941,10 +3958,10 @@ static test_return_t set_prefix(memcached_st *memc) char long_key[255]; memset(long_key, 0, 255); - rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL); - test_compare(MEMCACHED_SUCCESS, rc); + test_compare(MEMCACHED_SUCCESS, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, NULL)); - value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); + value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); test_false(value); test_true(rc == MEMCACHED_FAILURE); test_true(value == NULL); @@ -3952,27 +3969,59 @@ static test_return_t set_prefix(memcached_st *memc) /* Test a long key for failure */ /* TODO, extend test to determine based on setting, what result should be */ strncpy(long_key, "Thisismorethentheallottednumberofcharacters", sizeof(long_key)); - rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, long_key); - //test_compare(MEMCACHED_BAD_KEY_PROVIDED, rc); - test_compare(MEMCACHED_SUCCESS, rc); + test_compare(MEMCACHED_SUCCESS, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, long_key)); /* Now test a key with spaces (which will fail from long key, since bad key is not set) */ strncpy(long_key, "This is more then the allotted number of characters", sizeof(long_key)); - test_compare(MEMCACHED_BAD_KEY_PROVIDED, - memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, long_key)); + test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_SUCCESS : MEMCACHED_BAD_KEY_PROVIDED, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, long_key)); /* Test for a bad prefix, but with a short key */ - test_compare(MEMCACHED_SUCCESS, - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1)); + test_compare_got(MEMCACHED_SUCCESS, + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1), + memcached_strerror(NULL, rc)); - strncpy(long_key, "dog cat", sizeof(long_key)); - test_compare(MEMCACHED_BAD_KEY_PROVIDED, - memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, long_key)); + if (not memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) + { + strncpy(long_key, "dog cat", sizeof(long_key)); + test_compare(MEMCACHED_BAD_KEY_PROVIDED, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, long_key)); + } } return TEST_SUCCESS; } +static test_return_t set_namespace(memcached_st *memc) +{ + memcached_return_t rc; + const char *key= "mine"; + char *value; + + /* Make sure be default none exists */ + value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); + test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc)); + + /* Test a clean set */ + test_compare(MEMCACHED_SUCCESS, + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, (void *)key)); + + value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); + test_true(value); + test_memcmp(value, key, 4); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); + + return TEST_SUCCESS; +} + +static test_return_t set_namespace_and_binary(memcached_st *memc) +{ + test_return_if(pre_binary(memc)); + test_return_if(set_namespace(memc)); + + return TEST_SUCCESS; +} #ifdef MEMCACHED_ENABLE_DEPRECATED static test_return_t deprecated_set_memory_alloc(memcached_st *memc) @@ -6434,6 +6483,14 @@ test_st virtual_bucket_tests[] ={ {0, 0, (test_callback_fn*)0} }; +test_st namespace_tests[] ={ + {"basic tests", 0, (test_callback_fn*)selection_of_namespace_tests }, +#if 0 + {"increment", 0, (test_callback_fn*)memcached_increment_namespace }, +#endif + {0, 0, (test_callback_fn*)0} +}; + collection_st collection[] ={ #if 0 {"hash_sanity", 0, 0, hash_sanity}, @@ -6466,7 +6523,9 @@ collection_st collection[] ={ {"deprecated_memory_allocators", (test_callback_fn*)deprecated_set_memory_alloc, 0, tests}, #endif {"memory_allocators", (test_callback_fn*)set_memory_alloc, 0, tests}, - {"prefix", (test_callback_fn*)set_prefix, 0, tests}, + {"namespace", (test_callback_fn*)set_namespace, 0, tests}, + {"namespace(BINARY)", (test_callback_fn*)set_namespace_and_binary, 0, tests}, + {"specific namespace", 0, 0, namespace_tests}, {"sasl_auth", (test_callback_fn*)pre_sasl, 0, sasl_auth_tests }, {"sasl", (test_callback_fn*)pre_sasl, 0, tests }, {"version_1_2_3", (test_callback_fn*)check_for_1_2_3, 0, version_1_2_3}, diff --git a/tests/namespace.cc b/tests/namespace.cc new file mode 100644 index 00000000..15975c64 --- /dev/null +++ b/tests/namespace.cc @@ -0,0 +1,77 @@ +/* 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 + +test_return_t memcached_increment_namespace(memcached_st *memc) +{ + uint64_t new_number; + memcached_return_t rc; + const char *key= "number"; + const char *value= "0"; + + test_compare(MEMCACHED_SUCCESS, + memcached_set(memc, + test_literal_param("number"), + test_literal_param("0"), + (time_t)0, (uint32_t)0)); + + test_compare(MEMCACHED_SUCCESS, + memcached_increment(memc, + test_literal_param("number"), + 1, &new_number)); + test_compare(1, new_number); + + test_compare(MEMCACHED_SUCCESS, + memcached_increment(memc, + test_literal_param("number"), + 1, &new_number)); + test_compare(2, new_number); + + memcached_st *clone= memcached_clone(NULL, memc); + + test_compare(MEMCACHED_NOTFOUND, + memcached_increment(memc, + test_literal_param("number"), + 1, &new_number)); + test_compare(1, new_number); + + + + return TEST_SUCCESS; +} + diff --git a/tests/namespace.h b/tests/namespace.h new file mode 100644 index 00000000..600da6de --- /dev/null +++ b/tests/namespace.h @@ -0,0 +1,41 @@ +/* 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 + +LIBTEST_INTERNAL_API +test_return_t memcached_increment_namespace(memcached_st *memc);