X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=lib%2Fmemcached_get.c;h=8cc7ce30b04adee6eb7d62555ed9fd90b0c8ecd4;hb=8a86b578acc594d37a8638e3e0afba1286c4b6ca;hp=c688af34639684f8931d54c00e5db1b4a9c19946;hpb=be683ec76c3d55c427d72d3529f521e479967f6b;p=m6w6%2Flibmemcached diff --git a/lib/memcached_get.c b/lib/memcached_get.c index c688af34..8cc7ce30 100644 --- a/lib/memcached_get.c +++ b/lib/memcached_get.c @@ -1,101 +1,172 @@ -#include +#include "common.h" +#include "memcached_io.h" +/* + What happens if no servers exist? +*/ char *memcached_get(memcached_st *ptr, char *key, size_t key_length, size_t *value_length, - uint16_t *flags, + uint32_t *flags, memcached_return *error) { - size_t send_length; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - char *string_ptr; - unsigned int server_key; - - *value_length= 0; - *error= memcached_connect(ptr); + return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length, + flags, error); +} - if (*error != MEMCACHED_SUCCESS) +char *memcached_get_by_key(memcached_st *ptr, + char *master_key, size_t master_key_length, + char *key, size_t key_length, + size_t *value_length, + uint32_t *flags, + memcached_return *error) +{ + char *value; + size_t dummy_length; + uint32_t dummy_flags; + memcached_return dummy_error; + + /* Request the key */ + *error= memcached_mget_by_key(ptr, + master_key, + master_key_length, + &key, &key_length, 1); + + value= memcached_fetch(ptr, NULL, NULL, + value_length, flags, error); + /* This is for historical reasons */ + if (*error == MEMCACHED_END) + *error= MEMCACHED_NOTFOUND; + + if (value == NULL) return NULL; - server_key= memcached_generate_hash(key, key_length) % ptr->number_of_hosts; + (void)memcached_fetch(ptr, NULL, NULL, + &dummy_length, &dummy_flags, + &dummy_error); + WATCHPOINT_ASSERT(dummy_length == 0); - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n", - key_length, key); - if (*error != MEMCACHED_SUCCESS) - return NULL; + return value; +} - if ((send(ptr->hosts[server_key].fd, buffer, send_length, 0) == -1)) +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) { - fprintf(stderr, "failed fetch on %.*s TCP\n", key_length+1, key); - *error= MEMCACHED_WRITE_FAILURE; - return NULL; + get_command= "gets "; + get_command_length= 5; } - memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE); - *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key); + if (master_key && master_key_length) + master_server_key= memcached_generate_hash(ptr, master_key, master_key_length); - if (*error == MEMCACHED_SUCCESS) - { - char *end_ptr; + /* + 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. - string_ptr= buffer; - string_ptr+= 6; /* "VALUE " */ + 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]; - /* We do nothing with the key, since we only asked for one key */ - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); + if (ptr->flags & MEM_NO_BLOCK) + (void)memcached_io_write(&ptr->hosts[x], NULL, 0, 1); - /* Flags fetch */ - string_ptr= end_ptr + 1; - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); - *flags= (uint16_t)strtol(string_ptr, &end_ptr, 10); + while(memcached_server_response_count(&ptr->hosts[x])) + (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result); + } + } - /* Length fetch */ - string_ptr= end_ptr + 1; - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); - *value_length= strtoll(string_ptr, &end_ptr, 10); + /* + 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; - /* Skip past the \r\n */ - string_ptr= end_ptr +2; + if (master_server_key) + server_key= master_server_key; + else + server_key= memcached_generate_hash(ptr, keys[x], key_length[x]); - if (*value_length) + if (memcached_server_response_count(&ptr->hosts[server_key]) == 0) { - size_t need_to_copy; - char *pos_ptr; - char *value; + rc= memcached_connect(&ptr->hosts[server_key]); - value= (char *)malloc(*value_length * sizeof(char)); + if (rc != MEMCACHED_SUCCESS) + continue; - if (!value) + if ((memcached_io_write(&ptr->hosts[server_key], get_command, get_command_length, 0)) == -1) { - *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; - return NULL; + 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); + } - need_to_copy= (*value_length < (size_t)(buffer-string_ptr)) - ? *value_length - : (size_t)(buffer-string_ptr) ; + 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; + } - pos_ptr= memcpy(value, string_ptr, need_to_copy); + if ((memcached_io_write(&ptr->hosts[server_key], " ", 1, 0)) == -1) + { + memcached_server_response_reset(&ptr->hosts[server_key]); + rc= MEMCACHED_SOME_ERRORS; + continue; + } + } - if ( need_to_copy > *value_length) + /* + 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) { - size_t read_length; - size_t need_to_read; - - need_to_read= *value_length - need_to_copy; - - read_length= read(ptr->hosts[server_key].fd, pos_ptr, need_to_read); - if (read_length != need_to_read) - { - free(value); - *error= MEMCACHED_PARTIAL_READ; - - return NULL; - } + rc= MEMCACHED_SOME_ERRORS; } - - return value; } } - return NULL; + LIBMEMCACHED_MEMCACHED_MGET_END(); + return rc; }