源码分析章节,我尽量使用原生的redis源码,不去看黄建宏的注释,提高自己阅读源码的能力,此外,redis版本还是3.0
源码下载,大家可以到这 http://download.redis.io/releases/

sdsnew

typedef char *sds;

sds sdsnewlen(const void *init, size_t initlen) {
    struct sdshdr *sh;

    //分配内存
    if (init) {
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    } else {
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    }
    //分配失败返回NULL
    if (sh == NULL) return NULL;

    sh->len = initlen;
    sh->free = 0;//这里可以看到sds初始是不会分配多余空间的。

    if (initlen && init)
        //如果init中原来有内容则拷贝。
        memcpy(sh->buf, init, initlen);
    sh->buf[initlen] = '\0';
    return (char*)sh->buf;
}

这里有用到zmalloczcalloc两个函数,具体分析不在赘述。zmallocmalloc的主要区别在于zmallocmalloc多分配了一定的空间(据平台而定),这个多余的空间用来存储zmalloc本要分配的大小。zcalloczmalloc的区别在于zmalloc不会初始化内存,而zcalloc会初始化。

sdsempty

创建并返回一个只保存了空字符串 "" 的 sds。
sds sdsempty(void) {
return sdsnewlen(“”,0);
}

sdsnew

把一个给定的c字符串转为sds。

sds sdsnew(const char *init) {
    size_t initlen = (init == NULL) ? 0 : strlen(init);
    return sdsnewlen(init, initlen);
}

sdsdup

拷贝sds

sds sdsdup(const sds s) {
    return sdsnewlen(s, sdslen(s));
}

sdsfree

释放sds

void sdsfree(sds s) {
    if (s == NULL) return;
    zfree(s-sizeof(struct sdshdr));
}

zfree的功能
释放内存并修改redis使用的内存大小。

sdsupdatelen

?废弃函数
根据代码我猜测是重新设置sds的大小
eg.

sds={10,0,"abc"/"abc\0defghi"}
==>
sds={3,7,"abc"}
void sdsupdatelen(sds s) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
    int reallen = strlen(s);
    sh->free += (sh->len-reallen);
    sh->len = reallen;
}

sdsclear

在不去真实释放sds空间的情况下,将sds变为空字符串。

void sdsclear(sds s) {

    // 取出 sdshdr
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    sh->free += sh->len;
    sh->len = 0;
    sh->buf[0] = '\0';
}

sdsMakeRoomFor

sdsRemoveFreeSpace

真正的释放了惰性空间释放时的多余空间

sds sdsRemoveFreeSpace(sds s) {
    struct sdshdr *sh;

    sh = (void*) (s-(sizeof(struct sdshdr)));

    // 进行内存重分配,让 buf 的长度仅仅足够保存字符串内容
    // T = O(N)
    sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);

    // 空余空间为 0
    sh->free = 0;

    return sh->buf;
}

sdsAllocSize

获得sds一共分配保存字符串的空间(len+free+'\0')

size_t sdsAllocSize(sds s) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    return sizeof(*sh)+sh->len+sh->free+1;
}

sdsIncrLen

void sdsIncrLen(sds s, int incr) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    // 确保 sds 空间足够
    assert(sh->free >= incr);

    // 更新属性
    sh->len += incr;
    sh->free -= incr;

    // 这个 assert 其实可以忽略
    // 因为前一个 assert 已经确保 sh->free - incr >= 0 了
    assert(sh->free >= 0);

    // 放置新的结尾符号
    s[sh->len] = '\0';
}
posted on 2017-12-19 22:49  岚漾忆雨  阅读(93)  评论(0)    收藏  举报