// libmemcached_test.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libmemcached/memcached.h>
int main(void) {
memcached_st *memc;
memcached_server_st *servers = NULL;
memcached_return rc;
const char* server_list = "localhost:11211";
const char* key= "key";
const char* value= "value";
char* retval = NULL;
size_t len = 0;
time_t expire = 0;
uint32_t flags = 0;
memc = memcached_create(NULL);
servers = memcached_servers_parse(server_list);
rc = memcached_server_push(memc, servers);
memcached_server_list_free(servers);
if(rc == MEMCACHED_SUCCESS) {
printf("added server successfully\n");
} else {
printf("couldn't add server: %s\n", memcached_strerror(memc, rc));
}
// set
rc = memcached_set(memc, key, strlen(key), value, strlen(value), expire, flags);
if(rc == MEMCACHED_SUCCESS) {
printf("key stored successfully\n");
} else {
printf("couldn't store key: %s\n", memcached_strerror(memc, rc));
}
// get
retval = memcached_get(memc, key, strlen(key), &len, &flags, &rc);
if(rc == MEMCACHED_SUCCESS) {
printf("key got successfully\n");
printf("value: %s\n", retval);
} else {
printf("couldn't get key: %s\n", memcached_strerror(memc, rc));
}
free(retval);
// delete
rc = memcached_delete(memc, key, strlen(key), expire);
if(rc == MEMCACHED_SUCCESS) {
printf("key deleted successfully\n");
} else {
printf("couldn't delete key: %s\n", memcached_strerror(memc, rc));
}
// get
retval = memcached_get(memc, key, strlen(key), &len, &flags, &rc);
if(rc == MEMCACHED_SUCCESS) {
printf("key got successfully\n");
printf("value: %s\n", retval);
} else if(rc == MEMCACHED_NOTFOUND) {
printf("couldn't get key (not found): %s\n", memcached_strerror(memc, rc));
} else if(rc == MEMCACHED_FAILURE) {
printf("couldn't get key (failure): %s\n", memcached_strerror(memc, rc));
}
free(retval);
memcached_free(memc);
return 0;
}
1、memcached_st *memcached_create(memcached_st *ptr)
定义于libmemcached/memcached.cc。struct memcached_st定义于libmemcached-1.0/struct/memcached.h。
memcached_st *memcached_create(memcached_st *ptr)
{
if (ptr)
{
ptr->options.is_allocated= false;
} else {
ptr= (memcached_st *)malloc(sizeof(memcached_st));
if (ptr == NULL)
{
return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
}
ptr->options.is_allocated= true;
}
if (_memcached_init(ptr) == false)
{
memcached_free(ptr);
return NULL;
}
if (memcached_result_create(ptr, &ptr->result) == NULL) //设置memcached_result_st的root为memcached_st memc
{ //之后调用memcached_string_create()初始化memcached_result_st的value元素(类型为memcached_string_st)
memcached_free(ptr); //同时设置memcached_string_st value的root为memcached_st *memc
return NULL;
}
return ptr;
}
static inline bool _memcached_init(memcached_st *self)
{ //唯一没有对self->result(struct memcached_result_st)初始化,它由memcached_result_create()初始化
self->state.is_purging= false;
self->state.is_processing_input= false;
self->state.is_time_for_rebuild= false;
self->flags.auto_eject_hosts= false;
self->flags.binary_protocol= false;
self->flags.buffer_requests= false;
self->flags.hash_with_namespace= false;
self->flags.no_block= false;
self->flags.reply= true;
self->flags.randomize_replica_read= false;
self->flags.support_cas= false;
self->flags.tcp_nodelay= false;
self->flags.use_sort_hosts= false;
self->flags.use_udp= false;
self->flags.verify_key= false;
self->flags.tcp_keepalive= false;
self->virtual_bucket= NULL;
self->distribution= MEMCACHED_DISTRIBUTION_MODULA;
if (hashkit_create(&self->hashkit) == NULL) //调用_hashkit_create()和_hashkit_init()
{ //_hashkit_init()设置哈希函数为hashkit_one_ta_a_time()。
return false;
}
self->server_info.version= 0;
self->ketama.continuum= NULL;
self->ketama.continuum_count= 0;
self->ketama.continuum_points_counter= 0;
self->ketama.next_distribution_rebuild= 0;
self->ketama.weighted= false;
self->number_of_hosts= 0;
self->servers= NULL;
self->last_disconnected_server= NULL;
self->snd_timeout= 0;
self->rcv_timeout= 0;
self->server_failure_limit= MEMCACHED_SERVER_FAILURE_LIMIT;
self->query_id= 1; // 0 is considered invalid
/* TODO, Document why we picked these defaults */
self->io_msg_watermark= 500;
self->io_bytes_watermark= 65 * 1024;
self->tcp_keepidle= 0;
self->io_key_prefetch= 0;
self->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
self->connect_timeout= MEMCACHED_DEFAULT_CONNECT_TIMEOUT;
self->retry_timeout= MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT;
self->dead_timeout= MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT;
self->send_size= -1;
self->recv_size= -1;
self->user_data= NULL;
self->number_of_replicas= 0;
self->allocators= memcached_allocators_return_default(); //设置为struct memcached_allocator_t global_default_allocator
//即{ _libmemcached_calloc, _libmemcached_free, _libmemcached_malloc, _libmemcached_realloc, 0 }。
self->on_clone= NULL;
self->on_cleanup= NULL;
self->get_key_failure= NULL;
self->delete_trigger= NULL;
self->callbacks= NULL;
self->sasl.callbacks= NULL;
self->sasl.is_allocated= false;
self->error_messages= NULL;
self->_namespace= NULL;
self->configure.initial_pool_size= 1;
self->configure.max_pool_size= 1;
self->configure.version= -1;
self->configure.filename= NULL;
return true;
}
可以看出,
memcached_st 中有个memcached_result_st result,
memcached_result_st中有个
memcached_string_st value,并逐步初始化。
2、memcached_server_list_st memcached_servers_parse(const char *server_strings)
定义于libmemcached/parse.cc中;memcached_server_list_st即struct memcached_server_st *,后者定义于libmemcached-1.0/struct/server.h中。
分析字符串,来初始化服务器列表。memcached_server_st *servers= memcached_server_list_append_with_weight(...)(此处传入的memcached_st *memc为空)。其中调用__server_create_with(),进一步_server_init()来初始化memcached_server_st(设置其状态为MEMCACHED_SERVER_STATE_NEW)。
3、memcached_return_t memcached_server_push(memcached_st *memc, const memcached_server_list_st list)
作用是将list中的server加到memc->servers中(list实际上是一个数组,数组元素为memcached_server_st)。
这里和上一步相似,依旧调用__server_create_with(),只是传入参数memcached_st *memc不为空。因此多调用了ser_hostinfo(memcached_server_st *server)(初始化server->address_info),并设置server的状态server->state= MEMCACHED_SERVER_STATE_ADDRINFO。
最后,run_distribution(memcached_st *)。该函数根据memcached_st * ptr->distribution的类型,如果是MEMCACHED_DISTRIBUTION_CONSISTENT(一致性哈希算法的实现),则调用update_continuum(ptr);本次执行时是MEMCACHED_DISTRIBUTION_MODULA,则直接退出。
4、memcached_server_list_free(memcached_server_list_st servers)
循环调用__server_free()释放掉servers数组中的各个服务器,其中调用memcached_quit_server()、memcached_error_free();最后释放掉这个数组。
实际上这里的servers数组只是一个临时存储服务器的数组,当其内容已经通过上一步加入到memcached_st *memc中之后,当然就没有继续存在的理由了。
5、memcached_set
由于内部涉及memcached的连接等,下一节讨论。
6、void memcached_free(memcached_st *ptr)
只是调用_free():
static void _free(memcached_st *ptr, bool release_st)
{
/* If we have anything open, lets close it now */
send_quit(ptr); //循环调用memcached_quit_server()对每个服务器发送quit
memcached_server_list_free(memcached_server_list(ptr)); //执行完之后ptr->servers已free
memcached_result_free(&ptr->result);
memcached_virtual_bucket_free(ptr); //free(self->virtual_bucket)
memcached_server_free(ptr->last_disconnected_server);
if (ptr->on_cleanup)
{
ptr->on_cleanup(ptr);
}
libmemcached_free(ptr, ptr->ketama.continuum); //本例未使用ketama一致性哈希算法
memcached_array_free(ptr->_namespace);
ptr->_namespace= NULL;
memcached_error_free(*ptr);
if (LIBMEMCACHED_WITH_SASL_SUPPORT and ptr->sasl.callbacks)
{
memcached_destroy_sasl_auth_data(ptr);
}
if (release_st)
{
memcached_array_free(ptr->configure.filename);
ptr->configure.filename= NULL;
}
if (memcached_is_allocated(ptr) && release_st)
{
libmemcached_free(ptr, ptr); //最后释放掉memcached_st
}
}