1. 程式人生 > >fatcache原始碼閱讀記錄

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之後將其返回