Memcached源码分析之memcached.h

  1. //memcached.h
  2. //返回在item中data字段key的地址,即把指针指向key
  3. #define ITEM_key(item) (((char*)&((item)->data)) \
  4. + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
  5. //返回在item中data字段suffix的地址,即把指针指向suffix
  6. #define ITEM_suffix(item) ((char*) &((item)->data) + (item)->nkey + 1 \
  7. + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
  8. //返回在item中data字段value的地址,即把指针指向value
  9. #define ITEM_data(item) ((char*) &((item)->data) + (item)->nkey + 1 \
  10. + (item)->nsuffix \
  11. + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
  12. //item总字节数
  13. #define ITEM_ntotal(item) (sizeof(struct _stritem) + (item)->nkey + 1 \
  14. + (item)->nsuffix + (item)->nbytes \
  15. + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
  16. //conn结构体中state字段的枚举,代表连接状态
  17. enum conn_states {
  18. conn_listening, /**< the socket which listens for connections */
  19. conn_new_cmd, /**< Prepare connection for next command */
  20. conn_waiting, /**< waiting for a readable socket */
  21. conn_read, /**< reading in a command line */
  22. conn_parse_cmd, /**< try to parse a command from the input buffer */
  23. conn_write, /**< writing out a simple response */
  24. conn_nread, /**< reading in a fixed number of bytes */
  25. conn_swallow, /**< swallowing unnecessary bytes w/o storing */
  26. conn_closing, /**< closing this connection */
  27. conn_mwrite, /**< writing out many items sequentially */
  28. conn_closed, /**< connection is closed */
  29. conn_max_state /**< Max state value (used for assertion) */
  30. };
  31. //item保存结果枚举
  32. enum store_item_type {
  33. NOT_STORED=0, STORED, EXISTS, NOT_FOUND
  34. };
  35. //item结构体
  36. typedef struct _stritem {
  37. struct _stritem *next; //链表中下一个,这个链表有可能是slots链表,也有可能是LRU链表,但一个item不可能同时这两个链表中,所以复用一个指针。
  38. struct _stritem *prev; //链表中上一个。
  39. struct _stritem *h_next;  //相同hash值中链表的下一个。
  40. rel_time_t time;   //最近访问时间
  41. rel_time_t exptime;  //过期时间
  42. int nbytes;  //value的字节数
  43. unsigned short refcount; //引用计数
  44. uint8_t nsuffix;  //后缀长度
  45. uint8_t it_flags;  //标记
  46. uint8_t slabs_clsid;  //item所在的slabclass的id值
  47. uint8_t nkey; //键长
  48. /* this odd type prevents type-punning issues when we do
  49. * the little shuffle to save space when not using CAS. */
  50. union {
  51. uint64_t cas;
  52. char end;
  53. } data[]; //数据,这个数据不仅仅包括key对应的value,还有key、CAS、后缀等等数据也存在此,所以它有4部分“拼”成:CAS(可选),KEY,后缀,VALUE。
  54. /* if it_flags & ITEM_CAS we have 8 bytes CAS */
  55. /* then null-terminated key */
  56. /* then " flags length\r\n" (no terminating null) */
  57. /* then data with terminating \r\n (no terminating null; it‘s binary!) */
  58. } item;
  59. /**
  60. worker线程结构体
  61. */
  62. typedef struct {
  63. pthread_t thread_id; //线程id
  64. struct event_base *base; //每个线程自己独立的event_base,监听的就是下面的notify_event事件对象
  65. struct event notify_event; //事件对象,fd即为下面的notify_receive_fd
  66. int notify_receive_fd; //管道接收fd
  67. int notify_send_fd; //管道写入fd
  68. struct thread_stats stats; //线程的一些统计
  69. struct conn_queue *new_conn_queue; //连接参数对象CQ_ITEM队列
  70. cache_t *suffix_cache;
  71. uint8_t item_lock_type; //控制线程锁的粒度
  72. } LIBEVENT_THREAD;
  73. /**
  74. 主线程结构体
  75. */
  76. typedef struct {
  77. pthread_t thread_id; //线程id
  78. struct event_base *base; //event_base
  79. } LIBEVENT_DISPATCHER_THREAD;
  80. typedef struct conn conn;
  81. struct conn {
  82. int sfd; //连接的socket fd
  83. sasl_conn_t *sasl_conn;
  84. bool authenticated;
  85. enum conn_states state; //当前的连接状态
  86. enum bin_substates substate;
  87. rel_time_t last_cmd_time;
  88. struct event event; // 监听的事件
  89. short ev_flags; //监听的事件 类型
  90. short which; /** which events were just triggered */ //刚触发的事件
  91. /**
  92. 读buffer会涉及两个方向上的“读”:
  93. 一个是从socket读进来到rbuf里面
  94. 一个是从rbuf里面把数据读出去解析,读buffer相当于一个中介,从socket读进来最终还是得被别人读出去解析,而
  95. rcurr工作指针与rbytes就是在rbuf数据被读出去解析的时候用到,用来控制可以读出去被解析的数据还剩余多少。
  96. */
  97. char *rbuf; /** buffer to read commands into */ //读buffer
  98. char *rcurr; /** but if we parsed some already, this is where we stopped */ //读buffer的当前指针
  99. int rsize; /** total allocated size of rbuf */ //读buffer大小
  100. int rbytes; /** how much data, starting from rcur, do we have unparsed */ //剩余buffer字节数
  101. //下面4个属性和上面4个类似
  102. char *wbuf;
  103. char *wcurr;
  104. int wsize;
  105. int wbytes;
  106. /** which state to go into after finishing current write */
  107. enum conn_states write_and_go; //完成当前写操作后,连接状态将会置为此状态
  108. void *write_and_free; /** free this memory after finishing writing */
  109. char *ritem; /** when we read in an item‘s value, it goes here */ //这个指针指向item结构体中data中的value地址
  110. int rlbytes; //尚未读完item的data的value的字节数
  111. void *item; /* for commands set/add/replace */ //当执行set/add/replace 命令时,此指针用于指向分配的item空间
  112. /* data for the swallow state */
  113. int sbytes; /* how many bytes to swallow */
  114. //下面是往socket写出数据时用的字段
  115. struct iovec *iov; //iovec结构体数组
  116. int iovsize; //*iov数组大小
  117. int iovused; //*iov数组已被使用的元素个数
  118. struct msghdr *msglist; //msghdr结构体数组,表示sendmsg要发送的消息列表
  119. int msgsize; //*msglist数组大小
  120. int msgused; //*msglist数组已使用的元素个数
  121. int msgcurr; //当前要发送的msghdr
  122. int msgbytes; //当前msghdr的字节数
  123. item **ilist; //get key1 key2命令时,要发送给客户端的item列表
  124. int isize; //列表大小
  125. item **icurr; //当前要发送的item
  126. int ileft; //剩余数目
  127. char **suffixlist;
  128. int suffixsize;
  129. char **suffixcurr;
  130. int suffixleft;
  131. enum protocol protocol; /* which protocol this connection speaks */
  132. enum network_transport transport; /* what transport is used by this connection */
  133. //UDP相关的字段
  134. int request_id; /* Incoming UDP request ID, if this is a UDP "connection" */
  135. struct sockaddr_in6 request_addr; /* udp: Who sent the most recent request */
  136. socklen_t request_addr_size;
  137. unsigned char *hdrbuf; /* udp packet headers */
  138. int hdrsize; /* number of headers‘ worth of space is allocated */
  139. bool noreply; /* True if the reply should not be sent. */
  140. /* current stats command */
  141. struct {
  142. char *buffer;
  143. size_t size;
  144. size_t offset;
  145. } stats;
  146. // 二进制相关的字段
  147. protocol_binary_request_header binary_header;
  148. uint64_t cas; /* the cas to return */
  149. short cmd; /* current command being processed */
  150. int opaque;
  151. int keylen;
  152. conn *next; /* Used for generating a list of conn structures */
  153. LIBEVENT_THREAD *thread; /* Pointer to the thread object serving this connection */
  154. };
  155. //非阻塞方式获取互斥锁
  156. static inline int mutex_lock(pthread_mutex_t *mutex)
  157. {
  158. while (pthread_mutex_trylock(mutex));
  159. return 0;
  160. }
  161. //释放锁
  162. #define mutex_unlock(x) pthread_mutex_unlock(x)
  163. #include "stats.h"
  164. #include "slabs.h"
  165. #include "assoc.h"
  166. #include "items.h"
  167. #include "trace.h"
  168. #include "hash.h"
  169. #include "util.h"
时间: 2024-08-24 04:07:35

Memcached源码分析之memcached.h的相关文章

Memcached源码分析之memcached.c

memcached.c 由于代码太多,在此省略了部分代码,例如UPD连接,二进制协议,某些错误输出和调试输出等,建议从main函数开始看起. #include "memcached.h" //尝试从socket中读取数据的结果枚举 enum try_read_result { READ_DATA_RECEIVED, READ_NO_DATA_RECEIVED, READ_ERROR, /** an error occured (on the socket) (or client clo

Memcached源码分析

作者:Calix,转载请注明出处:http://calixwu.com 最近研究了一下memcached的源码,在这里系统总结了一下笔记和理解,写了几 篇源码分析和大家分享,整个系列分为“结构篇”和“源码篇”,建议先从结构篇开始看起,要特别说明的是我本次分析的是memcached1.4.20的版 本,不同版本会有所差异,另外,文章均为本人的个人理解,如果解析得不好或者错误的地方敬请指正. 好了,不啰嗦了,下面是导航: [结构篇] Memcached源码分析之从SET命令开始说起 Memcache

memcached源码分析-----item过期失效处理以及LRU爬虫

memcached源码分析-----item过期失效处理以及LRU爬虫,memcached-----item 转载请注明出处:http://blog.csdn.net/luotuo44/article/details/42963793 温馨提示:本文用到了一些可以在启动memcached设置的全局变量.关于这些全局变量的含义可以参考<memcached启动参数详解>.对于这些全局变量,处理方式就像<如何阅读memcached源代码>所说的那样直接取其默认值. 过期失效处理: 一个i

Linux c 开发 - Memcached源码分析之命令解析(2)

前言 从我们上一章<Linux c 开发 - Memcached源码分析之基于Libevent的网络模型>我们基本了解了Memcached的网络模型.这一章节,我们需要详细解读Memcached的命令解析. 我们回顾上一章发现Memcached会分成主线程和N个工作线程.主线程主要用于监听accpet客户端的Socket连接,而工作线程主要用于接管具体的客户端连接. 主线程和工作线程之间主要通过基于Libevent的pipe的读写事件来监听,当有连接练上来的时候,主线程会将连接交个某一个工作线

Memcached源码分析之内存管理

先再说明一下,我本次分析的memcached版本是1.4.20,有些旧的版本关于内存管理的机制和数据结构与1.4.20有一定的差异(本文中会提到). 一)模型分析在开始解剖memcached关于内存管理的源代码之前,先宏观上分析一下memcached内存管理的模型是怎样子的: 提个建议,我觉得memcached内存管理的模型与我们平时做作业的作业本“画格子给我们往格子里面写字”的逻辑很像,一本本作业本就是我们的内存空间,而我们往里写的字就是我们要存下来的数据,所以分析的时候可以想像一下用方格作业

Memcached源码分析之从SET命令开始说起

作者:Calix 如果直接把memcached的源码从main函数开始说,恐怕会有点头大,所以这里以一句经典的“SET”命令简单地开个头,算是回忆一下memcached的作用,后面的结构篇中关于命令解析部分主要也是围绕着SET命令展开分析,相信把一句SET命令背后做的事情都搞清楚,那么memcached大部分源码都了解得七七八八了. 那么,回忆一下,set命令做了个什么事情? 无非就是把一个value set到某个key上面,保存在内存当中. 再细化一下: 1)memcached是一个缓存服务器

Memcached源码分析之线程模型

作者:Calix 一)模型分析 memcached到底是如何处理我们的网络连接的? memcached通过epoll(使用libevent,下面具体再讲)实现异步的服务器,但仍然使用多线程,主要有两种线程,分别是“主线程”和“worker线程”,一个主线程,多个worker线程. 主线程负责监听网络连接,并且accept连接.当监听到连接时,accept后,连接成功,把相应的client fd丢给其中一个worker线程.worker线程接收主线程丢过来的client fd,加入到自己的epol

memcached源码分析-----memcached启动参数详解以及关键配置的默认值

转载请注明出处: http://blog.csdn.net/luotuo44/article/details/42672913 本文开启本系列博文的代码分析.本系列博文研究是memcached版本是1.4.21. 本文将给出memcached启动时各个参数的详细解释以及一些关键配置的默认值.以便在分析memcached源码的时候好随时查看.当然也方便使用memcached时可以随时查看各个参数的含义.<如何阅读memcached源码>说到memcached有很多全局变量(也就是关键配置),这些

memcached源码分析-----安装、调试以及如何阅读memcached源码

        转载请注明出处:http://blog.csdn.net/luotuo44/article/details/42639131 安装: 安装memcached之前要先安装Libevent.现在假定Libevent安装在/usr/local/libevent目录了. 因为memcached安装后不像Libevent那样,有一堆头文件和库文件.安装后的memcached不是用来编程而直接用来运行的.所以不需要在/usr/local目录下专门为memcached建立一个目录.直接把mem