redis源码一-----sds部分

281 阅读1分钟

sds对象的组成部分由header和buffer两部分组成
代码文件为sds.h和sds.c
header的组成
struct sdsheader{

len;//当前长度
alloc;//剩余空间
flag;//sdshdr5 sdshdr16 sdshdr32 sdshdr64
char buf[];//存放字符串内容
}

结构如图

初始化sds的操作
sds sdsnewlen(const void *init, size_t initlen) {

}

sds的新增

sds sdscat(sds s, const char *t){}

sds的切分

sds sdsstrim(sds s, const char *cset){} //这个方法不会进行内存回收,会有专门的内存回收机制

内存重新分配:

sds sdsMakeRoomFor(sds s, size_t addlen) {

void *sh, *newsh;
size_t avail = sdsavail(s);//拿到当前sds的可用空间 当前sds对象 alloc - len
size_t len, newlen;
char type, oldtype = s[-1] & SDS_TYPE_MASK;//老的flag
int hdrlen;

/* 如果当前可用空间大于新增空间直接返回,不涉及内存分配 */
if (avail >= addlen) return s;

len = sdslen(s);
sh = (char*)s-sdsHdrSize(oldtype);//取到header
newlen = (len+addlen);
if (newlen < SDS_MAX_PREALLOC)//SDS_MAX_PREALLOC是1M 新增后的长度小于1M就是newlen的两倍
    newlen *= 2;
else
    newlen += SDS_MAX_PREALLOC;//新增后的长度大于1M就分配1M的剩余空间 减少后期新增内存分配的次数

type = sdsReqType(newlen);

if (type == SDS_TYPE_5) type = SDS_TYPE_8;

hdrlen = sdsHdrSize(type);//计算头的长度
if (oldtype==type) {
    newsh = s_realloc(sh, hdrlen+newlen+1); //如果type没有改变就分配内存空间
    if (newsh == NULL) return NULL;
    s = (char*)newsh+hdrlen;
} else {
    newsh = s_malloc(hdrlen+newlen+1);
    if (newsh == NULL) return NULL;
    memcpy((char*)newsh+hdrlen, s, len+1);
    s_free(sh);
    s = (char*)newsh+hdrlen;
    s[-1] = type;
    sdssetlen(s, len);
}
sdssetalloc(s, newlen);
return s;
}