X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=lib%2Fmemcached_hosts.c;h=de006dd6794b6b5125583e24dfa2bd10e5786d78;hb=8a86b578acc594d37a8638e3e0afba1286c4b6ca;hp=d5ec56064534af7b1ff02de9797138eb59b3015a;hpb=46f12a5edfa0fc0382a9d25355b15d30f857b138;p=m6w6%2Flibmemcached diff --git a/lib/memcached_hosts.c b/lib/memcached_hosts.c index d5ec5606..de006dd6 100644 --- a/lib/memcached_hosts.c +++ b/lib/memcached_hosts.c @@ -6,50 +6,119 @@ static memcached_return server_add(memcached_st *ptr, char *hostname, unsigned int port, memcached_connection type); -static void host_reset(memcached_server_st *host, char *new_hostname, unsigned int port, +#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)); - host->hostname= new_hostname; + 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; - host->write_ptr= host->write_buffer; + 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; - ptr->hosts[ptr->number_of_hosts].stack_responses= list[x].stack_responses; - ptr->hosts[ptr->number_of_hosts].cursor_active= list[x].cursor_active; - ptr->hosts[ptr->number_of_hosts].type= list[x].type; + 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++; } - host_reset(&ptr->hosts[ptr->number_of_hosts], NULL, 0, - MEMCACHED_CONNECTION_UNKNOWN); + 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; } @@ -93,40 +162,28 @@ static memcached_return server_add(memcached_st *ptr, char *hostname, memcached_connection type) { memcached_server_st *new_host_list; - char *new_hostname; LIBMEMCACHED_MEMCACHED_SERVER_ADD_START(); - if (ptr->number_of_hosts) - { + 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; - host_reset(&new_host_list[ptr->number_of_hosts], NULL, 0, - MEMCACHED_CONNECTION_UNKNOWN); - } - else - { - new_host_list= - (memcached_server_st *)malloc(sizeof(memcached_server_st) * 2); - if (!new_host_list) - return MEMCACHED_MEMORY_ALLOCATION_FAILURE; - host_reset(&new_host_list[0], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN); - host_reset(&new_host_list[1], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN); - } + 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); - memcpy(new_hostname, hostname, strlen(hostname)); - host_reset(&ptr->hosts[ptr->number_of_hosts], new_hostname, port, type); - ptr->number_of_hosts++; + rebalance_wheel(ptr); LIBMEMCACHED_MEMCACHED_SERVER_ADD_END(); @@ -139,64 +196,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; - host_reset(&new_host_list[count-1], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN); - } - 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; - host_reset(&new_host_list[0], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN); - host_reset(&new_host_list[1], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN); + *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; - host_reset(&new_host_list[count-2], new_hostname, port, MEMCACHED_CONNECTION_TCP); *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); }