static memcached_return_t server_add(memcached_st *ptr, const char *hostname, in_port_t port, uint32_t weight, memcached_connection_t type) { memcached_server_st *new_host_list; memcached_server_write_instance_st instance; if ( (ptr->flags.use_udp && type != MEMCACHED_CONNECTION_UDP) || ( (type == MEMCACHED_CONNECTION_UDP) && (! ptr->flags.use_udp) ) ) return MEMCACHED_INVALID_HOST_PROTOCOL; new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr), sizeof(memcached_server_st) * (ptr->number_of_hosts + 1)); if (new_host_list == NULL) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; memcached_server_list_set(ptr, new_host_list); /* TODO: Check return type */ instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr)); (void)memcached_server_create_with(ptr, instance, hostname, port, weight, type); ptr->number_of_hosts++; instance= memcached_server_instance_fetch(ptr, 0); memcached_servers_set_count(instance, memcached_server_count(ptr)); return run_distribution(ptr); }
void memcached_servers_reset(memcached_st *ptr) { server_list_free(ptr, memcached_server_list(ptr)); memcached_server_list_set(ptr, NULL); ptr->number_of_hosts= 0; ptr->last_disconnected_server= NULL; ptr->server_failure_limit= 0; }
static void sort_hosts(memcached_st *ptr) { if (memcached_server_count(ptr)) { memcached_server_write_instance_st instance; qsort(memcached_server_list(ptr), memcached_server_count(ptr), sizeof(memcached_server_st), compare_servers); instance= memcached_server_instance_fetch(ptr, 0); instance->number_of_hosts= memcached_server_count(ptr); } }
memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list) { uint32_t count; memcached_server_st *new_host_list; uint32_t x; if (! list) return MEMCACHED_SUCCESS; count= memcached_server_list_count(list); new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr), sizeof(memcached_server_st) * (count + memcached_server_count(ptr))); if (! new_host_list) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; memcached_server_list_set(ptr, new_host_list); for (x= 0; x < count; x++) { memcached_server_write_instance_st instance; if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP) || ((list[x].type == MEMCACHED_CONNECTION_UDP) && ! (ptr->flags.use_udp)) ) return MEMCACHED_INVALID_HOST_PROTOCOL; WATCHPOINT_ASSERT(list[x].hostname[0] != 0); instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr)); /* TODO check return type */ (void)memcached_server_create_with(ptr, instance, list[x].hostname, list[x].port, list[x].weight, list[x].type); ptr->number_of_hosts++; } /* Provides backwards compatibility with server list. */ { memcached_server_write_instance_st instance; instance= memcached_server_instance_fetch(ptr, 0); instance->number_of_hosts= memcached_server_count(ptr); } return run_distribution(ptr); }
void memcached_free(memcached_st *ptr) { /* If we have anything open, lets close it now */ memcached_quit(ptr); server_list_free(ptr, memcached_server_list(ptr)); memcached_result_free(&ptr->result); if (ptr->on_cleanup) ptr->on_cleanup(ptr); if (ptr->continuum) libmemcached_free(ptr, ptr->continuum); if (memcached_is_allocated(ptr)) { libmemcached_free(ptr, ptr); } }
static test_return_t post_udp_op_check(memcached_st *memc, uint16_t *expected_req_ids) { (void)memc; (void)expected_req_ids; #if 0 memcached_server_st *cur_server = memcached_server_list(memc); uint16_t *cur_req_ids = get_udp_request_ids(memc); for (size_t x= 0; x < memcached_server_count(memc); x++) { test_true(cur_server[x].cursor_active == 0); test_true(cur_req_ids[x] == expected_req_ids[x]); } free(expected_req_ids); free(cur_req_ids); #endif return TEST_SUCCESS; }
/* ** There is a little bit of a hack here, instead of removing ** the servers, I just set num host to 0 and them add then new udp servers **/ static test_return_t init_udp(memcached_st *memc) { memcached_version(memc); #if 0 memcached_server_instance_st instance= memcached_server_instance_by_position(memc, 0); /* For the time being, only support udp test for >= 1.2.6 && < 1.3 */ if (instance->major_version != 1 || instance->minor_version != 2 || instance->micro_version < 6) return TEST_SKIPPED; uint32_t num_hosts= memcached_server_count(memc); memcached_server_st servers[num_hosts]; memcpy(servers, memcached_server_list(memc), sizeof(memcached_server_st) * num_hosts); for (uint32_t x= 0; x < num_hosts; x++) { memcached_server_instance_st set_instance= memcached_server_instance_by_position(memc, x); memcached_server_free(((memcached_server_write_instance_st)set_instance)); } memc->number_of_hosts= 0; memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1); for (uint32_t x= 0; x < num_hosts; x++) { memcached_server_instance_st set_instance= memcached_server_instance_by_position(memc, x); test_true(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS); test_true(set_instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); } #endif return TEST_SKIPPED; }
int main(int argc, char *argv[]) { memcached_return rc; memcached_st *memc; memcached_stat_st *stat; memcached_server_st *servers; memcached_server_st *server_list; memcached_analysis_st *report; options_parse(argc, argv); if (!opt_servers) { char *temp; if ((temp= getenv("MEMCACHED_SERVERS"))) opt_servers= strdup(temp); else { fprintf(stderr, "No Servers provided\n\n"); help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, 0); exit(1); } } memc= memcached_create(NULL); servers= memcached_servers_parse(opt_servers); memcached_server_push(memc, servers); memcached_server_list_free(servers); stat= memcached_stat(memc, NULL, &rc); if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS) { printf("Failure to communicate with servers (%s)\n", memcached_strerror(memc, rc)); exit(1); } server_list= memcached_server_list(memc); if (opt_analyze) { report= memcached_analyze(memc, stat, &rc); if (rc != MEMCACHED_SUCCESS || report == NULL) { printf("Failure to analyze servers (%s)\n", memcached_strerror(memc, rc)); exit(1); } print_analysis_report(memc, report, server_list); free(report); } else print_server_listing(memc, stat, server_list); free(stat); free(opt_servers); memcached_free(memc); return 0; }
static memcached_return_t update_continuum(memcached_st *ptr) { uint32_t host_index; uint32_t continuum_index= 0; uint32_t value; memcached_server_st *list; uint32_t pointer_index; uint32_t pointer_counter= 0; uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER; uint32_t pointer_per_hash= 1; uint64_t total_weight= 0; uint64_t is_ketama_weighted= 0; uint64_t is_auto_ejecting= 0; uint32_t points_per_server= 0; uint32_t live_servers= 0; struct timeval now; if (gettimeofday(&now, NULL) != 0) { ptr->cached_errno = errno; return MEMCACHED_ERRNO; } list = memcached_server_list(ptr); /* count live servers (those without a retry delay set) */ is_auto_ejecting= _is_auto_eject_host(ptr); if (is_auto_ejecting) { live_servers= 0; ptr->next_distribution_rebuild= 0; for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index) { if (list[host_index].next_retry <= now.tv_sec) live_servers++; else { if (ptr->next_distribution_rebuild == 0 || list[host_index].next_retry < ptr->next_distribution_rebuild) ptr->next_distribution_rebuild= list[host_index].next_retry; } } } else { live_servers= memcached_server_count(ptr); } is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER); if (live_servers == 0) return MEMCACHED_SUCCESS; if (live_servers > ptr->continuum_count) { memcached_continuum_item_st *new_ptr; new_ptr= libmemcached_realloc(ptr, ptr->continuum, sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server); if (new_ptr == 0) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; ptr->continuum= new_ptr; ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION; } if (is_ketama_weighted) { for (host_index = 0; host_index < memcached_server_count(ptr); ++host_index) { if (list[host_index].weight == 0) { list[host_index].weight = 1; } if (! is_auto_ejecting || list[host_index].next_retry <= now.tv_sec) total_weight += list[host_index].weight; } } for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index) { if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec) continue; if (is_ketama_weighted) { float pct = (float)list[host_index].weight / (float)total_weight; pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4); pointer_per_hash= 4; #ifdef DEBUG printf("ketama_weighted:%s|%d|%llu|%u\n", list[host_index].hostname, list[host_index].port, (unsigned long long)list[host_index].weight, pointer_per_server); #endif } if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY) { for (pointer_index= 0; pointer_index < pointer_per_server / pointer_per_hash; pointer_index++) { char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= ""; size_t sort_host_length; // Spymemcached ketema key format is: hostname/ip:port-index // If hostname is not available then: /ip:port-index sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, "/%s:%u-%u", list[host_index].hostname, (uint32_t)list[host_index].port, pointer_index); #ifdef DEBUG printf("update_continuum: key is %s\n", sort_host); #endif WATCHPOINT_ASSERT(sort_host_length); if (is_ketama_weighted) { for (uint32_t x= 0; x < pointer_per_hash; x++) { value= ketama_server_hash(sort_host, sort_host_length, x); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } else { value= hashkit_digest(&ptr->distribution_hashkit, sort_host, sort_host_length); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } } else { for (pointer_index= 1; pointer_index <= pointer_per_server / pointer_per_hash; pointer_index++) { char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= ""; size_t sort_host_length; if (list[host_index].port == MEMCACHED_DEFAULT_PORT) { sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, "%s-%u", list[host_index].hostname, pointer_index - 1); } else { sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, "%s:%u-%u", list[host_index].hostname, (uint32_t)list[host_index].port, pointer_index - 1); } WATCHPOINT_ASSERT(sort_host_length); if (is_ketama_weighted) { for (uint32_t x = 0; x < pointer_per_hash; x++) { value= ketama_server_hash(sort_host, sort_host_length, x); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } else { value= hashkit_digest(&ptr->distribution_hashkit, sort_host, sort_host_length); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } } pointer_counter+= pointer_per_server; } WATCHPOINT_ASSERT(ptr); WATCHPOINT_ASSERT(ptr->continuum); WATCHPOINT_ASSERT(memcached_server_count(ptr) * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE); ptr->continuum_points_counter= pointer_counter; qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp); #ifdef DEBUG for (pointer_index= 0; memcached_server_count(ptr) && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) { WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value); } #endif return MEMCACHED_SUCCESS; }
/* clone is the destination, while source is the structure to clone. If source is NULL the call is the same as if a memcached_create() was called. */ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source) { memcached_return_t rc= MEMCACHED_SUCCESS; memcached_st *new_clone; if (source == NULL) return memcached_create(clone); if (clone && memcached_is_allocated(clone)) { return NULL; } new_clone= memcached_create(clone); if (new_clone == NULL) return NULL; new_clone->flags= source->flags; new_clone->send_size= source->send_size; new_clone->recv_size= source->recv_size; new_clone->poll_timeout= source->poll_timeout; new_clone->connect_timeout= source->connect_timeout; new_clone->retry_timeout= source->retry_timeout; new_clone->distribution= source->distribution; hashkit_st *hash_ptr; hash_ptr= hashkit_clone(&new_clone->hashkit, &source->hashkit); if (! hash_ptr) { memcached_free(new_clone); return NULL; } hash_ptr= hashkit_clone(&new_clone->distribution_hashkit, &source->distribution_hashkit); if (! hash_ptr) { memcached_free(new_clone); return NULL; } new_clone->user_data= source->user_data; new_clone->snd_timeout= source->snd_timeout; new_clone->rcv_timeout= source->rcv_timeout; new_clone->on_clone= source->on_clone; new_clone->on_cleanup= source->on_cleanup; new_clone->allocators= source->allocators; new_clone->get_key_failure= source->get_key_failure; new_clone->delete_trigger= source->delete_trigger; new_clone->server_failure_limit= source->server_failure_limit; new_clone->io_msg_watermark= source->io_msg_watermark; new_clone->io_bytes_watermark= source->io_bytes_watermark; new_clone->io_key_prefetch= source->io_key_prefetch; new_clone->number_of_replicas= source->number_of_replicas; if (memcached_server_list(source)) rc= memcached_server_push(new_clone, memcached_server_list(source)); if (rc != MEMCACHED_SUCCESS) { memcached_free(new_clone); return NULL; } if (source->prefix_key_length) { strcpy(new_clone->prefix_key, source->prefix_key); new_clone->prefix_key_length= source->prefix_key_length; } rc= run_distribution(new_clone); if (rc != MEMCACHED_SUCCESS) { memcached_free(new_clone); return NULL; } if (source->on_clone) source->on_clone(new_clone, source); return new_clone; }