Ejemplo n.º 1
0
static int do_slabs_newslab(const unsigned int id, bool disk_item) {
    slabclass_t *p = &slabclass[id];
    int len = settings.slab_reassign ? settings.item_size_max
        : p->size * p->perslab;
    char *ptr;

    if (disk_item) {
      if ((disk_item_mem_limit && disk_item_mem_malloced + len > disk_item_mem_limit && p->slabs > 0) ||
          (grow_slab_list(id) == 0) ||
          ((ptr = memory_allocate((size_t)len)) == 0)) {

          MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
          return 0;
      }
      disk_item_mem_malloced += len;
    } else {
      if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
          (grow_slab_list(id) == 0) ||
          ((ptr = memory_allocate((size_t)len)) == 0)) {

          MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
          return 0;
      }
      mem_malloced += len;
    }

    memset(ptr, 0, (size_t)len);
    p->end_page_ptr = ptr;
    p->end_page_free = p->perslab;

    p->slab_list[p->slabs++] = ptr;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 2
0
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];
#ifdef ALLOW_SLABS_REASSIGN
    int len = POWER_BLOCK;
#else
    int len = p->size * p->perslab;
#endif
    char *ptr;

    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
        (grow_slab_list(id) == 0) ||
        ((ptr = memory_allocate((size_t)len)) == 0)) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    p->end_page_ptr = ptr;
    p->end_page_free = p->perslab;

    p->slab_list[p->slabs++] = ptr;
    mem_malloced += len;

    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);
    return 1;
}
Ejemplo n.º 3
0
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];
#ifdef ALLOW_SLABS_REASSIGN
    int len = POWER_BLOCK;
#else
    int len = p->size * p->perslab;
#endif
    char *ptr;

    if (mem_limit && mem_malloced + len > mem_limit && p->slabs > 0)
        return 0;

    if (grow_slab_list(id) == 0) return 0;

    ptr = malloc((size_t)len);
    if (ptr == 0) return 0;

    memset(ptr, 0, (size_t)len);
    p->end_page_ptr = ptr;
    p->end_page_free = p->perslab;

    p->slab_list[p->slabs++] = ptr;
    mem_malloced += len;
    return 1;
}
/**
 * 为slabclass[id]分配一个新的slab,成功返回1,否则返回0
 * 
 * 1. 确定slab的长度len
 * 2. 分配len大小的内存(预分配的内存中划分或者调malloc()分配)
 * 3. 把所分配的内存初始化成item链表,链接到slabclass[id]的slot中
 * 4. slabclass[i]属性的更新:slabs数增1
 * 5. 已分配内存数的更新
 */
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id]; //指向第i个slabclass
    int len = settings.slab_reassign ? settings.item_size_max //是否开启可自定slab大小,否则使用默认的大小1M
        : p->size * p->perslab;
    char *ptr;
	//grow_slab_list初始化slabclass的slab_list,而slab_list中的指针指向每个slab  
    //memory_allocate从内存池申请1M的空间  
    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
        (grow_slab_list(id) == 0) ||
        ((ptr = memory_allocate((size_t)len)) == 0)) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
	//将申请到的1M空间按照slabclass的size进行切分
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;//循环分配
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 5
0
//slabclass_t中slab的数目是慢慢增多的。该函数的作用就是为slabclass_t申请多一个slab  
//参数id指明是slabclass数组中的那个slabclass_t 
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];

    //settings.slab_reassign的默认值为false,这里就采用false
    int len = settings.slab_reassign ? settings.item_size_max
        : p->size * p->perslab;//其积 <= settings.item_size_max
    char *ptr;

    //mem_malloced的值通过环境变量设置,默认为0 
    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
        (grow_slab_list(id) == 0) ||//增长slab_list(失败返回0)。一般都会成功,除非无法分配内存
        ((ptr = memory_allocate((size_t)len)) == 0)) {//分配len字节内存(也就是一个页)

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);//清零内存块是必须的
    //将这块内存切成一个个的item,当然item的大小有id所控制
    split_slab_page_into_freelist(ptr, id);

    //将分配得到的内存页交由slab_list掌管
    p->slab_list[p->slabs++] = ptr;
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 6
0
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];
    slabclass_t *g = &slabclass[SLAB_GLOBAL_PAGE_POOL];
    int len = settings.slab_reassign ? settings.item_size_max
        : p->size * p->perslab;
    char *ptr;

    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0
         && g->slabs == 0)) {
        mem_limit_reached = true;
        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    if ((grow_slab_list(id) == 0) ||
        (((ptr = get_page_from_global_pool()) == NULL) &&
        ((ptr = memory_allocate((size_t)len)) == 0))) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 7
0
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];
    int len = settings.slab_reassign ? settings.item_size_max
        : p->size * p->perslab;
    char *ptr;

    DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: mem_limit = %u, len = %u\n",
		__func__, __LINE__, (unsigned int)mem_limit, (unsigned int)len);
    DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: p->slabs = %u\n", __func__, __LINE__, p->slabs);
    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
	(grow_slab_list(id) == 0) ||
	((ptr = memory_allocate((size_t)len)) == 0)) {
        mem_limit_reached = true;
        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
	DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: mem_limit = %u, mem_malloced = %u, len = %d\n", __func__, __LINE__,
		(unsigned int)mem_limit, (unsigned int)mem_malloced, len);
	DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: returning 0\n", __func__, __LINE__);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
	// TODO: Should this be commented?
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;
#ifdef HOPSCOTCH_CLOCK
	p->clock_max = p->slabs * p->perslab;
#endif
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 8
0
static int do_slabs_newslab(slabs_t* pst, const unsigned int id) {
    slabclass_t *p = &pst->slabclass[id];
    //int len = settings.slab_reassign ? settings.item_size_max
    //    : p->size * p->perslab;
    int len = p->size * p->perslab;
    char *ptr;

    if ((pst->mem_limit && pst->mem_malloced + len > pst->mem_limit && p->slabs > 0) ||
        (grow_slab_list(pst, id) == 0) ||
        ((ptr = memory_allocate(pst, (size_t)len)) == 0)) {

        //MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    p->end_page_ptr = ptr;
    p->end_page_free = p->perslab;

    p->slab_list[p->slabs++] = ptr;
    pst->mem_malloced += len;
    //MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 9
0
static int slab_rebalance_start(void) {
    slabclass_t *s_cls;
    int no_go = 0;

    pthread_mutex_lock(&cache_lock);
    pthread_mutex_lock(&slabs_lock);

    if (slab_rebal.s_clsid < POWER_SMALLEST ||
        slab_rebal.s_clsid > power_largest  ||
        slab_rebal.d_clsid < POWER_SMALLEST ||
        slab_rebal.d_clsid > power_largest  ||
        slab_rebal.s_clsid == slab_rebal.d_clsid)//非法下标索引
        no_go = -2;

    s_cls = &slabclass[slab_rebal.s_clsid];

    //为这个目标slab class增加一个页表项都失败,那么就
    //根本无法为之增加一个页了
    if (!grow_slab_list(slab_rebal.d_clsid)) {
        no_go = -1;
    }

    if (s_cls->slabs < 2)//目标slab class页数太少了,无法分一个页给别人
        no_go = -3;

    if (no_go != 0) {
        pthread_mutex_unlock(&slabs_lock);
        pthread_mutex_unlock(&cache_lock);
        return no_go; /* Should use a wrapper function... */
    }

    //标志将源slab class的第几个内存页分给目标slab class  
    //这里是默认是将第一个内存页分给目标slab class
    s_cls->killing = 1;

    //记录要移动的页的信息。slab_start指向页的开始位置。slab_end指向页  
    //的结束位置。slab_pos则记录当前处理的位置(item)
    slab_rebal.slab_start = s_cls->slab_list[s_cls->killing - 1];
    slab_rebal.slab_end   = (char *)slab_rebal.slab_start +
        (s_cls->size * s_cls->perslab);
    slab_rebal.slab_pos   = slab_rebal.slab_start;
    slab_rebal.done       = 0;

    /* Also tells do_item_get to search for items in this slab */
    slab_rebalance_signal = 2;//要rebalance线程接下来进行内存页移动

    if (settings.verbose > 1) {
        fprintf(stderr, "Started a slab rebalance\n");
    }

    pthread_mutex_unlock(&slabs_lock);
    pthread_mutex_unlock(&cache_lock);

    STATS_LOCK();
    stats.slab_reassign_running = true;
    STATS_UNLOCK();

    return 0;
}
Ejemplo n.º 10
0
static int slab_rebalance_start(void) {
    slabclass_t *s_cls;
    slabclass_t *d_cls;
    int no_go = 0;

    pthread_mutex_lock(&cache_lock);
    pthread_mutex_lock(&slabs_lock);

    if (slab_rebal.s_clsid < POWER_SMALLEST ||
        slab_rebal.s_clsid > power_largest  ||
        slab_rebal.d_clsid < POWER_SMALLEST ||
        slab_rebal.d_clsid > power_largest  ||
        slab_rebal.s_clsid == slab_rebal.d_clsid)
        no_go = -2;

    s_cls = &slabclass[slab_rebal.s_clsid];
    d_cls = &slabclass[slab_rebal.d_clsid];

    if (d_cls->end_page_ptr || s_cls->end_page_ptr ||
        !grow_slab_list(slab_rebal.d_clsid)) {
        no_go = -1;
    }

    if (s_cls->slabs < 2)
        no_go = -3;

    if (no_go != 0) {
        pthread_mutex_unlock(&slabs_lock);
        pthread_mutex_unlock(&cache_lock);
        return no_go; /* Should use a wrapper function... */
    }

    s_cls->killing = 1;

    slab_rebal.slab_start = s_cls->slab_list[s_cls->killing - 1];
    slab_rebal.slab_end   = (char *)slab_rebal.slab_start +
        (s_cls->size * s_cls->perslab);
    slab_rebal.slab_pos   = slab_rebal.slab_start;
    slab_rebal.done       = 0;

    /* Also tells do_item_get to search for items in this slab */
    slab_rebalance_signal = 2;

    if (settings.verbose > 1) {
        fprintf(stderr, "Started a slab rebalance\n");
    }

    pthread_mutex_unlock(&slabs_lock);
    pthread_mutex_unlock(&cache_lock);

    STATS_LOCK();
    stats.slab_reassign_running = true;
    STATS_UNLOCK();

    return 0;
}
Ejemplo n.º 11
0
static int slab_rebalance_start(void) {
    slabclass_t *s_cls;
    int no_go = 0;

    pthread_mutex_lock(&slabs_lock);

    if (slab_rebal.s_clsid < POWER_SMALLEST ||
        slab_rebal.s_clsid > power_largest  ||
        slab_rebal.d_clsid < SLAB_GLOBAL_PAGE_POOL ||
        slab_rebal.d_clsid > power_largest  ||
        slab_rebal.s_clsid == slab_rebal.d_clsid)
        no_go = -2;

    s_cls = &slabclass[slab_rebal.s_clsid];

    if (!grow_slab_list(slab_rebal.d_clsid)) {
        no_go = -1;
    }

    if (s_cls->slabs < 2)
        no_go = -3;

    if (no_go != 0) {
        pthread_mutex_unlock(&slabs_lock);
        return no_go; /* Should use a wrapper function... */
    }

    /* Always kill the first available slab page as it is most likely to
     * contain the oldest items
     */
    slab_rebal.slab_start = s_cls->slab_list[0];
    slab_rebal.slab_end   = (char *)slab_rebal.slab_start +
        (s_cls->size * s_cls->perslab);
    slab_rebal.slab_pos   = slab_rebal.slab_start;
    slab_rebal.done       = 0;

    /* Also tells do_item_get to search for items in this slab */
    slab_rebalance_signal = 2;

    if (settings.verbose > 1) {
        fprintf(stderr, "Started a slab rebalance\n");
    }

    pthread_mutex_unlock(&slabs_lock);

    STATS_LOCK();
    stats_state.slab_reassign_running = true;
    STATS_UNLOCK();

    return 0;
}
Ejemplo n.º 12
0
int Slab::do_slabs_newslab(unsigned int id) {
    slabclass& p = mem_base[id];
    int len = p.size * p.perslab;
    char* ptr;

    //异常情况
    //内存限制不为0,申请大小总计已超过限制,并且已经申请了一些slab数
    if ((mem_limit && mem_malloced+len > mem_limit && p.slabs > 0) ||
           (grow_slab_list(id) == 0)  ||
            ((ptr = memory_allocate((size_t)len)) == 0)) {
        return 0;
    }
    
    memset(ptr, 0, (size_t)len);
    //把内存分解为chunk
    split_slab_page_into_freelist(ptr, id);
    p.slab_list[p.slabs++] = ptr;
    mem_malloced += len;
    
    return 1;
}
Ejemplo n.º 13
0
static int do_slabs_newslab(struct default_engine *engine, const unsigned int id)
{
    slabclass_t *p = &engine->slabs.slabclass[id];
    int len = p->size * p->perslab;
    char *ptr;

    if ((engine->slabs.mem_limit && engine->slabs.mem_malloced + len > engine->slabs.mem_limit && p->slabs >= p->rsvd_slabs) ||
        (grow_slab_list(engine, id) == 0) ||
        ((ptr = memory_allocate(engine, (size_t)len)) == 0)) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    p->end_page_ptr = ptr;
    p->end_page_free = p->perslab;

    p->slab_list[p->slabs++] = ptr;
    engine->slabs.mem_malloced += len;

    if ((engine->slabs.mem_limit <= engine->slabs.mem_malloced) ||
        ((engine->slabs.mem_limit - engine->slabs.mem_malloced) < engine->slabs.mem_reserved))
    {
        if (engine->slabs.slabclass[sm_anchor.blck_clsid].rsvd_slabs == 0) { /* undefined */
            /* define the reserved slab count of slab class 0 */
            slabclass_t *z = &engine->slabs.slabclass[sm_anchor.blck_clsid];
            unsigned int additional_slabs = (z->slabs/100) * RESERVED_SLAB_RATIO;
            if (additional_slabs < RESERVED_SLABS)
                additional_slabs = RESERVED_SLABS;
            z->rsvd_slabs = z->slabs + additional_slabs;
            sm_anchor.free_limit_space = (additional_slabs * z->perslab) * sm_anchor.blck_tsize;
            sm_anchor.free_chunk_space = sm_anchor.free_limit_space
                                       + (z->sl_curr + z->end_page_free) * sm_anchor.blck_tsize;
        }
    }
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 14
0
int slabs_newslab(unsigned int id) {
    slabclass_t *p = &slabclass[id];
    int num = p->perslab;
    int len = POWER_BLOCK;
    char *ptr;

    if (mem_limit && mem_malloced + len > mem_limit)
        return 0;

    if (! grow_slab_list(id)) return 0;
   
    ptr = malloc(len);
    if (ptr == 0) return 0;

    memset(ptr, 0, len);
    p->end_page_ptr = ptr;
    p->end_page_free = num;

    p->slab_list[p->slabs++] = ptr;
    mem_malloced += len;
    return 1;
}
Ejemplo n.º 15
0
static int do_slabs_newslab(struct default_engine *engine, const unsigned int id) {
    slabclass_t *p = &engine->slabs.slabclass[id];
    int len = p->size * p->perslab;
    char *ptr;

    if ((engine->slabs.mem_limit && engine->slabs.mem_malloced + len > engine->slabs.mem_limit && p->slabs > 0) ||
        (grow_slab_list(engine, id) == 0) ||
        ((ptr = memory_allocate(engine, (size_t)len)) == 0)) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    p->end_page_ptr = ptr;
    p->end_page_free = p->perslab;

    p->slab_list[p->slabs++] = ptr;
    engine->slabs.mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Ejemplo n.º 16
0
/* 1 = success
   0 = fail
   -1 = tried. busy. send again shortly. */
int slabs_reassign(unsigned char srcid, unsigned char dstid) {
    void *slab, *slab_end;
    slabclass_t *p, *dp;
    void *iter;
    int was_busy = 0;

    if (srcid < POWER_SMALLEST || srcid > POWER_LARGEST ||
        dstid < POWER_SMALLEST || dstid > POWER_LARGEST)
        return 0;
   
    p = &slabclass[srcid];
    dp = &slabclass[dstid];

    /* fail if src still populating, or no slab to give up in src */
    if (p->end_page_ptr || ! p->slabs)
        return 0;

    /* fail if dst is still growing or we can't make room to hold its new one */
    if (dp->end_page_ptr || ! grow_slab_list(dstid))
        return 0;
        
    if (p->killing == 0) p->killing = 1;

    slab = p->slab_list[p->killing-1];
    slab_end = slab + POWER_BLOCK;
    
    for (iter=slab; iter<slab_end; iter+=p->size) {
        item *it = (item *) iter;
        if (it->slabs_clsid) {
            if (it->refcount) was_busy = 1;
            item_unlink(it);
        }
    }
    
    /* go through free list and discard items that are no longer part of this slab */
    {
        int fi;
        for (fi=p->sl_curr-1; fi>=0; fi--) {
            if (p->slots[fi] >= slab && p->slots[fi] < slab_end) {
                p->sl_curr--;
                if (p->sl_curr > fi) p->slots[fi] = p->slots[p->sl_curr];
            }
        }
    }

    if (was_busy) return -1;

    /* if good, now move it to the dst slab class */
    p->slab_list[p->killing-1] = p->slab_list[p->slabs-1];
    p->slabs--;
    p->killing = 0;
    dp->slab_list[dp->slabs++] = slab;
    dp->end_page_ptr = slab;
    dp->end_page_free = dp->perslab;

    /* this isn't too critical, but other parts of the code do asserts to
       make sure this field is always 0.  */
    for (iter=slab; iter<slab_end; iter+=dp->size) {
        ((item *)iter)->slabs_clsid = 0;
    }

    return 1;
}