[memcached] sgrimm,
r439: Fix for flush_all 1-second window bug. Y...
commits at code.sixapart.com
commits at code.sixapart.com
Mon Nov 20 22:13:31 UTC 2006
Fix for flush_all 1-second window bug. You can now do a "set" immediately
after a "flush_all" without the newly set data getting expired. (Ported
from trunk.)
U branches/multithreaded/server/items.c
U branches/multithreaded/server/memcached.c
U branches/multithreaded/server/memcached.h
U branches/multithreaded/server/t/flush-all.t
Modified: branches/multithreaded/server/items.c
===================================================================
--- branches/multithreaded/server/items.c 2006-11-20 22:05:31 UTC (rev 438)
+++ branches/multithreaded/server/items.c 2006-11-20 22:13:30 UTC (rev 439)
@@ -391,3 +391,29 @@
}
return it;
}
+
+/* expires items that are more recent than the oldest_live setting. */
+void item_flush_expired() {
+ int i;
+ item *iter, *next;
+ if (! settings.oldest_live)
+ return;
+ for (i = 0; i < LARGEST_ID; i++) {
+ /* The LRU is sorted in decreasing time order, and an item's timestamp
+ * is never newer than its last access time, so we only need to walk
+ * back until we hit an item older than the oldest_live time.
+ * The oldest_live checking will auto-expire the remaining items.
+ */
+ for (iter = heads[i]; iter != NULL; iter = next) {
+ if (iter->time >= settings.oldest_live) {
+ next = iter->next;
+ if ((iter->it_flags & ITEM_SLABBED) == 0) {
+ item_unlink(iter);
+ }
+ } else {
+ /* We've hit the first old item. Continue to the next queue. */
+ break;
+ }
+ }
+ }
+}
Modified: branches/multithreaded/server/memcached.c
===================================================================
--- branches/multithreaded/server/memcached.c 2006-11-20 22:05:31 UTC (rev 438)
+++ branches/multithreaded/server/memcached.c 2006-11-20 22:13:30 UTC (rev 439)
@@ -90,11 +90,11 @@
stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = 0;
stats.curr_bytes = stats.bytes_read = stats.bytes_written = 0;
- /* make the time we started always be 1 second before we really
+ /* make the time we started always be 2 seconds before we really
did, so time(0) - time.started is never zero. if so, things
like 'settings.oldest_live' which act as booleans as well as
values are now false in boolean context... */
- stats.started = time(0) - 1;
+ stats.started = time(0) - 2;
}
void stats_reset(void) {
@@ -1323,7 +1323,8 @@
set_current_time();
if(ntokens == 2) {
- settings.oldest_live = current_time;
+ settings.oldest_live = current_time - 1;
+ item_flush_expired();
out_string(c, "OK");
return;
}
@@ -1334,7 +1335,8 @@
return;
}
- settings.oldest_live = realtime(exptime);
+ settings.oldest_live = realtime(exptime) - 1;
+ item_flush_expired();
out_string(c, "OK");
return;
Modified: branches/multithreaded/server/memcached.h
===================================================================
--- branches/multithreaded/server/memcached.h 2006-11-20 22:05:31 UTC (rev 438)
+++ branches/multithreaded/server/memcached.h 2006-11-20 22:13:30 UTC (rev 439)
@@ -289,6 +289,7 @@
item *item_get_notedeleted(char *key, size_t nkey, int *delete_locked);
item *item_get_nocheck(char *key, size_t nkey);
item *item_get(char *key, size_t nkey);
+void item_flush_expired(void);
/* time handling */
void set_current_time (); /* update the global variable holding
Modified: branches/multithreaded/server/t/flush-all.t
===================================================================
--- branches/multithreaded/server/t/flush-all.t 2006-11-20 22:05:31 UTC (rev 438)
+++ branches/multithreaded/server/t/flush-all.t 2006-11-20 22:13:30 UTC (rev 439)
@@ -1,7 +1,7 @@
#!/usr/bin/perl
use strict;
-use Test::More tests => 11;
+use Test::More tests => 10;
use FindBin qw($Bin);
use lib "$Bin/lib";
use MemcachedTest;
@@ -16,19 +16,13 @@
mem_get_is($sock, "foo", "fooval");
print $sock "flush_all\r\n";
is(scalar <$sock>, "OK\r\n", "did flush_all");
-
mem_get_is($sock, "foo", undef);
-SKIP: {
- skip "flush_all is still only second-granularity. need atomic counter on flush_all.", 2 unless 0;
- print $sock "set foo 0 0 3\r\nnew\r\n";
- is(scalar <$sock>, "STORED\r\n", "stored foo = 'new'");
- mem_get_is($sock, "foo", 'new');
-}
+# check that flush_all doesn't blow away items that immediately get set
+print $sock "set foo 0 0 3\r\nnew\r\n";
+is(scalar <$sock>, "STORED\r\n", "stored foo = 'new'");
+mem_get_is($sock, "foo", 'new');
-sleep 1;
-mem_get_is($sock, "foo", undef);
-
# and the other form, specifying a flush_all time...
my $expire = time() + 2;
print $sock "flush_all $expire\r\n";
More information about the memcached-commits
mailing list