From: Date: Fri, 29 Feb 2008 07:19:55 +0000 (-0800) Subject: Branch merge. X-Git-Tag: _20~1^2~55^2~1^2~3 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;ds=inline;h=4012fdfefb1d0566398225cd280d9c3996960779;p=m6w6%2Flibmemcached Branch merge. --- 4012fdfefb1d0566398225cd280d9c3996960779 diff --cc lib/memcached_auto.c index 1f61a18c,a607ed66..3aa63eed --- a/lib/memcached_auto.c +++ b/lib/memcached_auto.c @@@ -7,15 -7,14 +7,15 @@@ static memcached_return memcached_auto( uint64_t *value) { size_t send_length; - memcached_return rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unsigned int server_key; + uint8_t replicas= 0; + memcached_return rc[MEMCACHED_MAX_REPLICAS]; - if (key_length == 0) + unlikely (key_length == 0) return MEMCACHED_NO_KEY_PROVIDED; - if (ptr->hosts == NULL || ptr->number_of_hosts == 0) + unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0) return MEMCACHED_NO_SERVERS; if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test(&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) @@@ -27,58 -26,39 +27,58 @@@ "%s %.*s %u\r\n", verb, (int)key_length, key, offset); - if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) + unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) return MEMCACHED_WRITE_FAILURE; - rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1); - if (rc != MEMCACHED_SUCCESS) - return rc; - - rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); - - /* - So why recheck responce? Because the protocol is brain dead :) - The number returned might end up equaling one of the string - values. Less chance of a mistake with strncmp() so we will - use it. We still called memcached_response() though since it - worked its magic for non-blocking IO. - */ - if (!strncmp(buffer, "ERROR\r\n", 7)) + do { - *value= 0; - rc= MEMCACHED_PROTOCOL_ERROR; - } - else if (!strncmp(buffer, "NOT_FOUND\r\n", 11)) + rc[replicas]= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1); + if (rc[replicas] != MEMCACHED_SUCCESS) + goto error; + + rc[replicas]= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); + + /* + So why recheck responce? Because the protocol is brain dead :) + The number returned might end up equaling one of the string + values. Less chance of a mistake with strncmp() so we will + use it. We still called memcached_response() though since it + worked its magic for non-blocking IO. + */ + if (!strncmp(buffer, "ERROR\r\n", 7)) + { + *value= 0; + rc[replicas]= MEMCACHED_PROTOCOL_ERROR; + } + else if (!strncmp(buffer, "NOT_FOUND\r\n", 11)) + { + *value= 0; + rc[replicas]= MEMCACHED_NOTFOUND; + } + else + { + *value= (uint64_t)strtoll(buffer, (char **)NULL, 10); + rc[replicas]= MEMCACHED_SUCCESS; + } + /* On error we just jump to the next potential server */ +error: + if (replicas > 1 && ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT) + { + if (server_key == (ptr->number_of_hosts - 1)) + server_key= 0; + else + server_key++; + } + } while ((++replicas) < ptr->number_of_replicas); + + /* As long as one object gets stored, we count this as a success */ + while (replicas--) { - *value= 0; - rc= MEMCACHED_NOTFOUND; - } - else - { - *value= (uint64_t)strtoll(buffer, (char **)NULL, 10); - rc= MEMCACHED_SUCCESS; + if (rc[replicas] == MEMCACHED_STORED) + return MEMCACHED_SUCCESS; } - return rc; + return rc[0]; } memcached_return memcached_increment(memcached_st *ptr, diff --cc lib/memcached_delete.c index 96db7b4e,60e3bed4..24dc1660 --- a/lib/memcached_delete.c +++ b/lib/memcached_delete.c @@@ -14,15 -14,16 +14,15 @@@ memcached_return memcached_delete_by_ke { char to_write; size_t send_length; - memcached_return rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unsigned int server_key; - - LIBMEMCACHED_MEMCACHED_DELETE_START(); + uint8_t replicas= 0; + memcached_return rc[MEMCACHED_MAX_REPLICAS]; - if (key_length == 0) + unlikely (key_length == 0) return MEMCACHED_NO_KEY_PROVIDED; - if (ptr->hosts == NULL || ptr->number_of_hosts == 0) + unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0) return MEMCACHED_NO_SERVERS; server_key= memcached_generate_hash(ptr, master_key, master_key_length); diff --cc lib/memcached_mget.c index 00000000,00000000..a25fa8e0 new file mode 100644 --- /dev/null +++ b/lib/memcached_mget.c @@@ -1,0 -1,0 +1,125 @@@ ++#include "common.h" ++#include "memcached_io.h" ++ ++memcached_return memcached_mget(memcached_st *ptr, ++ char **keys, size_t *key_length, ++ unsigned int number_of_keys) ++{ ++ return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys); ++} ++ ++memcached_return memcached_mget_by_key(memcached_st *ptr, ++ char *master_key, size_t master_key_length, ++ char **keys, size_t *key_length, ++ unsigned int number_of_keys) ++{ ++ unsigned int x; ++ memcached_return rc= MEMCACHED_NOTFOUND; ++ char *get_command= "get "; ++ uint8_t get_command_length= 4; ++ unsigned int master_server_key= 0; ++ ++ LIBMEMCACHED_MEMCACHED_MGET_START(); ++ ptr->cursor_server= 0; ++ ++ if (number_of_keys == 0) ++ return MEMCACHED_NOTFOUND; ++ ++ if (ptr->number_of_hosts == 0) ++ return MEMCACHED_NO_SERVERS; ++ ++ if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED)) ++ return MEMCACHED_BAD_KEY_PROVIDED; ++ ++ if (ptr->flags & MEM_SUPPORT_CAS) ++ { ++ get_command= "gets "; ++ get_command_length= 5; ++ } ++ ++ if (master_key && master_key_length) ++ master_server_key= memcached_generate_hash(ptr, master_key, master_key_length); ++ ++ /* ++ Here is where we pay for the non-block API. We need to remove any data sitting ++ in the queue before we start our get. ++ ++ It might be optimum to bounce the connection if count > some number. ++ */ ++ for (x= 0; x < ptr->number_of_hosts; x++) ++ { ++ if (memcached_server_response_count(&ptr->hosts[x])) ++ { ++ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; ++ ++ if (ptr->flags & MEM_NO_BLOCK) ++ (void)memcached_io_write(&ptr->hosts[x], NULL, 0, 1); ++ ++ while(memcached_server_response_count(&ptr->hosts[x])) ++ (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result); ++ } ++ } ++ ++ /* ++ If a server fails we warn about errors and start all over with sending keys ++ to the server. ++ */ ++ for (x= 0; x < number_of_keys; x++) ++ { ++ unsigned int server_key; ++ ++ if (master_server_key) ++ server_key= master_server_key; ++ else ++ server_key= memcached_generate_hash(ptr, keys[x], key_length[x]); ++ ++ if (memcached_server_response_count(&ptr->hosts[server_key]) == 0) ++ { ++ rc= memcached_connect(&ptr->hosts[server_key]); ++ ++ if (rc != MEMCACHED_SUCCESS) ++ continue; ++ ++ if ((memcached_io_write(&ptr->hosts[server_key], get_command, get_command_length, 0)) == -1) ++ { ++ rc= MEMCACHED_SOME_ERRORS; ++ continue; ++ } ++ WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 0); ++ memcached_server_response_increment(&ptr->hosts[server_key]); ++ WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 1); ++ } ++ ++ if ((memcached_io_write(&ptr->hosts[server_key], keys[x], key_length[x], 0)) == -1) ++ { ++ memcached_server_response_reset(&ptr->hosts[server_key]); ++ rc= MEMCACHED_SOME_ERRORS; ++ continue; ++ } ++ ++ if ((memcached_io_write(&ptr->hosts[server_key], " ", 1, 0)) == -1) ++ { ++ memcached_server_response_reset(&ptr->hosts[server_key]); ++ rc= MEMCACHED_SOME_ERRORS; ++ continue; ++ } ++ } ++ ++ /* ++ Should we muddle on if some servers are dead? ++ */ ++ for (x= 0; x < ptr->number_of_hosts; x++) ++ { ++ if (memcached_server_response_count(&ptr->hosts[x])) ++ { ++ /* We need to do something about non-connnected hosts in the future */ ++ if ((memcached_io_write(&ptr->hosts[x], "\r\n", 2, 1)) == -1) ++ { ++ rc= MEMCACHED_SOME_ERRORS; ++ } ++ } ++ } ++ ++ LIBMEMCACHED_MEMCACHED_MGET_END(); ++ return rc; ++} diff --cc tests/function.c index 69ae84b1,2258757d..b10ead9b --- a/tests/function.c +++ b/tests/function.c @@@ -2310,14 -2308,6 +2308,16 @@@ memcached_return enable_consistent(memc return MEMCACHED_SUCCESS; } +memcached_return enable_replication(memcached_st *memc) +{ + uint64_t value; + value= 2; + enable_consistent(memc); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_REPLICAS, &value); ++ ++ return MEMCACHED_SUCCESS; +} + memcached_return enable_cas(memcached_st *memc) { unsigned int set= 1;