static memcached_return_t memcached_flush_textual(memcached_st *ptr, time_t expiration) { unsigned int x; size_t send_length; memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; for (x= 0; x < memcached_server_count(ptr); x++) { bool no_reply= ptr->flags.no_reply; memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x); if (expiration) send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "flush_all %llu%s\r\n", (unsigned long long)expiration, no_reply ? " noreply" : ""); else send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "flush_all%s\r\n", no_reply ? " noreply" : ""); rc= memcached_do(instance, buffer, send_length, true); if (rc == MEMCACHED_SUCCESS && !no_reply) (void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); } return MEMCACHED_SUCCESS; }
/* One version is public and will not modify the distribution hash, the other will. */ static uint32_t _generate_hash_wrapper(const memcached_st *ptr, const char *key, size_t key_length) { WATCHPOINT_ASSERT(memcached_server_count(ptr)); if (memcached_server_count(ptr) == 1) return 0; if (ptr->flags.hash_with_prefix_key) { size_t temp_length= ptr->prefix_key_length + key_length; char *temp = malloc(temp_length); uint32_t ret; if (temp_length > MEMCACHED_MAX_KEY -1) return 0; strncpy(temp, ptr->prefix_key, ptr->prefix_key_length); strncpy(temp + ptr->prefix_key_length, key, key_length); ret = generate_hash(ptr, temp, temp_length); free(temp); return ret; } else { return generate_hash(ptr, key, key_length); } }
static void print_server_listing(memcached_st *memc, memcached_stat_st *stat, memcached_server_st *server_list) { unsigned int x; memcached_return rc; printf("Listing %u Server\n\n", memcached_server_count(memc)); for (x= 0; x < memcached_server_count(memc); x++) { char **list; char **ptr; list= memcached_stat_get_keys(memc, &stat[x], &rc); printf("Server: %s (%u)\n", memcached_server_name(memc, server_list[x]), memcached_server_port(memc, server_list[x])); for (ptr= list; *ptr; ptr++) { memcached_return rc; char *value= memcached_stat_get_value(memc, &stat[x], *ptr, &rc); printf("\t %s: %s\n", *ptr, value); free(value); } free(list); printf("\n"); } }
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); }
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); } }
static uint16_t *get_udp_request_ids(memcached_st *memc) { uint16_t *ids= malloc(sizeof(uint16_t) * memcached_server_count(memc)); assert(ids != NULL); for (uint32_t x= 0; x < memcached_server_count(memc); x++) { memcached_server_instance_st instance= memcached_server_instance_by_position(memc, x); ids[x]= get_udp_datagram_request_id((struct udp_datagram_header_st *) ((memcached_server_instance_st )instance)->write_buffer); } return ids; }
Array c_Memcache::t_getstats(const String& type /* = null_string */, int slabid /* = 0 */, int limit /* = 100 */) { if (!memcached_server_count(&m_memcache)) { return NULL; } char extra_args[30] = {0}; if (slabid) { snprintf(extra_args, sizeof(extra_args), "%s %d %d", type.c_str(), slabid, limit); } else if (!type.empty()) { snprintf(extra_args, sizeof(extra_args), "%s", type.c_str()); } LMCD_SERVER_POSITION_INSTANCE_TYPE instance = memcached_server_instance_by_position(&m_memcache, 0); const char *hostname = LMCD_SERVER_HOSTNAME(instance); in_port_t port = LMCD_SERVER_PORT(instance); memcached_stat_st stats; if (memcached_stat_servername(&stats, extra_args, hostname, port) != MEMCACHED_SUCCESS) { return NULL; } memcached_return_t ret; return memcache_build_stats(&m_memcache, &stats, &ret); }
static void print_analysis_report(memcached_st *memc, memcached_analysis_st *report, memcached_server_st *server_list) { uint32_t server_count= memcached_server_count(memc); printf("Memcached Cluster Analysis Report\n\n"); printf("\tNumber of Servers Analyzed : %d\n", server_count); printf("\tAverage Item Size (incl/overhead) : %u bytes\n", report->average_item_size); if (server_count == 1) { printf("\nFor a detailed report, you must supply multiple servers.\n"); return; } printf("\n"); printf("\tNode with most memory consumption : %s:%u (%u bytes)\n", memcached_server_name(memc, server_list[report->most_consumed_server]), memcached_server_port(memc, server_list[report->most_consumed_server]), report->most_used_bytes); printf("\tNode with least free space : %s:%u (%u bytes remaining)\n", memcached_server_name(memc, server_list[report->least_free_server]), memcached_server_port(memc, server_list[report->least_free_server]), report->least_remaining_bytes); printf("\tNode with longest uptime : %s:%u (%us)\n", memcached_server_name(memc, server_list[report->oldest_server]), memcached_server_port(memc, server_list[report->oldest_server]), report->longest_uptime); printf("\tPool-wide Hit Ratio : %1.f%%\n", report->pool_hit_ratio); printf("\n"); }
Variant c_Memcache::t_getversion() { int server_count = memcached_server_count(&m_memcache); char version[16]; int version_len = 0; if (memcached_version(&m_memcache) != MEMCACHED_SUCCESS) { return false; } for (int x = 0; x < server_count; x++) { memcached_server_instance_st instance = memcached_server_instance_by_position(&m_memcache, x); if (!instance->major_version) { continue; } version_len = snprintf(version, sizeof(version), "%d.%d.%d", instance->major_version, instance->minor_version, instance->micro_version); return String(version, version_len, CopyString); } return false; }
Array c_Memcache::t_getstats(CStrRef type /* = null_string */, int slabid /* = 0 */, int limit /* = 100 */) { if (!memcached_server_count(&m_memcache)) { return NULL; } char extra_args[30] = {0}; if (slabid) { snprintf(extra_args, sizeof(extra_args), "%s %d %d", type.c_str(), slabid, limit); } else if (!type.empty()) { snprintf(extra_args, sizeof(extra_args), "%s", type.c_str()); } memcached_server_instance_st instance = memcached_server_instance_by_position(&m_memcache, 0); memcached_stat_st stats; if (memcached_stat_servername(&stats, extra_args, instance->hostname, instance->port) != MEMCACHED_SUCCESS) { return NULL; } memcached_return_t ret; return memcache_build_stats(&m_memcache, &stats, &ret); }
Variant c_Memcache::t_getversion() { int server_count = memcached_server_count(&m_memcache); char version[16]; int version_len = 0; if (memcached_version(&m_memcache) != MEMCACHED_SUCCESS) { return false; } for (int x = 0; x < server_count; x++) { LMCD_SERVER_POSITION_INSTANCE_TYPE instance = memcached_server_instance_by_position(&m_memcache, x); uint8_t majorVersion = LMCD_SERVER_MAJOR_VERSION(instance); uint8_t minorVersion = LMCD_SERVER_MINOR_VERSION(instance); uint8_t microVersion = LMCD_SERVER_MICRO_VERSION(instance); if (!majorVersion) { continue; } version_len = snprintf(version, sizeof(version), "%" PRIu8 ".%" PRIu8 ".%" PRIu8, majorVersion, minorVersion, microVersion); return String(version, version_len, CopyString); } return false; }
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); }
/*doc Memcached stats Returns a Map with servers' statistics. Keys are server addresses, values are maps with actual stats. */ IoObject *IoMemcached_stats(IoMemcached *self, IoObject *locals, IoMessage *m) { IoMap *results_map = IoMap_new(IOSTATE); int errors = 0; uint32_t pos = 0; while(pos < memcached_server_count(DATA(self)->mc)) { memcached_server_instance_st server = memcached_server_instance_by_position(DATA(self)->mc, pos); if(server == NULL) continue; const char *hostname = memcached_server_name(server); const in_port_t port = memcached_server_port(server); memcached_stat_st stats; memcached_return_t rc = memcached_stat_servername(&stats, "", hostname, port); if(rc != MEMCACHED_SUCCESS) { errors++; continue; } char **ckeys = memcached_stat_get_keys(DATA(self)->mc, &stats, &rc); if(rc != MEMCACHED_SUCCESS) { errors++; continue; } IoMap *per_server_map = IoMap_new(IOSTATE); char *ckey = *ckeys; while(ckey != NULL) { char *cvalue = memcached_stat_get_value(DATA(self)->mc, &stats, ckey, &rc); if(rc != MEMCACHED_SUCCESS) { errors++; continue; } IoMap_rawAtPut(per_server_map, IOSYMBOL(ckey), IOSYMBOL(cvalue)); free(cvalue); ckey++; } free(ckeys); // "127.0.0.1:11211" char *server_key = (char *) malloc((strlen(hostname) + 1 + 5 + 1) * sizeof(char)); sprintf(server_key, "%s:%d", hostname, port); IoMap_rawAtPut(results_map, IOSYMBOL(server_key), per_server_map); free(server_key); pos++; } if(errors > 0) IoState_error_(IOSTATE, m, memcached_strerror(DATA(self)->mc, MEMCACHED_SOME_ERRORS)); return results_map; }
void memcached_quit(memcached_st *ptr) { uint32_t x; if (memcached_server_count(ptr) == 0) return; if (memcached_server_count(ptr)) { for (x= 0; x < memcached_server_count(ptr); x++) { memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x); memcached_quit_server(instance, false); } } }
static uint32_t dispatch_host(const memcached_st *ptr, uint32_t hash) { switch (ptr->distribution) { case MEMCACHED_DISTRIBUTION_CONSISTENT: case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA: case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY: { uint32_t num= ptr->continuum_points_counter; WATCHPOINT_ASSERT(ptr->continuum); hash= hash; memcached_continuum_item_st *begin, *end, *left, *right, *middle; begin= left= ptr->continuum; end= right= ptr->continuum + num; while (left < right) { middle= left + (right - left) / 2; if (middle->value < hash) left= middle + 1; else right= middle; } if (right == end) right= begin; return right->index; } case MEMCACHED_DISTRIBUTION_MODULA: return hash % memcached_server_count(ptr); case MEMCACHED_DISTRIBUTION_RANDOM: return (uint32_t) random() % memcached_server_count(ptr); case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX: default: WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */ return hash % memcached_server_count(ptr); } /* NOTREACHED */ }
static test_return_t udp_flush_test(memcached_st *memc) { memcached_return_t rc; uint16_t *expected_ids= get_udp_request_ids(memc); for (size_t x= 0; x < memcached_server_count(memc); x++) { increment_request_id(&expected_ids[x]); } rc= memcached_flush(memc,0); test_true(rc == MEMCACHED_SUCCESS); return post_udp_op_check(memc,expected_ids); }
my_bool memc_set_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { memcached_return rc; unsigned int count; memc_function_st *container; container= prepare_args(args, message, MEMC_SET, 2, 3); if (container == NULL) return 1; /* Init the memcached_st we will use for this pass */ rc= memc_get_servers(&container->memc); count= memcached_server_count(&container->memc); initid->ptr= (char *)container; return 0; }
static test_return_t set_udp_behavior_test(memcached_st *memc) { memcached_quit(memc); memc->number_of_hosts= 0; memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution); test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1) == MEMCACHED_SUCCESS); test_true(memc->flags.use_udp); test_true(memc->flags.no_reply); test_true(memcached_server_count(memc) == 0); memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,0); test_true(! (memc->flags.use_udp)); memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY,0); test_true(! (memc->flags.no_reply)); return TEST_SUCCESS; }
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; }
Array c_Memcache::t_getextendedstats(const String& type /* = null_string */, int slabid /* = 0 */, int limit /* = 100 */) { memcached_return_t ret; memcached_stat_st *stats; stats = memcached_stat(&m_memcache, NULL, &ret); if (ret != MEMCACHED_SUCCESS) { return NULL; } int server_count = memcached_server_count(&m_memcache); Array return_val; for (int server_id = 0; server_id < server_count; server_id++) { memcached_stat_st *stat; char stats_key[30] = {0}; size_t key_len; LMCD_SERVER_POSITION_INSTANCE_TYPE instance = memcached_server_instance_by_position(&m_memcache, server_id); const char *hostname = LMCD_SERVER_HOSTNAME(instance); in_port_t port = LMCD_SERVER_PORT(instance); stat = stats + server_id; Array server_stats = memcache_build_stats(&m_memcache, stat, &ret); if (ret != MEMCACHED_SUCCESS) { continue; } key_len = snprintf(stats_key, sizeof(stats_key), "%s:%d", hostname, port); return_val.set(String(stats_key, key_len, CopyString), server_stats); } free(stats); return return_val; }
Array c_Memcache::t_getextendedstats(CStrRef type /* = null_string */, int slabid /* = 0 */, int limit /* = 100 */) { memcached_return_t ret; memcached_stat_st *stats; stats = memcached_stat(&m_memcache, NULL, &ret); if (ret != MEMCACHED_SUCCESS) { return NULL; } int server_count = memcached_server_count(&m_memcache); Array return_val; for (int server_id = 0; server_id < server_count; server_id++) { memcached_server_instance_st server; memcached_stat_st *stat; char stats_key[30] = {0}; size_t key_len; server = memcached_server_instance_by_position(&m_memcache, server_id); stat = stats + server_id; Array server_stats = memcache_build_stats(&m_memcache, stat, &ret); if (ret != MEMCACHED_SUCCESS) { continue; } key_len = snprintf(stats_key, sizeof(stats_key), "%s:%d", server->hostname, server->port); return_val.set(String(stats_key, key_len, CopyString), server_stats); } free(stats); return return_val; }
bool ESPMemCached::checkServersUp() { memcached_return_t rc; char* args = nullptr; OwnedMalloc<memcached_stat_st> stats; stats.setown(memcached_stat(connection, args, &rc)); unsigned int numberOfServers = memcached_server_count(connection); if (numberOfServers < 1) { ESPLOG(LogMin,"ESPMemCached: no server connected."); return false; } unsigned int numberOfServersDown = 0; for (unsigned i = 0; i < numberOfServers; ++i) { if (stats[i].pid == -1)//perhaps not the best test? { numberOfServersDown++; VStringBuffer msg("ESPMemCached: Failed connecting to entry %u\nwithin the server list: %s", i+1, options.str()); ESPLOG(LogMin, "%s", msg.str()); } } if (numberOfServersDown == numberOfServers) { ESPLOG(LogMin,"ESPMemCached: Failed connecting to ALL servers. Check memcached on all servers and \"memcached -B ascii\" not used."); return false; } //check memcached version homogeneity for (unsigned i = 0; i < numberOfServers-1; ++i) { if (!streq(stats[i].version, stats[i+1].version)) DBGLOG("ESPMemCached: Inhomogeneous versions of memcached across servers."); } return true; }
/* ** 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; }
/* Used for broadcast commands, like flush_all or stats. */ bool cproxy_broadcast_a2a_downstream(downstream *d, char *command, conn *uc, char *suffix) { assert(d != NULL); assert(d->ptd != NULL); assert(d->ptd->proxy != NULL); assert(d->downstream_conns != NULL); assert(command != NULL); assert(uc != NULL); assert(uc->next == NULL); assert(uc->item == NULL); int nwrite = 0; int nconns = memcached_server_count(&d->mst); for (int i = 0; i < nconns; i++) { conn *c = d->downstream_conns[i]; if (c != NULL) { if (cproxy_prep_conn_for_write(c)) { assert(c->state == conn_pause); out_string(c, command); if (update_event(c, EV_WRITE | EV_PERSIST)) { nwrite++; if (uc->noreply) { c->write_and_go = conn_pause; } } else { if (settings.verbose > 1) fprintf(stderr, "Update cproxy write event failed\n"); d->ptd->stats.stats.err_oom++; cproxy_close_conn(c); } } else { d->ptd->stats.stats.err_downstream_write_prep++; cproxy_close_conn(c); } } } if (settings.verbose > 1) fprintf(stderr, "forward multiget nwrite %d out of %d\n", nwrite, nconns); d->downstream_used_start = nwrite; d->downstream_used = nwrite; if (cproxy_dettach_if_noreply(d, uc) == false) { d->upstream_suffix = suffix; cproxy_start_downstream_timeout(d, NULL); } else { // TODO: Handle flush_all's expiration parameter against // the front_cache. // if (strncmp(command, "flush_all", 9) == 0) { mcache_flush_all(&d->ptd->proxy->front_cache, 0); } } return nwrite > 0; }
{ memcached_return_t rc; LIBMEMCACHED_MEMCACHED_FLUSH_START(); if (ptr->flags.binary_protocol) rc= memcached_flush_binary(ptr, expiration); else rc= memcached_flush_textual(ptr, expiration); LIBMEMCACHED_MEMCACHED_FLUSH_END(); return rc; } static memcached_return_t memcached_flush_textual(memcached_st *ptr, time_t expiration) { unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; for (unsigned int x= 0; x < memcached_server_count(ptr); x++) { memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; bool no_reply= ptr->flags.no_reply; memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x); int send_length; if (expiration) { send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks) { memcached_return_t rc= MEMCACHED_SUCCESS; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; size_t send_length; uint32_t server_key; uint32_t x; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; for (server_key= 0; server_key < memcached_server_count(ptr); server_key++) { memcached_server_instance_st *instance; instance= memcached_server_instance_fetch(ptr, server_key); /* 256 I BELIEVE is the upper limit of slabs */ for (x= 0; x < 256; x++) { send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "stats cachedump %u 0 0\r\n", x); rc= memcached_do(instance, buffer, send_length, true); unlikely (rc != MEMCACHED_SUCCESS) goto error; while (1) { uint32_t callback_counter; rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); if (rc == MEMCACHED_ITEM) { char *string_ptr, *end_ptr; char *key; string_ptr= buffer; string_ptr+= 5; /* Move past ITEM */ for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++); key= string_ptr; key[(size_t)(end_ptr-string_ptr)]= 0; for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++) { rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context); if (rc != MEMCACHED_SUCCESS) break; } } else if (rc == MEMCACHED_END) break; else if (rc == MEMCACHED_SERVER_ERROR || rc == MEMCACHED_CLIENT_ERROR) { /* If we try to request stats cachedump for a slab class that is too big * the server will return an incorrect error message: * "MEMCACHED_SERVER_ERROR failed to allocate memory" * This isn't really a fatal error, so let's just skip it. I want to * fix the return value from the memcached server to a CLIENT_ERROR, * so let's add support for that as well right now. */ rc= MEMCACHED_END; break; } else goto error; } } } error: if (rc == MEMCACHED_END) return MEMCACHED_SUCCESS; else return rc; }
static inline memcached_return_t memcached_send(memcached_st *ptr, const char *master_key, size_t master_key_length, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags, uint64_t cas, memcached_storage_action_t verb) { bool to_write; size_t write_length; memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; uint32_t server_key; memcached_server_instance_st *instance; WATCHPOINT_ASSERT(!(value == NULL && value_length > 0)); rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol); unlikely (rc != MEMCACHED_SUCCESS) return rc; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) return MEMCACHED_BAD_KEY_PROVIDED; if (ptr->flags.binary_protocol) { return memcached_send_binary(ptr, master_key, master_key_length, key, key_length, value, value_length, expiration, flags, cas, verb); } server_key= memcached_generate_hash(ptr, master_key, master_key_length); instance= memcached_server_instance_fetch(ptr, server_key); if (cas) { write_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %.*s%.*s %u %llu %zu %llu%s\r\n", storage_op_string(verb), (int)ptr->prefix_key_length, ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (unsigned long long)cas, (ptr->flags.no_reply) ? " noreply" : ""); } else { char *buffer_ptr= buffer; const char *command= storage_op_string(verb); /* Copy in the command, no space needed, we handle that in the command function*/ memcpy(buffer_ptr, command, strlen(command)); /* Copy in the key prefix, switch to the buffer_ptr */ buffer_ptr= memcpy((buffer_ptr + strlen(command)), ptr->prefix_key, ptr->prefix_key_length); /* Copy in the key, adjust point if a key prefix was used. */ buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key_length ? ptr->prefix_key_length : 0), key, key_length); buffer_ptr+= key_length; buffer_ptr[0]= ' '; buffer_ptr++; write_length= (size_t)(buffer_ptr - buffer); write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, "%u %llu %zu%s\r\n", flags, (unsigned long long)expiration, value_length, ptr->flags.no_reply ? " noreply" : ""); } if (ptr->flags.use_udp && ptr->flags.buffer_requests) { size_t cmd_size= write_length + value_length + 2; if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH) return MEMCACHED_WRITE_FAILURE; if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) memcached_io_write(instance, NULL, 0, true); } if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) { rc= MEMCACHED_WRITE_FAILURE; goto error; } /* Send command header */ rc= memcached_do(instance, buffer, write_length, false); if (rc != MEMCACHED_SUCCESS) goto error; /* Send command body */ if (memcached_io_write(instance, value, value_length, false) == -1) { rc= MEMCACHED_WRITE_FAILURE; goto error; } if (ptr->flags.buffer_requests && verb == SET_OP) { to_write= false; } else { to_write= true; } if (memcached_io_write(instance, "\r\n", 2, to_write) == -1) { rc= MEMCACHED_WRITE_FAILURE; goto error; } if (ptr->flags.no_reply) return (to_write == false) ? MEMCACHED_BUFFERED : MEMCACHED_SUCCESS; if (to_write == false) return MEMCACHED_BUFFERED; rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); if (rc == MEMCACHED_STORED) return MEMCACHED_SUCCESS; else return rc; error: memcached_io_reset(instance); return rc; }
memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data) { switch (flag) { case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: ptr->number_of_replicas= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK: ptr->io_msg_watermark= (uint32_t) data; break; case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK: ptr->io_bytes_watermark= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH: ptr->io_key_prefetch = (uint32_t)data; break; case MEMCACHED_BEHAVIOR_SND_TIMEOUT: ptr->snd_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: ptr->rcv_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: ptr->server_failure_limit= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: memcached_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol if (data) { ptr->flags.verify_key= false; } ptr->flags.binary_protocol= set_flag(data); break; case MEMCACHED_BEHAVIOR_SUPPORT_CAS: ptr->flags.support_cas= set_flag(data); break; case MEMCACHED_BEHAVIOR_NO_BLOCK: ptr->flags.no_block= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: ptr->flags.buffer_requests= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_USE_UDP: if (memcached_server_count(ptr)) { return MEMCACHED_FAILURE; } ptr->flags.use_udp= set_flag(data); if (data) { ptr->flags.no_reply= set_flag(data); } break; case MEMCACHED_BEHAVIOR_TCP_NODELAY: ptr->flags.tcp_nodelay= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: ptr->flags.tcp_keepalive= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_DISTRIBUTION: return memcached_behavior_set_distribution(ptr, (memcached_server_distribution_t)data); case MEMCACHED_BEHAVIOR_KETAMA: { if (data) { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA); } else { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_DEFAULT); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_DEFAULT); (void)memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_MODULA); } break; } case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5); ptr->flags.ketama_weighted= set_flag(data); /** @note We try to keep the same distribution going. This should be deprecated and rewritten. */ return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA); } case MEMCACHED_BEHAVIOR_HASH: return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_KETAMA_HASH: return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: ptr->flags.use_cache_lookups= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_VERIFY_KEY: if (ptr->flags.binary_protocol) return MEMCACHED_FAILURE; ptr->flags.verify_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_SORT_HOSTS: { ptr->flags.use_sort_hosts= set_flag(data); run_distribution(ptr); break; } case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: ptr->poll_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: ptr->connect_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: ptr->retry_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: ptr->send_size= (int32_t)data; memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: ptr->recv_size= (int32_t)data; memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE: ptr->tcp_keepidle= (uint32_t)data; memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_USER_DATA: return MEMCACHED_FAILURE; case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: ptr->flags.hash_with_prefix_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_NOREPLY: ptr->flags.no_reply= set_flag(data); break; case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: ptr->flags.auto_eject_hosts= set_flag(data); break; case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ: srandom((uint32_t) time(NULL)); ptr->flags.randomize_replica_read= set_flag(data); break; case MEMCACHED_BEHAVIOR_CORK: { memcached_server_write_instance_st instance; bool action= set_flag(data); if (action == false) { ptr->flags.cork= set_flag(false); return MEMCACHED_SUCCESS; } instance= memcached_server_instance_fetch(ptr, 0); if (! instance) return MEMCACHED_NO_SERVERS; /* We just try the first host, and if it is down we return zero */ memcached_return_t rc; rc= memcached_connect(instance); if (rc != MEMCACHED_SUCCESS) { return rc; } /* Now we test! */ memcached_ternary_t enabled; enabled= test_cork(instance, true); switch (enabled) { case MEM_FALSE: return ptr->cached_errno ? MEMCACHED_ERRNO : MEMCACHED_FAILURE ; case MEM_TRUE: { enabled= test_cork(instance, false); if (enabled == false) // Possible bug in OS? { memcached_quit_server(instance, false); // We should reset everything on this error. return MEMCACHED_ERRNO; // Errno will be true because we will have already set it. } ptr->flags.cork= true; ptr->flags.tcp_nodelay= true; memcached_quit(ptr); // We go on and reset the connections. } break; case MEM_NOT: default: return MEMCACHED_NOT_SUPPORTED; } } break; case MEMCACHED_BEHAVIOR_MAX: default: /* Shouldn't get here */ WATCHPOINT_ASSERT(0); return MEMCACHED_FAILURE; } return MEMCACHED_SUCCESS; }
memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data) { switch (flag) { case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: ptr->number_of_replicas= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK: ptr->io_msg_watermark= (uint32_t) data; break; case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK: ptr->io_bytes_watermark= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH: ptr->io_key_prefetch = (uint32_t)data; break; case MEMCACHED_BEHAVIOR_SND_TIMEOUT: ptr->snd_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: ptr->rcv_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS: ptr->flags.auto_eject_hosts= set_flag(data); case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: ptr->server_failure_limit= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: send_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol if (data) { ptr->flags.verify_key= false; } ptr->flags.binary_protocol= set_flag(data); break; case MEMCACHED_BEHAVIOR_SUPPORT_CAS: ptr->flags.support_cas= set_flag(data); break; case MEMCACHED_BEHAVIOR_NO_BLOCK: ptr->flags.no_block= set_flag(data); send_quit(ptr); break; case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: ptr->flags.buffer_requests= set_flag(data); send_quit(ptr); break; case MEMCACHED_BEHAVIOR_USE_UDP: if (memcached_server_count(ptr)) { return MEMCACHED_FAILURE; } ptr->flags.use_udp= set_flag(data); if (data) { ptr->flags.no_reply= set_flag(data); } break; case MEMCACHED_BEHAVIOR_TCP_NODELAY: ptr->flags.tcp_nodelay= set_flag(data); send_quit(ptr); break; case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: ptr->flags.tcp_keepalive= set_flag(data); send_quit(ptr); break; case MEMCACHED_BEHAVIOR_DISTRIBUTION: return memcached_behavior_set_distribution(ptr, (memcached_server_distribution_t)data); case MEMCACHED_BEHAVIOR_KETAMA: { if (data) // Turn on return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA); return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_MODULA); } case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5); ptr->ketama.weighted= set_flag(data); /** @note We try to keep the same distribution going. This should be deprecated and rewritten. */ return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA); } case MEMCACHED_BEHAVIOR_HASH: return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_KETAMA_HASH: return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, memcached_string_with_size("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated.")); case MEMCACHED_BEHAVIOR_VERIFY_KEY: if (ptr->flags.binary_protocol) return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, memcached_string_with_size("MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled.")); ptr->flags.verify_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_SORT_HOSTS: { ptr->flags.use_sort_hosts= set_flag(data); run_distribution(ptr); break; } case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: ptr->poll_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: ptr->connect_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: ptr->retry_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: ptr->send_size= (int32_t)data; send_quit(ptr); break; case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: ptr->recv_size= (int32_t)data; send_quit(ptr); break; case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE: ptr->tcp_keepidle= (uint32_t)data; send_quit(ptr); break; case MEMCACHED_BEHAVIOR_USER_DATA: return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, memcached_string_with_size("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: ptr->flags.hash_with_prefix_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_NOREPLY: ptr->flags.no_reply= set_flag(data); break; case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: ptr->flags.auto_eject_hosts= set_flag(data); break; case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ: srandom((uint32_t) time(NULL)); ptr->flags.randomize_replica_read= set_flag(data); break; case MEMCACHED_BEHAVIOR_CORK: { return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, memcached_string_with_size("MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default.")); } break; case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, memcached_string_with_size("MEMCACHED_BEHAVIOR_LOAD_FROM_FILE can not be set with memcached_behavior_set()")); case MEMCACHED_BEHAVIOR_MAX: default: /* Shouldn't get here */ WATCHPOINT_ASSERT(0); return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, memcached_string_with_size("Invalid behavior passed to memcached_behavior_set()")); } return MEMCACHED_SUCCESS; }
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; }