Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 249 by [email protected]: Problem of reclaiming valid items.
http://code.google.com/p/memcached/issues/detail?id=249

What steps will reproduce the problem?
1.just make a small-sized(with -m <num> and -M option) memcached with full of items of exptime=0.
2. and, do send flush command with delay(86400): "flush_all 86400\r\n"
3. then, add new items into the memcached. The tail item of LRU will be reclaimed even if the item is still valid.


What is the expected output? What do you see instead?

Expected result is "out of memory". Because there is no available memory and no reclaimable items.

But, The tail item of LRU will be reclaimed even if the item is still valid.
It's a bug I think.


What version of the product are you using? On what operating system?

1.4.11 and below versions.

Please provide any additional information below.

The functionality of reclaiming flushed items are added memcached by fixing issue 183. But, the fix was not correct. It bring an another bug explained by this issue.

The needed code fix for this bug like followings:
In the following do_item_alloc(),
the check condition for invalidated items should be changed to the new code.
Because, flush can be requested with delay option.


item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes) {

    ...

    rel_time_t oldest_live = settings.oldest_live;

    search = tails[id];
    if (search == NULL) {
        it = slabs_alloc(ntotal, id);
    } else if (search->refcount == 0) {
#if 1 // new code
if ((search->time < oldest_live && oldest_live <= current_time) || // dead by flush
         (search->exptime != 0 && search->exptime < current_time)) {
#else // old code
        if ((search->time < oldest_live) || // dead by flush
         (search->exptime != 0 && search->exptime < current_time)) {
#endif
            STATS_LOCK();
            stats.reclaimed++;
            STATS_UNLOCK();
            itemstats[id].reclaimed++;
            if ((search->it_flags & ITEM_FETCHED) == 0) {
                STATS_LOCK();
                stats.expired_unfetched++;
                STATS_UNLOCK();
                itemstats[id].expired_unfetched++;
            }
            it = search;
            it->refcount = 1;
slabs_adjust_mem_requested(it->slabs_clsid, ITEM_ntotal(it), ntotal);
            do_item_unlink_nolock(it, hash(ITEM_key(it), it->nkey, 0));
            /* Initialize the item block: */
            it->slabs_clsid = 0;
            it->refcount = 0;
        }
    }

    ...

}






Reply via email to