X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=lib%2Fmemcached_get.c;h=12d301ec35319d0faabbe336f75e002a0d024777;hb=8ce1a267a6593221cdd887643517364694ea985f;hp=1b53b11973cad78f1d7934bd1d17cdda31498d3c;hpb=7cbcd28d0e2958df0572d965996a65e22b18e66a;p=awesomized%2Flibmemcached diff --git a/lib/memcached_get.c b/lib/memcached_get.c index 1b53b119..12d301ec 100644 --- a/lib/memcached_get.c +++ b/lib/memcached_get.c @@ -1,97 +1,107 @@ -#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) { + return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length, + flags, error); +} + +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) +{ + unsigned int server_key; size_t send_length; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - char *string_ptr; - - *error= memcached_connect(ptr); - - if (*error != MEMCACHED_SUCCESS) - return NULL; + memcached_result_st *result_buffer= &ptr->result; + memcached_return rc[MEMCACHED_MAX_REPLICAS]; + uint8_t replicas= 0; - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n", - key_length, key); - if (*error != MEMCACHED_SUCCESS) - return NULL; - - if ((send(ptr->fd, buffer, send_length, 0) == -1)) + if (ptr->number_of_hosts == 0) { - fprintf(stderr, "failed fetch on %.*s TCP\n", key_length+1, key); - *error= MEMCACHED_WRITE_FAILURE; + *error= MEMCACHED_NO_SERVERS; return NULL; } - memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE); - *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); - - if (*error == MEMCACHED_SUCCESS) + if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test(&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) { - char *end_ptr; - - string_ptr= buffer; - string_ptr+= 6; /* "VALUE " */ - - /* We do nothing with the key, since we only asked for one key */ - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); + *value_length= 0; + *error= MEMCACHED_BAD_KEY_PROVIDED; + return NULL; + } - /* 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); + if (master_key) + server_key= memcached_generate_hash(ptr, master_key, master_key_length); + else + server_key= memcached_generate_hash(ptr, key, key_length); - /* Length fetch */ - string_ptr= end_ptr + 1; - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); - *value_length= strtoll(string_ptr, &end_ptr, 10); + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, + "get %.*s\r\n", (int)key_length, key); - /* Skip past the \r\n */ - string_ptr= end_ptr +2; + do + { + char response_buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - if (*value_length) + if (memcached_server_response_count(&ptr->hosts[server_key])) { - size_t need_to_copy; - char *pos_ptr; - char *value; - - value= (char *)malloc(*value_length * sizeof(char)); + if (ptr->flags & MEM_NO_BLOCK) + (void)memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1); - if (!value) - { - *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; - return NULL; - } + while(memcached_server_response_count(&ptr->hosts[server_key])) + (void)memcached_response(&ptr->hosts[server_key], response_buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result_buffer); + } - need_to_copy= (*value_length < (size_t)(buffer-string_ptr)) - ? *value_length - : (size_t)(buffer-string_ptr) ; + rc[replicas]= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1); + if (rc[replicas] != MEMCACHED_SUCCESS) + goto error; - pos_ptr= memcpy(value, string_ptr, need_to_copy); + rc[replicas]= memcached_response(&ptr->hosts[server_key], response_buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result_buffer); - if ( need_to_copy > *value_length) - { - size_t read_length; - size_t need_to_read; + /* On no key found, we check the replica */ + if (rc[replicas] == MEMCACHED_END) /* END means that we move on to the next */ + { + memcached_server_response_reset(&ptr->hosts[server_key]); + } + else if (rc[replicas] == MEMCACHED_SUCCESS) + { + *value_length= memcached_string_length(&result_buffer->value); + + if (result_buffer->flags) + *flags= result_buffer->flags; - need_to_read= *value_length - need_to_copy; + *error= MEMCACHED_SUCCESS; + return memcached_string_c_copy(&result_buffer->value); + } - read_length= read(ptr->fd, pos_ptr, need_to_read); - if (read_length != need_to_read) - { - free(value); - *error= MEMCACHED_PARTIAL_READ; + /* On error we just jump to the next potential server */ +error: + if (ptr->number_of_replicas > 1) + { + if (server_key == (ptr->number_of_hosts - 1)) + server_key= 0; + else + server_key++; + } + } while ((++replicas) < ptr->number_of_replicas); - return NULL; - } - } + /* TODO: An error on replica 1 of host down, but not found on 2, will give wrong error */ + /* This is for historical reasons */ + if (rc[0] == MEMCACHED_END) + *error= MEMCACHED_NOTFOUND; + else + *error= rc[0]; - return value; - } - } + *value_length= 0; return NULL; }