memcached.c
enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey,
                                    const bool incr, const int64_t delta,
                                    char *buf, uint64_t *cas,
                                    const uint32_t hv) {
    char *ptr;
    uint64_t value;
    int res;
    item *it;

    it = do_item_get(key, nkey, hv);
    if (!it) {
        return DELTA_ITEM_NOT_FOUND;
    }

    if (cas != NULL && *cas != 0 && ITEM_get_cas(it) != *cas) {
        do_item_remove(it);
        return DELTA_ITEM_CAS_MISMATCH;
    }

    ptr = ITEM_data(it);

    if (!safe_strtoull(ptr, &value)) {
        do_item_remove(it);
        return NON_NUMERIC;
    }

    if (incr) {
        value += delta;
        MEMCACHED_COMMAND_INCR(c->sfd, ITEM_key(it), it->nkey, value);
    } else {
        if(delta > value) {
            value = 0;
        } else {
            value -= delta;
        }
        MEMCACHED_COMMAND_DECR(c->sfd, ITEM_key(it), it->nkey, value);
    }

    pthread_mutex_lock(&c->thread->stats.mutex);
    if (incr) {
        c->thread->stats.slab_stats[it->slabs_clsid].incr_hits++;
    } else {
        c->thread->stats.slab_stats[it->slabs_clsid].decr_hits++;
    }
    pthread_mutex_unlock(&c->thread->stats.mutex);

    snprintf(buf, INCR_MAX_STORAGE_LEN, "%llu", (unsigned long long)value);
    res = strlen(buf);
    if (res + 2 > it->nbytes || it->refcount != 1) { /* need to realloc */
        item *new_it;
        new_it = item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 );
        if (new_it == 0) {
            do_item_remove(it);
            return EOM;
        }
        memcpy(ITEM_data(new_it), buf, res);
        memcpy(ITEM_data(new_it) + res, "\r\n", 2);
        item_replace(it, new_it, hv);
        // Overwrite the older item's CAS with our new CAS since we're
        // returning the CAS of the old item below.
        ITEM_set_cas(it, (settings.use_cas) ? ITEM_get_cas(new_it) : 0);
        do_item_remove(new_it);       /* release our reference */
    } else { /* replace in-place */
        /* When changing the value without replacing the item, we
           need to update the CAS on the existing item. */
        mutex_lock(&cache_lock); /* FIXME */
        ITEM_set_cas(it, (settings.use_cas) ? get_cas_id() : 0);
        pthread_mutex_unlock(&cache_lock);

        memcpy(ITEM_data(it), buf, res);
        memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2);
        do_item_update(it);
    }

    if (cas) {
        *cas = ITEM_get_cas(it);    /* swap the incoming CAS value */
    }
    do_item_remove(it);         /* release our reference */
    return OK;
}
/*
 * adds a delta value to a numeric item.
 *
 * c     connection requesting the operation
 * it    item to adjust
 * incr  true to increment value, false to decrement
 * delta amount to adjust value by
 * buf   buffer for response string
 *
 * returns a response string to send back to the client.
 */
adds a delta value to a numeric item.
c     connection requesting the operation
it    item to adjust
incr  true to increment value, false to decrement
delta amount to adjust value by
buf   buffer for response string

returns a response string to send back to the client.
adds a delta value to a numeric item . c connection requesting the operation it item to adjust incr true to increment value false to decrement delta amount to adjust value by buf buffer for response string returns a response string to send back to the client .
enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey,
                                    const bool incr, const int64_t delta,
                                    char *buf, uint64_t *cas,
                                    const uint32_t hv) {
    char *ptr;
    uint64_t value;
    int res;
    item *it;
    it = do_item_get(key, nkey, hv);
    if (!it) {
        return DELTA_ITEM_NOT_FOUND;
    }
    if (cas != NULL && *cas != 0 && ITEM_get_cas(it) != *cas) {
        do_item_remove(it);
        return DELTA_ITEM_CAS_MISMATCH;
    }
    ptr = ITEM_data(it);
    if (!safe_strtoull(ptr, &value)) {
        do_item_remove(it);
        return NON_NUMERIC;
    }
    if (incr) {
        value += delta;
        MEMCACHED_COMMAND_INCR(c->sfd, ITEM_key(it), it->nkey, value);
    } else {
        if(delta > value) {
            value = 0;
        } else {
            value -= delta;
        }
        MEMCACHED_COMMAND_DECR(c->sfd, ITEM_key(it), it->nkey, value);
    }
    pthread_mutex_lock(&c->thread->stats.mutex);
    if (incr) {
        c->thread->stats.slab_stats[it->slabs_clsid].incr_hits++;
    } else {
        c->thread->stats.slab_stats[it->slabs_clsid].decr_hits++;
    }
    pthread_mutex_unlock(&c->thread->stats.mutex);
    snprintf(buf, INCR_MAX_STORAGE_LEN, "%llu", (unsigned long long)value);
    res = strlen(buf);
    if (res + 2 > it->nbytes || it->refcount != 1) { 
        item *new_it;
        new_it = item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 );
        if (new_it == 0) {
            do_item_remove(it);
            return EOM;
        }
        memcpy(ITEM_data(new_it), buf, res);
        memcpy(ITEM_data(new_it) + res, "\r\n", 2);
        item_replace(it, new_it, hv);
        ITEM_set_cas(it, (settings.use_cas) ? ITEM_get_cas(new_it) : 0);
        do_item_remove(new_it);       
    } else { 
        mutex_lock(&cache_lock); 
        ITEM_set_cas(it, (settings.use_cas) ? get_cas_id() : 0);
        pthread_mutex_unlock(&cache_lock);
        memcpy(ITEM_data(it), buf, res);
        memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2);
        do_item_update(it);
    }
    if (cas) {
        *cas = ITEM_get_cas(it);    
    }
    do_item_remove(it);         
    return OK;
}
enum delta_result_type do_add_delta ( conn * c , const char * key , const size_t nkey , const bool incr , const int64_t delta , char * buf , uint64_t * cas , const uint32_t hv ) { char * ptr ; uint64_t value ; int res ; item * it ; it = do_item_get ( key , nkey , hv ) ; if ( ! it ) { return DELTA_ITEM_NOT_FOUND ; } if ( cas != NULL && * cas != 0 && ITEM_get_cas ( it ) != * cas ) { do_item_remove ( it ) ; return DELTA_ITEM_CAS_MISMATCH ; } ptr = ITEM_data ( it ) ; if ( ! safe_strtoull ( ptr , & value ) ) { do_item_remove ( it ) ; return NON_NUMERIC ; } if ( incr ) { value += delta ; MEMCACHED_COMMAND_INCR ( c -> sfd , ITEM_key ( it ) , it -> nkey , value ) ; } else { if ( delta > value ) { value = 0 ; } else { value -= delta ; } MEMCACHED_COMMAND_DECR ( c -> sfd , ITEM_key ( it ) , it -> nkey , value ) ; } pthread_mutex_lock ( & c -> thread -> stats . mutex ) ; if ( incr ) { c -> thread -> stats . slab_stats [ it -> slabs_clsid ] . incr_hits ++ ; } else { c -> thread -> stats . slab_stats [ it -> slabs_clsid ] . decr_hits ++ ; } pthread_mutex_unlock ( & c -> thread -> stats . mutex ) ; snprintf ( buf , INCR_MAX_STORAGE_LEN , " " , ( unsigned long long ) value ) ; res = strlen ( buf ) ; if ( res + 2 > it -> nbytes || it -> refcount != 1 ) { item * new_it ; new_it = item_alloc ( ITEM_key ( it ) , it -> nkey , atoi ( ITEM_suffix ( it ) + 1 ) , it -> exptime , res + 2 ) ; if ( new_it == 0 ) { do_item_remove ( it ) ; return EOM ; } memcpy ( ITEM_data ( new_it ) , buf , res ) ; memcpy ( ITEM_data ( new_it ) + res , " \r \n " , 2 ) ; item_replace ( it , new_it , hv ) ; ITEM_set_cas ( it , ( settings . use_cas ) ? ITEM_get_cas ( new_it ) : 0 ) ; do_item_remove ( new_it ) ; } else { mutex_lock ( & cache_lock ) ; ITEM_set_cas ( it , ( settings . use_cas ) ? get_cas_id ( ) : 0 ) ; pthread_mutex_unlock ( & cache_lock ) ; memcpy ( ITEM_data ( it ) , buf , res ) ; memset ( ITEM_data ( it ) + res , ' ' , it -> nbytes - res - 2 ) ; do_item_update ( it ) ; } if ( cas ) { * cas = ITEM_get_cas ( it ) ; } do_item_remove ( it ) ; return OK ; }
adds a delta value to a numeric item.
adds a delta value to a numeric item .
/* need to realloc */ // Overwrite the older item's CAS with our new CAS since we're // returning the CAS of the old item below. /* release our reference */ /* replace in-place */ /* When changing the value without replacing the item, we
           need to update the CAS on the existing item. */ /* FIXME */ /* swap the incoming CAS value */ /* release our reference */