X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=lib%2Fmemcached_hosts.c;h=fb53fa229c9f471a35a1e6b004bb22a60e9a12dd;hb=5ed23cb1d7aaa03f05b58dfeabeee72f5aff91c5;hp=64892212009361da7d5b47ac37acd8e5acf984fd;hpb=85a66fec1e07e874e5410ce56a2976d68fbe14fd;p=awesomized%2Flibmemcached diff --git a/lib/memcached_hosts.c b/lib/memcached_hosts.c index 64892212..fb53fa22 100644 --- a/lib/memcached_hosts.c +++ b/lib/memcached_hosts.c @@ -1,82 +1,191 @@ #include #include "common.h" +/* Protoypes (static) */ +static memcached_return server_add(memcached_st *ptr, char *hostname, + unsigned int port, + memcached_connection type); + +#define MEMCACHED_WHEEL_SIZE 1024 +#define MEMCACHED_STRIDE 4 +static void rebalance_wheel(memcached_st *ptr) +{ + unsigned int x; + unsigned int y; + unsigned int latch; + + /* Seed the Wheel */ + memset(ptr->wheel, 0, sizeof(unsigned int) * MEMCACHED_WHEEL_SIZE); + + for (latch= y= x= 0; x < MEMCACHED_WHEEL_SIZE; x++, latch++) + { + if (latch == MEMCACHED_STRIDE) + { + y++; + if (y == ptr->number_of_hosts) + y= 0; + latch= 0; + } + + ptr->wheel[x]= y; + } +} + +static int compare_servers(const void *p1, const void *p2) +{ + int return_value; + memcached_server_st *a= (memcached_server_st *)p1; + memcached_server_st *b= (memcached_server_st *)p2; + + return_value= strcmp(a->hostname, b->hostname); + + if (return_value == 0) + { + if (a->port > b->port) + return_value++; + else + return_value--; + } + + return return_value; +} + +static void host_reset(memcached_st *ptr, memcached_server_st *host, + char *hostname, unsigned int port, + memcached_connection type) +{ + memset(host, 0, sizeof(memcached_server_st)); + strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1); + host->root= ptr ? ptr : NULL; + host->port= port; + host->fd= -1; + host->type= type; + host->read_ptr= host->read_buffer; + if (ptr) + host->next_retry= ptr->retry_timeout; + host->sockaddr_inited= MEMCACHED_NOT_ALLOCATED; +} + +void server_list_free(memcached_st *ptr, memcached_server_st *servers) +{ + unsigned int x; + + if (servers == NULL) + return; + + for (x= 0; x < servers->count; x++) + if (servers[x].address_info) + freeaddrinfo(servers[x].address_info); + + if (ptr && ptr->call_free) + ptr->call_free(ptr, servers); + else + free(servers); +} + memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list) { unsigned int x; - unsigned int count; + uint16_t count; memcached_server_st *new_host_list; if (!list) return MEMCACHED_SUCCESS; - for (count= 0; list[count].hostname; count++); + count= list[0].count; - new_host_list= - (memcached_server_st *)realloc(ptr->hosts, - sizeof(memcached_server_st) * (count + ptr->number_of_hosts + 1)); + if (ptr->call_realloc) + new_host_list= + (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts, + sizeof(memcached_server_st) * (count + ptr->number_of_hosts)); + else + new_host_list= + (memcached_server_st *)realloc(ptr->hosts, + sizeof(memcached_server_st) * (count + ptr->number_of_hosts)); if (!new_host_list) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; ptr->hosts= new_host_list; - for (x= 0; list[x].hostname; x++) + for (x= 0; x < count; x++) { - ptr->hosts[ptr->number_of_hosts].hostname= strdup(list[x].hostname); - ptr->hosts[ptr->number_of_hosts].port= list[x].port; - ptr->hosts[ptr->number_of_hosts].fd= list[x].fd; + WATCHPOINT_ASSERT(list[x].hostname[0] != 0); + host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname, + list[x].port, list[x].type); ptr->number_of_hosts++; } - memset(&ptr->hosts[ptr->number_of_hosts], 0, sizeof(memcached_server_st)); + ptr->hosts[0].count= ptr->number_of_hosts; + + if (ptr->number_of_hosts > 1) + qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers); + + rebalance_wheel(ptr); return MEMCACHED_SUCCESS; } -memcached_return memcached_server_add(memcached_st *ptr, char *hostname, unsigned int port) +memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename) { - memcached_server_st *new_host_list; - char *new_hostname; - LIBMEMCACHED_MEMCACHED_SERVER_ADD_START(); + if (!filename) + return MEMCACHED_FAILURE; + + return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET); +} +memcached_return memcached_server_add_udp(memcached_st *ptr, + char *hostname, + unsigned int port) +{ if (!port) port= MEMCACHED_DEFAULT_PORT; if (!hostname) hostname= "localhost"; + return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP); +} - if (ptr->number_of_hosts) - { +memcached_return memcached_server_add(memcached_st *ptr, + char *hostname, + unsigned int port) +{ + if (!port) + port= MEMCACHED_DEFAULT_PORT; + + if (!hostname) + hostname= "localhost"; + + return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_TCP); +} + +static memcached_return server_add(memcached_st *ptr, char *hostname, + unsigned int port, + memcached_connection type) +{ + memcached_server_st *new_host_list; + LIBMEMCACHED_MEMCACHED_SERVER_ADD_START(); + + + if (ptr->call_realloc) + new_host_list= (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts, + sizeof(memcached_server_st) * (ptr->number_of_hosts+1)); + else new_host_list= (memcached_server_st *)realloc(ptr->hosts, sizeof(memcached_server_st) * (ptr->number_of_hosts+1)); - if (!new_host_list) - return MEMCACHED_MEMORY_ALLOCATION_FAILURE; - memset(&new_host_list[ptr->number_of_hosts], 0, sizeof(memcached_server_st)); - } - else - { - new_host_list= - (memcached_server_st *)malloc(sizeof(memcached_server_st) * 2); - if (!new_host_list) - return MEMCACHED_MEMORY_ALLOCATION_FAILURE; - memset(new_host_list, 0, sizeof(memcached_server_st) * 2); - } + if (new_host_list == NULL) + return MEMCACHED_MEMORY_ALLOCATION_FAILURE; ptr->hosts= new_host_list; - new_hostname= - (char *)malloc(sizeof(char) * (strlen(hostname)+1)); + host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, type); + ptr->number_of_hosts++; + ptr->hosts[0].count++; - if (!new_hostname) - return MEMCACHED_MEMORY_ALLOCATION_FAILURE; + if (ptr->number_of_hosts > 1) + qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers); - memset(new_hostname, 0, strlen(hostname)+1); - memcpy(new_hostname, hostname, strlen(hostname)); - ptr->hosts[ptr->number_of_hosts].hostname= new_hostname; - ptr->hosts[ptr->number_of_hosts].port= port; - ptr->hosts[ptr->number_of_hosts].fd= -1; - ptr->number_of_hosts++; + rebalance_wheel(ptr); LIBMEMCACHED_MEMCACHED_SERVER_ADD_END(); @@ -89,65 +198,53 @@ memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, { unsigned int count; memcached_server_st *new_host_list; - char *new_hostname; - if (!hostname) - return ptr; + if (hostname == NULL || error == NULL) + return NULL; if (!port) port= MEMCACHED_DEFAULT_PORT; - /* Always count so that we keep a free host at the end */ - if (ptr) + /* Increment count for hosts */ + count= 1; + if (ptr != NULL) { - for (count= 0; ptr[count].hostname; count++); - count+= 2; - new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count); - if (!new_host_list) - goto error; - memset(&new_host_list[count-1], 0, sizeof(memcached_server_st)); - } - else + count+= ptr[0].count; + } + + new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count); + if (!new_host_list) { - count= 2; - new_host_list= (memcached_server_st *)malloc(sizeof(memcached_server_st) * count); - if (!new_host_list) - goto error; - memset(new_host_list, 0, sizeof(memcached_server_st) * 2); + *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; + return NULL; } - new_hostname= strdup(hostname); + host_reset(NULL, &new_host_list[count-1], hostname, port, MEMCACHED_CONNECTION_TCP); + + /* Backwards compatibility hack */ + new_host_list[0].count++; + + count= new_host_list[0].count; - if (!new_hostname) - goto error; + if (new_host_list[0].count > 1) + qsort(new_host_list, count, sizeof(memcached_server_st), compare_servers); + + new_host_list[0].count= count; - new_host_list[count-2].hostname= new_hostname; - new_host_list[count-2].port= port; - new_host_list[count-2].fd= -1; *error= MEMCACHED_SUCCESS; return new_host_list; -error: - *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; - - return NULL; } unsigned int memcached_server_list_count(memcached_server_st *ptr) { - unsigned int x; + if (ptr == NULL) + return 0; - for (x= 0; ptr[x].hostname; x++); - - return x; + return ptr[0].count; } void memcached_server_list_free(memcached_server_st *ptr) { - unsigned int x; - - for (x= 0; ptr[x].hostname; x++) - free(ptr[x].hostname); - - free(ptr); + server_list_free(NULL, ptr); }