From: Brian Aker Date: Mon, 12 Nov 2012 06:36:53 +0000 (-0500) Subject: When returning CLIENT_ERROR do not close the socket connection (i.e. it should not... X-Git-Tag: 1.0.14~3 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=a81ced7911d1c31812d7acfbf0680ba00143ac9c;p=m6w6%2Flibmemcached When returning CLIENT_ERROR do not close the socket connection (i.e. it should not be treated as a fatal error). --- diff --git a/libmemcached-1.0/return.h b/libmemcached-1.0/return.h index 65dc63af..781603b8 100644 --- a/libmemcached-1.0/return.h +++ b/libmemcached-1.0/return.h @@ -63,6 +63,7 @@ static inline bool memcached_fatal(memcached_return_t rc) { return ( rc != MEMCACHED_BUFFERED && + rc != MEMCACHED_CLIENT_ERROR && rc != MEMCACHED_DATA_EXISTS && rc != MEMCACHED_DELETED && rc != MEMCACHED_E2BIG && diff --git a/libmemcached/error.cc b/libmemcached/error.cc index f963e124..67edcce8 100644 --- a/libmemcached/error.cc +++ b/libmemcached/error.cc @@ -276,7 +276,7 @@ memcached_return_t memcached_set_error(org::libmemcached::Instance& self, memcac { 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 org::libmemcached::Instance"); - if (memcached_fatal(rc) == false) + if (memcached_fatal(rc) == false and rc != MEMCACHED_CLIENT_ERROR) { return rc; } @@ -295,7 +295,7 @@ memcached_return_t memcached_set_error(org::libmemcached::Instance& self, memcac memcached_string_t error_host= { hostname_port_message, size_t(size) }; - assert(self.root); + assert_msg(self.root, "Programmer error, root was not set on instance"); if (self.root == NULL) { return rc; @@ -305,6 +305,7 @@ memcached_return_t memcached_set_error(org::libmemcached::Instance& self, memcac _set(self, (*self.root)); assert(self.root->error_messages); assert(self.error_messages); + assert(self.error_messages->rc == self.root->error_messages->rc); return rc; } @@ -411,6 +412,15 @@ memcached_return_t memcached_set_errno(org::libmemcached::Instance& self, int lo _set(*self.root, &error_host, rc, at, local_errno); _set(self, (*self.root)); +#if 0 + if (self.root->error_messages->rc != self.error_messages->rc) + { + fprintf(stderr, "%s:%d %s != %s\n", __FILE__, __LINE__, + memcached_strerror(NULL, self.root->error_messages->rc), + memcached_strerror(NULL, self.error_messages->rc)); + } +#endif + return rc; } diff --git a/libmemcached/response.cc b/libmemcached/response.cc index 67b0999f..cb0e682b 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -416,7 +416,17 @@ static memcached_return_t textual_read_one_response(org::libmemcached::Instance* and buffer[6] == '_' and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R') { - return MEMCACHED_CLIENT_ERROR; + // Move past the basic error message and whitespace + char *startptr= buffer + memcached_literal_param_size("CLIENT_ERROR"); + if (startptr[0] == ' ') + { + startptr++; + } + + char *endptr= startptr; + while (*endptr != '\r' && *endptr != '\n') endptr++; + + return memcached_set_error(*instance, MEMCACHED_CLIENT_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr)); } } break; diff --git a/tests/libmemcached-1.0/all_tests.h b/tests/libmemcached-1.0/all_tests.h index 7bdfe394..74e619d2 100644 --- a/tests/libmemcached-1.0/all_tests.h +++ b/tests/libmemcached-1.0/all_tests.h @@ -279,6 +279,7 @@ test_st regression_tests[]= { {"lp:1009493", true, (test_callback_fn*)regression_1009493_TEST }, {"lp:1021819", true, (test_callback_fn*)regression_1021819_TEST }, {"lp:1048945", true, (test_callback_fn*)regression_1048945_TEST }, + {"lp:1067242", true, (test_callback_fn*)regression_1067242_TEST }, {0, false, (test_callback_fn*)0} }; diff --git a/tests/libmemcached-1.0/mem_functions.cc b/tests/libmemcached-1.0/mem_functions.cc index 38c0db77..a0570884 100644 --- a/tests/libmemcached-1.0/mem_functions.cc +++ b/tests/libmemcached-1.0/mem_functions.cc @@ -823,6 +823,34 @@ test_return_t memcached_add_SUCCESS_TEST(memcached_st *memc) return TEST_SUCCESS; } +test_return_t regression_1067242_TEST(memcached_st *memc) +{ + test_compare(MEMCACHED_SUCCESS, memcached_set(memc, + test_literal_param(__func__), + test_literal_param("-2"), + 0, 0)); + + memcached_return_t rc; + char* value; + test_true((value= memcached_get(memc, test_literal_param(__func__), NULL, NULL, &rc))); + test_compare(MEMCACHED_SUCCESS, rc); + free(value); + + for (size_t x= 0; x < 10; x++) + { + uint64_t new_number; + test_compare(MEMCACHED_CLIENT_ERROR, + memcached_increment(memc, + test_literal_param(__func__), 1, &new_number)); + test_compare(MEMCACHED_CLIENT_ERROR, memcached_last_error(memc)); + test_true((value= memcached_get(memc, test_literal_param(__func__), NULL, NULL, &rc))); + test_compare(MEMCACHED_SUCCESS, rc); + free(value); + } + + return TEST_SUCCESS; +} + /* Set the value, then quit to make sure it is flushed. Come back in and test that add fails. diff --git a/tests/libmemcached-1.0/mem_functions.h b/tests/libmemcached-1.0/mem_functions.h index eb9afa29..104d44ee 100644 --- a/tests/libmemcached-1.0/mem_functions.h +++ b/tests/libmemcached-1.0/mem_functions.h @@ -180,3 +180,4 @@ test_return_t regression_996813_TEST(memcached_st*); test_return_t regression_994772_TEST(memcached_st*); test_return_t regression_1009493_TEST(memcached_st*); test_return_t regression_1048945_TEST(memcached_st*); +test_return_t regression_1067242_TEST(memcached_st*);