slab_get_item(uint8_t cid)
{
rstatus_t status;
struct slabclass *c;
struct slabinfo *sinfo;
struct slab *slab;
ASSERT(cid >= SLABCLASS_MIN_ID && cid < nctable);
c = &ctable[cid];
if (itemx_empty()) {
status = slab_evict();
if (status != FC_OK) {
return NULL;
}
}
if (!TAILQ_EMPTY(&c->partial_msinfoq)) {
return _slab_get_item(cid);
}//这个class的partial_msinfoq不为空,取一个可用的item位置返回
if (!TAILQ_EMPTY(&free_msinfoq)) {//在free_msinfoq中取一个空的,初始化
/* move memory slab from free to partial q */
sinfo = TAILQ_FIRST(&free_msinfoq);//在free_msinfoq中取一个
ASSERT(nfree_msinfoq > 0);
nfree_msinfoq--;//free的少一个
c->nmslab++;//这个class的内存中的slab多一个
TAILQ_REMOVE(&free_msinfoq, sinfo, tqe);
/* init partial sinfo */
TAILQ_INSERT_HEAD(&c->partial_msinfoq, sinfo, tqe);//放入头部并初始化
/* sid is already initialized by slab_init */
/* addr is already initialized by slab_init */
sinfo->nalloc = 0;
sinfo->nfree = 0;
sinfo->cid = cid;
/* mem is already initialized by slab_init */
ASSERT(sinfo->mem == 1);//表明时内存中的slab
/* init slab of partial sinfo */
slab = slab_from_maddr(sinfo->addr, false);
slab->magic = SLAB_MAGIC;
slab->cid = cid;
/* unused[] is left uninitialized */
slab->sid = sinfo->sid;
/* data[] is initialized on-demand */
return _slab_get_item(cid);
}
ASSERT(!TAILQ_EMPTY(&full_msinfoq));
ASSERT(nfull_msinfoq > 0);
status = slab_drain();
if (status != FC_OK) {
return NULL;
}
return slab_get_item(cid);
}
若磁盘free非空,直接将内存的移至磁盘,返回,若为空,先slab_evict(),再把内存旧的移至磁盘,返回
slab_drain(void)
{
rstatus_t status;
if (!TAILQ_EMPTY(&free_dsinfoq)) {
ASSERT(nfree_dsinfoq > 0);
return _slab_drain();
}
status = slab_evict();
if (status != FC_OK) {
return status;
}
ASSERT(!TAILQ_EMPTY(&free_dsinfoq));
ASSERT(nfree_dsinfoq > 0);
return _slab_drain();
}
将内存中老的移至磁盘中free的位置
_slab_drain(void)
{
struct slabinfo *msinfo, *dsinfo; /* memory and disk slabinfo */
struct slab *slab; /* slab to write */
size_t size; /* bytes to write */
off_t off; /* offset to write at */
int n; /* written bytes */
ASSERT(!TAILQ_EMPTY(&full_msinfoq));
ASSERT(nfull_msinfoq > 0);
ASSERT(!TAILQ_EMPTY(&free_dsinfoq));
ASSERT(nfree_dsinfoq > 0);
/* get memory sinfo from full q */
msinfo = TAILQ_FIRST(&full_msinfoq);//从内存中满的里面取一个
nfull_msinfoq--;
TAILQ_REMOVE(&full_msinfoq, msinfo, tqe);
ASSERT(msinfo->mem);
ASSERT(slab_full(msinfo));
/* get disk sinfo from free q */
dsinfo = TAILQ_FIRST(&free_dsinfoq);//从磁盘中取一个空的
nfree_dsinfoq--;
TAILQ_REMOVE(&free_dsinfoq, dsinfo, tqe);
ASSERT(!dsinfo->mem);
/* drain the memory to disk slab */
slab = slab_from_maddr(msinfo->addr, true);
size = settings.slab_size;
off = slab_to_daddr(dsinfo);
n = pwrite(fd, slab, size, off);
if (n < size) {
log_error("pwrite fd %d %zu bytes at offset %"PRId64" failed: %s",
fd, size, off, strerror(errno));
return FC_ERROR;
}
ctable[msinfo->cid].nmslab--;
ctable[msinfo->cid].ndslab++;
log_debug(LOG_DEBUG, "drain slab at memory (sid %"PRIu32" addr %"PRIu32") "
"to disk (sid %"PRIu32" addr %"PRIu32")", msinfo->sid,
msinfo->addr, dsinfo->sid, dsinfo->addr);
/* swap msinfo <> dsinfo addresses */
slab_swap_addr(msinfo, dsinfo);
/* move dsinfo (now a memory sinfo) to free q */
nfree_msinfoq++;
TAILQ_INSERT_TAIL(&free_msinfoq, dsinfo, tqe);
/* move msinfo (now a disk sinfo) to full q */
nfull_dsinfoq++;
TAILQ_INSERT_TAIL(&full_dsinfoq, msinfo, tqe);
return FC_OK;
}
在_slab_get_item(uint8_t cid)中,若partial_msinfoq中的slab满了,则放进full_msinfoq中