redis6.0.5之quicklist阅读笔记1--定义

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

 

上一篇:redis(一)redis的数据结构


下一篇:redis6.0.5之quicklist阅读笔记2--函数解析