******************************************************************************************** /* Node, quicklist, and Iterator are the only data structures used currently. */ 节点,快速列表和迭代器 是仅有的当前使用的数据结构 /* quicklistNode is a 32 byte struct describing a ziplist for a quicklist. 快速列表节点是一个32字节的结构体,用于描述快排列表的压缩列表 * We use bit fields keep the quicklistNode at 32 bytes. 我们使用位域在32字节中保持快排节点 * count: 16 bits, max 65536 (max zl bytes is 65k, so max count actually < 32k). 计数: 16个比特,最大值为63335(最大的zl字节是65k,所以实际最大的计数是小于32k的) (因为一个实体最少需要2个字节表示,总的长度为65535个字节,所以肯定小于32k个实体) * encoding: 2 bits, RAW=1, LZF=2. 编码:2比特 原始为1 LZF压缩为2 * container: 2 bits, NONE=1, ZIPLIST=2. 容器: 2比特 空为1,压缩列表为2 * recompress: 1 bit, bool, true if node is temporarry decompressed for usage. 再压缩:1比特,如果节点临时解压使用,则为真 * attempted_compress: 1 bit, boolean, used for verifying during testing. 尝试压缩: 1比特,布尔型,用于测试过程中的验证 * extra: 10 bits, free for future use; pads out the remainder of 32 bits */ 额外:10比特,为将来使用准备,填充剩余32比特剩余位置 typedef struct quicklistNode { struct quicklistNode *prev; 指向当前节点前一个节点 struct quicklistNode *next; 指向当前节点下一个节点 unsigned char *zl; 指向当前接地那的压缩列表 unsigned int sz; /* ziplist size in bytes */ 压缩列表的总字节大小 unsigned int count : 16; /* count of items in ziplist */ 压缩列表中的元素个数 unsigned int encoding : 2; /* RAW==1 or LZF==2 */ 原始为1 LZF压缩为2 unsigned int container : 2; /* NONE==1 or ZIPLIST==2 */ 没有类型为1 压缩列表为2 unsigned int recompress : 1; /* was this node previous compressed? */ 这个节前之前压缩过? 标志临时性解压,后面操作完要压缩回去 unsigned int attempted_compress : 1; /* node can't compress; too small */ 节点太小不需要压缩 unsigned int extra : 10; /* more bits to steal for future usage */ 额外的比特位为将来使用准备 } quicklistNode; /* quicklistLZF is a 4+N byte struct holding 'sz' followed by 'compressed'. quicklistLZF是一个4+N个字节的结构,保存紧随压缩标志的'sz' * 'sz' is byte length of 'compressed' field. 'sz'是一个压缩域的字节长度 * 'compressed' is LZF data with total (compressed) length 'sz' 压缩域是一个LZF压缩的数据,并且附带压缩后的长度'sz' * NOTE: uncompressed length is stored in quicklistNode->sz. 注意: 不压缩的长度保存在quicklistNode->sz中 * When quicklistNode->zl is compressed, node->zl points to a quicklistLZF */ 当quicklistNode->zl 被压缩,那么node->zl指向一个quicklistLZF结构 typedef struct quicklistLZF { unsigned int sz; /* LZF size in bytes*/ char compressed[]; } quicklistLZF; /* Bookmarks are padded with realloc at the end of of the quicklist struct. 书签被补充在快排列表结构的最后,使用重新分配内存的方法 * They should only be used for very big lists if thousands of nodes were the * excess memory usage is negligible, and there's a real need to iterate on them * in portions. 它们只应该被使用在非常大的列表,即使上千的节点,超出的内纯也是非常有限,而且确实需要堆他们进行部分迭代操作 * When not used, they don't add any memory overhead, but when used and then * deleted, some overhead remains (to avoid resonance). 当不使用时,它们不增加任何内存开销,但是如果使用了然后删除,那么会有部分开销会保留(避免产生反复申请内存的问题) * The number of bookmarks used should be kept to minimum since it also adds * overhead on node deletion (searching for a bookmark to update). */ 书签的使用数量应该被保持在最小值,因为它会增加删除节点的开销(查找书签来更新) typedef struct quicklistBookmark { quicklistNode *node; 书签指向的快排列表的节点 char *name; 书签名字 } quicklistBookmark; #if UINTPTR_MAX == 0xffffffff /* 32-bit */ 是32位的机器 # define QL_FILL_BITS 14 # define QL_COMP_BITS 14 # define QL_BM_BITS 4 #elif UINTPTR_MAX == 0xffffffffffffffff /* 64-bit */ 64位的机器 # define QL_FILL_BITS 16 # define QL_COMP_BITS 16 # define QL_BM_BITS 4 /* we can encode more, but we rather limit the user since they cause performance degradation. */ 我们可以进行更多的编码,但是我们限制了用户这个操作,因为这样会导致性能退化 #else # error unknown arch bits count 错误,不知道的系统架构位数 #endif /* quicklist is a 40 byte struct (on 64-bit systems) describing a quicklist. * 'count' is the number of total entries. * 'len' is the number of quicklist nodes. * 'compress' is: -1 if compression disabled, otherwise it's the number * of quicklistNodes to leave uncompressed at ends of quicklist. * 'fill' is the user-requested (or default) fill factor. * 'bookmakrs are an optional feature that is used by realloc this struct, * so that they don't consume memory when not used. */ 快排列表是用40个字节的结构(在64位系统中)描述的快排列表 count是总的实体个数 len 是快排列表的节点个数 compress 如果-1,那么不允许压缩,否则就是快排列表末尾为压缩节点的数目 fill 是用户秦秋的(或默认)填充因子 bookmakrs是可选功能,需要重新给这个结构分配内存,所以如果不适用不会消耗内存 typedef struct quicklist { quicklistNode *head; 列表的头节点 quicklistNode *tail; 列表的尾节点 unsigned long count; /* total count of all entries in all ziplists */ 在所有压缩列表中的总实体元素数目 unsigned long len; /* number of quicklistNodes */ 快排列表节点的数目 int fill : QL_FILL_BITS; /* fill factor for individual nodes */ 单个节点的填充因子 这个填充因子如果是负数,有一个数组保存的字节数来限制,如果为正数就是元素个数限制,两种不同的限制方式 unsigned int compress : QL_COMP_BITS; /* depth of end nodes not to compress;0=off */ 不压缩的结束节点的深度,0关闭,意味全部不压缩 这个意思就是在这个深度之内的都是不压缩的,在这个深度里面的,才是需要压缩的 unsigned int bookmark_count: QL_BM_BITS; 书签数组的最大长度 quicklistBookmark bookmarks[]; 书签使用的数组 } quicklist; typedef struct quicklistIter { 快排迭代器 const quicklist *quicklist; 快排列表 quicklistNode *current; 当前节点 unsigned char *zi; 指向具体的实体元素 long offset; /* offset in current ziplist */ 指向的实体元素在当前压缩列表的偏移量 int direction; 方向,从前往后或从后往前 } quicklistIter; typedef struct quicklistEntry { 快排列表实体 const quicklist *quicklist; 快排列表 quicklistNode *node; 快片列表节点 unsigned char *zi; 指向压缩列表中的一个元素 unsigned char *value; 元素的值(如果是字符串) long long longval; 整型的值 unsigned int sz;字符串情况下的字节数 int offset; 在压缩列表中的偏移量 } quicklistEntry; #define QUICKLIST_HEAD 0 头部 #define QUICKLIST_TAIL -1 尾部 /* quicklist node encodings */ 快排列表编码 #define QUICKLIST_NODE_ENCODING_RAW 1 原始编码 #define QUICKLIST_NODE_ENCODING_LZF 2 压缩编码 /* quicklist compression disable */ 快排列表压缩禁用 #define QUICKLIST_NOCOMPRESS 0 /* quicklist container formats */ 快排列表容器格式 #define QUICKLIST_NODE_CONTAINER_NONE 1 无格式 #define QUICKLIST_NODE_CONTAINER_ZIPLIST 2 压缩列表格式 #define quicklistNodeIsCompressed(node) 判断压缩列表节点是否压缩 \ ((node)->encoding == QUICKLIST_NODE_ENCODING_LZF) /* Prototypes */ 相关函数原型,具体见源码解析 quicklist *quicklistCreate(void); quicklist *quicklistNew(int fill, int compress); void quicklistSetCompressDepth(quicklist *quicklist, int depth); void quicklistSetFill(quicklist *quicklist, int fill); void quicklistSetOptions(quicklist *quicklist, int fill, int depth); void quicklistRelease(quicklist *quicklist); int quicklistPushHead(quicklist *quicklist, void *value, const size_t sz); int quicklistPushTail(quicklist *quicklist, void *value, const size_t sz); void quicklistPush(quicklist *quicklist, void *value, const size_t sz, int where); void quicklistAppendZiplist(quicklist *quicklist, unsigned char *zl); quicklist *quicklistAppendValuesFromZiplist(quicklist *quicklist, unsigned char *zl); quicklist *quicklistCreateFromZiplist(int fill, int compress, unsigned char *zl); void quicklistInsertAfter(quicklist *quicklist, quicklistEntry *node, void *value, const size_t sz); void quicklistInsertBefore(quicklist *quicklist, quicklistEntry *node, void *value, const size_t sz); void quicklistDelEntry(quicklistIter *iter, quicklistEntry *entry); int quicklistReplaceAtIndex(quicklist *quicklist, long index, void *data, int sz); int quicklistDelRange(quicklist *quicklist, const long start, const long stop); quicklistIter *quicklistGetIterator(const quicklist *quicklist, int direction); quicklistIter *quicklistGetIteratorAtIdx(const quicklist *quicklist, int direction, const long long idx); int quicklistNext(quicklistIter *iter, quicklistEntry *node); void quicklistReleaseIterator(quicklistIter *iter); quicklist *quicklistDup(quicklist *orig); int quicklistIndex(const quicklist *quicklist, const long long index, quicklistEntry *entry); void quicklistRewind(quicklist *quicklist, quicklistIter *li); void quicklistRewindTail(quicklist *quicklist, quicklistIter *li); void quicklistRotate(quicklist *quicklist); int quicklistPopCustom(quicklist *quicklist, int where, unsigned char **data, unsigned int *sz, long long *sval, void *(*saver)(unsigned char *data, unsigned int sz)); int quicklistPop(quicklist *quicklist, int where, unsigned char **data, unsigned int *sz, long long *slong); unsigned long quicklistCount(const quicklist *ql); int quicklistCompare(unsigned char *p1, unsigned char *p2, int p2_len); size_t quicklistGetLzf(const quicklistNode *node, void **data); /* bookmarks */ int quicklistBookmarkCreate(quicklist **ql_ref, const char *name, quicklistNode *node); int quicklistBookmarkDelete(quicklist *ql, const char *name); quicklistNode *quicklistBookmarkFind(quicklist *ql, const char *name); void quicklistBookmarksClear(quicklist *ql); #ifdef REDIS_TEST int quicklistTest(int argc, char *argv[]); #endif /* Directions for iterators */ #define AL_START_HEAD 0 从头部开始,正向 #define AL_START_TAIL 1 从尾部开始,反向