设为首页 加入收藏

TOP

Redis内部数据结构详解之ziplist(三)
2014-11-24 00:44:28 来源: 作者: 【 】 浏览:38
Tags:Redis 内部 数据结构 详解 ziplist
he * size of prevlen doesn't have an effect on the *tail* offset. */ //如果p不是尾节点,那么尾节点指针的首地址还需要加上nextdiff tail = zipEntry(p); if (p[tail.headersize+tail.len] != ZIP_END) { ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff); } /* Move tail to the front of the ziplist */ //first.p至p之间的节点都是需要删除的,因此需要将p开始的数据向前偏移,zlend不需要处理,因此需要-1 memmove(first.p,p,intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1); } else { /* The entire tail was deleted. No need to move memory. */ //如果已经删除到zlend,那么尾节点指针应该指向被删除的first之前的节点首地址 ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe((first.p-zl)-first.prevrawlen); } /* Resize and update length */ offset = first.p-zl; zl = ziplistResize(zl, intrev32ifbe(ZIPLIST_BYTES(zl))-totlen+nextdiff); ZIPLIST_INCR_LENGTH(zl,-deleted); p = zl+offset; /* When nextdiff != 0, the raw length of the next entry has changed, so * we need to cascade the update throughout the ziplist */ /** 如果nextdiff不等于0,说明现在的p节点的长度变了,需要级联更新下个节点能否保存 p节点的长度值 */ if (nextdiff != 0) zl = __ziplistCascadeUpdate(zl,p); } return zl; }

/* Insert item at "p". */
//添加保存给定元素s的新节点插入到地址p之前,然后原有的数据向后偏移
//zl: ziplist首地址,p:插入位置指针,s:待插入的字符串首地址,slen:待插入字符串长度
static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {
    size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen, prevlen = 0;
    size_t offset;
    int nextdiff = 0;
    unsigned char encoding = 0;
    long long value = 123456789; /* initialized to avoid warning. Using a value
                                    that is easy to see if for some reason
                                    we use it uninitialized. */
    zlentry entry, tail;

    /* Find out prevlen for the entry that is inserted. */
    // 那么取出节点相关资料,以及 prevlen
    if (p[0] != ZIP_END) {//p之后存在节点
        entry = zipEntry(p);//取出p节点的相关资料
        prevlen = entry.prevrawlen;//得到p节点前一个节点所占字节数
    } else {//p之后没有节点,达到zlend,那么就取出尾节点
        unsigned char *ptail = ZIPLIST_ENTRY_TAIL(zl);
        if (ptail[0] != ZIP_END) {//如果存在尾节点
            prevlen = zipRawEntryLength(ptail);//得到尾节点的总字节数,然后在尾节点之后insert
        }//否则就应该是在一个空的ziplist第一个insert一个节点
    }

    /* See if the entry can be encoded */
    // 查看能否将新值保存为整数,如果可以的话返回 1 ,
    // 并将新值保存到 value ,编码形式保存到 encoding
    if (zipTryEncoding(s,slen,&value,&encoding)) {
        /* 'encoding' is set to the appropriate integer encoding */
        //s 可以保存为整数,那么继续计算保存它所需的空间
        reqlen = zipIntSize(encoding);
    } else {
        /* 'encoding' is untouched, however zipEncodeLength will use the
         * string length to figure out how to encode it. */
        // 不能保存为整数,直接使用字符串长度
        reqlen = slen;
    }
    /* We need space for both the length of the previous entry and
     * the length of the payload. */
    // 计算编码 prevlen 所需的长度
    reqlen += zipPrevEncodeLength(NULL,prevlen);
    //计算编码slen所需的长度
    reqlen += zipEncodeLength(NULL,encoding,slen);

    /* When the insert position is not equal to the tail, we need to
     * make sure that the next entry can hold this entry's length in
     * its prevlen field. */
    //当插入的位置不为尾部时,需要确保下一个节点的存储前一个
    //节点所占自己数的空间能够存储即将插入节点的长度
    // zipPrevLenByteDiff 的返回值有三种可能:
    // 1)新旧两个节点的编码长度相等,返回 0
    // 2)新节点编码长度 > 旧节点编码长度,返回 5 - 1 = 4
    // 3)旧节点编码长度 > 新编码节点长度,返回 1 - 5 = -4
    nextdiff = (p[0] != ZIP_END)   zipPrevLenByteDiff(p,reqlen) : 0;

    /* Store offset because a realloc may change the address of zl. */
    offset = p-zl;//保存当前的偏移量,在这偏移量之前的数据不需要改变,只需要改变在此之后的数据
    // 重分配空间,并更新长度属性和表尾
    // 新空间长度 = 现有长度 + 新节点所需长度 + 编码新节点长度所需的长度差
    zl = ziplistRes
首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MongoDB之整库备份还原单表collec.. 下一篇DbVisualizerPersonal中文乱码问..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: