redis源码分析(2)——SDS API详解

源码分析章节,我尽量使用原生的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';
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值