fatcache源码分析:
http://godorz.info/2013/03/fatcache/
想了解其内存,磁盘空间分配和使用
每个slab对应一个结构体slabinfo(slabinfo是永在内存中的)
Fc_slab.c 中slab_init开始初始化,初始化内存和磁盘两部分的空间,fd指向磁盘路径
路径在运行时配置
-D, --ssd-device=S : set the path to the ssd device file (default: n/a)
内存部分空间大小为:nmslab = MAX(nctable, settings.max_slab_memory / settings.slab_size);
mspace = nmslab * settings.slab_size;
mstart = fc_mmap(mspace); //映射内存空间
磁盘部分
status = fc_device_size(settings.ssd_device, &size);
再看fc_device_size函数:
int status; /* return status */
struct stat statinfo; /* stat info */
int fd; /* file descriptor */
status = stat(path, &statinfo); //通过文件名path获取文件信息,并保存在所指的结构体中
if (status < 0) {
log_error("stat '%s' failed: %s", path, strerror(errno));
return FC_ERROR;
}
fc_device_size函数完成初始化时的一些处理,获得size为文件字节数,
ndchunk = size / settings.slab_size;
ASSERT(settings.server_n <= ndchunk);
ndslab = ndchunk / settings.server_n;
dspace = ndslab * settings.slab_size;
dstart = (settings.server_id * ndslab) * settings.slab_size;
dend = ((settings.server_id + 1) * ndslab) * settings.slab_size;
-s, --server-id=I/N : set fatcache instance to be I out of total N instances (default: 0/1)
之后初始化其他几个数据结构,完成初始化
读取时,读取函数:slab_read_item
sinfo = &stable[sid];
c = &ctable[sinfo->cid];
size = settings.slab_size;
it = NULL;
if (sinfo->mem) {
off = (off_t)sinfo->addr * settings.slab_size + addr;
fc_memcpy(readbuf, mstart + off, c->size);
it = (struct item *)readbuf;
goto done;
}
off = slab_to_daddr(sinfo) + addr;
aligned_off = ROUND_DOWN(off, 512);
aligned_size = ROUND_UP((c->size + (off - aligned_off)), 512);
n = pread(fd, readbuf, aligned_size, aligned_off);
if (n < aligned_size) {
log_error("pread fd %d %zu bytes at offset %"PRIu64" failed: %s", fd,
aligned_size, (uint64_t)aligned_off, strerror(errno));
return NULL;
}
it = (struct item *)(readbuf + (off - aligned_off));
获取到具体slab后,若是在内存中,则直接获取到it中,若是在磁盘中,先调用slab_to_daddr函数:
off = dstart + ((off_t)sinfo->addr * settings.slab_size);
其中,dstart根据所在的实例有所不同:
dstart = (settings.server_id * ndslab) * settings.slab_size;
获取到it之后将其返回