********************************************************************************************
/* 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 从尾部开始,反向