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; }
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(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); }
/** @note This should be testing to see if the server really supports the binary protocol. */ static test_return_t pre_binary(memcached_st *memc) { memcached_return_t rc= MEMCACHED_FAILURE; memcached_st *memc_clone; memcached_server_instance_st instance; memc_clone= memcached_clone(NULL, memc); test_true(memc_clone); // The memcached_version needs to be done on a clone, because the server // will not toggle protocol on an connection. memcached_version(memc_clone); instance= memcached_server_instance_by_position(memc_clone, 0); if (instance->major_version >= 1 && instance->minor_version > 2) { rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); test_true(rc == MEMCACHED_SUCCESS); test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1); } memcached_free(memc_clone); return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED; }
static test_return_t udp_delete_test(memcached_st *memc) { unsigned int num_iters= 1025; //request id rolls over at 1024 for (size_t x= 0; x < num_iters; x++) { memcached_return_t rc; const char *key= "foo"; uint16_t *expected_ids=get_udp_request_ids(memc); unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); memcached_server_instance_st instance= memcached_server_instance_by_position(memc, server_key); size_t init_offset= instance->write_buffer_offset; rc= memcached_delete(memc, key, strlen(key), 0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); if (rc == MEMCACHED_SUCCESS || instance->write_buffer_offset < init_offset) increment_request_id(&expected_ids[server_key]); if (rc == MEMCACHED_SUCCESS) { test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); } else { test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH); test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH); } test_true(post_udp_op_check(memc,expected_ids) == TEST_SUCCESS); } return TEST_SUCCESS; }
/*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; }
/* Make sure that I cant add a tcp server to a udp client */ static test_return_t add_tcp_server_udp_client_test(memcached_st *memc) { (void)memc; #if 0 memcached_server_st server; memcached_server_instance_st instance= memcached_server_instance_by_position(memc, 0); memcached_server_clone(&server, &memc->hosts[0]); test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS); test_true(memcached_server_add(memc, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL); #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; }
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; }
std::pair<std::string, int> hashWrapper::getHost(const std::string &hashValue, const unsigned int& offset) { //check that we have a list of servers to hash to if(!this->pMemc) throw MemcacheConstructionException(); memcached_return_t memcRC; //get a pointer to the first host in the list of hosts const memcached_server_st* first = memcached_server_instance_by_position(this->pMemc, 0); //hash this value to pointer to its host in the list of hosts const memcached_server_st* original = memcached_server_by_key(this->pMemc, hashValue.c_str(), hashValue.length(), &memcRC); //TODO: if(memcRc != MEMCACHED_SUCCESS) throw() //get the host based on offset from the hashed host (useful for replication across multiple hosts) const memcached_server_st* selected = first + (((original - first) + offset) % serverCount); //give back the host and port return std::make_pair(selected->hostname, selected->port); }
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; }
static test_return_t udp_set_test(memcached_st *memc) { unsigned int num_iters= 1025; //request id rolls over at 1024 for (size_t x= 0; x < num_iters; x++) { memcached_return_t rc; const char *key= "foo"; const char *value= "when we sanitize"; uint16_t *expected_ids= get_udp_request_ids(memc); unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); memcached_server_instance_st instance= memcached_server_instance_by_position(memc, server_key); size_t init_offset= instance->write_buffer_offset; rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); /** NB, the check below assumes that if new write_ptr is less than * the original write_ptr that we have flushed. For large payloads, this * maybe an invalid assumption, but for the small payload we have it is OK */ if (rc == MEMCACHED_SUCCESS || instance->write_buffer_offset < init_offset) increment_request_id(&expected_ids[server_key]); if (rc == MEMCACHED_SUCCESS) { test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); } else { test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH); test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH); } test_true(post_udp_op_check(memc, expected_ids) == TEST_SUCCESS); } return TEST_SUCCESS; }
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; }
static int mcache_ping_servers(pr_memcache_t *mcache) { memcached_server_st *alive_server_list; memcached_return res; memcached_st *clone; uint32_t server_count; register unsigned int i; /* We always start with the configured list of servers. */ clone = memcached_clone(NULL, mcache->mc); if (clone == NULL) { errno = ENOMEM; return -1; } memcached_servers_reset(clone); /* Bug#4242: Don't use memcached_server_push() if we're using * libmemcached-1.0.18 or earlier. Doing so leads to a segfault, due to * this libmemcached bug: * * https://bugs.launchpad.net/libmemcached/+bug/1154159 */ #if LIBMEMCACHED_VERSION_HEX > 0x01000018 memcached_server_push(clone, configured_server_list); #endif server_count = memcached_server_count(clone); pr_trace_msg(trace_channel, 16, "pinging %lu memcached %s", (unsigned long) server_count, server_count != 1 ? "servers" : "server"); alive_server_list = NULL; for (i = 0; i < server_count; i++) { memcached_server_instance_st server; server = memcached_server_instance_by_position(clone, i); pr_trace_msg(trace_channel, 17, "pinging server %s:%d", memcached_server_name(server), memcached_server_port(server)); if (libmemcached_util_ping(memcached_server_name(server), memcached_server_port(server), &res) == FALSE) { pr_trace_msg(trace_channel, 4, "error pinging %s:%d: %s", memcached_server_name(server), memcached_server_port(server), memcached_strerror(clone, res)); } else { pr_trace_msg(trace_channel, 17, "server %s:%d is alive", memcached_server_name(server), memcached_server_port(server)); alive_server_list = memcached_server_list_append(alive_server_list, memcached_server_name(server), memcached_server_port(server), &res); if (alive_server_list == NULL) { pr_trace_msg(trace_channel, 1, "error appending server %s:%d to list: %s", memcached_server_name(server), memcached_server_port(server), memcached_strerror(clone, res)); memcached_free(clone); errno = EPERM; return -1; } } } if (alive_server_list != NULL) { memcached_servers_reset(mcache->mc); res = memcached_server_push(mcache->mc, alive_server_list); if (res != MEMCACHED_SUCCESS) { unsigned int count; count = memcached_server_list_count(alive_server_list); pr_trace_msg(trace_channel, 2, "error adding %u alive memcached %s to connection: %s", count, count != 1 ? "servers" : "server", memcached_strerror(mcache->mc, res)); memcached_free(clone); errno = EPERM; return -1; } else { unsigned int count; count = memcached_server_list_count(alive_server_list); pr_trace_msg(trace_channel, 9, "now using %d alive memcached %s", count, count != 1 ? "servers" : "server"); memcached_server_list_free(alive_server_list); } } memcached_free(clone); return 0; }