From b551d4aedecbd485277f9cc63bd33d860060194c Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 15 Jun 2011 17:56:49 -0700 Subject: [PATCH] Lossen up restrictions on the recv(). --- docs/memcached_get.rst | 6 ++- libmemcached/fetch.cc | 13 ++++-- libmemcached/io.cc | 31 ++++++++----- libmemcached/quit.cc | 7 +-- libmemcached/response.cc | 15 +++++-- libmemcached/result.cc | 4 +- libmemcached/return.h | 5 ++- libmemcached/strerror.cc | 7 +++ tests/mem_functions.cc | 94 +++++++++++++++++++++------------------- 9 files changed, 113 insertions(+), 69 deletions(-) diff --git a/docs/memcached_get.rst b/docs/memcached_get.rst index c563f396..556fcf7a 100644 --- a/docs/memcached_get.rst +++ b/docs/memcached_get.rst @@ -65,7 +65,7 @@ a size_t pointer which will be filled with size of of the object, and a memcached_return_t pointer to hold any error. The object will be returned upon success and NULL will be returned on failure. MEMCACHD_END is returned by the \*error value when all objects that have been found are returned. -The final value upon MEMCACHED_END is null. Values returned by +The final value upon :c:type:`MEMCACHED_END` is null. Values returned by memcached_fetch() must be freed by the caller. memcached_fetch() will be DEPRECATED in the near future, memcached_fetch_result() should be used instead. @@ -117,6 +117,10 @@ All objects returned must be freed by the calling application. memcached_get() and memcached_fetch() will return NULL on error. You must look at the value of error to determine what the actual error was. +:c:func:`memcached_fetch()`, :c:func:`memcached_fetch_execute()`, and +:c:func:`memcached_fetch_result()` all set error to :c:type:`MEMCACHED_END` +upon success. + MEMCACHED_KEY_TOO_BIG is set to error whenever memcached_fetch() was used and the key was set larger then MEMCACHED_MAX_KEY, which was the largest key allowed for the original memcached ascii server. diff --git a/libmemcached/fetch.cc b/libmemcached/fetch.cc index 89777534..e8f794c9 100644 --- a/libmemcached/fetch.cc +++ b/libmemcached/fetch.cc @@ -104,6 +104,7 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, { if (not (result= memcached_result_create(ptr, NULL))) { + *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; return NULL; } } @@ -137,6 +138,12 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, memcached_string_reset(&result->value); } + if (*error == MEMCACHED_NOTFOUND) + *error= MEMCACHED_END; + + if (*error == MEMCACHED_SUCCESS) + *error= MEMCACHED_END; + return NULL; } @@ -148,14 +155,14 @@ memcached_return_t memcached_fetch_execute(memcached_st *ptr, memcached_result_st *result= &ptr->result; memcached_return_t rc= MEMCACHED_FAILURE; - while ((result= memcached_fetch_result(ptr, result, &rc)) != NULL) + while ((result= memcached_fetch_result(ptr, result, &rc))) { - if (rc == MEMCACHED_SUCCESS) + if (memcached_success(rc)) { for (uint32_t x= 0; x < number_of_callbacks; x++) { rc= (*callback[x])(ptr, result, context); - if (rc != MEMCACHED_SUCCESS) + if (memcached_failed(rc)) break; } } diff --git a/libmemcached/io.cc b/libmemcached/io.cc index fd719d6e..fdb265ac 100644 --- a/libmemcached/io.cc +++ b/libmemcached/io.cc @@ -38,11 +38,12 @@ #include +#include -typedef enum { +enum memc_read_or_write { MEM_READ, MEM_WRITE -} memc_read_or_write; +}; static ssize_t io_flush(memcached_server_write_instance_st ptr, const bool with_flush, @@ -249,20 +250,16 @@ static bool process_input_buffer(memcached_server_write_instance_st ptr) memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr, void *buffer, size_t length, ssize_t *nread) { - char *buffer_ptr; - - buffer_ptr= static_cast(buffer); + char *buffer_ptr= static_cast(buffer); while (length) { if (not ptr->read_buffer_length) { ssize_t data_read; - do { data_read= recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT); - if (data_read == SOCKET_ERROR) { switch (get_socket_errno()) @@ -279,6 +276,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr, { continue; } + return MEMCACHED_IN_PROGRESS; /* fall through */ @@ -710,9 +708,13 @@ memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr, while (offset < size) { ssize_t nread; - memcached_return_t rc= memcached_io_read(ptr, data + offset, size - offset, - &nread); - if (rc != MEMCACHED_SUCCESS) + memcached_return_t rc= memcached_io_read(ptr, data + offset, size - offset, &nread); + if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS) + { + memcached_quit_server(ptr, true); + return memcached_set_error(*ptr, rc, MEMCACHED_AT); + } + else if (memcached_failed(rc)) { return rc; } @@ -730,7 +732,7 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr, bool line_complete= false; size_t total_nr= 0; - while (!line_complete) + while (not line_complete) { if (ptr->read_buffer_length == 0) { @@ -741,7 +743,12 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr, */ ssize_t nread; memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, &nread); - if (rc != MEMCACHED_SUCCESS) + if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS) + { + memcached_quit_server(ptr, true); + return memcached_set_error(*ptr, rc, MEMCACHED_AT); + } + else if (memcached_failed(rc)) { return rc; } diff --git a/libmemcached/quit.cc b/libmemcached/quit.cc index b44b508e..5eeac084 100644 --- a/libmemcached/quit.cc +++ b/libmemcached/quit.cc @@ -84,8 +84,7 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death) if (ptr->root->flags.buffer_requests || ptr->root->number_of_replicas) { ssize_t nread; - while (memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer), - &nread) == MEMCACHED_SUCCESS) {} ; + while (memcached_success(memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer), &nread))) {} ; } @@ -101,6 +100,8 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death) memcached_io_close(ptr); } + ptr->state= MEMCACHED_SERVER_STATE_NEW; + ptr->cursor_active= 0; ptr->io_bytes_sent= 0; ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0); ptr->read_buffer_length= 0; @@ -132,7 +133,7 @@ void send_quit(memcached_st *ptr) void memcached_quit(memcached_st *ptr) { - if (initialize_query(ptr) != MEMCACHED_SUCCESS) + if (memcached_failed(initialize_query(ptr))) { return; } diff --git a/libmemcached/response.cc b/libmemcached/response.cc index d3d2510e..e94ca31f 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -211,8 +211,15 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st */ to_read= (value_length) + 2; memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length); - if (memcached_failed(rrc)) + if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS) + { + memcached_quit_server(ptr, true); + return memcached_set_error(*ptr, rrc, MEMCACHED_AT); + } + else if (memcached_failed(rrc)) + { return rrc; + } } if (read_length != (ssize_t)(value_length + 2)) @@ -225,7 +232,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st char *char_ptr; char_ptr= memcached_string_value_mutable(&result->value);; char_ptr[value_length]= 0; - char_ptr[value_length + 1]= 0; + char_ptr[value_length +1]= 0; memcached_string_set_length(&result->value, value_length); } @@ -242,8 +249,10 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta memcached_result_st *result) { memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length); - if (rc != MEMCACHED_SUCCESS) + if (memcached_failed(rc)) + { return rc; + } switch(buffer[0]) { diff --git a/libmemcached/result.cc b/libmemcached/result.cc index f9d55a94..eb24fa36 100644 --- a/libmemcached/result.cc +++ b/libmemcached/result.cc @@ -69,8 +69,10 @@ memcached_result_st *memcached_result_create(const memcached_st *memc, { ptr= static_cast(libmemcached_malloc(memc, sizeof(memcached_result_st))); - if (ptr == NULL) + if (not ptr) + { return NULL; + } ptr->options.is_allocated= true; } diff --git a/libmemcached/return.h b/libmemcached/return.h index 35ad69d9..fd7194d0 100644 --- a/libmemcached/return.h +++ b/libmemcached/return.h @@ -83,6 +83,7 @@ enum memcached_return_t { MEMCACHED_PARSE_ERROR, MEMCACHED_PARSE_USER_ERROR, MEMCACHED_DEPRECATED, + MEMCACHED_IN_PROGRESS, MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */ }; @@ -91,6 +92,6 @@ typedef enum memcached_return_t memcached_return_t; #endif -#define memcached_success(X) ((X) == MEMCACHED_SUCCESS) -#define memcached_failed(A) ((A) != MEMCACHED_SUCCESS) +#define memcached_success(__memcached_return_t) ((__memcached_return_t) == MEMCACHED_SUCCESS or (__memcached_return_t) == MEMCACHED_END) +#define memcached_failed(__memcached_return_t) ((__memcached_return_t) != MEMCACHED_SUCCESS and (__memcached_return_t) != MEMCACHED_END) diff --git a/libmemcached/strerror.cc b/libmemcached/strerror.cc index d3781824..c58b1f65 100644 --- a/libmemcached/strerror.cc +++ b/libmemcached/strerror.cc @@ -53,8 +53,10 @@ const char *memcached_strerror(memcached_st *, memcached_return_t rc) return "CONNECTION BIND FAILURE"; case MEMCACHED_READ_FAILURE: return "READ FAILURE"; + case MEMCACHED_UNKNOWN_READ_FAILURE: return "UNKNOWN READ FAILURE"; + case MEMCACHED_PROTOCOL_ERROR: return "PROTOCOL ERROR"; case MEMCACHED_CLIENT_ERROR: @@ -131,8 +133,13 @@ const char *memcached_strerror(memcached_st *, memcached_return_t rc) return "ERROR OCCURED WHILE PARSING"; case MEMCACHED_PARSE_USER_ERROR: return "USER INITIATED ERROR OCCURED WHILE PARSING"; + case MEMCACHED_DEPRECATED: return "DEPRECATED"; + + case MEMCACHED_IN_PROGRESS: + return "OPERATION IN PROCESS"; + default: case MEMCACHED_MAXIMUM_RETURN: return "INVALID memcached_return_t"; diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index 97948f20..bc0f91f2 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -54,6 +54,8 @@ #include #include +#include + #include #include "clients/generator.h" @@ -433,7 +435,7 @@ static test_return_t error_test(memcached_st *memc) 54481931U, 4186304426U, 1741088401U, 2979625118U, 4159057246U, 3425930182U, 2593724503U, 1868899624U, 1769812374U, 2302537950U, 1110330676U, 3365377466U, - 1336171666U, 3021258493U, 3365377466U }; + 1336171666U, 3021258493U, 2334992265U, 3365377466U }; // You have updated the memcache_error messages but not updated docs/tests. for (int rc= int(MEMCACHED_SUCCESS); rc < int(MEMCACHED_MAXIMUM_RETURN); ++rc) @@ -449,7 +451,7 @@ static test_return_t error_test(memcached_st *memc) } test_true(values[rc] == hash_val); } - test_true(MEMCACHED_MAXIMUM_RETURN == 46); + test_compare(MEMCACHED_MAXIMUM_RETURN, 47); return TEST_SUCCESS; } @@ -519,7 +521,7 @@ static test_return_t append_binary_test(memcached_st *memc) key, strlen(key), NULL, 0, (time_t)0, (uint32_t)0); - test_true(rc == MEMCACHED_SUCCESS); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); for (x= 0; store_list[x] ; x++) { @@ -552,22 +554,20 @@ static test_return_t cas2_test(memcached_st *memc) size_t key_length[]= {5, 3, 4}; const char *value= "we the people"; size_t value_length= strlen("we the people"); - unsigned int x; memcached_result_st results_obj; memcached_result_st *results; unsigned int set= 1; - rc= memcached_flush(memc, 0); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0)); memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, set); - for (x= 0; x < 3; x++) + for (uint32_t x= 0; x < 3; x++) { rc= memcached_set(memc, keys[x], key_length[x], keys[x], key_length[x], (time_t)50, (uint32_t)9); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, rc); } rc= memcached_mget(memc, keys, key_length, 3); @@ -1668,7 +1668,8 @@ static test_return_t mget_result_function(memcached_st *memc) callbacks[0]= &callback_counter; counter= 0; - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + test_compare(MEMCACHED_END, + memcached_fetch_execute(memc, callbacks, (void *)&counter, 1)); test_true(counter == 3); @@ -1773,12 +1774,12 @@ static test_return_t mget_execute(memcached_st *memc) rc= memcached_mget_execute(memc, (const char**)keys, key_length, max_keys, callbacks, &counter, 1); - if (rc == MEMCACHED_SUCCESS) + if (memcached_success(rc)) { test_true(binary); uint64_t query_id= memcached_query_id(memc); - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); - test_true(rc == MEMCACHED_END); + test_compare(MEMCACHED_END, + memcached_fetch_execute(memc, callbacks, (void *)&counter, 1)); test_compare(query_id, memcached_query_id(memc)); /* Verify that we got all of the items */ @@ -3456,7 +3457,8 @@ static test_return_t mget_read_function(memcached_st *memc) memcached_execute_fn callbacks[]= { &callback_counter }; size_t counter= 0; - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + test_compare(MEMCACHED_END, + memcached_fetch_execute(memc, callbacks, (void *)&counter, 1)); return TEST_SUCCESS; } @@ -5043,7 +5045,8 @@ static test_return_t regression_bug_434843(memcached_st *memc) { rc= memcached_mget(memc, (const char**)keys, key_length, max_keys); test_true(rc == MEMCACHED_SUCCESS); - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + test_compare(MEMCACHED_END, + memcached_fetch_execute(memc, callbacks, (void *)&counter, 1)); if (y == 0) { @@ -5132,9 +5135,7 @@ static test_return_t regression_bug_421108(memcached_st *memc) */ static test_return_t regression_bug_442914(memcached_st *memc) { - memcached_return_t rc; - rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1); - test_true(rc == MEMCACHED_SUCCESS); + test_skip(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1)); memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); uint32_t number_of_hosts= memcached_server_count(memc); @@ -5146,20 +5147,18 @@ static test_return_t regression_bug_442914(memcached_st *memc) for (uint32_t x= 0; x < 250; ++x) { len= (size_t)snprintf(k, sizeof(k), "%0250u", x); - rc= memcached_delete(memc, k, len, 0); + 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); len= strlen(k); - rc= memcached_delete(memc, k, len, 0); + memcached_return_t rc= memcached_delete(memc, k, len, 0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); - rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 0); - test_true(rc == MEMCACHED_SUCCESS); - rc= memcached_delete(memc, k, len, 0); - test_true(rc == MEMCACHED_NOTFOUND); + test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 0)); + test_compare(MEMCACHED_NOTFOUND, memcached_delete(memc, k, len, 0)); memc->number_of_hosts= number_of_hosts; @@ -5171,13 +5170,11 @@ static test_return_t regression_bug_447342(memcached_st *memc) memcached_server_instance_st instance_one; memcached_server_instance_st instance_two; - if (memcached_server_count(memc) < 3 || pre_replication(memc) != TEST_SUCCESS) + if (memcached_server_count(memc) < 3 or pre_replication(memc) != TEST_SUCCESS) return TEST_SKIPPED; - memcached_return_t rc; - - rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 2); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 2)); const size_t max_keys= 100; char **keys= (char**)calloc(max_keys, sizeof(char*)); @@ -5189,9 +5186,9 @@ static test_return_t regression_bug_447342(memcached_st *memc) key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%lu", (unsigned long)x); keys[x]= strdup(k); - test_true(keys[x] != NULL); - rc= memcached_set(memc, k, key_length[x], k, key_length[x], 0, 0); - test_true(rc == MEMCACHED_SUCCESS); + test_true(keys[x]); + test_compare(MEMCACHED_SUCCESS, + memcached_set(memc, k, key_length[x], k, key_length[x], 0, 0)); } /* @@ -5212,14 +5209,20 @@ static test_return_t regression_bug_447342(memcached_st *memc) /* Verify that all messages are stored, and we didn't stuff too much * into the servers */ - rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, + memcached_mget(memc, (const char* const *)keys, key_length, max_keys)); + + size_t counter= 0; memcached_execute_fn callbacks[]= { &callback_counter }; - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + memcached_return_t rc; + test_compare_got(MEMCACHED_END, + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1), + memcached_last_error_message(memc)); + /* Verify that we received all of the key/value pairs */ - test_true(counter == max_keys); + test_compare(counter, max_keys); memcached_quit(memc); /* @@ -5236,11 +5239,12 @@ static test_return_t regression_bug_447342(memcached_st *memc) ((memcached_server_write_instance_st)instance_one)->port= 0; ((memcached_server_write_instance_st)instance_two)->port= 0; - rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, + memcached_mget(memc, (const char* const *)keys, key_length, max_keys)); counter= 0; - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + test_compare(MEMCACHED_END, + memcached_fetch_execute(memc, callbacks, (void *)&counter, 1)); test_true(counter == (unsigned int)max_keys); /* restore the memc handle */ @@ -5254,8 +5258,8 @@ static test_return_t regression_bug_447342(memcached_st *memc) { if (x & 1) { - rc= memcached_delete(memc, keys[x], key_length[x], 0); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, + memcached_delete(memc, keys[x], key_length[x], 0)); } } @@ -5264,11 +5268,13 @@ static test_return_t regression_bug_447342(memcached_st *memc) ((memcached_server_write_instance_st)instance_two)->port= 0; /* now retry the command, this time we should have cache misses */ - rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, + memcached_mget(memc, (const char* const *)keys, key_length, max_keys)); counter= 0; - rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + test_compare_got(MEMCACHED_END, + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1), + memcached_strerror(NULL, rc)); test_true(counter == (unsigned int)(max_keys >> 1)); /* Release allocated resources */ @@ -5289,7 +5295,7 @@ static test_return_t regression_bug_447342(memcached_st *memc) static test_return_t regression_bug_463297(memcached_st *memc) { memcached_st *memc_clone= memcached_clone(NULL, memc); - test_true(memc_clone != NULL); + test_true(memc_clone); test_true(memcached_version(memc_clone) == MEMCACHED_SUCCESS); memcached_server_instance_st instance= -- 2.30.2