slabs.c
/* refcount == 0 is safe since nobody can incr while cache_lock is held.
 * refcount != 0 is impossible since flags/etc can be modified in other
 * threads. instead, note we found a busy one and bail. logic in do_item_get
 * will prevent busy items from continuing to be busy
 */
refcount == 0 is safe since nobody can incr while cache_lock is held.
refcount != 0 is impossible since flags/etc can be modified in other
threads. instead, note we found a busy one and bail. logic in do_item_get
will prevent busy items from continuing to be busy
refcount == 0 is safe since nobody can incr while cache_lock is held . refcount ! = 0 is impossible since flags / etc can be modified in other threads . instead note we found a busy one and bail . logic in do_item_get will prevent busy items from continuing to be busy
static int slab_rebalance_move(void) {
    slabclass_t *s_cls;
    int x;
    int was_busy = 0;
    int refcount = 0;
    enum move_status status = MOVE_PASS;
    pthread_mutex_lock(&cache_lock);
    pthread_mutex_lock(&slabs_lock);
    s_cls = &slabclass[slab_rebal.s_clsid];
    for (x = 0; x < slab_bulk_check; x++) {
        item *it = slab_rebal.slab_pos;
        status = MOVE_PASS;
        if (it->slabs_clsid != 255) {
            refcount = refcount_incr(&it->refcount);
            if (refcount == 1) { 
                if (it->it_flags & ITEM_SLABBED) {
                    if (s_cls->slots == it) {
                        s_cls->slots = it->next;
                    }
                    if (it->next) it->next->prev = it->prev;
                    if (it->prev) it->prev->next = it->next;
                    s_cls->sl_curr--;
                    status = MOVE_DONE;
                } else {
                    status = MOVE_BUSY;
                }
            } else if (refcount == 2) { 
                if ((it->it_flags & ITEM_LINKED) != 0) {
                    do_item_unlink_nolock(it, hash(ITEM_key(it), it->nkey, 0));
                    status = MOVE_DONE;
                } else {
                    status = MOVE_BUSY;
                }
            } else {
                if (settings.verbose > 2) {
                    fprintf(stderr, "Slab reassign hit a busy item: refcount: %d (%d -> %d)\n",
                        it->refcount, slab_rebal.s_clsid, slab_rebal.d_clsid);
                }
                status = MOVE_BUSY;
            }
        }
        switch (status) {
            case MOVE_DONE:
                it->refcount = 0;
                it->it_flags = 0;
                it->slabs_clsid = 255;
                break;
            case MOVE_BUSY:
                slab_rebal.busy_items++;
                was_busy++;
                refcount_decr(&it->refcount);
                break;
            case MOVE_PASS:
                break;
        }
        slab_rebal.slab_pos = (char *)slab_rebal.slab_pos + s_cls->size;
        if (slab_rebal.slab_pos >= slab_rebal.slab_end)
            break;
    }
    if (slab_rebal.slab_pos >= slab_rebal.slab_end) {
        if (slab_rebal.busy_items) {
            slab_rebal.slab_pos = slab_rebal.slab_start;
            slab_rebal.busy_items = 0;
        } else {
            slab_rebal.done++;
        }
    }
    pthread_mutex_unlock(&slabs_lock);
    pthread_mutex_unlock(&cache_lock);
    return was_busy;
}
static int slab_rebalance_move ( void ) { slabclass_t * s_cls ; int x ; int was_busy = 0 ; int refcount = 0 ; enum move_status status = MOVE_PASS ; pthread_mutex_lock ( & cache_lock ) ; pthread_mutex_lock ( & slabs_lock ) ; s_cls = & slabclass [ slab_rebal . s_clsid ] ; for ( x = 0 ; x < slab_bulk_check ; x ++ ) { item * it = slab_rebal . slab_pos ; status = MOVE_PASS ; if ( it -> slabs_clsid != 255 ) { refcount = refcount_incr ( & it -> refcount ) ; if ( refcount == 1 ) { if ( it -> it_flags & ITEM_SLABBED ) { if ( s_cls -> slots == it ) { s_cls -> slots = it -> next ; } if ( it -> next ) it -> next -> prev = it -> prev ; if ( it -> prev ) it -> prev -> next = it -> next ; s_cls -> sl_curr -- ; status = MOVE_DONE ; } else { status = MOVE_BUSY ; } } else if ( refcount == 2 ) { if ( ( it -> it_flags & ITEM_LINKED ) != 0 ) { do_item_unlink_nolock ( it , hash ( ITEM_key ( it ) , it -> nkey , 0 ) ) ; status = MOVE_DONE ; } else { status = MOVE_BUSY ; } } else { if ( settings . verbose > 2 ) { fprintf ( stderr , " \n " , it -> refcount , slab_rebal . s_clsid , slab_rebal . d_clsid ) ; } status = MOVE_BUSY ; } } switch ( status ) { case MOVE_DONE : it -> refcount = 0 ; it -> it_flags = 0 ; it -> slabs_clsid = 255 ; break ; case MOVE_BUSY : slab_rebal . busy_items ++ ; was_busy ++ ; refcount_decr ( & it -> refcount ) ; break ; case MOVE_PASS : break ; } slab_rebal . slab_pos = ( char * ) slab_rebal . slab_pos + s_cls -> size ; if ( slab_rebal . slab_pos >= slab_rebal . slab_end ) break ; } if ( slab_rebal . slab_pos >= slab_rebal . slab_end ) { if ( slab_rebal . busy_items ) { slab_rebal . slab_pos = slab_rebal . slab_start ; slab_rebal . busy_items = 0 ; } else { slab_rebal . done ++ ; } } pthread_mutex_unlock ( & slabs_lock ) ; pthread_mutex_unlock ( & cache_lock ) ; return was_busy ; }
refcount == 0 is safe since nobody can incr while cache_lock is held.
refcount == 0 is safe since nobody can incr while cache_lock is held .
/* item is unlinked, unused */ /* remove from slab freelist */ /* item is linked but not busy */ /* refcount == 1 + !ITEM_LINKED means the item is being
                     * uploaded to, or was just unlinked but hasn't been freed
                     * yet. Let it bleed off on its own and try again later */ /* Some items were busy, start again from the top */