1关于书签 typedef struct quicklistBookmark { quicklistNode *node; 书签指向的快排列表的节点 char *name; 书签名字 } quicklistBookmark; 删除快排列表节点的逻辑中有关于更新书签,如果删除了书签关联的节点,那么需要更新对应的书签(如果存在) /* Update the bookmark if any */ 如果存在书签就更新它 quicklistBookmark *bm = _quicklistBookmarkFindByNode(quicklist, node); 通过节点查找书签 if (bm) {如果存在 bm->node = node->next;把当前节点的下一个节点赋值给书签 /* if the bookmark was to the last node, delete it. */ 如果书签节点就是最后一个节点,删除之 if (!bm->node) _quicklistBookmarkDelete(quicklist, bm); } 2关于 关于压缩深度和填充因子 unsigned int compress : QL_COMP_BITS; int fill : QL_FILL_BITS; 在结构体quicklist中 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; compress表示的意思是 当前quicklist首尾两端不压缩节点的个数,所以这个深度最多值需要所有节点的一半取上整即可 覆盖整个列表不被压缩 当然为了整个列表不压缩,只需要取0即可 若取0,则表示整个链表不压缩; 若取1,则两端各有1个节点不进行压缩, 若取2,则两端各有2个节点不进行压缩 以此类推... fill表示的意思是 具体填充多少内容,两个不同的衡量标准 一个是字节数 一个是元素个数 首先通过字节数判断时候,采用了一个数组,这个时候传入的fill为负数,显然必须在-1到-5之间,通过数组获取对应的大小 /* Optimization levels for size-based filling */ 基于大小填充的优化等级 static const size_t optimization_level[] = {4096, 8192, 16384, 32768, 65536}; 如果没有满足字节数的条件,但是小于SIZE_SAFETY_LIMIT时,还可以进行元素个数判断 /* Maximum size in bytes of any multi-element ziplist. * Larger values will live in their own isolated ziplists. */ #define SIZE_SAFETY_LIMIT 8192 判断代码如下: if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(merge_sz, fill))) 先判断字节数 return 1; else if (!sizeMeetsSafetyLimit(merge_sz)) 再判断是否到安全字节数值 return 0; else if ((int)(a->count + b->count) <= fill) 再判断个数 return 1; else return 0;