libmemcached的执行流程

来源:互联网 发布:linux socket编程教程 编辑:程序博客网 时间:2024/04/30 09:17

一、测试程序

// 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  }}