diff options
author | Trond Norbye <trond.norbye@gmail.com> | 2011-03-18 11:39:12 -0700 |
---|---|---|
committer | Trond Norbye <trond.norbye@gmail.com> | 2011-03-18 11:39:12 -0700 |
commit | 58a9fefa9742a896da51b3075a252e6f1233ad4b (patch) | |
tree | 395eb6a8bccb6e488374f467e3c89c03496e6999 | |
parent | 458d1e1986f53e65d84007e9f99da993607b027d (diff) | |
download | memcached-58a9fefa9742a896da51b3075a252e6f1233ad4b.tar.gz |
Allow in-place replace for incr
-rw-r--r-- | engines/default_engine/items.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/engines/default_engine/items.c b/engines/default_engine/items.c index 927bd26..cd09058 100644 --- a/engines/default_engine/items.c +++ b/engines/default_engine/items.c @@ -709,18 +709,27 @@ static ENGINE_ERROR_CODE do_add_delta(struct default_engine *engine, if ((res = snprintf(buf, sizeof(buf), "%" PRIu64, value)) == -1) { return ENGINE_EINVAL; } - hash_item *new_it = do_item_alloc(engine, item_get_key(it), - it->nkey, it->flags, - it->exptime, res, - cookie); - if (new_it == NULL) { - do_item_unlink(engine, it); - return ENGINE_ENOMEM; + + if (it->refcount == 1 && res <= it->nbytes) { + // we can do inline replacement + memcpy(item_get_data(it), buf, res); + memset(item_get_data(it) + res, ' ', it->nbytes - res); + item_set_cas(NULL, NULL, it, get_cas_id()); + *rcas = item_get_cas(it); + } else { + hash_item *new_it = do_item_alloc(engine, item_get_key(it), + it->nkey, it->flags, + it->exptime, res, + cookie); + if (new_it == NULL) { + do_item_unlink(engine, it); + return ENGINE_ENOMEM; + } + memcpy(item_get_data(new_it), buf, res); + do_item_replace(engine, it, new_it); + *rcas = item_get_cas(new_it); + do_item_release(engine, new_it); /* release our reference */ } - memcpy(item_get_data(new_it), buf, res); - do_item_replace(engine, it, new_it); - *rcas = item_get_cas(new_it); - do_item_release(engine, new_it); /* release our reference */ return ENGINE_SUCCESS; } |