diff options
author | Dustin Sallings <dustin@spy.net> | 2009-02-11 18:03:14 -0800 |
---|---|---|
committer | Dustin Sallings <dustin@spy.net> | 2009-02-11 18:03:14 -0800 |
commit | bad6c614e58639d0685706f17dc9562323c30f39 (patch) | |
tree | 72c54982d8cbc049f0b8353289255842acedc3f3 | |
parent | ed69f308cbf9b562d389c2dfe122551ae4e9cfa2 (diff) | |
download | memcached-bad6c614e58639d0685706f17dc9562323c30f39.tar.gz |
Update CAS on non-replace incr/decr.
This fixes a problem reported as bug 15 where incr and decr do not
change CAS values when they aren't completely replacing the item
(which is the typical case).
http://code.google.com/p/memcached/issues/detail?id=15
-rw-r--r-- | items.c | 1 | ||||
-rw-r--r-- | items.h | 2 | ||||
-rw-r--r-- | memcached.c | 4 | ||||
-rw-r--r-- | t/cas.t | 27 |
4 files changed, 32 insertions, 2 deletions
@@ -17,7 +17,6 @@ /* Forward Declarations */ static void item_link_q(item *it); static void item_unlink_q(item *it); -static uint64_t get_cas_id(void); /* * We only reposition items in the LRU queue if they haven't been repositioned @@ -1,5 +1,7 @@ /* See items.c */ void item_init(void); +uint64_t get_cas_id(void); + /*@null@*/ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes); void item_free(item *it); diff --git a/memcached.c b/memcached.c index 508f04d..a5fc781 100644 --- a/memcached.c +++ b/memcached.c @@ -2633,6 +2633,10 @@ char *do_add_delta(conn *c, item *it, const bool incr, const int64_t delta, char item_replace(it, new_it); 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. */ + ITEM_set_cas(it, (settings.use_cas) ? get_cas_id() : 0); + memcpy(ITEM_data(it), buf, res); memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2); } @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; -use Test::More tests => 30; +use Test::More tests => 39; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; @@ -115,3 +115,28 @@ ok( ( $res1 eq "STORED\r\n" && $res2 eq "EXISTS\r\n") || ( $res1 eq "EXISTS\r\n" && $res2 eq "STORED\r\n"), "cas on same item from two sockets"); +### bug 15: http://code.google.com/p/memcached/issues/detail?id=15 + +# set foo +print $sock "set bug15 0 0 1\r\n0\r\n"; +is(scalar <$sock>, "STORED\r\n", "stored 0"); + +# Check out the first gets. +print $sock "gets bug15\r\n"; +ok(scalar <$sock> =~ /VALUE bug15 0 1 (\d+)\r\n/, "gets bug15 regexp success"); +my $bug15_cas = $1; +is(scalar <$sock>, "0\r\n", "gets bug15 data is 0"); +is(scalar <$sock>, "END\r\n","gets bug15 END"); + +# Increment +print $sock "incr bug15 1\r\n"; +is(scalar <$sock>, "1\r\n", "incr worked"); + +# Validate a changed CAS +print $sock "gets bug15\r\n"; +ok(scalar <$sock> =~ /VALUE bug15 0 1 (\d+)\r\n/, "gets bug15 regexp success"); +my $next_bug15_cas = $1; +is(scalar <$sock>, "1\r\n", "gets bug15 data is 0"); +is(scalar <$sock>, "END\r\n","gets bug15 END"); + +ok($bug15_cas != $next_bug15_cas, "CAS changed"); |