fatcache原始碼閱讀記錄
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;
}
status = ioctl(fd, BLKGETSIZE64, size);// ioctl是裝置驅動程式中對裝置的I/O通道進行管理的函式
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;
其中server_n server_id來源於設定:可能為多個例項
-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之後將其返回